Home | History | Annotate | Download | only in xkbcomp
      1 /************************************************************
      2  * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
      3  *
      4  * Permission to use, copy, modify, and distribute this
      5  * software and its documentation for any purpose and without
      6  * fee is hereby granted, provided that the above copyright
      7  * notice appear in all copies and that both that copyright
      8  * notice and this permission notice appear in supporting
      9  * documentation, and that the name of Silicon Graphics not be
     10  * used in advertising or publicity pertaining to distribution
     11  * of the software without specific prior written permission.
     12  * Silicon Graphics makes no representation about the suitability
     13  * of this software for any purpose. It is provided "as is"
     14  * without any express or implied warranty.
     15  *
     16  * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
     17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     18  * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
     19  * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
     20  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
     22  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
     23  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
     24  *
     25  ********************************************************/
     26 
     27 /*
     28  * Copyright  2012 Intel Corporation
     29  * Copyright  2012 Ran Benita <ran234 (at) gmail.com>
     30  *
     31  * Permission is hereby granted, free of charge, to any person obtaining a
     32  * copy of this software and associated documentation files (the "Software"),
     33  * to deal in the Software without restriction, including without limitation
     34  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     35  * and/or sell copies of the Software, and to permit persons to whom the
     36  * Software is furnished to do so, subject to the following conditions:
     37  *
     38  * The above copyright notice and this permission notice (including the next
     39  * paragraph) shall be included in all copies or substantial portions of the
     40  * Software.
     41  *
     42  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     43  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     44  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     45  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     46  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     47  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     48  * DEALINGS IN THE SOFTWARE.
     49  *
     50  * Author: Daniel Stone <daniel (at) fooishbar.org>
     51  *         Ran Benita <ran234 (at) gmail.com>
     52  */
     53 
     54 #include "xkbcomp-priv.h"
     55 #include "text.h"
     56 #include "expr.h"
     57 #include "action.h"
     58 #include "vmod.h"
     59 #include "include.h"
     60 #include "keysym.h"
     61 
     62 enum key_repeat {
     63     KEY_REPEAT_UNDEFINED = 0,
     64     KEY_REPEAT_YES = 1,
     65     KEY_REPEAT_NO = 2,
     66 };
     67 
     68 enum group_field {
     69     GROUP_FIELD_SYMS = (1 << 0),
     70     GROUP_FIELD_ACTS = (1 << 1),
     71     GROUP_FIELD_TYPE = (1 << 2),
     72 };
     73 
     74 enum key_field {
     75     KEY_FIELD_REPEAT = (1 << 0),
     76     KEY_FIELD_DEFAULT_TYPE = (1 << 1),
     77     KEY_FIELD_GROUPINFO = (1 << 2),
     78     KEY_FIELD_VMODMAP = (1 << 3),
     79 };
     80 
     81 typedef struct {
     82     enum group_field defined;
     83     darray(struct xkb_level) levels;
     84     xkb_atom_t type;
     85 } GroupInfo;
     86 
     87 typedef struct {
     88     enum key_field defined;
     89     enum merge_mode merge;
     90 
     91     xkb_atom_t name;
     92 
     93     darray(GroupInfo) groups;
     94 
     95     enum key_repeat repeat;
     96     xkb_mod_mask_t vmodmap;
     97     xkb_atom_t default_type;
     98 
     99     enum xkb_range_exceed_type out_of_range_group_action;
    100     xkb_layout_index_t out_of_range_group_number;
    101 } KeyInfo;
    102 
    103 static void
    104 ClearLevelInfo(struct xkb_level *leveli)
    105 {
    106     if (leveli->num_syms > 1)
    107         free(leveli->u.syms);
    108 }
    109 
    110 static void
    111 InitGroupInfo(GroupInfo *groupi)
    112 {
    113     memset(groupi, 0, sizeof(*groupi));
    114 }
    115 
    116 static void
    117 ClearGroupInfo(GroupInfo *groupi)
    118 {
    119     struct xkb_level *leveli;
    120     darray_foreach(leveli, groupi->levels)
    121         ClearLevelInfo(leveli);
    122     darray_free(groupi->levels);
    123 }
    124 
    125 static void
    126 CopyGroupInfo(GroupInfo *to, const GroupInfo *from)
    127 {
    128     to->defined = from->defined;
    129     to->type = from->type;
    130     darray_init(to->levels);
    131     darray_copy(to->levels, from->levels);
    132     for (xkb_level_index_t j = 0; j < darray_size(to->levels); j++)
    133         if (darray_item(from->levels, j).num_syms > 1)
    134             darray_item(to->levels, j).u.syms =
    135                 memdup(darray_item(from->levels, j).u.syms,
    136                        darray_item(from->levels, j).num_syms,
    137                        sizeof(xkb_keysym_t));
    138 }
    139 
    140 static void
    141 InitKeyInfo(struct xkb_context *ctx, KeyInfo *keyi)
    142 {
    143     memset(keyi, 0, sizeof(*keyi));
    144     keyi->merge = MERGE_OVERRIDE;
    145     keyi->name = xkb_atom_intern_literal(ctx, "*");
    146     keyi->out_of_range_group_action = RANGE_WRAP;
    147 }
    148 
    149 static void
    150 ClearKeyInfo(KeyInfo *keyi)
    151 {
    152     GroupInfo *groupi;
    153     darray_foreach(groupi, keyi->groups)
    154         ClearGroupInfo(groupi);
    155     darray_free(keyi->groups);
    156 }
    157 
    158 /***====================================================================***/
    159 
    160 typedef struct {
    161     enum merge_mode merge;
    162     bool haveSymbol;
    163     xkb_mod_index_t modifier;
    164     union {
    165         xkb_atom_t keyName;
    166         xkb_keysym_t keySym;
    167     } u;
    168 } ModMapEntry;
    169 
    170 typedef struct {
    171     char *name;         /* e.g. pc+us+inet(evdev) */
    172     int errorCount;
    173     enum merge_mode merge;
    174     xkb_layout_index_t explicit_group;
    175     darray(KeyInfo) keys;
    176     KeyInfo default_key;
    177     ActionsInfo *actions;
    178     darray(xkb_atom_t) group_names;
    179     darray(ModMapEntry) modmaps;
    180     struct xkb_mod_set mods;
    181 
    182     struct xkb_context *ctx;
    183     /* Needed for AddKeySymbols. */
    184     const struct xkb_keymap *keymap;
    185 } SymbolsInfo;
    186 
    187 static void
    188 InitSymbolsInfo(SymbolsInfo *info, const struct xkb_keymap *keymap,
    189                 ActionsInfo *actions, const struct xkb_mod_set *mods)
    190 {
    191     memset(info, 0, sizeof(*info));
    192     info->ctx = keymap->ctx;
    193     info->keymap = keymap;
    194     info->merge = MERGE_OVERRIDE;
    195     InitKeyInfo(keymap->ctx, &info->default_key);
    196     info->actions = actions;
    197     info->mods = *mods;
    198     info->explicit_group = XKB_LAYOUT_INVALID;
    199 }
    200 
    201 static void
    202 ClearSymbolsInfo(SymbolsInfo *info)
    203 {
    204     KeyInfo *keyi;
    205     free(info->name);
    206     darray_foreach(keyi, info->keys)
    207         ClearKeyInfo(keyi);
    208     darray_free(info->keys);
    209     darray_free(info->group_names);
    210     darray_free(info->modmaps);
    211     ClearKeyInfo(&info->default_key);
    212 }
    213 
    214 static const char *
    215 KeyInfoText(SymbolsInfo *info, KeyInfo *keyi)
    216 {
    217     return KeyNameText(info->ctx, keyi->name);
    218 }
    219 
    220 static bool
    221 LevelsSameSyms(const struct xkb_level *a, const struct xkb_level *b)
    222 {
    223     if (a->num_syms != b->num_syms)
    224         return false;
    225     if (a->num_syms <= 1)
    226         return a->u.sym == b->u.sym;
    227     else
    228         return memcmp(a->u.syms, b->u.syms,
    229                       sizeof(*a->u.syms) * a->num_syms) == 0;
    230 
    231 }
    232 
    233 static bool
    234 MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber,
    235             bool report, xkb_layout_index_t group, xkb_atom_t key_name)
    236 {
    237     xkb_level_index_t i, levels_in_both;
    238     struct xkb_level *level;
    239 
    240     /* First find the type of the merged group. */
    241     if (into->type != from->type) {
    242         if (from->type == XKB_ATOM_NONE) {
    243         }
    244         else if (into->type == XKB_ATOM_NONE) {
    245             into->type = from->type;
    246         }
    247         else {
    248             xkb_atom_t use = (clobber ? from->type : into->type);
    249             xkb_atom_t ignore = (clobber ? into->type : from->type);
    250 
    251             if (report)
    252                 log_warn(info->ctx,
    253                          "Multiple definitions for group %d type of key %s; "
    254                          "Using %s, ignoring %s\n",
    255                          group + 1, KeyNameText(info->ctx, key_name),
    256                          xkb_atom_text(info->ctx, use),
    257                          xkb_atom_text(info->ctx, ignore));
    258 
    259             into->type = use;
    260         }
    261     }
    262     into->defined |= (from->defined & GROUP_FIELD_TYPE);
    263 
    264     /* Now look at the levels. */
    265 
    266     if (darray_empty(from->levels)) {
    267         InitGroupInfo(from);
    268         return true;
    269     }
    270 
    271     if (darray_empty(into->levels)) {
    272         from->type = into->type;
    273         *into = *from;
    274         InitGroupInfo(from);
    275         return true;
    276     }
    277 
    278     /* Merge the actions and syms. */
    279     levels_in_both = MIN(darray_size(into->levels), darray_size(from->levels));
    280     for (i = 0; i < levels_in_both; i++) {
    281         struct xkb_level *intoLevel = &darray_item(into->levels, i);
    282         struct xkb_level *fromLevel = &darray_item(from->levels, i);
    283 
    284         if (fromLevel->action.type == ACTION_TYPE_NONE) {
    285         }
    286         else if (intoLevel->action.type == ACTION_TYPE_NONE) {
    287             intoLevel->action = fromLevel->action;
    288         }
    289         else {
    290             union xkb_action *use, *ignore;
    291             use = (clobber ? &fromLevel->action : &intoLevel->action);
    292             ignore = (clobber ? &intoLevel->action : &fromLevel->action);
    293 
    294             if (report)
    295                 log_warn(info->ctx,
    296                          "Multiple actions for level %d/group %u on key %s; "
    297                          "Using %s, ignoring %s\n",
    298                          i + 1, group + 1, KeyNameText(info->ctx, key_name),
    299                          ActionTypeText(use->type),
    300                          ActionTypeText(ignore->type));
    301 
    302             intoLevel->action = *use;
    303         }
    304 
    305         if (fromLevel->num_syms == 0) {
    306         }
    307         else if (intoLevel->num_syms == 0) {
    308             intoLevel->num_syms = fromLevel->num_syms;
    309             if (fromLevel->num_syms > 1)
    310                 intoLevel->u.syms = fromLevel->u.syms;
    311             else
    312                 intoLevel->u.sym = fromLevel->u.sym;
    313             fromLevel->num_syms = 0;
    314         }
    315         else if (!LevelsSameSyms(fromLevel, intoLevel)) {
    316             if (report)
    317                 log_warn(info->ctx,
    318                          "Multiple symbols for level %d/group %u on key %s; "
    319                          "Using %s, ignoring %s\n",
    320                          i + 1, group + 1, KeyNameText(info->ctx, key_name),
    321                          (clobber ? "from" : "to"),
    322                          (clobber ? "to" : "from"));
    323 
    324             if (clobber) {
    325                 ClearLevelInfo(intoLevel);
    326                 intoLevel->num_syms = fromLevel->num_syms;
    327                 if (fromLevel->num_syms > 1)
    328                     intoLevel->u.syms = fromLevel->u.syms;
    329                 else
    330                     intoLevel->u.sym = fromLevel->u.sym;
    331                 fromLevel->num_syms = 0;
    332             }
    333         }
    334     }
    335     /* If @from has extra levels, get them as well. */
    336     darray_foreach_from(level, from->levels, levels_in_both) {
    337         darray_append(into->levels, *level);
    338         level->num_syms = 0;
    339     }
    340     into->defined |= (from->defined & GROUP_FIELD_ACTS);
    341     into->defined |= (from->defined & GROUP_FIELD_SYMS);
    342 
    343     return true;
    344 }
    345 
    346 static bool
    347 UseNewKeyField(enum key_field field, enum key_field old, enum key_field new,
    348                bool clobber, bool report, enum key_field *collide)
    349 {
    350     if (!(old & field))
    351         return (new & field);
    352 
    353     if (new & field) {
    354         if (report)
    355             *collide |= field;
    356 
    357         if (clobber)
    358             return true;
    359     }
    360 
    361     return false;
    362 }
    363 
    364 static bool
    365 MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from, bool same_file)
    366 {
    367     xkb_layout_index_t i;
    368     xkb_layout_index_t groups_in_both;
    369     enum key_field collide = 0;
    370     const int verbosity = xkb_context_get_log_verbosity(info->ctx);
    371     const bool clobber = (from->merge != MERGE_AUGMENT);
    372     const bool report = (same_file && verbosity > 0) || verbosity > 9;
    373 
    374     if (from->merge == MERGE_REPLACE) {
    375         ClearKeyInfo(into);
    376         *into = *from;
    377         InitKeyInfo(info->ctx, from);
    378         return true;
    379     }
    380 
    381     groups_in_both = MIN(darray_size(into->groups), darray_size(from->groups));
    382     for (i = 0; i < groups_in_both; i++)
    383         MergeGroups(info,
    384                     &darray_item(into->groups, i),
    385                     &darray_item(from->groups, i),
    386                     clobber, report, i, into->name);
    387     /* If @from has extra groups, just move them to @into. */
    388     for (i = groups_in_both; i < darray_size(from->groups); i++) {
    389         darray_append(into->groups, darray_item(from->groups, i));
    390         InitGroupInfo(&darray_item(from->groups, i));
    391     }
    392 
    393     if (UseNewKeyField(KEY_FIELD_VMODMAP, into->defined, from->defined,
    394                        clobber, report, &collide)) {
    395         into->vmodmap = from->vmodmap;
    396         into->defined |= KEY_FIELD_VMODMAP;
    397     }
    398     if (UseNewKeyField(KEY_FIELD_REPEAT, into->defined, from->defined,
    399                        clobber, report, &collide)) {
    400         into->repeat = from->repeat;
    401         into->defined |= KEY_FIELD_REPEAT;
    402     }
    403     if (UseNewKeyField(KEY_FIELD_DEFAULT_TYPE, into->defined, from->defined,
    404                        clobber, report, &collide)) {
    405         into->default_type = from->default_type;
    406         into->defined |= KEY_FIELD_DEFAULT_TYPE;
    407     }
    408     if (UseNewKeyField(KEY_FIELD_GROUPINFO, into->defined, from->defined,
    409                        clobber, report, &collide)) {
    410         into->out_of_range_group_action = from->out_of_range_group_action;
    411         into->out_of_range_group_number = from->out_of_range_group_number;
    412         into->defined |= KEY_FIELD_GROUPINFO;
    413     }
    414 
    415     if (collide)
    416         log_warn(info->ctx,
    417                  "Symbol map for key %s redefined; "
    418                  "Using %s definition for conflicting fields\n",
    419                  KeyNameText(info->ctx, into->name),
    420                  (clobber ? "first" : "last"));
    421 
    422     ClearKeyInfo(from);
    423     InitKeyInfo(info->ctx, from);
    424     return true;
    425 }
    426 
    427 /* TODO: Make it so this function doesn't need the entire keymap. */
    428 static bool
    429 AddKeySymbols(SymbolsInfo *info, KeyInfo *keyi, bool same_file)
    430 {
    431     xkb_atom_t real_name;
    432     KeyInfo *iter;
    433 
    434     /*
    435      * Don't keep aliases in the keys array; this guarantees that
    436      * searching for keys to merge with by straight comparison (see the
    437      * following loop) is enough, and we won't get multiple KeyInfo's
    438      * for the same key because of aliases.
    439      */
    440     real_name = XkbResolveKeyAlias(info->keymap, keyi->name);
    441     if (real_name != XKB_ATOM_NONE)
    442         keyi->name = real_name;
    443 
    444     darray_foreach(iter, info->keys)
    445         if (iter->name == keyi->name)
    446             return MergeKeys(info, iter, keyi, same_file);
    447 
    448     darray_append(info->keys, *keyi);
    449     InitKeyInfo(info->ctx, keyi);
    450     return true;
    451 }
    452 
    453 static bool
    454 AddModMapEntry(SymbolsInfo *info, ModMapEntry *new)
    455 {
    456     ModMapEntry *old;
    457     bool clobber = (new->merge != MERGE_AUGMENT);
    458 
    459     darray_foreach(old, info->modmaps) {
    460         xkb_mod_index_t use, ignore;
    461 
    462         if ((new->haveSymbol != old->haveSymbol) ||
    463             (new->haveSymbol && new->u.keySym != old->u.keySym) ||
    464             (!new->haveSymbol && new->u.keyName != old->u.keyName))
    465             continue;
    466 
    467         if (new->modifier == old->modifier)
    468             return true;
    469 
    470         use = (clobber ? new->modifier : old->modifier);
    471         ignore = (clobber ? old->modifier : new->modifier);
    472 
    473         if (new->haveSymbol)
    474             log_err(info->ctx,
    475                     "Symbol \"%s\" added to modifier map for multiple modifiers; "
    476                     "Using %s, ignoring %s\n",
    477                     KeysymText(info->ctx, new->u.keySym),
    478                     ModIndexText(info->ctx, &info->mods, use),
    479                     ModIndexText(info->ctx, &info->mods, ignore));
    480         else
    481             log_err(info->ctx,
    482                     "Key \"%s\" added to modifier map for multiple modifiers; "
    483                     "Using %s, ignoring %s\n",
    484                     KeyNameText(info->ctx, new->u.keyName),
    485                     ModIndexText(info->ctx, &info->mods, use),
    486                     ModIndexText(info->ctx, &info->mods, ignore));
    487 
    488         old->modifier = use;
    489         return true;
    490     }
    491 
    492     darray_append(info->modmaps, *new);
    493     return true;
    494 }
    495 
    496 /***====================================================================***/
    497 
    498 static void
    499 MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
    500                      enum merge_mode merge)
    501 {
    502     KeyInfo *keyi;
    503     ModMapEntry *mm;
    504     xkb_atom_t *group_name;
    505     xkb_layout_index_t group_names_in_both;
    506 
    507     if (from->errorCount > 0) {
    508         into->errorCount += from->errorCount;
    509         return;
    510     }
    511 
    512     into->mods = from->mods;
    513 
    514     if (into->name == NULL) {
    515         into->name = from->name;
    516         from->name = NULL;
    517     }
    518 
    519     group_names_in_both = MIN(darray_size(into->group_names),
    520                               darray_size(from->group_names));
    521     for (xkb_layout_index_t i = 0; i < group_names_in_both; i++) {
    522         if (!darray_item(from->group_names, i))
    523             continue;
    524 
    525         if (merge == MERGE_AUGMENT && darray_item(into->group_names, i))
    526             continue;
    527 
    528         darray_item(into->group_names, i) = darray_item(from->group_names, i);
    529     }
    530     /* If @from has more, get them as well. */
    531     darray_foreach_from(group_name, from->group_names, group_names_in_both)
    532         darray_append(into->group_names, *group_name);
    533 
    534     if (darray_empty(into->keys)) {
    535         into->keys = from->keys;
    536         darray_init(from->keys);
    537     }
    538     else {
    539         darray_foreach(keyi, from->keys) {
    540             keyi->merge = (merge == MERGE_DEFAULT ? keyi->merge : merge);
    541             if (!AddKeySymbols(into, keyi, false))
    542                 into->errorCount++;
    543         }
    544     }
    545 
    546     if (darray_empty(into->modmaps)) {
    547         into->modmaps = from->modmaps;
    548         darray_init(from->modmaps);
    549     }
    550     else {
    551         darray_foreach(mm, from->modmaps) {
    552             mm->merge = (merge == MERGE_DEFAULT ? mm->merge : merge);
    553             if (!AddModMapEntry(into, mm))
    554                 into->errorCount++;
    555         }
    556     }
    557 }
    558 
    559 static void
    560 HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge);
    561 
    562 static bool
    563 HandleIncludeSymbols(SymbolsInfo *info, IncludeStmt *include)
    564 {
    565     SymbolsInfo included;
    566 
    567     InitSymbolsInfo(&included, info->keymap, info->actions, &info->mods);
    568     included.name = include->stmt;
    569     include->stmt = NULL;
    570 
    571     for (IncludeStmt *stmt = include; stmt; stmt = stmt->next_incl) {
    572         SymbolsInfo next_incl;
    573         XkbFile *file;
    574 
    575         file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_SYMBOLS);
    576         if (!file) {
    577             info->errorCount += 10;
    578             ClearSymbolsInfo(&included);
    579             return false;
    580         }
    581 
    582         InitSymbolsInfo(&next_incl, info->keymap, info->actions,
    583                         &included.mods);
    584         if (stmt->modifier) {
    585             next_incl.explicit_group = atoi(stmt->modifier) - 1;
    586             if (next_incl.explicit_group >= XKB_MAX_GROUPS) {
    587                 log_err(info->ctx,
    588                         "Cannot set explicit group to %d - must be between 1..%d; "
    589                         "Ignoring group number\n",
    590                         next_incl.explicit_group + 1, XKB_MAX_GROUPS);
    591                 next_incl.explicit_group = info->explicit_group;
    592             }
    593         }
    594         else {
    595             next_incl.explicit_group = info->explicit_group;
    596         }
    597 
    598         HandleSymbolsFile(&next_incl, file, MERGE_OVERRIDE);
    599 
    600         MergeIncludedSymbols(&included, &next_incl, stmt->merge);
    601 
    602         ClearSymbolsInfo(&next_incl);
    603         FreeXkbFile(file);
    604     }
    605 
    606     MergeIncludedSymbols(info, &included, include->merge);
    607     ClearSymbolsInfo(&included);
    608 
    609     return (info->errorCount == 0);
    610 }
    611 
    612 #define SYMBOLS 1
    613 #define ACTIONS 2
    614 
    615 static bool
    616 GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
    617               unsigned what, xkb_layout_index_t *ndx_rtrn)
    618 {
    619     const char *name = (what == SYMBOLS ? "symbols" : "actions");
    620 
    621     if (arrayNdx == NULL) {
    622         xkb_layout_index_t i;
    623         GroupInfo *groupi;
    624         enum group_field field = (what == SYMBOLS ?
    625                                   GROUP_FIELD_SYMS : GROUP_FIELD_ACTS);
    626 
    627         darray_enumerate(i, groupi, keyi->groups) {
    628             if (!(groupi->defined & field)) {
    629                 *ndx_rtrn = i;
    630                 return true;
    631             }
    632         }
    633 
    634         if (i >= XKB_MAX_GROUPS) {
    635             log_err(info->ctx,
    636                     "Too many groups of %s for key %s (max %u); "
    637                     "Ignoring %s defined for extra groups\n",
    638                     name, KeyInfoText(info, keyi), XKB_MAX_GROUPS, name);
    639             return false;
    640         }
    641 
    642         darray_resize0(keyi->groups, darray_size(keyi->groups) + 1);
    643         *ndx_rtrn = darray_size(keyi->groups) - 1;
    644         return true;
    645     }
    646 
    647     if (!ExprResolveGroup(info->ctx, arrayNdx, ndx_rtrn)) {
    648         log_err(info->ctx,
    649                 "Illegal group index for %s of key %s\n"
    650                 "Definition with non-integer array index ignored\n",
    651                 name, KeyInfoText(info, keyi));
    652         return false;
    653     }
    654 
    655     (*ndx_rtrn)--;
    656     if (*ndx_rtrn >= darray_size(keyi->groups))
    657         darray_resize0(keyi->groups, *ndx_rtrn + 1);
    658 
    659     return true;
    660 }
    661 
    662 static bool
    663 AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
    664                 ExprDef *value)
    665 {
    666     xkb_layout_index_t ndx;
    667     GroupInfo *groupi;
    668     xkb_level_index_t nLevels;
    669 
    670     if (!GetGroupIndex(info, keyi, arrayNdx, SYMBOLS, &ndx))
    671         return false;
    672 
    673     groupi = &darray_item(keyi->groups, ndx);
    674 
    675     if (value == NULL) {
    676         groupi->defined |= GROUP_FIELD_SYMS;
    677         return true;
    678     }
    679 
    680     if (value->expr.op != EXPR_KEYSYM_LIST) {
    681         log_err(info->ctx,
    682                 "Expected a list of symbols, found %s; "
    683                 "Ignoring symbols for group %u of %s\n",
    684                 expr_op_type_to_string(value->expr.op), ndx + 1,
    685                 KeyInfoText(info, keyi));
    686         return false;
    687     }
    688 
    689     if (groupi->defined & GROUP_FIELD_SYMS) {
    690         log_err(info->ctx,
    691                 "Symbols for key %s, group %u already defined; "
    692                 "Ignoring duplicate definition\n",
    693                 KeyInfoText(info, keyi), ndx + 1);
    694         return false;
    695     }
    696 
    697     nLevels = darray_size(value->keysym_list.symsMapIndex);
    698     if (darray_size(groupi->levels) < nLevels)
    699         darray_resize0(groupi->levels, nLevels);
    700 
    701     groupi->defined |= GROUP_FIELD_SYMS;
    702 
    703     for (xkb_level_index_t i = 0; i < nLevels; i++) {
    704         unsigned int sym_index;
    705         struct xkb_level *leveli = &darray_item(groupi->levels, i);
    706 
    707         sym_index = darray_item(value->keysym_list.symsMapIndex, i);
    708         leveli->num_syms = darray_item(value->keysym_list.symsNumEntries, i);
    709         if (leveli->num_syms > 1)
    710             leveli->u.syms = calloc(leveli->num_syms, sizeof(*leveli->u.syms));
    711 
    712         for (unsigned j = 0; j < leveli->num_syms; j++) {
    713             xkb_keysym_t keysym = darray_item(value->keysym_list.syms,
    714                                               sym_index + j);
    715 
    716             if (leveli->num_syms == 1) {
    717                 if (keysym == XKB_KEY_NoSymbol)
    718                     leveli->num_syms = 0;
    719                 else
    720                     leveli->u.sym = keysym;
    721             }
    722             else if (leveli->num_syms > 1) {
    723                 leveli->u.syms[j] = keysym;
    724             }
    725         }
    726     }
    727 
    728     return true;
    729 }
    730 
    731 static bool
    732 AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
    733                 ExprDef *value)
    734 {
    735     xkb_layout_index_t ndx;
    736     GroupInfo *groupi;
    737     unsigned int nActs;
    738     ExprDef *act;
    739 
    740     if (!GetGroupIndex(info, keyi, arrayNdx, ACTIONS, &ndx))
    741         return false;
    742 
    743     groupi = &darray_item(keyi->groups, ndx);
    744 
    745     if (value == NULL) {
    746         groupi->defined |= GROUP_FIELD_ACTS;
    747         return true;
    748     }
    749 
    750     if (value->expr.op != EXPR_ACTION_LIST) {
    751         log_wsgo(info->ctx,
    752                  "Bad expression type (%d) for action list value; "
    753                  "Ignoring actions for group %u of %s\n",
    754                  value->expr.op, ndx, KeyInfoText(info, keyi));
    755         return false;
    756     }
    757 
    758     if (groupi->defined & GROUP_FIELD_ACTS) {
    759         log_wsgo(info->ctx,
    760                  "Actions for key %s, group %u already defined\n",
    761                  KeyInfoText(info, keyi), ndx);
    762         return false;
    763     }
    764 
    765     nActs = 0;
    766     for (act = value->unary.child; act; act = (ExprDef *) act->common.next)
    767         nActs++;
    768 
    769     if (darray_size(groupi->levels) < nActs)
    770         darray_resize0(groupi->levels, nActs);
    771 
    772     groupi->defined |= GROUP_FIELD_ACTS;
    773 
    774     act = value->unary.child;
    775     for (unsigned i = 0; i < nActs; i++) {
    776         union xkb_action *toAct = &darray_item(groupi->levels, i).action;
    777 
    778         if (!HandleActionDef(info->ctx, info->actions, &info->mods, act, toAct))
    779             log_err(info->ctx,
    780                     "Illegal action definition for %s; "
    781                     "Action for group %u/level %u ignored\n",
    782                     KeyInfoText(info, keyi), ndx + 1, i + 1);
    783 
    784         act = (ExprDef *) act->common.next;
    785     }
    786 
    787     return true;
    788 }
    789 
    790 static const LookupEntry repeatEntries[] = {
    791     { "true", KEY_REPEAT_YES },
    792     { "yes", KEY_REPEAT_YES },
    793     { "on", KEY_REPEAT_YES },
    794     { "false", KEY_REPEAT_NO },
    795     { "no", KEY_REPEAT_NO },
    796     { "off", KEY_REPEAT_NO },
    797     { "default", KEY_REPEAT_UNDEFINED },
    798     { NULL, 0 }
    799 };
    800 
    801 static bool
    802 SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
    803                 ExprDef *arrayNdx, ExprDef *value)
    804 {
    805     if (istreq(field, "type")) {
    806         xkb_layout_index_t ndx;
    807         xkb_atom_t val;
    808 
    809         if (!ExprResolveString(info->ctx, value, &val)) {
    810             log_err(info->ctx,
    811                     "The type field of a key symbol map must be a string; "
    812                     "Ignoring illegal type definition\n");
    813             return false;
    814         }
    815 
    816         if (!arrayNdx) {
    817             keyi->default_type = val;
    818             keyi->defined |= KEY_FIELD_DEFAULT_TYPE;
    819         }
    820         else if (!ExprResolveGroup(info->ctx, arrayNdx, &ndx)) {
    821             log_err(info->ctx,
    822                     "Illegal group index for type of key %s; "
    823                     "Definition with non-integer array index ignored\n",
    824                     KeyInfoText(info, keyi));
    825             return false;
    826         }
    827         else {
    828             ndx--;
    829             if (ndx >= darray_size(keyi->groups))
    830                 darray_resize0(keyi->groups, ndx + 1);
    831             darray_item(keyi->groups, ndx).type = val;
    832             darray_item(keyi->groups, ndx).defined |= GROUP_FIELD_TYPE;
    833         }
    834     }
    835     else if (istreq(field, "symbols")) {
    836         return AddSymbolsToKey(info, keyi, arrayNdx, value);
    837     }
    838     else if (istreq(field, "actions")) {
    839         return AddActionsToKey(info, keyi, arrayNdx, value);
    840     }
    841     else if (istreq(field, "vmods") ||
    842              istreq(field, "virtualmods") ||
    843              istreq(field, "virtualmodifiers")) {
    844         xkb_mod_mask_t mask;
    845 
    846         if (!ExprResolveModMask(info->ctx, value, MOD_VIRT, &info->mods,
    847                                 &mask)) {
    848             log_err(info->ctx,
    849                     "Expected a virtual modifier mask, found %s; "
    850                     "Ignoring virtual modifiers definition for key %s\n",
    851                     expr_op_type_to_string(value->expr.op),
    852                     KeyInfoText(info, keyi));
    853             return false;
    854         }
    855 
    856         keyi->vmodmap = mask;
    857         keyi->defined |= KEY_FIELD_VMODMAP;
    858     }
    859     else if (istreq(field, "locking") ||
    860              istreq(field, "lock") ||
    861              istreq(field, "locks")) {
    862         log_vrb(info->ctx, 1,
    863                 "Key behaviors not supported; "
    864                 "Ignoring locking specification for key %s\n",
    865                 KeyInfoText(info, keyi));
    866     }
    867     else if (istreq(field, "radiogroup") ||
    868              istreq(field, "permanentradiogroup") ||
    869              istreq(field, "allownone")) {
    870         log_vrb(info->ctx, 1,
    871                 "Radio groups not supported; "
    872                 "Ignoring radio group specification for key %s\n",
    873                 KeyInfoText(info, keyi));
    874     }
    875     else if (istreq_prefix("overlay", field) ||
    876              istreq_prefix("permanentoverlay", field)) {
    877         log_vrb(info->ctx, 1,
    878                 "Overlays not supported; "
    879                 "Ignoring overlay specification for key %s\n",
    880                 KeyInfoText(info, keyi));
    881     }
    882     else if (istreq(field, "repeating") ||
    883              istreq(field, "repeats") ||
    884              istreq(field, "repeat")) {
    885         unsigned int val;
    886 
    887         if (!ExprResolveEnum(info->ctx, value, &val, repeatEntries)) {
    888             log_err(info->ctx,
    889                     "Illegal repeat setting for %s; "
    890                     "Non-boolean repeat setting ignored\n",
    891                     KeyInfoText(info, keyi));
    892             return false;
    893         }
    894 
    895         keyi->repeat = val;
    896         keyi->defined |= KEY_FIELD_REPEAT;
    897     }
    898     else if (istreq(field, "groupswrap") ||
    899              istreq(field, "wrapgroups")) {
    900         bool set;
    901 
    902         if (!ExprResolveBoolean(info->ctx, value, &set)) {
    903             log_err(info->ctx,
    904                     "Illegal groupsWrap setting for %s; "
    905                     "Non-boolean value ignored\n",
    906                     KeyInfoText(info, keyi));
    907             return false;
    908         }
    909 
    910         keyi->out_of_range_group_action = (set ? RANGE_WRAP : RANGE_SATURATE);
    911         keyi->defined |= KEY_FIELD_GROUPINFO;
    912     }
    913     else if (istreq(field, "groupsclamp") ||
    914              istreq(field, "clampgroups")) {
    915         bool set;
    916 
    917         if (!ExprResolveBoolean(info->ctx, value, &set)) {
    918             log_err(info->ctx,
    919                     "Illegal groupsClamp setting for %s; "
    920                     "Non-boolean value ignored\n",
    921                     KeyInfoText(info, keyi));
    922             return false;
    923         }
    924 
    925         keyi->out_of_range_group_action = (set ? RANGE_SATURATE : RANGE_WRAP);
    926         keyi->defined |= KEY_FIELD_GROUPINFO;
    927     }
    928     else if (istreq(field, "groupsredirect") ||
    929              istreq(field, "redirectgroups")) {
    930         xkb_layout_index_t grp;
    931 
    932         if (!ExprResolveGroup(info->ctx, value, &grp)) {
    933             log_err(info->ctx,
    934                     "Illegal group index for redirect of key %s; "
    935                     "Definition with non-integer group ignored\n",
    936                     KeyInfoText(info, keyi));
    937             return false;
    938         }
    939 
    940         keyi->out_of_range_group_action = RANGE_REDIRECT;
    941         keyi->out_of_range_group_number = grp - 1;
    942         keyi->defined |= KEY_FIELD_GROUPINFO;
    943     }
    944     else {
    945         log_err(info->ctx,
    946                 "Unknown field %s in a symbol interpretation; "
    947                 "Definition ignored\n",
    948                 field);
    949         return false;
    950     }
    951 
    952     return true;
    953 }
    954 
    955 static bool
    956 SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value)
    957 {
    958     xkb_layout_index_t group, group_to_use;
    959     xkb_atom_t name;
    960 
    961     if (!arrayNdx) {
    962         log_vrb(info->ctx, 1,
    963                 "You must specify an index when specifying a group name; "
    964                 "Group name definition without array subscript ignored\n");
    965         return false;
    966     }
    967 
    968     if (!ExprResolveGroup(info->ctx, arrayNdx, &group)) {
    969         log_err(info->ctx,
    970                 "Illegal index in group name definition; "
    971                 "Definition with non-integer array index ignored\n");
    972         return false;
    973     }
    974 
    975     if (!ExprResolveString(info->ctx, value, &name)) {
    976         log_err(info->ctx,
    977                 "Group name must be a string; "
    978                 "Illegal name for group %d ignored\n", group);
    979         return false;
    980     }
    981 
    982     if (info->explicit_group == XKB_LAYOUT_INVALID) {
    983         group_to_use = group - 1;
    984     }
    985     else if (group - 1 == 0) {
    986         group_to_use = info->explicit_group;
    987     }
    988     else {
    989         log_warn(info->ctx,
    990                  "An explicit group was specified for the '%s' map, "
    991                  "but it provides a name for a group other than Group1 (%d); "
    992                  "Ignoring group name '%s'\n",
    993                  info->name, group,
    994                  xkb_atom_text(info->ctx, name));
    995         return false;
    996     }
    997 
    998     if (group_to_use >= darray_size(info->group_names))
    999         darray_resize0(info->group_names, group_to_use + 1);
   1000     darray_item(info->group_names, group_to_use) = name;
   1001 
   1002     return true;
   1003 }
   1004 
   1005 static bool
   1006 HandleGlobalVar(SymbolsInfo *info, VarDef *stmt)
   1007 {
   1008     const char *elem, *field;
   1009     ExprDef *arrayNdx;
   1010     bool ret;
   1011 
   1012     if (!ExprResolveLhs(info->ctx, stmt->name, &elem, &field, &arrayNdx))
   1013         return false;
   1014 
   1015     if (elem && istreq(elem, "key")) {
   1016         ret = SetSymbolsField(info, &info->default_key, field, arrayNdx,
   1017                               stmt->value);
   1018     }
   1019     else if (!elem && (istreq(field, "name") ||
   1020                        istreq(field, "groupname"))) {
   1021         ret = SetGroupName(info, arrayNdx, stmt->value);
   1022     }
   1023     else if (!elem && (istreq(field, "groupswrap") ||
   1024                        istreq(field, "wrapgroups"))) {
   1025         log_err(info->ctx,
   1026                 "Global \"groupswrap\" not supported; Ignored\n");
   1027         ret = true;
   1028     }
   1029     else if (!elem && (istreq(field, "groupsclamp") ||
   1030                        istreq(field, "clampgroups"))) {
   1031         log_err(info->ctx,
   1032                 "Global \"groupsclamp\" not supported; Ignored\n");
   1033         ret = true;
   1034     }
   1035     else if (!elem && (istreq(field, "groupsredirect") ||
   1036                        istreq(field, "redirectgroups"))) {
   1037         log_err(info->ctx,
   1038                 "Global \"groupsredirect\" not supported; Ignored\n");
   1039         ret = true;
   1040     }
   1041     else if (!elem && istreq(field, "allownone")) {
   1042         log_err(info->ctx,
   1043                 "Radio groups not supported; "
   1044                 "Ignoring \"allownone\" specification\n");
   1045         ret = true;
   1046     }
   1047     else {
   1048         ret = SetActionField(info->ctx, info->actions, &info->mods,
   1049                              elem, field, arrayNdx, stmt->value);
   1050     }
   1051 
   1052     return ret;
   1053 }
   1054 
   1055 static bool
   1056 HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
   1057 {
   1058     bool ok = true;
   1059     const char *elem, *field;
   1060     ExprDef *arrayNdx;
   1061 
   1062     for (; def; def = (VarDef *) def->common.next) {
   1063         if (def->name && def->name->expr.op == EXPR_FIELD_REF) {
   1064             log_err(info->ctx,
   1065                     "Cannot set a global default value from within a key statement; "
   1066                     "Move statements to the global file scope\n");
   1067             continue;
   1068         }
   1069 
   1070         if (!def->name) {
   1071             if (!def->value || def->value->expr.op == EXPR_KEYSYM_LIST)
   1072                 field = "symbols";
   1073             else
   1074                 field = "actions";
   1075             arrayNdx = NULL;
   1076         }
   1077         else {
   1078             ok = ExprResolveLhs(info->ctx, def->name, &elem, &field,
   1079                                 &arrayNdx);
   1080         }
   1081 
   1082         if (ok)
   1083             ok = SetSymbolsField(info, keyi, field, arrayNdx, def->value);
   1084     }
   1085 
   1086     return ok;
   1087 }
   1088 
   1089 static bool
   1090 SetExplicitGroup(SymbolsInfo *info, KeyInfo *keyi)
   1091 {
   1092     xkb_layout_index_t i;
   1093     GroupInfo *groupi;
   1094     bool warn = false;
   1095 
   1096     if (info->explicit_group == XKB_LAYOUT_INVALID)
   1097         return true;
   1098 
   1099     darray_enumerate_from(i, groupi, keyi->groups, 1) {
   1100         if (groupi->defined) {
   1101             warn = true;
   1102             ClearGroupInfo(groupi);
   1103             InitGroupInfo(groupi);
   1104         }
   1105     }
   1106 
   1107     if (warn)
   1108         log_warn(info->ctx,
   1109                  "For the map %s an explicit group specified, "
   1110                  "but key %s has more than one group defined; "
   1111                  "All groups except first one will be ignored\n",
   1112                  info->name, KeyInfoText(info, keyi));
   1113 
   1114     darray_resize0(keyi->groups, info->explicit_group + 1);
   1115     if (info->explicit_group > 0) {
   1116         darray_item(keyi->groups, info->explicit_group) =
   1117             darray_item(keyi->groups, 0);
   1118         InitGroupInfo(&darray_item(keyi->groups, 0));
   1119     }
   1120 
   1121     return true;
   1122 }
   1123 
   1124 static bool
   1125 HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt)
   1126 {
   1127     KeyInfo keyi;
   1128 
   1129     keyi = info->default_key;
   1130     darray_init(keyi.groups);
   1131     darray_copy(keyi.groups, info->default_key.groups);
   1132     for (xkb_layout_index_t i = 0; i < darray_size(keyi.groups); i++)
   1133         CopyGroupInfo(&darray_item(keyi.groups, i),
   1134                       &darray_item(info->default_key.groups, i));
   1135     keyi.merge = stmt->merge;
   1136     keyi.name = stmt->keyName;
   1137 
   1138     if (!HandleSymbolsBody(info, stmt->symbols, &keyi)) {
   1139         info->errorCount++;
   1140         return false;
   1141     }
   1142 
   1143     if (!SetExplicitGroup(info, &keyi)) {
   1144         info->errorCount++;
   1145         return false;
   1146     }
   1147 
   1148     if (!AddKeySymbols(info, &keyi, true)) {
   1149         info->errorCount++;
   1150         return false;
   1151     }
   1152 
   1153     return true;
   1154 }
   1155 
   1156 static bool
   1157 HandleModMapDef(SymbolsInfo *info, ModMapDef *def)
   1158 {
   1159     ModMapEntry tmp;
   1160     xkb_mod_index_t ndx;
   1161     bool ok;
   1162     struct xkb_context *ctx = info->ctx;
   1163 
   1164     ndx = XkbModNameToIndex(&info->mods, def->modifier, MOD_REAL);
   1165     if (ndx == XKB_MOD_INVALID) {
   1166         log_err(info->ctx,
   1167                 "Illegal modifier map definition; "
   1168                 "Ignoring map for non-modifier \"%s\"\n",
   1169                 xkb_atom_text(ctx, def->modifier));
   1170         return false;
   1171     }
   1172 
   1173     ok = true;
   1174     tmp.modifier = ndx;
   1175     tmp.merge = def->merge;
   1176 
   1177     for (ExprDef *key = def->keys; key; key = (ExprDef *) key->common.next) {
   1178         xkb_keysym_t sym;
   1179 
   1180         if (key->expr.op == EXPR_VALUE &&
   1181             key->expr.value_type == EXPR_TYPE_KEYNAME) {
   1182             tmp.haveSymbol = false;
   1183             tmp.u.keyName = key->key_name.key_name;
   1184         }
   1185         else if (ExprResolveKeySym(ctx, key, &sym)) {
   1186             tmp.haveSymbol = true;
   1187             tmp.u.keySym = sym;
   1188         }
   1189         else {
   1190             log_err(info->ctx,
   1191                     "Modmap entries may contain only key names or keysyms; "
   1192                     "Illegal definition for %s modifier ignored\n",
   1193                     ModIndexText(info->ctx, &info->mods, tmp.modifier));
   1194             continue;
   1195         }
   1196 
   1197         ok = AddModMapEntry(info, &tmp) && ok;
   1198     }
   1199     return ok;
   1200 }
   1201 
   1202 static void
   1203 HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
   1204 {
   1205     bool ok;
   1206 
   1207     free(info->name);
   1208     info->name = strdup_safe(file->name);
   1209 
   1210     for (ParseCommon *stmt = file->defs; stmt; stmt = stmt->next) {
   1211         switch (stmt->type) {
   1212         case STMT_INCLUDE:
   1213             ok = HandleIncludeSymbols(info, (IncludeStmt *) stmt);
   1214             break;
   1215         case STMT_SYMBOLS:
   1216             ok = HandleSymbolsDef(info, (SymbolsDef *) stmt);
   1217             break;
   1218         case STMT_VAR:
   1219             ok = HandleGlobalVar(info, (VarDef *) stmt);
   1220             break;
   1221         case STMT_VMOD:
   1222             ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt, merge);
   1223             break;
   1224         case STMT_MODMAP:
   1225             ok = HandleModMapDef(info, (ModMapDef *) stmt);
   1226             break;
   1227         default:
   1228             log_err(info->ctx,
   1229                     "Symbols files may not include other types; "
   1230                     "Ignoring %s\n", stmt_type_to_string(stmt->type));
   1231             ok = false;
   1232             break;
   1233         }
   1234 
   1235         if (!ok)
   1236             info->errorCount++;
   1237 
   1238         if (info->errorCount > 10) {
   1239             log_err(info->ctx, "Abandoning symbols file \"%s\"\n",
   1240                     file->topName);
   1241             break;
   1242         }
   1243     }
   1244 }
   1245 
   1246 /**
   1247  * Given a keysym @sym, return a key which generates it, or NULL.
   1248  * This is used for example in a modifier map definition, such as:
   1249  *      modifier_map Lock           { Caps_Lock };
   1250  * where we want to add the Lock modifier to the modmap of the key
   1251  * which matches the keysym Caps_Lock.
   1252  * Since there can be many keys which generates the keysym, the key
   1253  * is chosen first by lowest group in which the keysym appears, than
   1254  * by lowest level and than by lowest key code.
   1255  */
   1256 static struct xkb_key *
   1257 FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym)
   1258 {
   1259     struct xkb_key *key;
   1260     xkb_layout_index_t group;
   1261     xkb_level_index_t level;
   1262     bool got_one_group, got_one_level;
   1263 
   1264     group = 0;
   1265     do {
   1266         got_one_group = false;
   1267         level = 0;
   1268         do {
   1269             got_one_level = false;
   1270             xkb_keys_foreach(key, keymap) {
   1271                 if (group < key->num_groups &&
   1272                     level < XkbKeyNumLevels(key, group)) {
   1273                     got_one_group = got_one_level = true;
   1274                     if (key->groups[group].levels[level].num_syms == 1 &&
   1275                         key->groups[group].levels[level].u.sym == sym)
   1276                         return key;
   1277                 }
   1278             }
   1279             level++;
   1280         } while (got_one_level);
   1281         group++;
   1282     } while (got_one_group);
   1283 
   1284     return NULL;
   1285 }
   1286 
   1287 /*
   1288  * Find an appropriate type for a group and return its name.
   1289  *
   1290  * Simple recipe:
   1291  * - ONE_LEVEL for width 0/1
   1292  * - ALPHABETIC for 2 shift levels, with lower/upercase keysyms
   1293  * - KEYPAD for keypad keys.
   1294  * - TWO_LEVEL for other 2 shift level keys.
   1295  * and the same for four level keys.
   1296  *
   1297  * FIXME: Decide how to handle multiple-syms-per-level, and do it.
   1298  */
   1299 static xkb_atom_t
   1300 FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi)
   1301 {
   1302     xkb_keysym_t sym0, sym1, sym2, sym3;
   1303     xkb_level_index_t width = darray_size(groupi->levels);
   1304 
   1305 #define GET_SYM(level) \
   1306     (darray_item(groupi->levels, level).num_syms == 0 ? \
   1307         XKB_KEY_NoSymbol : \
   1308      darray_item(groupi->levels, level).num_syms == 1 ? \
   1309         darray_item(groupi->levels, level).u.sym : \
   1310      /* num_syms > 1 */ \
   1311         darray_item(groupi->levels, level).u.syms[0])
   1312 
   1313     if (width == 1 || width <= 0)
   1314         return xkb_atom_intern_literal(ctx, "ONE_LEVEL");
   1315 
   1316     sym0 = GET_SYM(0);
   1317     sym1 = GET_SYM(1);
   1318 
   1319     if (width == 2) {
   1320         if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper(sym1))
   1321             return xkb_atom_intern_literal(ctx, "ALPHABETIC");
   1322 
   1323         if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1))
   1324             return xkb_atom_intern_literal(ctx, "KEYPAD");
   1325 
   1326         return xkb_atom_intern_literal(ctx, "TWO_LEVEL");
   1327     }
   1328 
   1329     if (width <= 4) {
   1330         if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper(sym1)) {
   1331             sym2 = GET_SYM(2);
   1332             sym3 = (width == 4 ? GET_SYM(3) : XKB_KEY_NoSymbol);
   1333 
   1334             if (xkb_keysym_is_lower(sym2) && xkb_keysym_is_upper(sym3))
   1335                 return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_ALPHABETIC");
   1336 
   1337             return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_SEMIALPHABETIC");
   1338         }
   1339 
   1340         if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1))
   1341             return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_KEYPAD");
   1342 
   1343         return xkb_atom_intern_literal(ctx, "FOUR_LEVEL");
   1344     }
   1345 
   1346     return XKB_ATOM_NONE;
   1347 
   1348 #undef GET_SYM
   1349 }
   1350 
   1351 static const struct xkb_key_type *
   1352 FindTypeForGroup(struct xkb_keymap *keymap, KeyInfo *keyi,
   1353                  xkb_layout_index_t group, bool *explicit_type)
   1354 {
   1355     unsigned int i;
   1356     GroupInfo *groupi = &darray_item(keyi->groups, group);
   1357     xkb_atom_t type_name = groupi->type;
   1358 
   1359     *explicit_type = true;
   1360 
   1361     if (type_name == XKB_ATOM_NONE) {
   1362         if (keyi->default_type != XKB_ATOM_NONE) {
   1363             type_name  = keyi->default_type;
   1364         }
   1365         else {
   1366             type_name = FindAutomaticType(keymap->ctx, groupi);
   1367             if (type_name != XKB_ATOM_NONE)
   1368                 *explicit_type = false;
   1369         }
   1370     }
   1371 
   1372     if (type_name == XKB_ATOM_NONE) {
   1373         log_warn(keymap->ctx,
   1374                  "Couldn't find an automatic type for key '%s' group %d with %lu levels; "
   1375                  "Using the default type\n",
   1376                  KeyNameText(keymap->ctx, keyi->name), group + 1,
   1377                  (unsigned long) darray_size(groupi->levels));
   1378         goto use_default;
   1379     }
   1380 
   1381     for (i = 0; i < keymap->num_types; i++)
   1382         if (keymap->types[i].name == type_name)
   1383             break;
   1384 
   1385     if (i >= keymap->num_types) {
   1386         log_warn(keymap->ctx,
   1387                  "The type \"%s\" for key '%s' group %d was not previously defined; "
   1388                  "Using the default type\n",
   1389                  xkb_atom_text(keymap->ctx, type_name),
   1390                  KeyNameText(keymap->ctx, keyi->name), group + 1);
   1391         goto use_default;
   1392     }
   1393 
   1394     return &keymap->types[i];
   1395 
   1396 use_default:
   1397     /*
   1398      * Index 0 is guaranteed to contain something, usually
   1399      * ONE_LEVEL or at least some default one-level type.
   1400      */
   1401     return &keymap->types[0];
   1402 }
   1403 
   1404 static bool
   1405 CopySymbolsDefToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info,
   1406                        KeyInfo *keyi)
   1407 {
   1408     struct xkb_key *key;
   1409     GroupInfo *groupi;
   1410     const GroupInfo *group0;
   1411     xkb_layout_index_t i;
   1412 
   1413     /*
   1414      * The name is guaranteed to be real and not an alias (see
   1415      * AddKeySymbols), so 'false' is safe here.
   1416      */
   1417     key = XkbKeyByName(keymap, keyi->name, false);
   1418     if (!key) {
   1419         log_vrb(info->ctx, 5,
   1420                 "Key %s not found in keycodes; Symbols ignored\n",
   1421                 KeyInfoText(info, keyi));
   1422         return false;
   1423     }
   1424 
   1425     /* Find the range of groups we need. */
   1426     key->num_groups = 0;
   1427     darray_enumerate(i, groupi, keyi->groups)
   1428         if (groupi->defined)
   1429             key->num_groups = i + 1;
   1430 
   1431     if (key->num_groups <= 0)
   1432         return false; /* WSGO */
   1433 
   1434     darray_resize(keyi->groups, key->num_groups);
   1435 
   1436     /*
   1437      * If there are empty groups between non-empty ones, fill them with data
   1438      * from the first group.
   1439      * We can make a wrong assumption here. But leaving gaps is worse.
   1440      */
   1441     group0 = &darray_item(keyi->groups, 0);
   1442     darray_foreach_from(groupi, keyi->groups, 1) {
   1443         if (groupi->defined)
   1444             continue;
   1445 
   1446         CopyGroupInfo(groupi, group0);
   1447     }
   1448 
   1449     key->groups = calloc(key->num_groups, sizeof(*key->groups));
   1450 
   1451     /* Find and assign the groups' types in the keymap. */
   1452     darray_enumerate(i, groupi, keyi->groups) {
   1453         const struct xkb_key_type *type;
   1454         bool explicit_type;
   1455 
   1456         type = FindTypeForGroup(keymap, keyi, i, &explicit_type);
   1457 
   1458         /* Always have as many levels as the type specifies. */
   1459         if (type->num_levels < darray_size(groupi->levels)) {
   1460             struct xkb_level *leveli;
   1461 
   1462             log_vrb(info->ctx, 1,
   1463                     "Type \"%s\" has %d levels, but %s has %d levels; "
   1464                     "Ignoring extra symbols\n",
   1465                     xkb_atom_text(keymap->ctx, type->name), type->num_levels,
   1466                     KeyInfoText(info, keyi),
   1467                     (int) darray_size(groupi->levels));
   1468 
   1469             darray_foreach_from(leveli, groupi->levels, type->num_levels)
   1470                 ClearLevelInfo(leveli);
   1471         }
   1472         darray_resize0(groupi->levels, type->num_levels);
   1473 
   1474         key->groups[i].explicit_type = explicit_type;
   1475         key->groups[i].type = type;
   1476     }
   1477 
   1478     /* Copy levels. */
   1479     darray_enumerate(i, groupi, keyi->groups)
   1480         darray_steal(groupi->levels, &key->groups[i].levels, NULL);
   1481 
   1482     key->out_of_range_group_number = keyi->out_of_range_group_number;
   1483     key->out_of_range_group_action = keyi->out_of_range_group_action;
   1484 
   1485     if (keyi->defined & KEY_FIELD_VMODMAP) {
   1486         key->vmodmap = keyi->vmodmap;
   1487         key->explicit |= EXPLICIT_VMODMAP;
   1488     }
   1489 
   1490     if (keyi->repeat != KEY_REPEAT_UNDEFINED) {
   1491         key->repeats = (keyi->repeat == KEY_REPEAT_YES);
   1492         key->explicit |= EXPLICIT_REPEAT;
   1493     }
   1494 
   1495     darray_foreach(groupi, keyi->groups) {
   1496         if (groupi->defined & GROUP_FIELD_ACTS) {
   1497             key->explicit |= EXPLICIT_INTERP;
   1498             break;
   1499         }
   1500     }
   1501 
   1502     return true;
   1503 }
   1504 
   1505 static bool
   1506 CopyModMapDefToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info,
   1507                       ModMapEntry *entry)
   1508 {
   1509     struct xkb_key *key;
   1510 
   1511     if (!entry->haveSymbol) {
   1512         key = XkbKeyByName(keymap, entry->u.keyName, true);
   1513         if (!key) {
   1514             log_vrb(info->ctx, 5,
   1515                     "Key %s not found in keycodes; "
   1516                     "Modifier map entry for %s not updated\n",
   1517                     KeyNameText(info->ctx, entry->u.keyName),
   1518                     ModIndexText(info->ctx, &info->mods, entry->modifier));
   1519             return false;
   1520         }
   1521     }
   1522     else {
   1523         key = FindKeyForSymbol(keymap, entry->u.keySym);
   1524         if (!key) {
   1525             log_vrb(info->ctx, 5,
   1526                     "Key \"%s\" not found in symbol map; "
   1527                     "Modifier map entry for %s not updated\n",
   1528                     KeysymText(info->ctx, entry->u.keySym),
   1529                     ModIndexText(info->ctx, &info->mods, entry->modifier));
   1530             return false;
   1531         }
   1532     }
   1533 
   1534     key->modmap |= (1u << entry->modifier);
   1535     return true;
   1536 }
   1537 
   1538 static bool
   1539 CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info)
   1540 {
   1541     KeyInfo *keyi;
   1542     ModMapEntry *mm;
   1543 
   1544     keymap->symbols_section_name = strdup_safe(info->name);
   1545     XkbEscapeMapName(keymap->symbols_section_name);
   1546 
   1547     keymap->mods = info->mods;
   1548 
   1549     darray_steal(info->group_names,
   1550                  &keymap->group_names, &keymap->num_group_names);
   1551 
   1552     darray_foreach(keyi, info->keys)
   1553         if (!CopySymbolsDefToKeymap(keymap, info, keyi))
   1554             info->errorCount++;
   1555 
   1556     if (xkb_context_get_log_verbosity(keymap->ctx) > 3) {
   1557         struct xkb_key *key;
   1558 
   1559         xkb_keys_foreach(key, keymap) {
   1560             if (key->name == XKB_ATOM_NONE)
   1561                 continue;
   1562 
   1563             if (key->num_groups < 1)
   1564                 log_info(info->ctx,
   1565                          "No symbols defined for %s\n",
   1566                          KeyNameText(info->ctx, key->name));
   1567         }
   1568     }
   1569 
   1570     darray_foreach(mm, info->modmaps)
   1571         if (!CopyModMapDefToKeymap(keymap, info, mm))
   1572             info->errorCount++;
   1573 
   1574     /* XXX: If we don't ignore errorCount, things break. */
   1575     return true;
   1576 }
   1577 
   1578 bool
   1579 CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
   1580                enum merge_mode merge)
   1581 {
   1582     SymbolsInfo info;
   1583     ActionsInfo *actions;
   1584 
   1585     actions = NewActionsInfo();
   1586     if (!actions)
   1587         return false;
   1588 
   1589     InitSymbolsInfo(&info, keymap, actions, &keymap->mods);
   1590     info.default_key.merge = merge;
   1591 
   1592     HandleSymbolsFile(&info, file, merge);
   1593 
   1594     if (info.errorCount != 0)
   1595         goto err_info;
   1596 
   1597     if (!CopySymbolsToKeymap(keymap, &info))
   1598         goto err_info;
   1599 
   1600     ClearSymbolsInfo(&info);
   1601     FreeActionsInfo(actions);
   1602     return true;
   1603 
   1604 err_info:
   1605     FreeActionsInfo(actions);
   1606     ClearSymbolsInfo(&info);
   1607     return false;
   1608 }
   1609