symbols: don't use CommonInfo in KeyInfo
[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 #include <limits.h>
28
29 #include "xkbcomp-priv.h"
30 #include "parseutils.h"
31 #include "action.h"
32 #include "keycodes.h"
33 #include "vmod.h"
34
35 /***====================================================================***/
36
37 /* Needed to work with the typechecker. */
38 typedef darray (xkb_keysym_t) darray_xkb_keysym_t;
39 typedef darray (union xkb_action) darray_xkb_action;
40
41 #define RepeatYes       1
42 #define RepeatNo        0
43 #define RepeatUndefined ~((unsigned) 0)
44
45 #define _Key_Syms       (1 << 0)
46 #define _Key_Acts       (1 << 1)
47 #define _Key_Repeat     (1 << 2)
48 #define _Key_Behavior   (1 << 3)
49 #define _Key_Type_Dflt  (1 << 4)
50 #define _Key_Types      (1 << 5)
51 #define _Key_GroupInfo  (1 << 6)
52 #define _Key_VModMap    (1 << 7)
53
54 typedef struct _KeyInfo {
55     unsigned short defined;
56     unsigned file_id;
57     enum merge_mode merge;
58
59     unsigned long name; /* the 4 chars of the key name, as long */
60     unsigned char typesDefined;
61     unsigned char symsDefined;
62     unsigned char actsDefined;
63     unsigned int numLevels[XkbNumKbdGroups];
64
65     /* syms[group] -> Single array for all the keysyms in the group. */
66     darray_xkb_keysym_t syms[XkbNumKbdGroups];
67     /*
68      * symsMapIndex[group][level] -> The index from which the syms for
69      * the level begin in the syms[group] array. Remember each keycode
70      * can have multiple keysyms in each level (that is, each key press
71      * can result in multiple keysyms).
72      */
73     darray(int) symsMapIndex[XkbNumKbdGroups];
74     /*
75      * symsMapNumEntries[group][level] -> How many syms are in
76      * syms[group][symsMapIndex[group][level]].
77      */
78     darray(size_t) symsMapNumEntries[XkbNumKbdGroups];
79
80     darray_xkb_action acts[XkbNumKbdGroups];
81
82     xkb_atom_t types[XkbNumKbdGroups];
83     unsigned repeat;
84     struct xkb_behavior behavior;
85     unsigned short vmodmap;
86     xkb_atom_t dfltType;
87
88     uint8_t out_of_range_group_action;
89     uint8_t out_of_range_group_number;
90 } KeyInfo;
91
92 /**
93  * Init the given key info to sane values.
94  */
95 static void
96 InitKeyInfo(KeyInfo *keyi, unsigned file_id)
97 {
98     int i;
99     static const char dflt[4] = "*";
100
101     keyi->defined = 0;
102     keyi->file_id = file_id;
103     keyi->merge = MERGE_OVERRIDE;
104     keyi->name = KeyNameToLong(dflt);
105     keyi->typesDefined = keyi->symsDefined = keyi->actsDefined = 0;
106
107     for (i = 0; i < XkbNumKbdGroups; i++) {
108         keyi->numLevels[i] = 0;
109         keyi->types[i] = XKB_ATOM_NONE;
110         darray_init(keyi->syms[i]);
111         darray_init(keyi->symsMapIndex[i]);
112         darray_init(keyi->symsMapNumEntries[i]);
113         darray_init(keyi->acts[i]);
114     }
115
116     keyi->dfltType = XKB_ATOM_NONE;
117     keyi->behavior.type = XkbKB_Default;
118     keyi->behavior.data = 0;
119     keyi->vmodmap = 0;
120     keyi->repeat = RepeatUndefined;
121     keyi->out_of_range_group_action = 0;
122     keyi->out_of_range_group_number = 0;
123 }
124
125 static void
126 FreeKeyInfo(KeyInfo *keyi)
127 {
128     int i;
129
130     for (i = 0; i < XkbNumKbdGroups; i++) {
131         darray_free(keyi->syms[i]);
132         darray_free(keyi->symsMapIndex[i]);
133         darray_free(keyi->symsMapNumEntries[i]);
134         darray_free(keyi->acts[i]);
135     }
136 }
137
138 /**
139  * Copy old into new, optionally reset old to 0.
140  * If old is reset, new simply re-uses old's memory. Otherwise, the memory is
141  * newly allocated and new points to the new memory areas.
142  */
143 static bool
144 CopyKeyInfo(KeyInfo * old, KeyInfo * new, bool clearOld)
145 {
146     int i;
147
148     *new = *old;
149
150     if (clearOld) {
151         for (i = 0; i < XkbNumKbdGroups; i++) {
152             old->numLevels[i] = 0;
153             darray_init(old->symsMapIndex[i]);
154             darray_init(old->symsMapNumEntries[i]);
155             darray_init(old->syms[i]);
156             darray_init(old->acts[i]);
157         }
158     }
159     else {
160         for (i = 0; i < XkbNumKbdGroups; i++) {
161             darray_copy(new->syms[i], old->syms[i]);
162             darray_copy(new->symsMapIndex[i], old->symsMapIndex[i]);
163             darray_copy(new->symsMapNumEntries[i], old->symsMapNumEntries[i]);
164             darray_copy(new->acts[i], old->acts[i]);
165         }
166     }
167
168     return true;
169 }
170
171 /***====================================================================***/
172
173 typedef struct _ModMapEntry {
174     struct list entry;
175     enum merge_mode merge;
176     bool haveSymbol;
177     int modifier;
178     union {
179         unsigned long keyName;
180         xkb_keysym_t keySym;
181     } u;
182 } ModMapEntry;
183
184 typedef struct _SymbolsInfo {
185     char *name;         /* e.g. pc+us+inet(evdev) */
186     int errorCount;
187     unsigned file_id;
188     enum merge_mode merge;
189     unsigned explicit_group;
190     darray(KeyInfo) keys;
191     KeyInfo dflt;
192     VModInfo vmods;
193     ActionInfo *action;
194     xkb_atom_t groupNames[XkbNumKbdGroups];
195
196     struct list modMaps;
197 } SymbolsInfo;
198
199 static void
200 InitSymbolsInfo(SymbolsInfo * info, struct xkb_keymap *keymap,
201                 unsigned file_id)
202 {
203     int i;
204
205     info->name = NULL;
206     info->explicit_group = 0;
207     info->errorCount = 0;
208     info->file_id = file_id;
209     info->merge = MERGE_OVERRIDE;
210     darray_init(info->keys);
211     darray_growalloc(info->keys, 110);
212     list_init(&info->modMaps);
213     for (i = 0; i < XkbNumKbdGroups; i++)
214         info->groupNames[i] = XKB_ATOM_NONE;
215     InitKeyInfo(&info->dflt, file_id);
216     InitVModInfo(&info->vmods, keymap);
217     info->action = NULL;
218 }
219
220 static void
221 FreeSymbolsInfo(SymbolsInfo * info)
222 {
223     KeyInfo *keyi;
224     ModMapEntry *mm, *next;
225
226     free(info->name);
227     darray_foreach(keyi, info->keys) {
228         FreeKeyInfo(keyi);
229     }
230     darray_free(info->keys);
231     list_foreach_safe(mm, next, &info->modMaps, entry)
232         free(mm);
233     memset(info, 0, sizeof(SymbolsInfo));
234 }
235
236 static bool
237 ResizeKeyGroup(KeyInfo *keyi, unsigned int group, unsigned int numLevels,
238                unsigned sizeSyms, bool forceActions)
239 {
240     int i;
241
242     if (darray_size(keyi->syms[group]) < sizeSyms)
243         darray_resize0(keyi->syms[group], sizeSyms);
244
245     if (darray_empty(keyi->symsMapIndex[group]) ||
246         keyi->numLevels[group] < numLevels) {
247         darray_resize(keyi->symsMapIndex[group], numLevels);
248         for (i = keyi->numLevels[group]; i < numLevels; i++)
249             darray_item(keyi->symsMapIndex[group], i) = -1;
250     }
251
252     if (darray_empty(keyi->symsMapNumEntries[group]) ||
253         keyi->numLevels[group] < numLevels)
254         darray_resize0(keyi->symsMapNumEntries[group], numLevels);
255
256     if ((forceActions && (keyi->numLevels[group] < numLevels ||
257                           darray_empty(keyi->acts[group]))) ||
258         (keyi->numLevels[group] < numLevels && !darray_empty(keyi->acts[group])))
259         darray_resize0(keyi->acts[group], numLevels);
260
261     if (keyi->numLevels[group] < numLevels)
262         keyi->numLevels[group] = numLevels;
263
264     return true;
265 }
266
267 enum key_group_selector {
268     NONE = 0,
269     FROM = (1 << 0),
270     TO = (1 << 1),
271 };
272
273 static bool
274 MergeKeyGroups(SymbolsInfo * info,
275                KeyInfo * into, KeyInfo * from, unsigned group)
276 {
277     darray_xkb_keysym_t resultSyms;
278     enum key_group_selector using = NONE;
279     darray_xkb_action resultActs;
280     unsigned int resultWidth;
281     unsigned int resultSize = 0;
282     int cur_idx = 0;
283     int i;
284     bool report, clobber;
285
286     clobber = (from->merge != MERGE_AUGMENT);
287
288     report = (warningLevel > 9) ||
289              (into->file_id == from->file_id && warningLevel > 0);
290
291     darray_init(resultSyms);
292
293     if (into->numLevels[group] >= from->numLevels[group]) {
294         resultActs = into->acts[group];
295         resultWidth = into->numLevels[group];
296     }
297     else {
298         resultActs = from->acts[group];
299         resultWidth = from->numLevels[group];
300         darray_resize(into->symsMapIndex[group],
301                       from->numLevels[group]);
302         darray_resize0(into->symsMapNumEntries[group],
303                        from->numLevels[group]);
304
305         for (i = into->numLevels[group]; i < from->numLevels[group]; i++)
306             darray_item(into->symsMapIndex[group], i) = -1;
307     }
308
309     if (darray_empty(resultActs) && (!darray_empty(into->acts[group]) ||
310                                      !darray_empty(from->acts[group]))) {
311         darray_resize0(resultActs, resultWidth);
312         for (i = 0; i < resultWidth; i++) {
313             union xkb_action *fromAct = NULL, *toAct = NULL;
314
315             if (!darray_empty(from->acts[group]))
316                 fromAct = &darray_item(from->acts[group], i);
317
318             if (!darray_empty(into->acts[group]))
319                 toAct = &darray_item(into->acts[group], i);
320
321             if (((fromAct == NULL) || (fromAct->type == XkbSA_NoAction))
322                 && (toAct != NULL)) {
323                 darray_item(resultActs, i) = *toAct;
324             }
325             else if (((toAct == NULL) || (toAct->type == XkbSA_NoAction))
326                      && (fromAct != NULL)) {
327                 darray_item(resultActs, i) = *fromAct;
328             }
329             else {
330                 union xkb_action *use, *ignore;
331                 if (clobber) {
332                     use = fromAct;
333                     ignore = toAct;
334                 }
335                 else {
336                     use = toAct;
337                     ignore = fromAct;
338                 }
339                 if (report) {
340                     WARN
341                         ("Multiple actions for level %d/group %d on key %s\n",
342                         i + 1, group + 1, longText(into->name));
343                     ACTION("Using %s, ignoring %s\n",
344                            XkbcActionTypeText(use->type),
345                            XkbcActionTypeText(ignore->type));
346                 }
347                 if (use)
348                     darray_item(resultActs, i) = *use;
349             }
350         }
351     }
352
353     for (i = 0; i < resultWidth; i++) {
354         unsigned int fromSize = 0;
355         unsigned toSize = 0;
356
357         if (!darray_empty(from->symsMapNumEntries[group]) &&
358             i < from->numLevels[group])
359             fromSize = darray_item(from->symsMapNumEntries[group], i);
360
361         if (!darray_empty(into->symsMapNumEntries[group]) &&
362             i < into->numLevels[group])
363             toSize = darray_item(into->symsMapNumEntries[group], i);
364
365         if (fromSize == 0) {
366             resultSize += toSize;
367             using |= TO;
368         }
369         else if (toSize == 0 || clobber) {
370             resultSize += fromSize;
371             using |= FROM;
372         }
373         else {
374             resultSize += toSize;
375             using |= TO;
376         }
377     }
378
379     if (resultSize == 0)
380         goto out;
381
382     if (using == FROM) {
383         resultSyms = from->syms[group];
384         darray_free(into->symsMapNumEntries[group]);
385         darray_free(into->symsMapIndex[group]);
386         into->symsMapNumEntries[group] = from->symsMapNumEntries[group];
387         into->symsMapIndex[group] = from->symsMapIndex[group];
388         darray_init(from->symsMapNumEntries[group]);
389         darray_init(from->symsMapIndex[group]);
390         goto out;
391     }
392     else if (using == TO) {
393         resultSyms = into->syms[group];
394         goto out;
395     }
396
397     darray_resize0(resultSyms, resultSize);
398
399     for (i = 0; i < resultWidth; i++) {
400         enum key_group_selector use = NONE;
401         unsigned int fromSize = 0;
402         unsigned int toSize = 0;
403
404         if (i < from->numLevels[group])
405             fromSize = darray_item(from->symsMapNumEntries[group], i);
406
407         if (i < into->numLevels[group])
408             toSize = darray_item(into->symsMapNumEntries[group], i);
409
410         if (fromSize == 0 && toSize == 0) {
411             darray_item(into->symsMapIndex[group], i) = -1;
412             darray_item(into->symsMapNumEntries[group], i) = 0;
413             continue;
414         }
415
416         if (fromSize == 0)
417             use = TO;
418         else if (toSize == 0 || clobber)
419             use = FROM;
420         else
421             use = TO;
422
423         if (toSize && fromSize && report) {
424             INFO("Multiple symbols for group %d, level %d on key %s\n",
425                  group + 1, i + 1, longText(into->name));
426             ACTION("Using %s, ignoring %s\n",
427                    (use == FROM ? "from" : "to"),
428                    (use == FROM ? "to" : "from"));
429         }
430
431         if (use == FROM) {
432             memcpy(darray_mem(resultSyms, cur_idx),
433                    darray_mem(from->syms[group],
434                               darray_item(from->symsMapIndex[group], i)),
435                    darray_item(from->symsMapNumEntries[group],
436                                i) * sizeof(xkb_keysym_t));
437             darray_item(into->symsMapIndex[group], i) = cur_idx;
438             darray_item(into->symsMapNumEntries[group], i) =
439                 darray_item(from->symsMapNumEntries[group], i);
440         }
441         else {
442             memcpy(darray_mem(resultSyms, cur_idx),
443                    darray_mem(into->syms[group],
444                               darray_item(into->symsMapIndex[group], i)),
445                    darray_item(into->symsMapNumEntries[group],
446                                i) * sizeof(xkb_keysym_t));
447             darray_item(into->symsMapIndex[group], i) = cur_idx;
448         }
449         cur_idx += darray_item(into->symsMapNumEntries[group], i);
450     }
451
452 out:
453     if (!darray_same(resultActs, into->acts[group]))
454         darray_free(into->acts[group]);
455     if (!darray_same(resultActs, from->acts[group]))
456         darray_free(from->acts[group]);
457     into->numLevels[group] = resultWidth;
458     if (!darray_same(resultSyms, into->syms[group]))
459         darray_free(into->syms[group]);
460     into->syms[group] = resultSyms;
461     if (!darray_same(resultSyms, from->syms[group]))
462         darray_free(from->syms[group]);
463     darray_init(from->syms[group]);
464     darray_free(from->symsMapIndex[group]);
465     darray_free(from->symsMapNumEntries[group]);
466     into->acts[group] = resultActs;
467     darray_init(from->acts[group]);
468     if (!darray_empty(into->syms[group]))
469         into->symsDefined |= (1 << group);
470     from->symsDefined &= ~(1 << group);
471     into->actsDefined |= (1 << group);
472     from->actsDefined &= ~(1 << group);
473
474     return true;
475 }
476
477 static bool
478 use_new_field(unsigned field, short old_defined, unsigned old_file_id,
479               short new_defined, unsigned new_file_id, enum merge_mode new_merge,
480               unsigned *collide)
481 {
482     if (!(old_defined & field))
483         return true;
484
485     if (new_defined & field) {
486         if ((old_file_id == new_file_id && warningLevel > 0) || warningLevel > 9)
487             *collide |= field;
488
489         if (new_merge != MERGE_AUGMENT)
490             return true;
491     }
492
493     return false;
494 }
495
496 static bool
497 MergeKeys(SymbolsInfo *info, struct xkb_keymap *keymap,
498           KeyInfo *into, KeyInfo *from)
499 {
500     int i;
501     unsigned collide = 0;
502     bool report;
503
504     if (from->merge == MERGE_REPLACE) {
505         for (i = 0; i < XkbNumKbdGroups; i++) {
506             if (into->numLevels[i] != 0) {
507                 darray_free(into->syms[i]);
508                 darray_free(into->acts[i]);
509             }
510         }
511         *into = *from;
512         memset(from, 0, sizeof(KeyInfo));
513         return true;
514     }
515     report = ((warningLevel > 9) ||
516               ((into->file_id == from->file_id)
517                && (warningLevel > 0)));
518     for (i = 0; i < XkbNumKbdGroups; i++) {
519         if (from->numLevels[i] > 0) {
520             if (into->numLevels[i] == 0) {
521                 into->numLevels[i] = from->numLevels[i];
522                 into->syms[i] = from->syms[i];
523                 into->symsMapIndex[i] = from->symsMapIndex[i];
524                 into->symsMapNumEntries[i] = from->symsMapNumEntries[i];
525                 into->acts[i] = from->acts[i];
526                 into->symsDefined |= (1 << i);
527                 darray_init(from->syms[i]);
528                 darray_init(from->symsMapIndex[i]);
529                 darray_init(from->symsMapNumEntries[i]);
530                 darray_init(from->acts[i]);
531                 from->numLevels[i] = 0;
532                 from->symsDefined &= ~(1 << i);
533                 if (!darray_empty(into->syms[i]))
534                     into->defined |= _Key_Syms;
535                 if (!darray_empty(into->acts[i]))
536                     into->defined |= _Key_Acts;
537             }
538             else {
539                 if (report) {
540                     if (!darray_empty(into->syms[i]))
541                         collide |= _Key_Syms;
542                     if (!darray_empty(into->acts[i]))
543                         collide |= _Key_Acts;
544                 }
545                 MergeKeyGroups(info, into, from, (unsigned) i);
546             }
547         }
548         if (from->types[i] != XKB_ATOM_NONE) {
549             if ((into->types[i] != XKB_ATOM_NONE) && report &&
550                 (into->types[i] != from->types[i])) {
551                 xkb_atom_t use, ignore;
552                 collide |= _Key_Types;
553                 if (from->merge != MERGE_AUGMENT) {
554                     use = from->types[i];
555                     ignore = into->types[i];
556                 }
557                 else {
558                     use = into->types[i];
559                     ignore = from->types[i];
560                 }
561                 WARN
562                     ("Multiple definitions for group %d type of key %s\n",
563                     i, longText(into->name));
564                 ACTION("Using %s, ignoring %s\n",
565                        xkb_atom_text(keymap->ctx, use),
566                        xkb_atom_text(keymap->ctx, ignore));
567             }
568             if (from->merge != MERGE_AUGMENT ||
569                 into->types[i] == XKB_ATOM_NONE) {
570                 into->types[i] = from->types[i];
571             }
572         }
573     }
574     if (use_new_field(_Key_Behavior, into->defined, into->file_id,
575                       from->defined, from->file_id, from->merge, &collide)) {
576         into->behavior = from->behavior;
577         into->defined |= _Key_Behavior;
578     }
579     if (use_new_field(_Key_VModMap, into->defined, into->file_id,
580                       from->defined, from->file_id, from->merge, &collide)) {
581         into->vmodmap = from->vmodmap;
582         into->defined |= _Key_VModMap;
583     }
584     if (use_new_field(_Key_Repeat, into->defined, into->file_id,
585                       from->defined, from->file_id, from->merge, &collide)) {
586         into->repeat = from->repeat;
587         into->defined |= _Key_Repeat;
588     }
589     if (use_new_field(_Key_Type_Dflt, into->defined, into->file_id,
590                       from->defined, from->file_id, from->merge, &collide)) {
591         into->dfltType = from->dfltType;
592         into->defined |= _Key_Type_Dflt;
593     }
594     if (use_new_field(_Key_GroupInfo, into->defined, into->file_id,
595                       from->defined, from->file_id, from->merge, &collide)) {
596         into->out_of_range_group_action = from->out_of_range_group_action;
597         into->out_of_range_group_number = from->out_of_range_group_number;
598         into->defined |= _Key_GroupInfo;
599     }
600     if (collide) {
601         WARN("Symbol map for key %s redefined\n",
602              longText(into->name));
603         ACTION("Using %s definition for conflicting fields\n",
604                (from->merge == MERGE_AUGMENT ? "first" : "last"));
605     }
606     return true;
607 }
608
609 static bool
610 AddKeySymbols(SymbolsInfo *info, KeyInfo *keyi, struct xkb_keymap *keymap)
611 {
612     unsigned long real_name;
613     KeyInfo *iter, *new;
614
615     darray_foreach(iter, info->keys)
616         if (iter->name == keyi->name)
617             return MergeKeys(info, keymap, iter, keyi);
618
619     if (FindKeyNameForAlias(keymap, keyi->name, &real_name))
620         darray_foreach(iter, info->keys)
621             if (iter->name == real_name)
622                 return MergeKeys(info, keymap, iter, keyi);
623
624     darray_resize0(info->keys, darray_size(info->keys) + 1);
625     new = &darray_item(info->keys, darray_size(info->keys) - 1);
626     return CopyKeyInfo(keyi, new, true);
627 }
628
629 static bool
630 AddModMapEntry(SymbolsInfo * info, ModMapEntry * new)
631 {
632     ModMapEntry *mm;
633     bool clobber;
634
635     clobber = (new->merge != MERGE_AUGMENT);
636     list_foreach(mm, &info->modMaps, entry) {
637         if (new->haveSymbol && mm->haveSymbol
638             && (new->u.keySym == mm->u.keySym)) {
639             unsigned use, ignore;
640             if (mm->modifier != new->modifier) {
641                 if (clobber) {
642                     use = new->modifier;
643                     ignore = mm->modifier;
644                 }
645                 else {
646                     use = mm->modifier;
647                     ignore = new->modifier;
648                 }
649                 ERROR
650                     ("%s added to symbol map for multiple modifiers\n",
651                     XkbcKeysymText(new->u.keySym));
652                 ACTION("Using %s, ignoring %s.\n",
653                        XkbcModIndexText(use),
654                        XkbcModIndexText(ignore));
655                 mm->modifier = use;
656             }
657             return true;
658         }
659         if ((!new->haveSymbol) && (!mm->haveSymbol) &&
660             (new->u.keyName == mm->u.keyName)) {
661             unsigned use, ignore;
662             if (mm->modifier != new->modifier) {
663                 if (clobber) {
664                     use = new->modifier;
665                     ignore = mm->modifier;
666                 }
667                 else {
668                     use = mm->modifier;
669                     ignore = new->modifier;
670                 }
671                 ERROR("Key %s added to map for multiple modifiers\n",
672                       longText(new->u.keyName));
673                 ACTION("Using %s, ignoring %s.\n",
674                        XkbcModIndexText(use),
675                        XkbcModIndexText(ignore));
676                 mm->modifier = use;
677             }
678             return true;
679         }
680     }
681
682     mm = malloc(sizeof(*mm));
683     if (!mm) {
684         WSGO("Could not allocate modifier map entry\n");
685         ACTION("Modifier map for %s will be incomplete\n",
686                XkbcModIndexText(new->modifier));
687         return false;
688     }
689
690     *mm = *new;
691     list_add(&mm->entry, &info->modMaps);
692     return true;
693 }
694
695 /***====================================================================***/
696
697 static void
698 MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
699                      enum merge_mode merge, struct xkb_keymap *keymap)
700 {
701     unsigned int i;
702     KeyInfo *keyi;
703     ModMapEntry *mm, *next;
704
705     if (from->errorCount > 0) {
706         into->errorCount += from->errorCount;
707         return;
708     }
709     if (into->name == NULL) {
710         into->name = from->name;
711         from->name = NULL;
712     }
713     for (i = 0; i < XkbNumKbdGroups; i++) {
714         if (from->groupNames[i] != XKB_ATOM_NONE) {
715             if ((merge != MERGE_AUGMENT) ||
716                 (into->groupNames[i] == XKB_ATOM_NONE))
717                 into->groupNames[i] = from->groupNames[i];
718         }
719     }
720
721     darray_foreach(keyi, from->keys) {
722         if (merge != MERGE_DEFAULT)
723             keyi->merge = merge;
724
725         if (!AddKeySymbols(into, keyi, keymap))
726             into->errorCount++;
727     }
728
729     list_foreach_safe(mm, next, &from->modMaps, entry) {
730         if (merge != MERGE_DEFAULT)
731             mm->merge = merge;
732         if (!AddModMapEntry(into, mm))
733             into->errorCount++;
734         free(mm);
735     }
736     list_init(&from->modMaps);
737 }
738
739 static void
740 HandleSymbolsFile(XkbFile *file, struct xkb_keymap *keymap,
741                   enum merge_mode merge,
742                   SymbolsInfo *info);
743
744 static bool
745 HandleIncludeSymbols(IncludeStmt *stmt, struct xkb_keymap *keymap,
746                      SymbolsInfo *info)
747 {
748     enum merge_mode newMerge;
749     XkbFile *rtrn;
750     SymbolsInfo included;
751     bool haveSelf;
752
753     haveSelf = false;
754     if ((stmt->file == NULL) && (stmt->map == NULL)) {
755         haveSelf = true;
756         included = *info;
757         memset(info, 0, sizeof(SymbolsInfo));
758     }
759     else if (ProcessIncludeFile(keymap->ctx, stmt, FILE_TYPE_SYMBOLS, &rtrn,
760                                 &newMerge)) {
761         InitSymbolsInfo(&included, keymap, rtrn->id);
762         included.merge = included.dflt.merge = MERGE_OVERRIDE;
763         if (stmt->modifier)
764             included.explicit_group = atoi(stmt->modifier) - 1;
765         else
766             included.explicit_group = info->explicit_group;
767         HandleSymbolsFile(rtrn, keymap, MERGE_OVERRIDE, &included);
768         if (stmt->stmt != NULL) {
769             free(included.name);
770             included.name = stmt->stmt;
771             stmt->stmt = NULL;
772         }
773         FreeXKBFile(rtrn);
774     }
775     else {
776         info->errorCount += 10;
777         return false;
778     }
779     if ((stmt->next != NULL) && (included.errorCount < 1)) {
780         IncludeStmt *next;
781         unsigned op;
782         SymbolsInfo next_incl;
783
784         for (next = stmt->next; next != NULL; next = next->next) {
785             if ((next->file == NULL) && (next->map == NULL)) {
786                 haveSelf = true;
787                 MergeIncludedSymbols(&included, info, next->merge, keymap);
788                 FreeSymbolsInfo(info);
789             }
790             else if (ProcessIncludeFile(keymap->ctx, next, FILE_TYPE_SYMBOLS,
791                                         &rtrn, &op)) {
792                 InitSymbolsInfo(&next_incl, keymap, rtrn->id);
793                 next_incl.merge = next_incl.dflt.merge = MERGE_OVERRIDE;
794                 if (next->modifier)
795                     next_incl.explicit_group = atoi(next->modifier) - 1;
796                 else
797                     next_incl.explicit_group = info->explicit_group;
798                 HandleSymbolsFile(rtrn, keymap, MERGE_OVERRIDE, &next_incl);
799                 MergeIncludedSymbols(&included, &next_incl, op, keymap);
800                 FreeSymbolsInfo(&next_incl);
801                 FreeXKBFile(rtrn);
802             }
803             else {
804                 info->errorCount += 10;
805                 FreeSymbolsInfo(&included);
806                 return false;
807             }
808         }
809     }
810     else if (stmt->next) {
811         info->errorCount += included.errorCount;
812     }
813     if (haveSelf)
814         *info = included;
815     else {
816         MergeIncludedSymbols(info, &included, newMerge, keymap);
817         FreeSymbolsInfo(&included);
818     }
819     return (info->errorCount == 0);
820 }
821
822 #define SYMBOLS 1
823 #define ACTIONS 2
824
825 static bool
826 GetGroupIndex(KeyInfo *keyi, struct xkb_keymap *keymap,
827               ExprDef * arrayNdx, unsigned what, unsigned *ndx_rtrn)
828 {
829     const char *name;
830     ExprResult tmp;
831
832     if (what == SYMBOLS)
833         name = "symbols";
834     else
835         name = "actions";
836
837     if (arrayNdx == NULL) {
838         int i;
839         unsigned defined;
840         if (what == SYMBOLS)
841             defined = keyi->symsDefined;
842         else
843             defined = keyi->actsDefined;
844
845         for (i = 0; i < XkbNumKbdGroups; i++) {
846             if ((defined & (1 << i)) == 0) {
847                 *ndx_rtrn = i;
848                 return true;
849             }
850         }
851         ERROR("Too many groups of %s for key %s (max %d)\n", name,
852               longText(keyi->name), XkbNumKbdGroups + 1);
853         ACTION("Ignoring %s defined for extra groups\n", name);
854         return false;
855     }
856     if (!ExprResolveGroup(keymap->ctx, arrayNdx, &tmp)) {
857         ERROR("Illegal group index for %s of key %s\n", name,
858               longText(keyi->name));
859         ACTION("Definition with non-integer array index ignored\n");
860         return false;
861     }
862     *ndx_rtrn = tmp.uval - 1;
863     return true;
864 }
865
866 static bool
867 AddSymbolsToKey(KeyInfo *keyi, struct xkb_keymap *keymap,
868                 ExprDef *arrayNdx, ExprDef *value, SymbolsInfo *info)
869 {
870     unsigned ndx, nSyms, nLevels;
871     unsigned int i;
872     long j;
873
874     if (!GetGroupIndex(keyi, keymap, arrayNdx, SYMBOLS, &ndx))
875         return false;
876     if (value == NULL) {
877         keyi->symsDefined |= (1 << ndx);
878         return true;
879     }
880     if (value->op != ExprKeysymList) {
881         ERROR("Expected a list of symbols, found %s\n", exprOpText(value->op));
882         ACTION("Ignoring symbols for group %d of %s\n", ndx + 1,
883                longText(keyi->name));
884         return false;
885     }
886     if (!darray_empty(keyi->syms[ndx])) {
887         ERROR("Symbols for key %s, group %d already defined\n",
888                longText(keyi->name), ndx + 1);
889         ACTION("Ignoring duplicate definition\n");
890         return false;
891     }
892     nSyms = darray_size(value->value.list.syms);
893     nLevels = darray_size(value->value.list.symsMapIndex);
894     if ((keyi->numLevels[ndx] < nSyms || darray_empty(keyi->syms[ndx])) &&
895         (!ResizeKeyGroup(keyi, ndx, nLevels, nSyms, false))) {
896         WSGO("Could not resize group %d of key %s to contain %d levels\n",
897              ndx + 1, longText(keyi->name), nSyms);
898         ACTION("Symbols lost\n");
899         return false;
900     }
901     keyi->symsDefined |= (1 << ndx);
902     for (i = 0; i < nLevels; i++) {
903         darray_item(keyi->symsMapIndex[ndx], i) =
904             darray_item(value->value.list.symsMapIndex, i);
905         darray_item(keyi->symsMapNumEntries[ndx], i) =
906             darray_item(value->value.list.symsNumEntries, i);
907
908         for (j = 0; j < darray_item(keyi->symsMapNumEntries[ndx], i); j++) {
909             /* FIXME: What's abort() doing here? */
910             if (darray_item(keyi->symsMapIndex[ndx], i) + j >= nSyms)
911                 abort();
912             if (!LookupKeysym(darray_item(value->value.list.syms,
913                                           darray_item(value->value.list.symsMapIndex,
914                                                       i) + j),
915                               &darray_item(keyi->syms[ndx],
916                                            darray_item(keyi->symsMapIndex[ndx],
917                                                        i) + j))) {
918                 WARN(
919                     "Could not resolve keysym %s for key %s, group %d (%s), level %d\n",
920                     darray_item(value->value.list.syms, i),
921                     longText(keyi->name),
922                     ndx + 1,
923                     xkb_atom_text(keymap->ctx, info->groupNames[ndx]), nSyms);
924                 while (--j >= 0)
925                     darray_item(keyi->syms[ndx],
926                                 darray_item(keyi->symsMapIndex[ndx],
927                                             i) + j) = XKB_KEY_NoSymbol;
928                 darray_item(keyi->symsMapIndex[ndx], i) = -1;
929                 darray_item(keyi->symsMapNumEntries[ndx], i) = 0;
930                 break;
931             }
932             if (darray_item(keyi->symsMapNumEntries[ndx], i) == 1 &&
933                 darray_item(keyi->syms[ndx],
934                             darray_item(keyi->symsMapIndex[ndx],
935                                         i) + j) == XKB_KEY_NoSymbol) {
936                 darray_item(keyi->symsMapIndex[ndx], i) = -1;
937                 darray_item(keyi->symsMapNumEntries[ndx], i) = 0;
938             }
939         }
940     }
941     for (j = keyi->numLevels[ndx] - 1;
942          j >= 0 && darray_item(keyi->symsMapNumEntries[ndx], j) == 0; j--)
943         keyi->numLevels[ndx]--;
944     return true;
945 }
946
947 static bool
948 AddActionsToKey(KeyInfo *keyi, struct xkb_keymap *keymap, ExprDef *arrayNdx,
949                 ExprDef *value, SymbolsInfo *info)
950 {
951     unsigned int i;
952     unsigned ndx, nActs;
953     ExprDef *act;
954     struct xkb_any_action *toAct;
955
956     if (!GetGroupIndex(keyi, keymap, arrayNdx, ACTIONS, &ndx))
957         return false;
958
959     if (value == NULL) {
960         keyi->actsDefined |= (1 << ndx);
961         return true;
962     }
963     if (value->op != ExprActionList) {
964         WSGO("Bad expression type (%d) for action list value\n", value->op);
965         ACTION("Ignoring actions for group %d of %s\n", ndx,
966                longText(keyi->name));
967         return false;
968     }
969     if (!darray_empty(keyi->acts[ndx])) {
970         WSGO("Actions for key %s, group %d already defined\n",
971              longText(keyi->name), ndx);
972         return false;
973     }
974     for (nActs = 0, act = value->value.child; act != NULL; nActs++) {
975         act = (ExprDef *) act->common.next;
976     }
977     if (nActs < 1) {
978         WSGO("Action list but not actions in AddActionsToKey\n");
979         return false;
980     }
981     if ((keyi->numLevels[ndx] < nActs || darray_empty(keyi->acts[ndx])) &&
982         !ResizeKeyGroup(keyi, ndx, nActs, nActs, true)) {
983         WSGO("Could not resize group %d of key %s\n", ndx,
984               longText(keyi->name));
985         ACTION("Actions lost\n");
986         return false;
987     }
988     keyi->actsDefined |= (1 << ndx);
989
990     toAct = (struct xkb_any_action *) darray_mem(keyi->acts[ndx], 0);
991     act = value->value.child;
992     for (i = 0; i < nActs; i++, toAct++) {
993         if (!HandleActionDef(act, keymap, toAct, info->action)) {
994             ERROR("Illegal action definition for %s\n",
995                   longText(keyi->name));
996             ACTION("Action for group %d/level %d ignored\n", ndx + 1, i + 1);
997         }
998         act = (ExprDef *) act->common.next;
999     }
1000     return true;
1001 }
1002
1003 static const LookupEntry lockingEntries[] = {
1004     { "true", XkbKB_Lock },
1005     { "yes", XkbKB_Lock },
1006     { "on", XkbKB_Lock },
1007     { "false", XkbKB_Default },
1008     { "no", XkbKB_Default },
1009     { "off", XkbKB_Default },
1010     { "permanent", XkbKB_Lock | XkbKB_Permanent },
1011     { NULL, 0 }
1012 };
1013
1014 static const LookupEntry repeatEntries[] = {
1015     { "true", RepeatYes },
1016     { "yes", RepeatYes },
1017     { "on", RepeatYes },
1018     { "false", RepeatNo },
1019     { "no", RepeatNo },
1020     { "off", RepeatNo },
1021     { "default", RepeatUndefined },
1022     { NULL, 0 }
1023 };
1024
1025 static bool
1026 SetSymbolsField(KeyInfo *keyi, struct xkb_keymap *keymap, char *field,
1027                 ExprDef *arrayNdx, ExprDef *value, SymbolsInfo *info)
1028 {
1029     bool ok = true;
1030     ExprResult tmp;
1031
1032     if (strcasecmp(field, "type") == 0) {
1033         ExprResult ndx;
1034         if ((!ExprResolveString(keymap->ctx, value, &tmp))
1035             && (warningLevel > 0)) {
1036             WARN("The type field of a key symbol map must be a string\n");
1037             ACTION("Ignoring illegal type definition\n");
1038         }
1039         if (arrayNdx == NULL) {
1040             keyi->dfltType = xkb_atom_intern(keymap->ctx, tmp.str);
1041             keyi->defined |= _Key_Type_Dflt;
1042         }
1043         else if (!ExprResolveGroup(keymap->ctx, arrayNdx, &ndx)) {
1044             ERROR("Illegal group index for type of key %s\n",
1045                   longText(keyi->name));
1046             ACTION("Definition with non-integer array index ignored\n");
1047             free(tmp.str);
1048             return false;
1049         }
1050         else {
1051             keyi->types[ndx.uval - 1] = xkb_atom_intern(keymap->ctx, tmp.str);
1052             keyi->typesDefined |= (1 << (ndx.uval - 1));
1053         }
1054         free(tmp.str);
1055     }
1056     else if (strcasecmp(field, "symbols") == 0)
1057         return AddSymbolsToKey(keyi, keymap, arrayNdx, value, info);
1058     else if (strcasecmp(field, "actions") == 0)
1059         return AddActionsToKey(keyi, keymap, arrayNdx, value, info);
1060     else if ((strcasecmp(field, "vmods") == 0) ||
1061              (strcasecmp(field, "virtualmods") == 0) ||
1062              (strcasecmp(field, "virtualmodifiers") == 0)) {
1063         ok = ExprResolveVModMask(value, &tmp, keymap);
1064         if (ok) {
1065             keyi->vmodmap = (tmp.uval >> 8);
1066             keyi->defined |= _Key_VModMap;
1067         }
1068         else {
1069             ERROR("Expected a virtual modifier mask, found %s\n",
1070                   exprOpText(value->op));
1071             ACTION("Ignoring virtual modifiers definition for key %s\n",
1072                    longText(keyi->name));
1073         }
1074     }
1075     else if ((strcasecmp(field, "locking") == 0) ||
1076              (strcasecmp(field, "lock") == 0) ||
1077              (strcasecmp(field, "locks") == 0)) {
1078         ok = ExprResolveEnum(keymap->ctx, value, &tmp, lockingEntries);
1079         if (ok)
1080             keyi->behavior.type = tmp.uval;
1081         keyi->defined |= _Key_Behavior;
1082     }
1083     else if ((strcasecmp(field, "radiogroup") == 0) ||
1084              (strcasecmp(field, "permanentradiogroup") == 0) ||
1085              (strcasecmp(field, "allownone") == 0)) {
1086         ERROR("Radio groups not supported\n");
1087         ACTION("Ignoring radio group specification for key %s\n",
1088                longText(keyi->name));
1089         return false;
1090     }
1091     else if (uStrCasePrefix("overlay", field) ||
1092              uStrCasePrefix("permanentoverlay", field)) {
1093         ERROR("Overlays not supported\n");
1094         ACTION("Ignoring overlay specification for key %s\n",
1095                longText(keyi->name));
1096     }
1097     else if ((strcasecmp(field, "repeating") == 0) ||
1098              (strcasecmp(field, "repeats") == 0) ||
1099              (strcasecmp(field, "repeat") == 0)) {
1100         ok = ExprResolveEnum(keymap->ctx, value, &tmp, repeatEntries);
1101         if (!ok) {
1102             ERROR("Illegal repeat setting for %s\n",
1103                   longText(keyi->name));
1104             ACTION("Non-boolean repeat setting ignored\n");
1105             return false;
1106         }
1107         keyi->repeat = tmp.uval;
1108         keyi->defined |= _Key_Repeat;
1109     }
1110     else if ((strcasecmp(field, "groupswrap") == 0) ||
1111              (strcasecmp(field, "wrapgroups") == 0)) {
1112         ok = ExprResolveBoolean(keymap->ctx, value, &tmp);
1113         if (!ok) {
1114             ERROR("Illegal groupsWrap setting for %s\n",
1115                   longText(keyi->name));
1116             ACTION("Non-boolean value ignored\n");
1117             return false;
1118         }
1119         if (tmp.uval)
1120             keyi->out_of_range_group_action = XkbWrapIntoRange;
1121         else
1122             keyi->out_of_range_group_action = XkbClampIntoRange;
1123         keyi->defined |= _Key_GroupInfo;
1124     }
1125     else if ((strcasecmp(field, "groupsclamp") == 0) ||
1126              (strcasecmp(field, "clampgroups") == 0)) {
1127         ok = ExprResolveBoolean(keymap->ctx, value, &tmp);
1128         if (!ok) {
1129             ERROR("Illegal groupsClamp setting for %s\n",
1130                   longText(keyi->name));
1131             ACTION("Non-boolean value ignored\n");
1132             return false;
1133         }
1134         if (tmp.uval)
1135             keyi->out_of_range_group_action = XkbClampIntoRange;
1136         else
1137             keyi->out_of_range_group_action = XkbWrapIntoRange;
1138         keyi->defined |= _Key_GroupInfo;
1139     }
1140     else if ((strcasecmp(field, "groupsredirect") == 0) ||
1141              (strcasecmp(field, "redirectgroups") == 0)) {
1142         if (!ExprResolveGroup(keymap->ctx, value, &tmp)) {
1143             ERROR("Illegal group index for redirect of key %s\n",
1144                   longText(keyi->name));
1145             ACTION("Definition with non-integer group ignored\n");
1146             return false;
1147         }
1148         keyi->out_of_range_group_action = XkbRedirectIntoRange;
1149         keyi->out_of_range_group_number = tmp.uval - 1;
1150         keyi->defined |= _Key_GroupInfo;
1151     }
1152     else {
1153         ERROR("Unknown field %s in a symbol interpretation\n", field);
1154         ACTION("Definition ignored\n");
1155         ok = false;
1156     }
1157     return ok;
1158 }
1159
1160 static int
1161 SetGroupName(SymbolsInfo *info, struct xkb_keymap *keymap, ExprDef *arrayNdx,
1162              ExprDef *value)
1163 {
1164     ExprResult tmp, name;
1165
1166     if ((arrayNdx == NULL) && (warningLevel > 0)) {
1167         WARN("You must specify an index when specifying a group name\n");
1168         ACTION("Group name definition without array subscript ignored\n");
1169         return false;
1170     }
1171     if (!ExprResolveGroup(keymap->ctx, arrayNdx, &tmp)) {
1172         ERROR("Illegal index in group name definition\n");
1173         ACTION("Definition with non-integer array index ignored\n");
1174         return false;
1175     }
1176     if (!ExprResolveString(keymap->ctx, value, &name)) {
1177         ERROR("Group name must be a string\n");
1178         ACTION("Illegal name for group %d ignored\n", tmp.uval);
1179         return false;
1180     }
1181     info->groupNames[tmp.uval - 1 + info->explicit_group] =
1182         xkb_atom_intern(keymap->ctx, name.str);
1183     free(name.str);
1184
1185     return true;
1186 }
1187
1188 static int
1189 HandleSymbolsVar(VarDef *stmt, struct xkb_keymap *keymap, SymbolsInfo *info)
1190 {
1191     ExprResult elem, field;
1192     ExprDef *arrayNdx;
1193     bool ret;
1194
1195     if (ExprResolveLhs(keymap, stmt->name, &elem, &field, &arrayNdx) == 0)
1196         return 0;               /* internal error, already reported */
1197     if (elem.str && (strcasecmp(elem.str, "key") == 0)) {
1198         ret = SetSymbolsField(&info->dflt, keymap, field.str, arrayNdx,
1199                               stmt->value, info);
1200     }
1201     else if ((elem.str == NULL) && ((strcasecmp(field.str, "name") == 0) ||
1202                                     (strcasecmp(field.str, "groupname") ==
1203                                      0))) {
1204         ret = SetGroupName(info, keymap, arrayNdx, stmt->value);
1205     }
1206     else if ((elem.str == NULL)
1207              && ((strcasecmp(field.str, "groupswrap") == 0) ||
1208                  (strcasecmp(field.str, "wrapgroups") == 0))) {
1209         ERROR("Global \"groupswrap\" not supported\n");
1210         ACTION("Ignored\n");
1211         ret = true;
1212     }
1213     else if ((elem.str == NULL)
1214              && ((strcasecmp(field.str, "groupsclamp") == 0) ||
1215                  (strcasecmp(field.str, "clampgroups") == 0))) {
1216         ERROR("Global \"groupsclamp\" not supported\n");
1217         ACTION("Ignored\n");
1218         ret = true;
1219     }
1220     else if ((elem.str == NULL)
1221              && ((strcasecmp(field.str, "groupsredirect") == 0) ||
1222                  (strcasecmp(field.str, "redirectgroups") == 0))) {
1223         ERROR("Global \"groupsredirect\" not supported\n");
1224         ACTION("Ignored\n");
1225         ret = true;
1226     }
1227     else if ((elem.str == NULL) &&
1228              (strcasecmp(field.str, "allownone") == 0)) {
1229         ERROR("Radio groups not supported\n");
1230         ACTION("Ignoring \"allownone\" specification\n");
1231         ret = true;
1232     }
1233     else {
1234         ret = SetActionField(keymap, elem.str, field.str, arrayNdx,
1235                              stmt->value, &info->action);
1236     }
1237
1238     free(elem.str);
1239     free(field.str);
1240     return ret;
1241 }
1242
1243 static bool
1244 HandleSymbolsBody(VarDef *def, struct xkb_keymap *keymap, KeyInfo *keyi,
1245                   SymbolsInfo *info)
1246 {
1247     bool ok = true;
1248     ExprResult tmp, field;
1249     ExprDef *arrayNdx;
1250
1251     for (; def != NULL; def = (VarDef *) def->common.next) {
1252         if ((def->name) && (def->name->type == ExprFieldRef)) {
1253             ok = HandleSymbolsVar(def, keymap, info);
1254             continue;
1255         }
1256         else {
1257             if (def->name == NULL) {
1258                 if ((def->value == NULL)
1259                     || (def->value->op == ExprKeysymList))
1260                     field.str = strdup("symbols");
1261                 else
1262                     field.str = strdup("actions");
1263                 arrayNdx = NULL;
1264             }
1265             else {
1266                 ok = ExprResolveLhs(keymap, def->name, &tmp, &field,
1267                                     &arrayNdx);
1268             }
1269             if (ok)
1270                 ok = SetSymbolsField(keyi, keymap, field.str, arrayNdx,
1271                                      def->value, info);
1272             free(field.str);
1273         }
1274     }
1275     return ok;
1276 }
1277
1278 static bool
1279 SetExplicitGroup(SymbolsInfo *info, KeyInfo *keyi)
1280 {
1281     unsigned group = info->explicit_group;
1282
1283     if (group == 0)
1284         return true;
1285
1286     if ((keyi->typesDefined | keyi->symsDefined | keyi->actsDefined) & ~1) {
1287         int i;
1288         WARN("For the map %s an explicit group specified\n", info->name);
1289         WARN("but key %s has more than one group defined\n",
1290              longText(keyi->name));
1291         ACTION("All groups except first one will be ignored\n");
1292         for (i = 1; i < XkbNumKbdGroups; i++) {
1293             keyi->numLevels[i] = 0;
1294             darray_free(keyi->syms[i]);
1295             darray_free(keyi->acts[i]);
1296             keyi->types[i] = 0;
1297         }
1298     }
1299     keyi->typesDefined = keyi->symsDefined = keyi->actsDefined = 1 << group;
1300
1301     keyi->numLevels[group] = keyi->numLevels[0];
1302     keyi->numLevels[0] = 0;
1303     keyi->syms[group] = keyi->syms[0];
1304     darray_init(keyi->syms[0]);
1305     keyi->symsMapIndex[group] = keyi->symsMapIndex[0];
1306     darray_init(keyi->symsMapIndex[0]);
1307     keyi->symsMapNumEntries[group] = keyi->symsMapNumEntries[0];
1308     darray_init(keyi->symsMapNumEntries[0]);
1309     keyi->acts[group] = keyi->acts[0];
1310     darray_init(keyi->acts[0]);
1311     keyi->types[group] = keyi->types[0];
1312     keyi->types[0] = 0;
1313     return true;
1314 }
1315
1316 static int
1317 HandleSymbolsDef(SymbolsDef *stmt, struct xkb_keymap *keymap,
1318                  SymbolsInfo *info)
1319 {
1320     KeyInfo keyi;
1321
1322     InitKeyInfo(&keyi, info->file_id);
1323     CopyKeyInfo(&info->dflt, &keyi, false);
1324     keyi.merge = stmt->merge;
1325     keyi.name = KeyNameToLong(stmt->keyName);
1326     if (!HandleSymbolsBody((VarDef *) stmt->symbols, keymap, &keyi, info)) {
1327         info->errorCount++;
1328         return false;
1329     }
1330
1331     if (!SetExplicitGroup(info, &keyi)) {
1332         info->errorCount++;
1333         return false;
1334     }
1335
1336     if (!AddKeySymbols(info, &keyi, keymap)) {
1337         info->errorCount++;
1338         return false;
1339     }
1340     return true;
1341 }
1342
1343 static bool
1344 HandleModMapDef(ModMapDef *def, struct xkb_keymap *keymap, SymbolsInfo *info)
1345 {
1346     ExprDef *key;
1347     ModMapEntry tmp;
1348     ExprResult rtrn;
1349     bool ok;
1350
1351     if (!LookupModIndex(keymap->ctx, NULL, def->modifier, TypeInt, &rtrn)) {
1352         ERROR("Illegal modifier map definition\n");
1353         ACTION("Ignoring map for non-modifier \"%s\"\n",
1354                xkb_atom_text(keymap->ctx, def->modifier));
1355         return false;
1356     }
1357     ok = true;
1358     tmp.modifier = rtrn.uval;
1359     for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) {
1360         if ((key->op == ExprValue) && (key->type == TypeKeyName)) {
1361             tmp.haveSymbol = false;
1362             tmp.u.keyName = KeyNameToLong(key->value.keyName);
1363         }
1364         else if (ExprResolveKeySym(keymap->ctx, key, &rtrn)) {
1365             tmp.haveSymbol = true;
1366             tmp.u.keySym = rtrn.uval;
1367         }
1368         else {
1369             ERROR("Modmap entries may contain only key names or keysyms\n");
1370             ACTION("Illegal definition for %s modifier ignored\n",
1371                    XkbcModIndexText(tmp.modifier));
1372             continue;
1373         }
1374
1375         ok = AddModMapEntry(info, &tmp) && ok;
1376     }
1377     return ok;
1378 }
1379
1380 static void
1381 HandleSymbolsFile(XkbFile *file, struct xkb_keymap *keymap,
1382                   enum merge_mode merge, SymbolsInfo *info)
1383 {
1384     ParseCommon *stmt;
1385
1386     free(info->name);
1387     info->name = uDupString(file->name);
1388     stmt = file->defs;
1389     while (stmt)
1390     {
1391         switch (stmt->stmtType) {
1392         case StmtInclude:
1393             if (!HandleIncludeSymbols((IncludeStmt *) stmt, keymap, info))
1394                 info->errorCount++;
1395             break;
1396         case StmtSymbolsDef:
1397             if (!HandleSymbolsDef((SymbolsDef *) stmt, keymap, info))
1398                 info->errorCount++;
1399             break;
1400         case StmtVarDef:
1401             if (!HandleSymbolsVar((VarDef *) stmt, keymap, info))
1402                 info->errorCount++;
1403             break;
1404         case StmtVModDef:
1405             if (!HandleVModDef((VModDef *) stmt, keymap, merge, &info->vmods))
1406                 info->errorCount++;
1407             break;
1408         case StmtInterpDef:
1409             ERROR("Interpretation files may not include other types\n");
1410             ACTION("Ignoring definition of symbol interpretation\n");
1411             info->errorCount++;
1412             break;
1413         case StmtKeycodeDef:
1414             ERROR("Interpretation files may not include other types\n");
1415             ACTION("Ignoring definition of key name\n");
1416             info->errorCount++;
1417             break;
1418         case StmtModMapDef:
1419             if (!HandleModMapDef((ModMapDef *) stmt, keymap, info))
1420                 info->errorCount++;
1421             break;
1422         default:
1423             WSGO("Unexpected statement type %d in HandleSymbolsFile\n",
1424                  stmt->stmtType);
1425             break;
1426         }
1427         stmt = stmt->next;
1428         if (info->errorCount > 10) {
1429 #ifdef NOISY
1430             ERROR("Too many errors\n");
1431 #endif
1432             ACTION("Abandoning symbols file \"%s\"\n", file->topName);
1433             break;
1434         }
1435     }
1436 }
1437
1438 /**
1439  * Given a keysym @sym, return a key which generates it, or NULL.
1440  * This is used for example in a modifier map definition, such as:
1441  *      modifier_map Lock           { Caps_Lock };
1442  * where we want to add the Lock modifier to the modmap of the key
1443  * which matches the keysym Caps_Lock.
1444  * Since there can be many keys which generates the keysym, the key
1445  * is chosen first by lowest group in which the keysym appears, than
1446  * by lowest level and than by lowest key code.
1447  */
1448 static struct xkb_key *
1449 FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym)
1450 {
1451     struct xkb_key *key, *ret = NULL;
1452     unsigned int group, level, min_group = UINT_MAX, min_level = UINT_MAX;
1453
1454     xkb_foreach_key(key, keymap) {
1455         for (group = 0; group < key->num_groups; group++) {
1456             for (level = 0; level < XkbKeyGroupWidth(keymap, key, group);
1457                  level++) {
1458                 if (XkbKeyNumSyms(key, group, level) != 1 ||
1459                     (XkbKeySymEntry(key, group, level))[0] != sym)
1460                     continue;
1461
1462                 /*
1463                  * If the keysym was found in a group or level > 0, we must
1464                  * keep looking since we might find a key in which the keysym
1465                  * is in a lower group or level.
1466                  */
1467                 if (group < min_group ||
1468                     (group == min_group && level < min_level)) {
1469                     ret = key;
1470                     if (group == 0 && level == 0) {
1471                         return ret;
1472                     }
1473                     else {
1474                         min_group = group;
1475                         min_level = level;
1476                     }
1477                 }
1478             }
1479         }
1480     }
1481
1482     return ret;
1483 }
1484
1485 /**
1486  * Find the given name in the keymap->map->types and return its index.
1487  *
1488  * @param atom The atom to search for.
1489  * @param type_rtrn Set to the index of the name if found.
1490  *
1491  * @return true if found, false otherwise.
1492  */
1493 static bool
1494 FindNamedType(struct xkb_keymap *keymap, xkb_atom_t atom, unsigned *type_rtrn)
1495 {
1496     unsigned n = 0;
1497     const char *name = xkb_atom_text(keymap->ctx, atom);
1498     struct xkb_key_type *type;
1499
1500     if (keymap) {
1501         darray_foreach(type, keymap->types) {
1502             if (strcmp(type->name, name) == 0) {
1503                 *type_rtrn = n;
1504                 return true;
1505             }
1506             n++;
1507         }
1508     }
1509     return false;
1510 }
1511
1512 /**
1513  * Assign a type to the given sym and return the Atom for the type assigned.
1514  *
1515  * Simple recipe:
1516  * - ONE_LEVEL for width 0/1
1517  * - ALPHABETIC for 2 shift levels, with lower/upercase
1518  * - KEYPAD for keypad keys.
1519  * - TWO_LEVEL for other 2 shift level keys.
1520  * and the same for four level keys.
1521  *
1522  * @param width Number of sysms in syms.
1523  * @param syms The keysyms for the given key (must be size width).
1524  * @param typeNameRtrn Set to the Atom of the type name.
1525  *
1526  * @returns true if a type could be found, false otherwise.
1527  *
1528  * FIXME: I need to take the KeyInfo so I can look at symsMapIndex and
1529  *        all that fun stuff rather than just assuming there's always one
1530  *        symbol per level.
1531  */
1532 static bool
1533 FindAutomaticType(struct xkb_keymap *keymap, int width,
1534                   const xkb_keysym_t *syms, xkb_atom_t *typeNameRtrn,
1535                   bool *autoType)
1536 {
1537     *autoType = false;
1538     if ((width == 1) || (width == 0)) {
1539         *typeNameRtrn = xkb_atom_intern(keymap->ctx, "ONE_LEVEL");
1540         *autoType = true;
1541     }
1542     else if (width == 2) {
1543         if (syms && xkb_keysym_is_lower(syms[0]) &&
1544             xkb_keysym_is_upper(syms[1])) {
1545             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "ALPHABETIC");
1546         }
1547         else if (syms && (xkb_keysym_is_keypad(syms[0]) ||
1548                           xkb_keysym_is_keypad(syms[1]))) {
1549             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "KEYPAD");
1550             *autoType = true;
1551         }
1552         else {
1553             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "TWO_LEVEL");
1554             *autoType = true;
1555         }
1556     }
1557     else if (width <= 4) {
1558         if (syms && xkb_keysym_is_lower(syms[0]) &&
1559             xkb_keysym_is_upper(syms[1]))
1560             if (xkb_keysym_is_lower(syms[2]) && xkb_keysym_is_upper(syms[3]))
1561                 *typeNameRtrn =
1562                     xkb_atom_intern(keymap->ctx, "FOUR_LEVEL_ALPHABETIC");
1563             else
1564                 *typeNameRtrn = xkb_atom_intern(keymap->ctx,
1565                                                 "FOUR_LEVEL_SEMIALPHABETIC");
1566
1567         else if (syms && (xkb_keysym_is_keypad(syms[0]) ||
1568                           xkb_keysym_is_keypad(syms[1])))
1569             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "FOUR_LEVEL_KEYPAD");
1570         else
1571             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "FOUR_LEVEL");
1572         /* XXX: why not set autoType here? */
1573     }
1574     return ((width >= 0) && (width <= 4));
1575 }
1576
1577 /**
1578  * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the
1579  * groups, and reduce to one group if all groups are identical anyway.
1580  */
1581 static void
1582 PrepareKeyDef(KeyInfo *keyi)
1583 {
1584     int i, j, width, defined, lastGroup;
1585     bool identical;
1586
1587     defined = keyi->symsDefined | keyi->actsDefined | keyi->typesDefined;
1588     /* get highest group number */
1589     for (i = XkbNumKbdGroups - 1; i >= 0; i--) {
1590         if (defined & (1 << i))
1591             break;
1592     }
1593     lastGroup = i;
1594
1595     if (lastGroup == 0)
1596         return;
1597
1598     /* If there are empty groups between non-empty ones fill them with data */
1599     /* from the first group. */
1600     /* We can make a wrong assumption here. But leaving gaps is worse. */
1601     for (i = lastGroup; i > 0; i--) {
1602         if (defined & (1 << i))
1603             continue;
1604         width = keyi->numLevels[0];
1605         if (keyi->typesDefined & 1) {
1606             for (j = 0; j < width; j++) {
1607                 keyi->types[i] = keyi->types[0];
1608             }
1609             keyi->typesDefined |= 1 << i;
1610         }
1611         if ((keyi->actsDefined & 1) && !darray_empty(keyi->acts[0])) {
1612             darray_copy(keyi->acts[i], keyi->acts[0]);
1613             keyi->actsDefined |= 1 << i;
1614         }
1615         if ((keyi->symsDefined & 1) && !darray_empty(keyi->syms[0])) {
1616             darray_copy(keyi->syms[i], keyi->syms[0]);
1617             darray_copy(keyi->symsMapIndex[i], keyi->symsMapIndex[0]);
1618             darray_copy(keyi->symsMapNumEntries[i],
1619                         keyi->symsMapNumEntries[0]);
1620             keyi->symsDefined |= 1 << i;
1621         }
1622         if (defined & 1) {
1623             keyi->numLevels[i] = keyi->numLevels[0];
1624         }
1625     }
1626     /* If all groups are completely identical remove them all */
1627     /* exept the first one. */
1628     identical = true;
1629     for (i = lastGroup; i > 0; i--) {
1630         if ((keyi->numLevels[i] != keyi->numLevels[0]) ||
1631             (keyi->types[i] != keyi->types[0])) {
1632             identical = false;
1633             break;
1634         }
1635         if (!darray_same(keyi->syms[i], keyi->syms[0]) &&
1636             (darray_empty(keyi->syms[i]) || darray_empty(keyi->syms[0]) ||
1637              darray_size(keyi->syms[i]) != darray_size(keyi->syms[0]) ||
1638              memcmp(darray_mem(keyi->syms[i], 0),
1639                     darray_mem(keyi->syms[0], 0),
1640                    sizeof(xkb_keysym_t) * darray_size(keyi->syms[0])))) {
1641             identical = false;
1642             break;
1643         }
1644         if (!darray_same(keyi->symsMapIndex[i], keyi->symsMapIndex[0]) &&
1645             (darray_empty(keyi->symsMapIndex[i]) ||
1646              darray_empty(keyi->symsMapIndex[0]) ||
1647              memcmp(darray_mem(keyi->symsMapIndex[i], 0),
1648                     darray_mem(keyi->symsMapIndex[0], 0),
1649                     keyi->numLevels[0] * sizeof(int)))) {
1650             identical = false;
1651             continue;
1652         }
1653         if (!darray_same(keyi->symsMapNumEntries[i],
1654                          keyi->symsMapNumEntries[0]) &&
1655             (darray_empty(keyi->symsMapNumEntries[i]) ||
1656              darray_empty(keyi->symsMapNumEntries[0]) ||
1657              memcmp(darray_mem(keyi->symsMapNumEntries[i], 0),
1658                     darray_mem(keyi->symsMapNumEntries[0], 0),
1659                     keyi->numLevels[0] * sizeof(size_t)))) {
1660             identical = false;
1661             continue;
1662         }
1663         if (!darray_same(keyi->acts[i], keyi->acts[0]) &&
1664             (darray_empty(keyi->acts[i]) || darray_empty(keyi->acts[0]) ||
1665              memcmp(darray_mem(keyi->acts[i], 0),
1666                     darray_mem(keyi->acts[0], 0),
1667                     keyi->numLevels[0] * sizeof(union xkb_action)))) {
1668             identical = false;
1669             break;
1670         }
1671     }
1672     if (identical) {
1673         for (i = lastGroup; i > 0; i--) {
1674             keyi->numLevels[i] = 0;
1675             darray_free(keyi->syms[i]);
1676             darray_free(keyi->symsMapIndex[i]);
1677             darray_free(keyi->symsMapNumEntries[i]);
1678             darray_free(keyi->acts[i]);
1679             keyi->types[i] = 0;
1680         }
1681         keyi->symsDefined &= 1;
1682         keyi->actsDefined &= 1;
1683         keyi->typesDefined &= 1;
1684     }
1685 }
1686
1687 /**
1688  * Copy the KeyInfo into the keyboard description.
1689  *
1690  * This function recurses.
1691  */
1692 static bool
1693 CopySymbolsDef(struct xkb_keymap *keymap, KeyInfo *keyi, int start_from)
1694 {
1695     unsigned int i;
1696     xkb_keycode_t kc;
1697     struct xkb_key *key;
1698     unsigned int sizeSyms = 0;
1699     unsigned width, tmp, nGroups;
1700     struct xkb_key_type * type;
1701     bool haveActions, autoType, useAlias;
1702     unsigned types[XkbNumKbdGroups];
1703     union xkb_action *outActs;
1704     unsigned int symIndex = 0;
1705
1706     useAlias = (start_from == 0);
1707
1708     key = FindNamedKey(keymap, keyi->name, useAlias,
1709                        CreateKeyNames(keymap), start_from);
1710     if (!key) {
1711         if (start_from == 0 && warningLevel >= 5) {
1712             WARN("Key %s not found in keycodes\n", longText(keyi->name));
1713             ACTION("Symbols ignored\n");
1714         }
1715         return false;
1716     }
1717     kc = XkbKeyGetKeycode(keymap, key);
1718
1719     haveActions = false;
1720     for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++) {
1721         if (((i + 1) > nGroups)
1722             && (((keyi->symsDefined | keyi->actsDefined) & (1 << i))
1723                 || (keyi->typesDefined) & (1 << i)))
1724             nGroups = i + 1;
1725         if (!darray_empty(keyi->acts[i]))
1726             haveActions = true;
1727         autoType = false;
1728         /* Assign the type to the key, if it is missing. */
1729         if (keyi->types[i] == XKB_ATOM_NONE) {
1730             if (keyi->dfltType != XKB_ATOM_NONE)
1731                 keyi->types[i] = keyi->dfltType;
1732             else if (FindAutomaticType(keymap, keyi->numLevels[i],
1733                                        darray_mem(keyi->syms[i], 0),
1734                                        &keyi->types[i], &autoType)) { }
1735             else {
1736                 if (warningLevel >= 5) {
1737                     WARN("No automatic type for %d symbols\n",
1738                           (unsigned int) keyi->numLevels[i]);
1739                     ACTION("Using %s for the %s key (keycode %d)\n",
1740                             xkb_atom_text(keymap->ctx, keyi->types[i]),
1741                             longText(keyi->name), kc);
1742                 }
1743             }
1744         }
1745         if (FindNamedType(keymap, keyi->types[i], &types[i])) {
1746             if (!autoType || keyi->numLevels[i] > 2)
1747                 key->explicit |= (1 << i);
1748         }
1749         else {
1750             if (warningLevel >= 3) {
1751                 WARN("Type \"%s\" is not defined\n",
1752                      xkb_atom_text(keymap->ctx, keyi->types[i]));
1753                 ACTION("Using TWO_LEVEL for the %s key (keycode %d)\n",
1754                        longText(keyi->name), kc);
1755             }
1756             types[i] = XkbTwoLevelIndex;
1757         }
1758         /* if the type specifies fewer levels than the key has, shrink the key */
1759         type = &darray_item(keymap->types, types[i]);
1760         if (type->num_levels < keyi->numLevels[i]) {
1761             if (warningLevel > 0) {
1762                 WARN("Type \"%s\" has %d levels, but %s has %d symbols\n",
1763                      type->name, type->num_levels,
1764                      xkb_atom_text(keymap->ctx, keyi->name), keyi->numLevels[i]);
1765                 ACTION("Ignoring extra symbols\n");
1766             }
1767             keyi->numLevels[i] = type->num_levels;
1768         }
1769         if (keyi->numLevels[i] > width)
1770             width = keyi->numLevels[i];
1771         if (type->num_levels > width)
1772             width = type->num_levels;
1773         sizeSyms += darray_size(keyi->syms[i]);
1774     }
1775
1776     darray_resize0(key->syms, sizeSyms);
1777
1778     if (haveActions) {
1779         outActs = XkbcResizeKeyActions(keymap, key, width * nGroups);
1780         if (outActs == NULL) {
1781             WSGO("Could not enlarge actions for %s (key %d)\n",
1782                  longText(keyi->name), kc);
1783             return false;
1784         }
1785         key->explicit |= XkbExplicitInterpretMask;
1786     }
1787     else
1788         outActs = NULL;
1789
1790     key->num_groups = nGroups;
1791     if (keyi->defined & _Key_GroupInfo) {
1792         key->out_of_range_group_number = keyi->out_of_range_group_number;
1793         key->out_of_range_group_action = keyi->out_of_range_group_action;
1794     }
1795     key->width = width;
1796     key->sym_index = calloc(nGroups * width, sizeof(*key->sym_index));
1797     key->num_syms = calloc(nGroups * width, sizeof(*key->num_syms));
1798
1799     for (i = 0; i < nGroups; i++) {
1800         /* assign kt_index[i] to the index of the type in map->types.
1801          * kt_index[i] may have been set by a previous run (if we have two
1802          * layouts specified). Let's not overwrite it with the ONE_LEVEL
1803          * default group if we dont even have keys for this group anyway.
1804          *
1805          * FIXME: There should be a better fix for this.
1806          */
1807         if (keyi->numLevels[i])
1808             key->kt_index[i] = types[i];
1809         if (!darray_empty(keyi->syms[i])) {
1810             /* fill key to "width" symbols*/
1811             for (tmp = 0; tmp < width; tmp++) {
1812                 if (tmp < keyi->numLevels[i] &&
1813                     darray_item(keyi->symsMapNumEntries[i], tmp) != 0) {
1814                     memcpy(darray_mem(key->syms, symIndex),
1815                            darray_mem(keyi->syms[i],
1816                                       darray_item(keyi->symsMapIndex[i], tmp)),
1817                            darray_item(keyi->symsMapNumEntries[i],
1818                                        tmp) * sizeof(xkb_keysym_t));
1819                     key->sym_index[(i * width) + tmp] = symIndex;
1820                     key->num_syms[(i * width) + tmp] =
1821                         darray_item(keyi->symsMapNumEntries[i], tmp);
1822                     symIndex += key->num_syms[(i * width) + tmp];
1823                 }
1824                 else {
1825                     key->sym_index[(i * width) + tmp] = -1;
1826                     key->num_syms[(i * width) + tmp] = 0;
1827                 }
1828                 if (outActs != NULL && !darray_empty(keyi->acts[i])) {
1829                     if (tmp < keyi->numLevels[i])
1830                         outActs[tmp] = darray_item(keyi->acts[i], tmp);
1831                     else
1832                         outActs[tmp].type = XkbSA_NoAction;
1833                 }
1834             }
1835         }
1836     }
1837     switch (keyi->behavior.type & XkbKB_OpMask) {
1838     case XkbKB_Default:
1839         break;
1840
1841     default:
1842         key->behavior = keyi->behavior;
1843         key->explicit |= XkbExplicitBehaviorMask;
1844         break;
1845     }
1846     if (keyi->defined & _Key_VModMap) {
1847         key->vmodmap = keyi->vmodmap;
1848         key->explicit |= XkbExplicitVModMapMask;
1849     }
1850     if (keyi->repeat != RepeatUndefined) {
1851         key->repeats = keyi->repeat == RepeatYes;
1852         key->explicit |= XkbExplicitAutoRepeatMask;
1853     }
1854
1855     /* do the same thing for the next key */
1856     CopySymbolsDef(keymap, keyi, kc + 1);
1857     return true;
1858 }
1859
1860 static bool
1861 CopyModMapDef(struct xkb_keymap *keymap, ModMapEntry *entry)
1862 {
1863     struct xkb_key *key;
1864
1865     if (!entry->haveSymbol) {
1866         key = FindNamedKey(keymap, entry->u.keyName, true,
1867                            CreateKeyNames(keymap), 0);
1868         if (!key) {
1869             if (warningLevel >= 5) {
1870                 WARN("Key %s not found in keycodes\n",
1871                      longText(entry->u.keyName));
1872                 ACTION("Modifier map entry for %s not updated\n",
1873                        XkbcModIndexText(entry->modifier));
1874             }
1875             return false;
1876         }
1877     }
1878     else {
1879         key = FindKeyForSymbol(keymap, entry->u.keySym);
1880         if (!key) {
1881             if (warningLevel > 5) {
1882                 WARN("Key \"%s\" not found in symbol map\n",
1883                      XkbcKeysymText(entry->u.keySym));
1884                 ACTION("Modifier map entry for %s not updated\n",
1885                        XkbcModIndexText(entry->modifier));
1886             }
1887             return false;
1888         }
1889     }
1890
1891     key->modmap |= (1 << entry->modifier);
1892     return true;
1893 }
1894
1895 /**
1896  * Handle the xkb_symbols section of an xkb file.
1897  *
1898  * @param file The parsed xkb_symbols section of the xkb file.
1899  * @param keymap Handle to the keyboard description to store the symbols in.
1900  * @param merge Merge strategy (e.g. MERGE_OVERRIDE).
1901  */
1902 bool
1903 CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
1904                enum merge_mode merge)
1905 {
1906     int i;
1907     struct xkb_key *key;
1908     SymbolsInfo info;
1909     KeyInfo *keyi;
1910     ModMapEntry *mm;
1911
1912     InitSymbolsInfo(&info, keymap, file->id);
1913     info.dflt.merge = merge;
1914
1915     HandleSymbolsFile(file, keymap, merge, &info);
1916
1917     if (darray_empty(info.keys))
1918         goto err_info;
1919
1920     if (info.errorCount != 0)
1921         goto err_info;
1922
1923     darray_resize0(keymap->acts, darray_size(keymap->acts) + 32 + 1);
1924
1925     if (info.name)
1926         keymap->symbols_section_name = strdup(info.name);
1927
1928     for (i = 0; i < XkbNumKbdGroups; i++) {
1929         if (info.groupNames[i] != XKB_ATOM_NONE) {
1930             free(keymap->group_names[i]);
1931             keymap->group_names[i] = xkb_atom_strdup(keymap->ctx,
1932                                                      info.groupNames[i]);
1933         }
1934     }
1935
1936     /* sanitize keys */
1937     darray_foreach(keyi, info.keys)
1938         PrepareKeyDef(keyi);
1939
1940     /* copy! */
1941     darray_foreach(keyi, info.keys)
1942         if (!CopySymbolsDef(keymap, keyi, 0))
1943             info.errorCount++;
1944
1945     if (warningLevel > 3) {
1946         xkb_foreach_key(key, keymap) {
1947             if (key->name[0] == '\0')
1948                 continue;
1949
1950             if (key->num_groups < 1)
1951                 WARN("No symbols defined for <%.4s> (keycode %d)\n",
1952                      key->name, XkbKeyGetKeycode(keymap, key));
1953         }
1954     }
1955
1956     list_foreach(mm, &info.modMaps, entry)
1957         if (!CopyModMapDef(keymap, mm))
1958             info.errorCount++;
1959
1960     FreeSymbolsInfo(&info);
1961     return true;
1962
1963 err_info:
1964     FreeSymbolsInfo(&info);
1965     return false;
1966 }