d5c75c3168f39c006b57fb5323a85aca542e157c
[platform/upstream/libxkbcommon.git] / src / xkbcomp / keytypes.c
1 /************************************************************
2  * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3  *
4  * Permission to use, copy, modify, and distribute this
5  * software and its documentation for any purpose and without
6  * fee is hereby granted, provided that the above copyright
7  * notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting
9  * documentation, and that the name of Silicon Graphics not be
10  * used in advertising or publicity pertaining to distribution
11  * of the software without specific prior written permission.
12  * Silicon Graphics makes no representation about the suitability
13  * of this software for any purpose. It is provided "as is"
14  * without any express or implied warranty.
15  *
16  * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18  * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19  * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
24  *
25  ********************************************************/
26
27 #include "xkbcomp-priv.h"
28 #include "parseutils.h"
29 #include "vmod.h"
30
31 typedef struct _PreserveInfo {
32     struct list entry;
33     short matchingMapIndex;
34     unsigned char indexMods;
35     unsigned char preMods;
36     unsigned short indexVMods;
37     unsigned short preVMods;
38 } PreserveInfo;
39
40 #define _KT_Name       (1 << 0)
41 #define _KT_Mask       (1 << 1)
42 #define _KT_Map        (1 << 2)
43 #define _KT_Preserve   (1 << 3)
44 #define _KT_LevelNames (1 << 4)
45
46 typedef struct _KeyTypeInfo {
47     unsigned short defined;
48     unsigned file_id;
49     enum merge_mode merge;
50     struct list entry;
51
52     xkb_atom_t name;
53     xkb_mod_mask_t mask;
54     xkb_mod_mask_t vmask;
55     unsigned numLevels;
56     darray(struct xkb_kt_map_entry) entries;
57     struct list preserves;
58     darray(xkb_atom_t) lvlNames;
59 } KeyTypeInfo;
60
61 typedef struct _KeyTypesInfo {
62     char *name;
63     int errorCount;
64     unsigned file_id;
65     unsigned stdPresent;
66     unsigned nTypes;
67     struct list types;
68     KeyTypeInfo dflt;
69     VModInfo vmods;
70     struct xkb_keymap *keymap;
71
72     xkb_atom_t tok_ONE_LEVEL;
73     xkb_atom_t tok_TWO_LEVEL;
74     xkb_atom_t tok_ALPHABETIC;
75     xkb_atom_t tok_KEYPAD;
76 } KeyTypesInfo;
77
78 /***====================================================================***/
79
80 static inline const char *
81 MapEntryTxt(KeyTypesInfo *info, struct xkb_kt_map_entry *entry)
82 {
83     return VModMaskText(info->keymap, entry->mods.real_mods,
84                         entry->mods.vmods);
85 }
86
87 static inline const char *
88 PreserveIndexTxt(KeyTypesInfo *info, PreserveInfo *pi)
89 {
90     return VModMaskText(info->keymap, pi->indexMods, pi->indexVMods);
91 }
92
93 static inline const char *
94 PreserveTxt(KeyTypesInfo *info, PreserveInfo *pi)
95 {
96     return VModMaskText(info->keymap, pi->preMods, pi->preVMods);
97 }
98
99 static inline const char *
100 TypeTxt(KeyTypesInfo *info, KeyTypeInfo *type)
101 {
102     return xkb_atom_text(info->keymap->ctx, type->name);
103 }
104
105 static inline const char *
106 TypeMaskTxt(KeyTypesInfo *info, KeyTypeInfo *type)
107 {
108     return VModMaskText(info->keymap, type->mask, type->vmask);
109 }
110
111 static inline bool
112 ReportTypeShouldBeArray(KeyTypesInfo *info, KeyTypeInfo *type,
113                         const char *field)
114 {
115     return ReportShouldBeArray(info->keymap, "key type", field,
116                                TypeTxt(info, type));
117 }
118
119 static inline bool
120 ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type,
121                   const char *field, const char *wanted)
122 {
123     return ReportBadType(info->keymap, "key type", field, TypeTxt(info, type),
124                          wanted);
125 }
126
127 static inline bool
128 ReportTypeBadWidth(KeyTypesInfo *info, const char *type, int has, int needs)
129 {
130     log_err(info->keymap->ctx,
131             "Key type \"%s\" has %d levels, must have %d; "
132             "Illegal type definition ignored\n",
133             type, has, needs);
134     return false;
135 }
136
137 /***====================================================================***/
138
139 static void
140 InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_keymap *keymap,
141                  KeyTypesInfo *from, unsigned file_id)
142 {
143     PreserveInfo *old, *new;
144
145     info->tok_ONE_LEVEL = xkb_atom_intern(keymap->ctx, "ONE_LEVEL");
146     info->tok_TWO_LEVEL = xkb_atom_intern(keymap->ctx, "TWO_LEVEL");
147     info->tok_ALPHABETIC = xkb_atom_intern(keymap->ctx, "ALPHABETIC");
148     info->tok_KEYPAD = xkb_atom_intern(keymap->ctx, "KEYPAD");
149     info->name = strdup("default");
150     info->errorCount = 0;
151     info->stdPresent = 0;
152     info->nTypes = 0;
153     list_init(&info->types);
154     info->file_id = file_id;
155     info->dflt.defined = 0;
156     info->dflt.file_id = file_id;
157     info->dflt.merge = MERGE_OVERRIDE;
158     info->dflt.name = XKB_ATOM_NONE;
159     info->dflt.mask = 0;
160     info->dflt.vmask = 0;
161     info->dflt.numLevels = 1;
162     darray_init(info->dflt.entries);
163     darray_init(info->dflt.lvlNames);
164     list_init(&info->dflt.preserves);
165     InitVModInfo(&info->vmods, keymap);
166     info->keymap = keymap;
167
168     if (!from)
169         return;
170
171     info->dflt = from->dflt;
172
173     darray_copy(info->dflt.entries, from->dflt.entries);
174     darray_copy(info->dflt.lvlNames, from->dflt.lvlNames);
175
176     list_init(&info->dflt.preserves);
177     list_foreach(old, &from->dflt.preserves, entry) {
178         new = malloc(sizeof(*new));
179         if (!new)
180             return;
181
182         *new = *old;
183         list_append(&new->entry, &info->dflt.preserves);
184     }
185 }
186
187 static void
188 FreeKeyTypeInfo(KeyTypeInfo * type)
189 {
190     PreserveInfo *pi, *next_pi;
191     darray_free(type->entries);
192     darray_free(type->lvlNames);
193     list_foreach_safe(pi, next_pi, &type->preserves, entry)
194         free(pi);
195     list_init(&type->preserves);
196 }
197
198 static void
199 FreeKeyTypesInfo(KeyTypesInfo * info)
200 {
201     KeyTypeInfo *type, *next_type;
202     free(info->name);
203     info->name = NULL;
204     list_foreach_safe(type, next_type, &info->types, entry) {
205         FreeKeyTypeInfo(type);
206         free(type);
207     }
208     FreeKeyTypeInfo(&info->dflt);
209 }
210
211 static KeyTypeInfo *
212 NextKeyType(KeyTypesInfo * info)
213 {
214     KeyTypeInfo *type;
215
216     type = calloc(1, sizeof(*type));
217     if (!type)
218         return NULL;
219
220     list_init(&type->preserves);
221     type->file_id = info->file_id;
222
223     list_append(&type->entry, &info->types);
224     info->nTypes++;
225     return type;
226 }
227
228 static KeyTypeInfo *
229 FindMatchingKeyType(KeyTypesInfo * info, KeyTypeInfo * new)
230 {
231     KeyTypeInfo *old;
232
233     list_foreach(old, &info->types, entry)
234         if (old->name == new->name)
235             return old;
236
237     return NULL;
238 }
239
240 static bool
241 AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new)
242 {
243     KeyTypeInfo *old;
244     struct list type_entry, preserves_entry;
245     int verbosity = xkb_get_log_verbosity(info->keymap->ctx);
246
247     if (new->name == info->tok_ONE_LEVEL) {
248         if (new->numLevels > 1)
249             return ReportTypeBadWidth(info, "ONE_LEVEL", new->numLevels, 1);
250         info->stdPresent |= XkbOneLevelMask;
251     }
252     else if (new->name == info->tok_TWO_LEVEL) {
253         if (new->numLevels > 2)
254             return ReportTypeBadWidth(info, "TWO_LEVEL", new->numLevels, 2);
255         else if (new->numLevels < 2)
256             new->numLevels = 2;
257         info->stdPresent |= XkbTwoLevelMask;
258     }
259     else if (new->name == info->tok_ALPHABETIC) {
260         if (new->numLevels > 2)
261             return ReportTypeBadWidth(info, "ALPHABETIC", new->numLevels, 2);
262         else if (new->numLevels < 2)
263             new->numLevels = 2;
264         info->stdPresent |= XkbAlphabeticMask;
265     }
266     else if (new->name == info->tok_KEYPAD) {
267         if (new->numLevels > 2)
268             return ReportTypeBadWidth(info, "KEYPAD", new->numLevels, 2);
269         else if (new->numLevels < 2)
270             new->numLevels = 2;
271         info->stdPresent |= XkbKeypadMask;
272     }
273
274     old = FindMatchingKeyType(info, new);
275     if (old) {
276         if (new->merge == MERGE_REPLACE || new->merge == MERGE_OVERRIDE) {
277             if ((old->file_id == new->file_id && verbosity > 0) ||
278                 verbosity > 9) {
279                 log_warn(info->keymap->ctx,
280                          "Multiple definitions of the %s key type; "
281                          "Earlier definition ignored\n",
282                          xkb_atom_text(info->keymap->ctx, new->name));
283             }
284
285             type_entry = old->entry;
286             FreeKeyTypeInfo(old);
287             *old = *new;
288             old->entry = type_entry;
289             darray_init(new->entries);
290             darray_init(new->lvlNames);
291             list_init(&new->preserves);
292             return true;
293         }
294
295         if (old->file_id == new->file_id)
296             log_lvl(info->keymap->ctx, 4,
297                     "Multiple definitions of the %s key type; "
298                     "Later definition ignored\n",
299                     xkb_atom_text(info->keymap->ctx, new->name));
300
301         FreeKeyTypeInfo(new);
302         return true;
303     }
304
305     old = NextKeyType(info);
306     if (old == NULL)
307         return false;
308     list_replace(&new->preserves, &old->preserves);
309     type_entry = old->entry;
310     preserves_entry = old->preserves;
311     *old = *new;
312     old->preserves = preserves_entry;
313     old->entry = type_entry;
314     darray_init(new->entries);
315     darray_init(new->lvlNames);
316     list_init(&new->preserves);
317     return true;
318 }
319
320 /***====================================================================***/
321
322 static void
323 MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from,
324                       enum merge_mode merge)
325 {
326     KeyTypeInfo *type, *next_type;
327
328     if (from->errorCount > 0) {
329         into->errorCount += from->errorCount;
330         return;
331     }
332
333     if (into->name == NULL) {
334         into->name = from->name;
335         from->name = NULL;
336     }
337
338     list_foreach_safe(type, next_type, &from->types, entry) {
339         type->merge = (merge == MERGE_DEFAULT ? type->merge : merge);
340         if (!AddKeyType(into, type))
341             into->errorCount++;
342     }
343
344     into->stdPresent |= from->stdPresent;
345 }
346
347 static void
348 HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge);
349
350 static bool
351 HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *stmt)
352 {
353     enum merge_mode merge = MERGE_DEFAULT;
354     XkbFile *rtrn;
355     KeyTypesInfo included, next_incl;
356
357     InitKeyTypesInfo(&included, info->keymap, info, info->file_id);
358     if (stmt->stmt) {
359         free(included.name);
360         included.name = stmt->stmt;
361         stmt->stmt = NULL;
362     }
363
364     for (; stmt; stmt = stmt->next_incl) {
365         if (!ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_TYPES,
366                                 &rtrn, &merge)) {
367             info->errorCount += 10;
368             FreeKeyTypesInfo(&included);
369             return false;
370         }
371
372         InitKeyTypesInfo(&next_incl, info->keymap, &included, rtrn->id);
373         next_incl.dflt.merge = merge;
374
375         HandleKeyTypesFile(&next_incl, rtrn, merge);
376
377         MergeIncludedKeyTypes(&included, &next_incl, merge);
378
379         FreeKeyTypesInfo(&next_incl);
380         FreeXKBFile(rtrn);
381     }
382
383     MergeIncludedKeyTypes(info, &included, merge);
384     FreeKeyTypesInfo(&included);
385
386     return (info->errorCount == 0);
387 }
388
389 /***====================================================================***/
390
391 static struct xkb_kt_map_entry *
392 FindMatchingMapEntry(KeyTypeInfo * type, unsigned mask, unsigned vmask)
393 {
394     struct xkb_kt_map_entry *entry;
395
396     darray_foreach(entry, type->entries)
397         if (entry->mods.real_mods == mask && entry->mods.vmods == vmask)
398             return entry;
399
400     return NULL;
401 }
402
403 static void
404 DeleteLevel1MapEntries(KeyTypeInfo * type)
405 {
406     unsigned int i, n;
407
408     /* TODO: Be just a bit more clever here. */
409     for (i = 0; i < darray_size(type->entries); i++) {
410         if (darray_item(type->entries, i).level == 0) {
411             for (n = i; n < darray_size(type->entries) - 1; n++)
412                 darray_item(type->entries, n) =
413                     darray_item(type->entries, n + 1);
414             (void) darray_pop(type->entries);
415         }
416     }
417 }
418
419 static struct xkb_kt_map_entry *
420 NextMapEntry(KeyTypesInfo *info, KeyTypeInfo * type)
421 {
422     darray_resize0(type->entries, darray_size(type->entries) + 1);
423     return &darray_item(type->entries, darray_size(type->entries) - 1);
424 }
425
426 static bool
427 AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type,
428             PreserveInfo *new, bool clobber, bool report)
429 {
430     PreserveInfo *old;
431
432     list_foreach(old, &type->preserves, entry) {
433         if (old->indexMods != new->indexMods ||
434             old->indexVMods != new->indexVMods)
435             continue;
436
437         if (old->preMods == new->preMods && old->preVMods == new->preVMods) {
438             log_lvl(info->keymap->ctx, 10,
439                     "Identical definitions for preserve[%s] in %s; "
440                     "Ignored\n",
441                     PreserveIndexTxt(info, old), TypeTxt(info, type));
442             return true;
443         }
444
445         if (report)
446             log_lvl(info->keymap->ctx, 1,
447                     "Multiple definitions for preserve[%s] in %s; "
448                     "Using %s, ignoring %s\n",
449                     PreserveIndexTxt(info, old), TypeTxt(info, type),
450                     PreserveTxt(info, clobber ? new : old),
451                     PreserveTxt(info, clobber ? old : new));
452
453         if (clobber) {
454             old->preMods = new->preMods;
455             old->preVMods = new->preVMods;
456         }
457
458         return true;
459     }
460
461     old = malloc(sizeof(*old));
462     if (!old) {
463         log_wsgo(info->keymap->ctx,
464                  "Couldn't allocate preserve in %s; Preserve[%s] lost\n",
465                  TypeTxt(info, type), PreserveIndexTxt(info, new));
466         return false;
467     }
468
469     *old = *new;
470     old->matchingMapIndex = -1;
471     list_append(&old->entry, &type->preserves);
472
473     return true;
474 }
475
476 /**
477  * Add a new KTMapEntry to the given key type. If an entry with the same mods
478  * already exists, the level is updated (if clobber is TRUE). Otherwise, a new
479  * entry is created.
480  *
481  * @param clobber Overwrite existing entry.
482  * @param report true if a warning is to be printed on.
483  */
484 static bool
485 AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
486             struct xkb_kt_map_entry *new, bool clobber, bool report)
487 {
488     struct xkb_kt_map_entry * old;
489
490     if ((old = FindMatchingMapEntry(type, new->mods.real_mods,
491                                     new->mods.vmods))) {
492         if (report && (old->level != new->level)) {
493             unsigned use, ignore;
494             if (clobber) {
495                 use = new->level + 1;
496                 ignore = old->level + 1;
497             }
498             else {
499                 use = old->level + 1;
500                 ignore = new->level + 1;
501             }
502             log_warn(info->keymap->ctx,
503                      "Multiple map entries for %s in %s; "
504                      "Using %d, ignoring %d\n",
505                      MapEntryTxt(info, new), TypeTxt(info, type), use,
506                      ignore);
507         }
508         else {
509             log_lvl(info->keymap->ctx, 10,
510                     "Multiple occurences of map[%s]= %d in %s; Ignored\n",
511                     MapEntryTxt(info, new), new->level + 1,
512                     TypeTxt(info, type));
513             return true;
514         }
515         if (clobber)
516             old->level = new->level;
517         return true;
518     }
519     if ((old = NextMapEntry(info, type)) == NULL)
520         return false;           /* allocation failure, already reported */
521     if (new->level >= type->numLevels)
522         type->numLevels = new->level + 1;
523     old->mods.mask = new->mods.real_mods;
524     old->mods.real_mods = new->mods.real_mods;
525     old->mods.vmods = new->mods.vmods;
526     old->level = new->level;
527     return true;
528 }
529
530 static bool
531 SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
532             ExprDef *value)
533 {
534     ExprResult rtrn;
535     struct xkb_kt_map_entry entry;
536
537     if (arrayNdx == NULL)
538         return ReportTypeShouldBeArray(info, type, "map entry");
539
540     if (!ExprResolveVModMask(info->keymap, arrayNdx, &rtrn))
541         return ReportTypeBadType(info, type, "map entry", "modifier mask");
542
543     entry.mods.real_mods = rtrn.uval & 0xff;      /* modifiers < 512 */
544     entry.mods.vmods = (rtrn.uval >> 8) & 0xffff; /* modifiers > 512 */
545
546     if ((entry.mods.real_mods & (~type->mask)) ||
547         ((entry.mods.vmods & (~type->vmask)) != 0)) {
548         log_lvl(info->keymap->ctx, 1,
549                 "Map entry for unused modifiers in %s; "
550                 "Using %s instead of %s\n",
551                 TypeTxt(info, type),
552                 VModMaskText(info->keymap,
553                              entry.mods.real_mods & type->mask,
554                              entry.mods.vmods & type->vmask),
555                 MapEntryTxt(info, &entry));
556         entry.mods.real_mods &= type->mask;
557         entry.mods.vmods &= type->vmask;
558     }
559
560     if (!ExprResolveLevel(info->keymap->ctx, value, &rtrn)) {
561         log_err(info->keymap->ctx,
562                 "Level specifications in a key type must be integer; "
563                 "Ignoring malformed level specification\n");
564         return false;
565     }
566
567     entry.level = rtrn.ival - 1;
568     return AddMapEntry(info, type, &entry, true, true);
569 }
570
571 static bool
572 SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
573             ExprDef *value)
574 {
575     ExprResult rtrn;
576     PreserveInfo new;
577
578     if (arrayNdx == NULL)
579         return ReportTypeShouldBeArray(info, type, "preserve entry");
580
581     if (!ExprResolveVModMask(info->keymap, arrayNdx, &rtrn))
582         return ReportTypeBadType(info, type, "preserve entry",
583                                  "modifier mask");
584
585     new.indexMods = rtrn.uval & 0xff;
586     new.indexVMods = (rtrn.uval >> 8) & 0xffff;
587
588     if ((new.indexMods & (~type->mask)) ||
589         (new.indexVMods & (~type->vmask))) {
590         const char *before = PreserveIndexTxt(info, &new);
591
592         new.indexMods &= type->mask;
593         new.indexVMods &= type->vmask;
594
595         log_lvl(info->keymap->ctx, 1,
596                 "Preserve for modifiers not used by the %s type; "
597                 "Index %s converted to %s\n",
598                 TypeTxt(info, type), before,
599                 PreserveIndexTxt(info, &new));
600     }
601
602     if (!ExprResolveVModMask(info->keymap, value, &rtrn)) {
603         log_err(info->keymap->ctx,
604                 "Preserve value in a key type is not a modifier mask; "
605                 "Ignoring preserve[%s] in type %s\n",
606                 PreserveIndexTxt(info, &new), TypeTxt(info, type));
607         return false;
608     }
609
610     new.preMods = rtrn.uval & 0xff;
611     new.preVMods = (rtrn.uval >> 16) & 0xffff;
612
613     if ((new.preMods & (~new.indexMods)) ||
614         (new.preVMods & (~new.indexVMods))) {
615         const char *before = PreserveIndexTxt(info, &new);
616
617         new.preMods &= new.indexMods;
618         new.preVMods &= new.indexVMods;
619
620         log_lvl(info->keymap->ctx, 1,
621                 "Illegal value for preserve[%s] in type %s; "
622                 "Converted %s to %s\n",
623                 PreserveTxt(info, &new), TypeTxt(info, type),
624                 before, PreserveIndexTxt(info, &new));
625     }
626
627     return AddPreserve(info, type, &new, true, true);
628 }
629
630 /***====================================================================***/
631
632 static bool
633 AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type,
634              unsigned level, xkb_atom_t name, bool clobber)
635 {
636     if (level >= darray_size(type->lvlNames))
637         darray_resize0(type->lvlNames, level + 1);
638
639     if (darray_item(type->lvlNames, level) == name) {
640         log_lvl(info->keymap->ctx, 10,
641                 "Duplicate names for level %d of key type %s; Ignored\n",
642                 level + 1, TypeTxt(info, type));
643         return true;
644     }
645     else if (darray_item(type->lvlNames, level) != XKB_ATOM_NONE) {
646         if (xkb_get_log_verbosity(info->keymap->ctx) > 0) {
647             const char *old, *new;
648             old = xkb_atom_text(info->keymap->ctx,
649                                 darray_item(type->lvlNames, level));
650             new = xkb_atom_text(info->keymap->ctx, name);
651             log_lvl(info->keymap->ctx, 1,
652                     "Multiple names for level %d of key type %s; "
653                     "Using %s, ignoring %s\n",
654                     level + 1, TypeTxt(info, type),
655                     (clobber ? new : old), (clobber ? old : new));
656         }
657
658         if (!clobber)
659             return true;
660     }
661
662     darray_item(type->lvlNames, level) = name;
663     return true;
664 }
665
666 static bool
667 SetLevelName(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
668              ExprDef *value)
669 {
670     ExprResult rtrn;
671     unsigned level;
672     xkb_atom_t level_name;
673     struct xkb_context *ctx = info->keymap->ctx;
674     const char *str;
675
676     if (arrayNdx == NULL)
677         return ReportTypeShouldBeArray(info, type, "level name");
678
679     if (!ExprResolveLevel(ctx, arrayNdx, &rtrn))
680         return ReportTypeBadType(info, type, "level name", "integer");
681     level = rtrn.ival - 1;
682
683     if (!ExprResolveString(ctx, value, &str)) {
684         log_err(info->keymap->ctx,
685                 "Non-string name for level %d in key type %s; "
686                 "Ignoring illegal level name definition\n",
687                 level + 1, xkb_atom_text(ctx, type->name));
688         return false;
689     }
690
691     level_name = xkb_atom_intern(ctx, str);
692
693     return AddLevelName(info, type, level, level_name, true);
694 }
695
696 /***====================================================================***/
697
698 /**
699  * Parses the fields in a type "..." { } description.
700  *
701  * @param field The field to parse (e.g. modifiers, map, level_name)
702  */
703 static bool
704 SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type,
705                 const char *field, ExprDef *arrayNdx, ExprDef *value)
706 {
707     ExprResult tmp;
708
709     if (istreq(field, "modifiers")) {
710         unsigned mods, vmods;
711         if (arrayNdx != NULL)
712             log_warn(info->keymap->ctx,
713                      "The modifiers field of a key type is not an array; "
714                      "Illegal array subscript ignored\n");
715         /* get modifier mask for current type */
716         if (!ExprResolveVModMask(info->keymap, value, &tmp)) {
717             log_err(info->keymap->ctx,
718                     "Key type mask field must be a modifier mask; "
719                     "Key type definition ignored\n");
720             return false;
721         }
722         mods = tmp.uval & 0xff; /* core mods */
723         vmods = (tmp.uval >> 8) & 0xffff; /* xkb virtual mods */
724         if (type->defined & _KT_Mask) {
725             log_warn(info->keymap->ctx,
726                      "Multiple modifier mask definitions for key type %s; "
727                      "Using %s, ignoring %s\n",
728                      xkb_atom_text(info->keymap->ctx, type->name),
729                      TypeMaskTxt(info, type),
730                      VModMaskText(info->keymap, mods, vmods));
731             return false;
732         }
733         type->mask = mods;
734         type->vmask = vmods;
735         type->defined |= _KT_Mask;
736         return true;
737     }
738     else if (istreq(field, "map")) {
739         type->defined |= _KT_Map;
740         return SetMapEntry(info, type, arrayNdx, value);
741     }
742     else if (istreq(field, "preserve")) {
743         type->defined |= _KT_Preserve;
744         return SetPreserve(info, type, arrayNdx, value);
745     }
746     else if (istreq(field, "levelname") || istreq(field, "level_name")) {
747         type->defined |= _KT_LevelNames;
748         return SetLevelName(info, type, arrayNdx, value);
749     }
750
751     log_err(info->keymap->ctx,
752             "Unknown field %s in key type %s; Definition ignored\n",
753             field, TypeTxt(info, type));
754
755     return false;
756 }
757
758 static bool
759 HandleKeyTypeVar(KeyTypesInfo *info, VarDef *stmt)
760 {
761     const char *elem, *field;
762     ExprDef *arrayNdx;
763
764     if (!ExprResolveLhs(info->keymap->ctx, stmt->name, &elem, &field,
765                         &arrayNdx))
766         return false;           /* internal error, already reported */
767
768     if (elem && istreq(elem, "type"))
769         return SetKeyTypeField(info, &info->dflt, field, arrayNdx,
770                                stmt->value);
771
772     if (elem) {
773         log_err(info->keymap->ctx,
774                 "Default for unknown element %s; "
775                 "Value for field %s ignored\n", field, elem);
776     }
777     else if (field) {
778         log_err(info->keymap->ctx,
779                 "Default defined for unknown field %s; Ignored\n", field);
780     }
781
782     return false;
783 }
784
785 static int
786 HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type)
787 {
788     int ok = 1;
789     const char *elem, *field;
790     ExprDef *arrayNdx;
791
792     for (; def; def = (VarDef *) def->common.next) {
793         if (def->name && def->name->op == EXPR_FIELD_REF) {
794             ok = HandleKeyTypeVar(info, def);
795             continue;
796         }
797         ok = ExprResolveLhs(info->keymap->ctx, def->name, &elem, &field,
798                             &arrayNdx);
799         if (ok) {
800             ok = SetKeyTypeField(info, type, field, arrayNdx,
801                                  def->value);
802         }
803     }
804
805     return ok;
806 }
807
808 /**
809  * Process a type "XYZ" { } specification in the xkb_types section.
810  *
811  */
812 static int
813 HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge)
814 {
815     unsigned int i;
816     KeyTypeInfo type;
817     struct xkb_kt_map_entry *entry;
818     PreserveInfo *pi, *pi_next;
819
820     if (def->merge != MERGE_DEFAULT)
821         merge = def->merge;
822
823     type.defined = 0;
824     type.file_id = info->file_id;
825     type.merge = merge;
826     type.name = def->name;
827     type.mask = info->dflt.mask;
828     type.vmask = info->dflt.vmask;
829     type.numLevels = 1;
830     darray_init(type.entries);
831     darray_init(type.lvlNames);
832     list_init(&type.preserves);
833
834     /* Parse the actual content. */
835     if (!HandleKeyTypeBody(info, def->body, &type)) {
836         info->errorCount++;
837         return false;
838     }
839
840     /* now copy any appropriate map, preserve or level names from the */
841     /* default type */
842     darray_foreach(entry, info->dflt.entries) {
843         if ((entry->mods.real_mods & type.mask) == entry->mods.real_mods &&
844             (entry->mods.vmods & type.vmask) == entry->mods.vmods)
845             AddMapEntry(info, &type, entry, false, false);
846     }
847
848     list_foreach_safe(pi, pi_next, &info->dflt.preserves, entry) {
849         if ((pi->indexMods & type.mask) == pi->indexMods &&
850             (pi->indexVMods & type.vmask) == pi->indexVMods)
851             AddPreserve(info, &type, pi, false, false);
852     }
853
854     for (i = 0; i < darray_size(info->dflt.lvlNames); i++) {
855         if (i < type.numLevels &&
856             darray_item(info->dflt.lvlNames, i) != XKB_ATOM_NONE) {
857             AddLevelName(info, &type, i,
858                          darray_item(info->dflt.lvlNames, i), false);
859         }
860     }
861
862     /* Now add the new keytype to the info struct */
863     if (!AddKeyType(info, &type)) {
864         info->errorCount++;
865         return false;
866     }
867     return true;
868 }
869
870 /**
871  * Process an xkb_types section.
872  *
873  * @param file The parsed xkb_types section.
874  * @param merge Merge Strategy (e.g. MERGE_OVERRIDE)
875  * @param info Pointer to memory where the outcome will be stored.
876  */
877 static void
878 HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
879 {
880     ParseCommon *stmt;
881
882     free(info->name);
883     info->name = strdup_safe(file->name);
884     stmt = file->defs;
885     while (stmt)
886     {
887         switch (stmt->type) {
888         case STMT_INCLUDE:
889             if (!HandleIncludeKeyTypes(info, (IncludeStmt *) stmt))
890                 info->errorCount++;
891             break;
892         case STMT_TYPE: /* e.g. type "ONE_LEVEL" */
893             if (!HandleKeyTypeDef(info, (KeyTypeDef *) stmt, merge))
894                 info->errorCount++;
895             break;
896         case STMT_VAR:
897             if (!HandleKeyTypeVar(info, (VarDef *) stmt))
898                 info->errorCount++;
899             break;
900         case STMT_VMOD: /* virtual_modifiers NumLock, ... */
901             if (!HandleVModDef((VModDef *) stmt, info->keymap, merge,
902                                &info->vmods))
903                 info->errorCount++;
904             break;
905         case STMT_ALIAS:
906             log_err(info->keymap->ctx,
907                     "Key type files may not include other declarations; "
908                     "Ignoring definition of key alias\n");
909             info->errorCount++;
910             break;
911         case STMT_KEYCODE:
912             log_err(info->keymap->ctx,
913                     "Key type files may not include other declarations; "
914                     "Ignoring definition of key name\n");
915             info->errorCount++;
916             break;
917         case STMT_INTERP:
918             log_err(info->keymap->ctx,
919                     "Key type files may not include other declarations; "
920                     "Ignoring definition of symbol interpretation\n");
921             info->errorCount++;
922             break;
923         default:
924             log_wsgo(info->keymap->ctx,
925                      "Unexpected statement type %d in HandleKeyTypesFile\n",
926                      stmt->type);
927             break;
928         }
929         stmt = stmt->next;
930         if (info->errorCount > 10) {
931             log_err(info->keymap->ctx,
932                     "Abandoning keytypes file \"%s\"\n", file->topName);
933             break;
934         }
935     }
936 }
937
938 static bool
939 ComputeEffectiveMap(struct xkb_keymap *keymap, struct xkb_key_type *type)
940 {
941     uint32_t tmp;
942     struct xkb_kt_map_entry *entry = NULL;
943
944     if (type->mods.vmods != 0) {
945         tmp = VModsToReal(keymap, type->mods.vmods);
946         type->mods.mask = tmp | type->mods.real_mods;
947         darray_foreach(entry, type->map) {
948             tmp = 0;
949             if (entry->mods.vmods != 0) {
950                 tmp = VModsToReal(keymap, entry->mods.vmods);
951                 if (tmp == 0)
952                     continue;
953             }
954             entry->mods.mask =
955                 (entry->mods.real_mods | tmp) & type->mods.mask;
956         }
957     }
958     else
959         type->mods.mask = type->mods.real_mods;
960
961     return true;
962 }
963
964 static bool
965 CopyDefToKeyType(KeyTypesInfo *info, KeyTypeInfo *def,
966                  struct xkb_key_type *type)
967 {
968     unsigned int i;
969     PreserveInfo *pre;
970     struct xkb_keymap *keymap = info->keymap;
971
972     list_foreach(pre, &def->preserves, entry) {
973         struct xkb_kt_map_entry * match;
974         struct xkb_kt_map_entry tmp;
975         tmp.mods.real_mods = pre->indexMods;
976         tmp.mods.vmods = pre->indexVMods;
977         tmp.level = 0;
978         AddMapEntry(info, def, &tmp, false, false);
979         match = FindMatchingMapEntry(def, pre->indexMods, pre->indexVMods);
980         if (!match) {
981             log_wsgo(info->keymap->ctx,
982                      "Couldn't find matching entry for preserve; Aborting\n");
983             return false;
984         }
985         pre->matchingMapIndex = match - &darray_item(def->entries, 0);
986     }
987     type->mods.real_mods = def->mask;
988     type->mods.vmods = def->vmask;
989     type->num_levels = def->numLevels;
990     memcpy(&type->map, &def->entries, sizeof(def->entries));
991     if (!list_empty(&def->preserves)) {
992         type->preserve = calloc(darray_size(type->map),
993                                 sizeof(*type->preserve));
994         if (!type->preserve) {
995             log_warn(info->keymap->ctx,
996                      "Couldn't allocate preserve array in CopyDefToKeyType; "
997                      "Preserve setting for type %s lost\n",
998                      xkb_atom_text(keymap->ctx, def->name));
999         }
1000         else {
1001             list_foreach(pre, &def->preserves, entry) {
1002                 int ndx = pre->matchingMapIndex;
1003                 type->preserve[ndx].mask = pre->preMods;
1004                 type->preserve[ndx].real_mods = pre->preMods;
1005                 type->preserve[ndx].vmods = pre->preVMods;
1006             }
1007         }
1008     }
1009     else
1010         type->preserve = NULL;
1011     type->name = xkb_atom_text(keymap->ctx, def->name);
1012
1013     if (!darray_empty(def->lvlNames)) {
1014         type->level_names = calloc(darray_size(def->lvlNames),
1015                                    sizeof(*type->level_names));
1016
1017         /* assert def->szNames<=def->numLevels */
1018         for (i = 0; i < darray_size(def->lvlNames); i++)
1019             type->level_names[i] =
1020                 xkb_atom_text(keymap->ctx, darray_item(def->lvlNames, i));
1021     }
1022     else {
1023         type->level_names = NULL;
1024     }
1025
1026     darray_init(def->entries);
1027     return ComputeEffectiveMap(keymap, type);
1028 }
1029
1030 static struct xkb_kt_map_entry map2Level[] = {
1031     {
1032         .level = ShiftMask,
1033         .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1034     }
1035 };
1036
1037 static struct xkb_kt_map_entry mapAlpha[] = {
1038     {
1039         .level = ShiftMask,
1040         .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1041     },
1042     {
1043         .level = LockMask,
1044         .mods = { .mask = 0, .vmods = LockMask, .real_mods = 0 }
1045     }
1046 };
1047
1048 static struct xkb_mods preAlpha[] = {
1049     { .mask = 0, .vmods = 0, .real_mods = 0 },
1050     { .mask = LockMask, .vmods = LockMask, .real_mods = 0 }
1051 };
1052
1053 static struct xkb_kt_map_entry mapKeypad[] = {
1054     {
1055         .level = ShiftMask,
1056         .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1057     },
1058     {
1059         .level = 0,
1060         .mods = { .mask = 1, .vmods = 0, .real_mods = 0 }
1061     }
1062 };
1063
1064 static const struct xkb_key_type canonicalTypes[XkbNumRequiredTypes] = {
1065     [XkbOneLevelIndex] = {
1066         .mods = { .mask = 0, .vmods = 0, .real_mods = 0 },
1067         .num_levels = 1,
1068         .preserve = NULL,
1069         .name = NULL,
1070         .level_names = NULL
1071     },
1072     [XkbTwoLevelIndex] = {
1073         .mods = { .mask = ShiftMask, .vmods = ShiftMask, .real_mods = 0 },
1074         .num_levels = 2,
1075         .map = darray_lit(map2Level),
1076         .preserve = NULL,
1077         .name = NULL,
1078         .level_names = NULL
1079     },
1080     [XkbAlphabeticIndex] = {
1081         .mods = {
1082             .mask = ShiftMask | LockMask,
1083             .vmods = ShiftMask | LockMask,
1084             .real_mods = 0
1085         },
1086         .num_levels = 2,
1087         .map = darray_lit(mapAlpha),
1088         .preserve = preAlpha,
1089         .name = NULL,
1090         .level_names = NULL
1091     },
1092     [XkbKeypadIndex] = {
1093         .mods = { .mask = ShiftMask, .vmods = ShiftMask, .real_mods = 0 },
1094         .num_levels = 2,
1095         .map = darray_lit(mapKeypad),
1096         .preserve = NULL,
1097         .name = NULL,
1098         .level_names = NULL
1099     }
1100 };
1101
1102 static int
1103 CopyKeyType(const struct xkb_key_type *from, struct xkb_key_type *into)
1104 {
1105     int i;
1106
1107     darray_free(into->map);
1108     free(into->preserve);
1109     free(into->level_names);
1110
1111     *into = *from;
1112     darray_init(into->map);
1113
1114     darray_copy(into->map, from->map);
1115
1116     if (from->preserve && !darray_empty(into->map)) {
1117         into->preserve = calloc(darray_size(into->map),
1118                                 sizeof(*into->preserve));
1119         if (!into->preserve)
1120             return BadAlloc;
1121         memcpy(into->preserve, from->preserve,
1122                darray_size(into->map) * sizeof(*into->preserve));
1123     }
1124
1125     if (from->level_names && into->num_levels > 0) {
1126         into->level_names = calloc(into->num_levels,
1127                                    sizeof(*into->level_names));
1128         if (!into->level_names)
1129             return BadAlloc;
1130
1131         for (i = 0; i < into->num_levels; i++)
1132             into->level_names[i] = strdup(from->level_names[i]);
1133     }
1134
1135     return Success;
1136 }
1137
1138 static int
1139 InitCanonicalKeyTypes(struct xkb_keymap *keymap, unsigned which,
1140                       int keypadVMod)
1141 {
1142     const struct xkb_key_type *from;
1143     int rtrn;
1144
1145     darray_growalloc(keymap->types, XkbNumRequiredTypes);
1146
1147     if ((which & XkbAllRequiredTypes) == 0)
1148         return Success;
1149
1150     rtrn = Success;
1151     from = canonicalTypes;
1152
1153     if (which & XkbOneLevelMask)
1154         rtrn = CopyKeyType(&from[XkbOneLevelIndex],
1155                            &darray_item(keymap->types, XkbOneLevelIndex));
1156
1157     if ((which & XkbTwoLevelMask) && rtrn == Success)
1158         rtrn = CopyKeyType(&from[XkbTwoLevelIndex],
1159                            &darray_item(keymap->types, XkbTwoLevelIndex));
1160
1161     if ((which & XkbAlphabeticMask) && rtrn == Success)
1162         rtrn = CopyKeyType(&from[XkbAlphabeticIndex],
1163                            &darray_item(keymap->types, XkbAlphabeticIndex));
1164
1165     if ((which & XkbKeypadMask) && rtrn == Success) {
1166         struct xkb_key_type *type;
1167
1168         rtrn = CopyKeyType(&from[XkbKeypadIndex],
1169                            &darray_item(keymap->types, XkbKeypadIndex));
1170         type = &darray_item(keymap->types, XkbKeypadIndex);
1171
1172         if (keypadVMod >= 0 && keypadVMod < XkbNumVirtualMods &&
1173             rtrn == Success) {
1174             struct xkb_kt_map_entry *entry;
1175             type->mods.vmods = (1 << keypadVMod);
1176
1177             entry = &darray_item(type->map, 0);
1178             entry->mods.mask = ShiftMask;
1179             entry->mods.real_mods = ShiftMask;
1180             entry->mods.vmods = 0;
1181             entry->level = 1;
1182
1183             entry = &darray_item(type->map, 1);
1184             entry->mods.mask = 0;
1185             entry->mods.real_mods = 0;
1186             entry->mods.vmods = (1 << keypadVMod);
1187             entry->level = 1;
1188         }
1189     }
1190
1191     return Success;
1192 }
1193
1194 bool
1195 CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
1196                 enum merge_mode merge)
1197 {
1198     unsigned int i;
1199     struct xkb_key_type *type, *next;
1200     KeyTypesInfo info;
1201     KeyTypeInfo *def;
1202
1203     InitKeyTypesInfo(&info, keymap, NULL, file->id);
1204
1205     HandleKeyTypesFile(&info, file, merge);
1206
1207     if (info.errorCount != 0)
1208         goto err_info;
1209
1210     if (info.name)
1211         keymap->types_section_name = strdup(info.name);
1212
1213     i = info.nTypes;
1214     if ((info.stdPresent & XkbOneLevelMask) == 0)
1215         i++;
1216     if ((info.stdPresent & XkbTwoLevelMask) == 0)
1217         i++;
1218     if ((info.stdPresent & XkbKeypadMask) == 0)
1219         i++;
1220     if ((info.stdPresent & XkbAlphabeticMask) == 0)
1221         i++;
1222
1223     darray_resize0(keymap->types, i);
1224
1225     if (XkbAllRequiredTypes & (~info.stdPresent)) {
1226         unsigned missing, keypadVMod;
1227
1228         missing = XkbAllRequiredTypes & (~info.stdPresent);
1229         keypadVMod = FindKeypadVMod(keymap);
1230
1231         if (InitCanonicalKeyTypes(keymap, missing, keypadVMod) != Success) {
1232             log_wsgo(info.keymap->ctx,
1233                      "Couldn't initialize canonical key types\n");
1234             goto err_info;
1235         }
1236
1237         if (missing & XkbOneLevelMask)
1238             darray_item(keymap->types, XkbOneLevelIndex).name =
1239                 xkb_atom_text(keymap->ctx, info.tok_ONE_LEVEL);
1240         if (missing & XkbTwoLevelMask)
1241             darray_item(keymap->types, XkbTwoLevelIndex).name =
1242                 xkb_atom_text(keymap->ctx, info.tok_TWO_LEVEL);
1243         if (missing & XkbAlphabeticMask)
1244             darray_item(keymap->types, XkbAlphabeticIndex).name =
1245                 xkb_atom_text(keymap->ctx, info.tok_ALPHABETIC);
1246         if (missing & XkbKeypadMask)
1247             darray_item(keymap->types, XkbKeypadIndex).name =
1248                 xkb_atom_text(keymap->ctx, info.tok_KEYPAD);
1249     }
1250
1251     next = &darray_item(keymap->types, XkbLastRequiredType + 1);
1252     list_foreach(def, &info.types, entry) {
1253         if (def->name == info.tok_ONE_LEVEL)
1254             type = &darray_item(keymap->types, XkbOneLevelIndex);
1255         else if (def->name == info.tok_TWO_LEVEL)
1256             type = &darray_item(keymap->types, XkbTwoLevelIndex);
1257         else if (def->name == info.tok_ALPHABETIC)
1258             type = &darray_item(keymap->types, XkbAlphabeticIndex);
1259         else if (def->name == info.tok_KEYPAD)
1260             type = &darray_item(keymap->types, XkbKeypadIndex);
1261         else
1262             type = next++;
1263
1264         DeleteLevel1MapEntries(def);
1265
1266         if (!CopyDefToKeyType(&info, def, type))
1267             goto err_info;
1268     }
1269
1270     FreeKeyTypesInfo(&info);
1271     return true;
1272
1273 err_info:
1274     FreeKeyTypesInfo(&info);
1275     return false;
1276 }