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