xkbcomp: 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(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) {
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                 XkbcVModMaskText(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
675     if (arrayNdx == NULL)
676         return ReportTypeShouldBeArray(info, type, "level name");
677     if (!ExprResolveLevel(ctx, arrayNdx, &rtrn))
678         return ReportTypeBadType(info, type, "level name", "integer");
679     level = rtrn.ival - 1;
680     if (!ExprResolveString(ctx, value, &rtrn)) {
681         log_err(info->keymap->ctx,
682                 "Non-string name for level %d in key type %s; "
683                 "Ignoring illegal level name definition\n",
684                 level + 1, xkb_atom_text(ctx, type->name));
685         return false;
686     }
687     level_name = xkb_atom_intern(ctx, rtrn.str);
688     free(rtrn.str);
689     return AddLevelName(info, type, level, level_name, true);
690 }
691
692 /***====================================================================***/
693
694 /**
695  * Parses the fields in a type "..." { } description.
696  *
697  * @param field The field to parse (e.g. modifiers, map, level_name)
698  */
699 static bool
700 SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type,
701                 char *field, ExprDef *arrayNdx, ExprDef *value)
702 {
703     ExprResult tmp;
704
705     if (strcasecmp(field, "modifiers") == 0) {
706         unsigned mods, vmods;
707         if (arrayNdx != NULL)
708             log_warn(info->keymap->ctx,
709                      "The modifiers field of a key type is not an array; "
710                      "Illegal array subscript ignored\n");
711         /* get modifier mask for current type */
712         if (!ExprResolveVModMask(info->keymap, value, &tmp)) {
713             log_err(info->keymap->ctx,
714                     "Key type mask field must be a modifier mask; "
715                     "Key type definition ignored\n");
716             return false;
717         }
718         mods = tmp.uval & 0xff; /* core mods */
719         vmods = (tmp.uval >> 8) & 0xffff; /* xkb virtual mods */
720         if (type->defined & _KT_Mask) {
721             log_warn(info->keymap->ctx,
722                      "Multiple modifier mask definitions for key type %s; "
723                      "Using %s, ignoring %s\n",
724                      xkb_atom_text(info->keymap->ctx, type->name),
725                      TypeMaskTxt(info, type),
726                      XkbcVModMaskText(info->keymap, mods, vmods));
727             return false;
728         }
729         type->mask = mods;
730         type->vmask = vmods;
731         type->defined |= _KT_Mask;
732         return true;
733     }
734     else if (strcasecmp(field, "map") == 0) {
735         type->defined |= _KT_Map;
736         return SetMapEntry(info, type, arrayNdx, value);
737     }
738     else if (strcasecmp(field, "preserve") == 0) {
739         type->defined |= _KT_Preserve;
740         return SetPreserve(info, type, arrayNdx, value);
741     }
742     else if ((strcasecmp(field, "levelname") == 0) ||
743              (strcasecmp(field, "level_name") == 0)) {
744         type->defined |= _KT_LevelNames;
745         return SetLevelName(info, type, arrayNdx, value);
746     }
747
748     log_err(info->keymap->ctx,
749             "Unknown field %s in key type %s; Definition ignored\n",
750             field, TypeTxt(info, type));
751
752     return false;
753 }
754
755 static bool
756 HandleKeyTypeVar(KeyTypesInfo *info, VarDef *stmt)
757 {
758     ExprResult elem, field;
759     ExprDef *arrayNdx;
760
761     if (!ExprResolveLhs(info->keymap, stmt->name, &elem, &field, &arrayNdx))
762         return false;           /* internal error, already reported */
763     if (elem.str && (strcasecmp(elem.str, "type") == 0))
764         return SetKeyTypeField(info, &info->dflt, field.str, arrayNdx,
765                                stmt->value);
766     if (elem.str != NULL) {
767         log_err(info->keymap->ctx,
768                 "Default for unknown element %s; "
769                 "Value for field %s ignored\n",
770                 field.str, elem.str);
771     }
772     else if (field.str != NULL) {
773         log_err(info->keymap->ctx,
774                 "Default defined for unknown field %s; Ignored\n", field.str);
775     }
776     return false;
777 }
778
779 static int
780 HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type)
781 {
782     int ok = 1;
783     ExprResult tmp, field;
784     ExprDef *arrayNdx;
785
786     for (; def != NULL; def = (VarDef *) def->common.next) {
787         if ((def->name) && (def->name->type == ExprFieldRef)) {
788             ok = HandleKeyTypeVar(info, def);
789             continue;
790         }
791         ok = ExprResolveLhs(info->keymap, def->name, &tmp, &field, &arrayNdx);
792         if (ok) {
793             ok = SetKeyTypeField(info, type, field.str, arrayNdx,
794                                  def->value);
795             free(field.str);
796         }
797     }
798     return ok;
799 }
800
801 /**
802  * Process a type "XYZ" { } specification in the xkb_types section.
803  *
804  */
805 static int
806 HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge)
807 {
808     unsigned int i;
809     KeyTypeInfo type;
810     struct xkb_kt_map_entry *entry;
811     PreserveInfo *pi, *pi_next;
812
813     if (def->merge != MERGE_DEFAULT)
814         merge = def->merge;
815
816     type.defined = 0;
817     type.file_id = info->file_id;
818     type.merge = merge;
819     type.name = def->name;
820     type.mask = info->dflt.mask;
821     type.vmask = info->dflt.vmask;
822     type.numLevels = 1;
823     darray_init(type.entries);
824     darray_init(type.lvlNames);
825     list_init(&type.preserves);
826
827     /* Parse the actual content. */
828     if (!HandleKeyTypeBody(info, def->body, &type)) {
829         info->errorCount++;
830         return false;
831     }
832
833     /* now copy any appropriate map, preserve or level names from the */
834     /* default type */
835     darray_foreach(entry, info->dflt.entries) {
836         if ((entry->mods.real_mods & type.mask) == entry->mods.real_mods &&
837             (entry->mods.vmods & type.vmask) == entry->mods.vmods)
838             AddMapEntry(info, &type, entry, false, false);
839     }
840
841     list_foreach_safe(pi, pi_next, &info->dflt.preserves, entry) {
842         if ((pi->indexMods & type.mask) == pi->indexMods &&
843             (pi->indexVMods & type.vmask) == pi->indexVMods)
844             AddPreserve(info, &type, pi, false, false);
845     }
846
847     for (i = 0; i < darray_size(info->dflt.lvlNames); i++) {
848         if (i < type.numLevels &&
849             darray_item(info->dflt.lvlNames, i) != XKB_ATOM_NONE) {
850             AddLevelName(info, &type, i,
851                          darray_item(info->dflt.lvlNames, i), false);
852         }
853     }
854
855     /* Now add the new keytype to the info struct */
856     if (!AddKeyType(info, &type)) {
857         info->errorCount++;
858         return false;
859     }
860     return true;
861 }
862
863 /**
864  * Process an xkb_types section.
865  *
866  * @param file The parsed xkb_types section.
867  * @param merge Merge Strategy (e.g. MERGE_OVERRIDE)
868  * @param info Pointer to memory where the outcome will be stored.
869  */
870 static void
871 HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
872 {
873     ParseCommon *stmt;
874
875     free(info->name);
876     info->name = uDupString(file->name);
877     stmt = file->defs;
878     while (stmt)
879     {
880         switch (stmt->stmtType) {
881         case StmtInclude:
882             if (!HandleIncludeKeyTypes(info, (IncludeStmt *) stmt))
883                 info->errorCount++;
884             break;
885         case StmtKeyTypeDef: /* e.g. type "ONE_LEVEL" */
886             if (!HandleKeyTypeDef(info, (KeyTypeDef *) stmt, merge))
887                 info->errorCount++;
888             break;
889         case StmtVarDef:
890             if (!HandleKeyTypeVar(info, (VarDef *) stmt))
891                 info->errorCount++;
892             break;
893         case StmtVModDef: /* virtual_modifiers NumLock, ... */
894             if (!HandleVModDef((VModDef *) stmt, info->keymap, merge,
895                                &info->vmods))
896                 info->errorCount++;
897             break;
898         case StmtKeyAliasDef:
899             log_err(info->keymap->ctx,
900                     "Key type files may not include other declarations; "
901                     "Ignoring definition of key alias\n");
902             info->errorCount++;
903             break;
904         case StmtKeycodeDef:
905             log_err(info->keymap->ctx,
906                     "Key type files may not include other declarations; "
907                     "Ignoring definition of key name\n");
908             info->errorCount++;
909             break;
910         case StmtInterpDef:
911             log_err(info->keymap->ctx,
912                     "Key type files may not include other declarations; "
913                     "Ignoring definition of symbol interpretation\n");
914             info->errorCount++;
915             break;
916         default:
917             log_wsgo(info->keymap->ctx,
918                      "Unexpected statement type %d in HandleKeyTypesFile\n",
919                      stmt->stmtType);
920             break;
921         }
922         stmt = stmt->next;
923         if (info->errorCount > 10) {
924             log_err(info->keymap->ctx,
925                     "Abandoning keytypes file \"%s\"\n", file->topName);
926             break;
927         }
928     }
929 }
930
931 static bool
932 ComputeEffectiveMap(struct xkb_keymap *keymap, struct xkb_key_type *type)
933 {
934     uint32_t tmp;
935     struct xkb_kt_map_entry *entry = NULL;
936
937     if (type->mods.vmods != 0) {
938         tmp = VModsToReal(keymap, type->mods.vmods);
939         type->mods.mask = tmp | type->mods.real_mods;
940         darray_foreach(entry, type->map) {
941             tmp = 0;
942             if (entry->mods.vmods != 0) {
943                 tmp = VModsToReal(keymap, entry->mods.vmods);
944                 if (tmp == 0)
945                     continue;
946             }
947             entry->mods.mask =
948                 (entry->mods.real_mods | tmp) & type->mods.mask;
949         }
950     }
951     else
952         type->mods.mask = type->mods.real_mods;
953
954     return true;
955 }
956
957 static bool
958 CopyDefToKeyType(KeyTypesInfo *info, KeyTypeInfo *def,
959                  struct xkb_key_type *type)
960 {
961     unsigned int i;
962     PreserveInfo *pre;
963     struct xkb_keymap *keymap = info->keymap;
964
965     list_foreach(pre, &def->preserves, entry) {
966         struct xkb_kt_map_entry * match;
967         struct xkb_kt_map_entry tmp;
968         tmp.mods.real_mods = pre->indexMods;
969         tmp.mods.vmods = pre->indexVMods;
970         tmp.level = 0;
971         AddMapEntry(info, def, &tmp, false, false);
972         match = FindMatchingMapEntry(def, pre->indexMods, pre->indexVMods);
973         if (!match) {
974             log_wsgo(info->keymap->ctx,
975                      "Couldn't find matching entry for preserve; Aborting\n");
976             return false;
977         }
978         pre->matchingMapIndex = match - &darray_item(def->entries, 0);
979     }
980     type->mods.real_mods = def->mask;
981     type->mods.vmods = def->vmask;
982     type->num_levels = def->numLevels;
983     memcpy(&type->map, &def->entries, sizeof(def->entries));
984     if (!list_empty(&def->preserves)) {
985         type->preserve = calloc(darray_size(type->map),
986                                 sizeof(*type->preserve));
987         if (!type->preserve) {
988             log_warn(info->keymap->ctx,
989                      "Couldn't allocate preserve array in CopyDefToKeyType; "
990                      "Preserve setting for type %s lost\n",
991                      xkb_atom_text(keymap->ctx, def->name));
992         }
993         else {
994             list_foreach(pre, &def->preserves, entry) {
995                 int ndx = pre->matchingMapIndex;
996                 type->preserve[ndx].mask = pre->preMods;
997                 type->preserve[ndx].real_mods = pre->preMods;
998                 type->preserve[ndx].vmods = pre->preVMods;
999             }
1000         }
1001     }
1002     else
1003         type->preserve = NULL;
1004     type->name = xkb_atom_strdup(keymap->ctx, def->name);
1005
1006     if (!darray_empty(def->lvlNames)) {
1007         type->level_names = calloc(darray_size(def->lvlNames),
1008                                    sizeof(*type->level_names));
1009
1010         /* assert def->szNames<=def->numLevels */
1011         for (i = 0; i < darray_size(def->lvlNames); i++)
1012             type->level_names[i] =
1013                 xkb_atom_strdup(keymap->ctx, darray_item(def->lvlNames, i));
1014     }
1015     else {
1016         type->level_names = NULL;
1017     }
1018
1019     darray_init(def->entries);
1020     return ComputeEffectiveMap(keymap, type);
1021 }
1022
1023 static struct xkb_kt_map_entry map2Level[] = {
1024     {
1025         .level = ShiftMask,
1026         .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1027     }
1028 };
1029
1030 static struct xkb_kt_map_entry mapAlpha[] = {
1031     {
1032         .level = ShiftMask,
1033         .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1034     },
1035     {
1036         .level = LockMask,
1037         .mods = { .mask = 0, .vmods = LockMask, .real_mods = 0 }
1038     }
1039 };
1040
1041 static struct xkb_mods preAlpha[] = {
1042     { .mask = 0, .vmods = 0, .real_mods = 0 },
1043     { .mask = LockMask, .vmods = LockMask, .real_mods = 0 }
1044 };
1045
1046 static struct xkb_kt_map_entry mapKeypad[] = {
1047     {
1048         .level = ShiftMask,
1049         .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1050     },
1051     {
1052         .level = 0,
1053         .mods = { .mask = 1, .vmods = 0, .real_mods = 0 }
1054     }
1055 };
1056
1057 static const struct xkb_key_type canonicalTypes[XkbNumRequiredTypes] = {
1058     {
1059         .mods = { .mask = 0, .vmods = 0, .real_mods = 0 },
1060         .num_levels = 1,
1061         .preserve = NULL,
1062         .name = NULL,
1063         .level_names = NULL
1064     },
1065     {
1066         .mods = { .mask = ShiftMask, .vmods = ShiftMask, .real_mods = 0 },
1067         .num_levels = 2,
1068         .map = darray_lit(map2Level),
1069         .preserve = NULL,
1070         .name = NULL,
1071         .level_names = NULL
1072     },
1073     {
1074         .mods = {
1075             .mask = ShiftMask | LockMask,
1076             .vmods = ShiftMask | LockMask,
1077             .real_mods = 0
1078         },
1079         .num_levels = 2,
1080         .map = darray_lit(mapAlpha),
1081         .preserve = preAlpha,
1082         .name = NULL,
1083         .level_names = NULL
1084     },
1085     {
1086         .mods = { .mask = ShiftMask, .vmods = ShiftMask, .real_mods = 0 },
1087         .num_levels = 2,
1088         .map = darray_lit(mapKeypad),
1089         .preserve = NULL,
1090         .name = NULL,
1091         .level_names = NULL
1092     }
1093 };
1094
1095 static int
1096 InitCanonicalKeyTypes(struct xkb_keymap *keymap, unsigned which,
1097                       int keypadVMod)
1098 {
1099     const struct xkb_key_type *from;
1100     int rtrn;
1101
1102     darray_growalloc(keymap->types, XkbNumRequiredTypes);
1103
1104     if ((which & XkbAllRequiredTypes) == 0)
1105         return Success;
1106
1107     rtrn = Success;
1108     from = canonicalTypes;
1109
1110     if (which & XkbOneLevelMask)
1111         rtrn = XkbcCopyKeyType(&from[XkbOneLevelIndex],
1112                                &darray_item(keymap->types, XkbOneLevelIndex));
1113
1114     if ((which & XkbTwoLevelMask) && rtrn == Success)
1115         rtrn = XkbcCopyKeyType(&from[XkbTwoLevelIndex],
1116                                &darray_item(keymap->types, XkbTwoLevelIndex));
1117
1118     if ((which & XkbAlphabeticMask) && rtrn == Success)
1119         rtrn = XkbcCopyKeyType(&from[XkbAlphabeticIndex],
1120                                &darray_item(keymap->types, XkbAlphabeticIndex));
1121
1122     if ((which & XkbKeypadMask) && rtrn == Success) {
1123         struct xkb_key_type *type;
1124
1125         rtrn = XkbcCopyKeyType(&from[XkbKeypadIndex],
1126                                &darray_item(keymap->types, XkbKeypadIndex));
1127         type = &darray_item(keymap->types, XkbKeypadIndex);
1128
1129         if (keypadVMod >= 0 && keypadVMod < XkbNumVirtualMods &&
1130             rtrn == Success) {
1131             struct xkb_kt_map_entry *entry;
1132             type->mods.vmods = (1 << keypadVMod);
1133
1134             entry = &darray_item(type->map, 0);
1135             entry->mods.mask = ShiftMask;
1136             entry->mods.real_mods = ShiftMask;
1137             entry->mods.vmods = 0;
1138             entry->level = 1;
1139
1140             entry = &darray_item(type->map, 1);
1141             entry->mods.mask = 0;
1142             entry->mods.real_mods = 0;
1143             entry->mods.vmods = (1 << keypadVMod);
1144             entry->level = 1;
1145         }
1146     }
1147
1148     return Success;
1149 }
1150
1151 bool
1152 CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
1153                 enum merge_mode merge)
1154 {
1155     unsigned int i;
1156     struct xkb_key_type *type, *next;
1157     KeyTypesInfo info;
1158     KeyTypeInfo *def;
1159
1160     InitKeyTypesInfo(&info, keymap, NULL, file->id);
1161
1162     HandleKeyTypesFile(&info, file, merge);
1163
1164     if (info.errorCount != 0)
1165         goto err_info;
1166
1167     if (info.name)
1168         keymap->types_section_name = strdup(info.name);
1169
1170     i = info.nTypes;
1171     if ((info.stdPresent & XkbOneLevelMask) == 0)
1172         i++;
1173     if ((info.stdPresent & XkbTwoLevelMask) == 0)
1174         i++;
1175     if ((info.stdPresent & XkbKeypadMask) == 0)
1176         i++;
1177     if ((info.stdPresent & XkbAlphabeticMask) == 0)
1178         i++;
1179
1180     darray_resize0(keymap->types, i);
1181
1182     if (XkbAllRequiredTypes & (~info.stdPresent)) {
1183         unsigned missing, keypadVMod;
1184
1185         missing = XkbAllRequiredTypes & (~info.stdPresent);
1186         keypadVMod = FindKeypadVMod(keymap);
1187
1188         if (InitCanonicalKeyTypes(keymap, missing, keypadVMod) != Success) {
1189             log_wsgo(info.keymap->ctx,
1190                      "Couldn't initialize canonical key types\n");
1191             goto err_info;
1192         }
1193
1194         if (missing & XkbOneLevelMask)
1195             darray_item(keymap->types, XkbOneLevelIndex).name =
1196                 xkb_atom_strdup(keymap->ctx, info.tok_ONE_LEVEL);
1197         if (missing & XkbTwoLevelMask)
1198             darray_item(keymap->types, XkbTwoLevelIndex).name =
1199                 xkb_atom_strdup(keymap->ctx, info.tok_TWO_LEVEL);
1200         if (missing & XkbAlphabeticMask)
1201             darray_item(keymap->types, XkbAlphabeticIndex).name =
1202                 xkb_atom_strdup(keymap->ctx, info.tok_ALPHABETIC);
1203         if (missing & XkbKeypadMask)
1204             darray_item(keymap->types, XkbKeypadIndex).name =
1205                 xkb_atom_strdup(keymap->ctx, info.tok_KEYPAD);
1206     }
1207
1208     next = &darray_item(keymap->types, XkbLastRequiredType + 1);
1209     list_foreach(def, &info.types, entry) {
1210         if (def->name == info.tok_ONE_LEVEL)
1211             type = &darray_item(keymap->types, XkbOneLevelIndex);
1212         else if (def->name == info.tok_TWO_LEVEL)
1213             type = &darray_item(keymap->types, XkbTwoLevelIndex);
1214         else if (def->name == info.tok_ALPHABETIC)
1215             type = &darray_item(keymap->types, XkbAlphabeticIndex);
1216         else if (def->name == info.tok_KEYPAD)
1217             type = &darray_item(keymap->types, XkbKeypadIndex);
1218         else
1219             type = next++;
1220
1221         DeleteLevel1MapEntries(def);
1222
1223         if (!CopyDefToKeyType(&info, def, type))
1224             goto err_info;
1225     }
1226
1227     FreeKeyTypesInfo(&info);
1228     return true;
1229
1230 err_info:
1231     FreeKeyTypesInfo(&info);
1232     return false;
1233 }