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