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