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