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