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