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