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