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