keycodes: use list instead of CommonInfo in AliasInfo
[platform/upstream/libxkbcommon.git] / src / xkbcomp / keycodes.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 "keycodes.h"
28 #include "expr.h"
29 #include "parseutils.h"
30
31 const char *
32 longText(unsigned long val)
33 {
34     char buf[4];
35
36     LongToKeyName(val, buf);
37     return XkbcKeyNameText(buf);
38 }
39
40 /***====================================================================***/
41
42 void
43 LongToKeyName(unsigned long val, char *name)
44 {
45     name[0] = ((val >> 24) & 0xff);
46     name[1] = ((val >> 16) & 0xff);
47     name[2] = ((val >> 8) & 0xff);
48     name[3] = (val & 0xff);
49 }
50
51 /***====================================================================***/
52
53 typedef struct _AliasInfo {
54     enum merge_mode merge;
55     unsigned file_id;
56     struct list entry;
57
58     char alias[XkbKeyNameLength + 1];
59     char real[XkbKeyNameLength + 1];
60 } AliasInfo;
61
62 typedef struct _IndicatorNameInfo {
63     CommonInfo defs;
64     int ndx;
65     xkb_atom_t name;
66     bool virtual;
67 } IndicatorNameInfo;
68
69 typedef struct _KeyNamesInfo {
70     char *name;     /* e.g. evdev+aliases(qwerty) */
71     int errorCount;
72     unsigned file_id;
73     enum merge_mode merge;
74     xkb_keycode_t computedMin; /* lowest keycode stored */
75     xkb_keycode_t computedMax; /* highest keycode stored */
76     xkb_keycode_t explicitMin;
77     xkb_keycode_t explicitMax;
78     darray(unsigned long) names;
79     darray(unsigned int) files;
80     IndicatorNameInfo *leds;
81     struct list aliases;
82 } KeyNamesInfo;
83
84 static void
85 HandleKeycodesFile(XkbFile *file, struct xkb_keymap *keymap,
86                    enum merge_mode merge,
87                    KeyNamesInfo *info);
88
89 static void
90 ResizeKeyNameArrays(KeyNamesInfo *info, int newMax)
91 {
92     if (newMax < darray_size(info->names))
93         return;
94
95     darray_resize0(info->names, newMax + 1);
96     darray_resize0(info->files, newMax + 1);
97 }
98
99 static void
100 InitAliasInfo(AliasInfo *info, enum merge_mode merge, unsigned file_id,
101               char *alias, char *real)
102 {
103     memset(info, 0, sizeof(*info));
104     info->merge = merge;
105     info->file_id = file_id;
106     strncpy(info->alias, alias, XkbKeyNameLength);
107     strncpy(info->real, real, XkbKeyNameLength);
108 }
109
110 static void
111 InitIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
112 {
113     ii->defs.defined = 0;
114     ii->defs.merge = info->merge;
115     ii->defs.file_id = info->file_id;
116     ii->defs.next = NULL;
117     ii->ndx = 0;
118     ii->name = XKB_ATOM_NONE;
119     ii->virtual = false;
120 }
121
122 static void
123 ClearIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
124 {
125     if (ii == info->leds) {
126         ClearCommonInfo(&ii->defs);
127         info->leds = NULL;
128     }
129 }
130
131 static IndicatorNameInfo *
132 NextIndicatorName(KeyNamesInfo * info)
133 {
134     IndicatorNameInfo *ii;
135
136     ii = uTypedAlloc(IndicatorNameInfo);
137     if (ii) {
138         InitIndicatorNameInfo(ii, info);
139         info->leds = AddCommonInfo(&info->leds->defs, &ii->defs);
140     }
141     return ii;
142 }
143
144 static IndicatorNameInfo *
145 FindIndicatorByIndex(KeyNamesInfo * info, int ndx)
146 {
147     IndicatorNameInfo *old;
148
149     for (old = info->leds; old != NULL;
150          old = (IndicatorNameInfo *) old->defs.next) {
151         if (old->ndx == ndx)
152             return old;
153     }
154     return NULL;
155 }
156
157 static IndicatorNameInfo *
158 FindIndicatorByName(KeyNamesInfo * info, xkb_atom_t name)
159 {
160     IndicatorNameInfo *old;
161
162     for (old = info->leds; old != NULL;
163          old = (IndicatorNameInfo *) old->defs.next) {
164         if (old->name == name)
165             return old;
166     }
167     return NULL;
168 }
169
170 static bool
171 AddIndicatorName(KeyNamesInfo *info, struct xkb_keymap *keymap,
172                  enum merge_mode merge,
173                  IndicatorNameInfo *new)
174 {
175     IndicatorNameInfo *old;
176     bool replace;
177
178     replace = (merge == MERGE_REPLACE) || (merge == MERGE_OVERRIDE);
179     old = FindIndicatorByName(info, new->name);
180     if (old) {
181         if (((old->defs.file_id == new->defs.file_id) && (warningLevel > 0))
182             || (warningLevel > 9)) {
183             WARN("Multiple indicators named %s\n",
184                  xkb_atom_text(keymap->ctx, new->name));
185             if (old->ndx == new->ndx) {
186                 if (old->virtual != new->virtual) {
187                     if (replace)
188                         old->virtual = new->virtual;
189                     ACTION("Using %s instead of %s\n",
190                            (old->virtual ? "virtual" : "real"),
191                            (old->virtual ? "real" : "virtual"));
192                 }
193                 else {
194                     ACTION("Identical definitions ignored\n");
195                 }
196                 return true;
197             }
198             else {
199                 if (replace)
200                     ACTION("Ignoring %d, using %d\n", old->ndx, new->ndx);
201                 else
202                     ACTION("Using %d, ignoring %d\n", old->ndx, new->ndx);
203             }
204             if (replace) {
205                 if (info->leds == old)
206                     info->leds = (IndicatorNameInfo *) old->defs.next;
207                 else {
208                     IndicatorNameInfo *tmp;
209                     tmp = info->leds;
210                     for (; tmp != NULL;
211                          tmp = (IndicatorNameInfo *) tmp->defs.next) {
212                         if (tmp->defs.next == (CommonInfo *) old) {
213                             tmp->defs.next = old->defs.next;
214                             break;
215                         }
216                     }
217                 }
218                 free(old);
219             }
220         }
221     }
222     old = FindIndicatorByIndex(info, new->ndx);
223     if (old) {
224         if (((old->defs.file_id == new->defs.file_id) && (warningLevel > 0))
225             || (warningLevel > 9)) {
226             WARN("Multiple names for indicator %d\n", new->ndx);
227             if ((old->name == new->name) && (old->virtual == new->virtual))
228                 ACTION("Identical definitions ignored\n");
229             else {
230                 const char *oldType, *newType;
231                 xkb_atom_t using, ignoring;
232                 if (old->virtual)
233                     oldType = "virtual indicator";
234                 else
235                     oldType = "real indicator";
236                 if (new->virtual)
237                     newType = "virtual indicator";
238                 else
239                     newType = "real indicator";
240                 if (replace) {
241                     using = new->name;
242                     ignoring = old->name;
243                 }
244                 else {
245                     using = old->name;
246                     ignoring = new->name;
247                 }
248                 ACTION("Using %s %s, ignoring %s %s\n",
249                        oldType, xkb_atom_text(keymap->ctx, using),
250                        newType, xkb_atom_text(keymap->ctx, ignoring));
251             }
252         }
253         if (replace) {
254             old->name = new->name;
255             old->virtual = new->virtual;
256         }
257         return true;
258     }
259     old = new;
260     new = NextIndicatorName(info);
261     if (!new) {
262         WSGO("Couldn't allocate name for indicator %d\n", old->ndx);
263         ACTION("Ignored\n");
264         return false;
265     }
266     new->name = old->name;
267     new->ndx = old->ndx;
268     new->virtual = old->virtual;
269     return true;
270 }
271
272 static void
273 ClearKeyNamesInfo(KeyNamesInfo * info)
274 {
275     AliasInfo *alias, *next_alias;
276
277     free(info->name);
278     info->name = NULL;
279     info->computedMax = info->explicitMax = info->explicitMin = 0;
280     info->computedMin = XKB_KEYCODE_MAX;
281     darray_free(info->names);
282     darray_free(info->files);
283     if (info->leds)
284         ClearIndicatorNameInfo(info->leds, info);
285     list_foreach_safe(alias, next_alias, &info->aliases, entry)
286         free(alias);
287 }
288
289 static void
290 InitKeyNamesInfo(KeyNamesInfo * info, unsigned file_id)
291 {
292     info->name = NULL;
293     info->leds = NULL;
294     list_init(&info->aliases);
295     info->file_id = file_id;
296     darray_init(info->names);
297     darray_init(info->files);
298     ClearKeyNamesInfo(info);
299     info->errorCount = 0;
300 }
301
302 static int
303 FindKeyByLong(KeyNamesInfo * info, unsigned long name)
304 {
305     uint64_t i;
306
307     for (i = info->computedMin; i <= info->computedMax; i++)
308         if (darray_item(info->names, i) == name)
309             return i;
310
311     return 0;
312 }
313
314 /**
315  * Store the name of the key as a long in the info struct under the given
316  * keycode. If the same keys is referred to twice, print a warning.
317  * Note that the key's name is stored as a long, the keycode is the index.
318  */
319 static bool
320 AddKeyName(KeyNamesInfo * info,
321            xkb_keycode_t kc, char *name, enum merge_mode merge,
322            unsigned file_id, bool reportCollisions)
323 {
324     xkb_keycode_t old;
325     unsigned long lval;
326
327     ResizeKeyNameArrays(info, kc);
328
329     if (kc < info->computedMin)
330         info->computedMin = kc;
331     if (kc > info->computedMax)
332         info->computedMax = kc;
333     lval = KeyNameToLong(name);
334
335     if (reportCollisions) {
336         reportCollisions = (warningLevel > 7 ||
337                             (warningLevel > 0 &&
338                              file_id == darray_item(info->files, kc)));
339     }
340
341     if (darray_item(info->names, kc) != 0) {
342         char buf[6];
343
344         LongToKeyName(darray_item(info->names, kc), buf);
345         buf[4] = '\0';
346         if (darray_item(info->names, kc) == lval && reportCollisions) {
347             WARN("Multiple identical key name definitions\n");
348             ACTION("Later occurences of \"<%s> = %d\" ignored\n",
349                    buf, kc);
350             return true;
351         }
352         if (merge == MERGE_AUGMENT) {
353             if (reportCollisions) {
354                 WARN("Multiple names for keycode %d\n", kc);
355                 ACTION("Using <%s>, ignoring <%s>\n", buf, name);
356             }
357             return true;
358         }
359         else {
360             if (reportCollisions) {
361                 WARN("Multiple names for keycode %d\n", kc);
362                 ACTION("Using <%s>, ignoring <%s>\n", name, buf);
363             }
364             darray_item(info->names, kc) = 0;
365             darray_item(info->files, kc) = 0;
366         }
367     }
368     old = FindKeyByLong(info, lval);
369     if ((old != 0) && (old != kc)) {
370         if (merge == MERGE_OVERRIDE) {
371             darray_item(info->names, old) = 0;
372             darray_item(info->files, old) = 0;
373             if (reportCollisions) {
374                 WARN("Key name <%s> assigned to multiple keys\n", name);
375                 ACTION("Using %d, ignoring %d\n", kc, old);
376             }
377         }
378         else {
379             if ((reportCollisions) && (warningLevel > 3)) {
380                 WARN("Key name <%s> assigned to multiple keys\n", name);
381                 ACTION("Using %d, ignoring %d\n", old, kc);
382             }
383             return true;
384         }
385     }
386     darray_item(info->names, kc) = lval;
387     darray_item(info->files, kc) = file_id;
388     return true;
389 }
390
391 /***====================================================================***/
392
393 static int
394 HandleAliasDef(KeyAliasDef *def, enum merge_mode merge, unsigned file_id,
395                KeyNamesInfo *info);
396
397 static bool
398 MergeAliases(KeyNamesInfo *into, KeyNamesInfo *from, enum merge_mode merge)
399 {
400     AliasInfo *alias, *next;
401     KeyAliasDef def;
402
403     if (list_empty(&from->aliases))
404         return true;
405
406     if (list_empty(&into->aliases)) {
407         list_replace(&from->aliases, &into->aliases);
408         list_init(&from->aliases);
409         return true;
410     }
411
412     memset(&def, 0, sizeof(def));
413
414     list_foreach_safe(alias, next, &from->aliases, entry) {
415         def.merge = (merge == MERGE_DEFAULT) ? alias->merge : merge;
416         memcpy(def.alias, alias->alias, XkbKeyNameLength);
417         memcpy(def.real, alias->real, XkbKeyNameLength);
418
419         if (!HandleAliasDef(&def, def.merge, alias->file_id, into))
420             return false;
421     }
422
423     return true;
424 }
425
426 static void
427 MergeIncludedKeycodes(KeyNamesInfo *into, struct xkb_keymap *keymap,
428                       KeyNamesInfo *from, enum merge_mode merge)
429 {
430     uint64_t i;
431     char buf[5];
432
433     if (from->errorCount > 0) {
434         into->errorCount += from->errorCount;
435         return;
436     }
437     if (into->name == NULL) {
438         into->name = from->name;
439         from->name = NULL;
440     }
441
442     ResizeKeyNameArrays(into, from->computedMax);
443
444     for (i = from->computedMin; i <= from->computedMax; i++) {
445         if (darray_item(from->names, i) == 0)
446             continue;
447         LongToKeyName(darray_item(from->names, i), buf);
448         buf[4] = '\0';
449         if (!AddKeyName(into, i, buf, merge, from->file_id, false))
450             into->errorCount++;
451     }
452     if (from->leds) {
453         IndicatorNameInfo *led, *next;
454         for (led = from->leds; led != NULL; led = next) {
455             if (merge != MERGE_DEFAULT)
456                 led->defs.merge = merge;
457             if (!AddIndicatorName(into, keymap, led->defs.merge, led))
458                 into->errorCount++;
459             next = (IndicatorNameInfo *) led->defs.next;
460         }
461     }
462
463     if (!MergeAliases(into, from, merge))
464         into->errorCount++;
465     if (from->explicitMin != 0) {
466         if ((into->explicitMin == 0)
467             || (into->explicitMin > from->explicitMin))
468             into->explicitMin = from->explicitMin;
469     }
470     if (from->explicitMax > 0) {
471         if ((into->explicitMax == 0)
472             || (into->explicitMax < from->explicitMax))
473             into->explicitMax = from->explicitMax;
474     }
475 }
476
477 /**
478  * Handle the given include statement (e.g. "include "evdev+aliases(qwerty)").
479  *
480  * @param stmt The include statement from the keymap file.
481  * @param keymap Unused for all but the keymap->flags.
482  * @param info Struct to store the key info in.
483  */
484 static bool
485 HandleIncludeKeycodes(IncludeStmt *stmt, struct xkb_keymap *keymap,
486                       KeyNamesInfo *info)
487 {
488     enum merge_mode newMerge;
489     XkbFile *rtrn;
490     KeyNamesInfo included;
491     bool haveSelf;
492
493     memset(&included, 0, sizeof(included));
494
495     haveSelf = false;
496     if ((stmt->file == NULL) && (stmt->map == NULL)) {
497         haveSelf = true;
498         included = *info;
499         memset(info, 0, sizeof(KeyNamesInfo));
500     }
501     else if (stmt->file && strcmp(stmt->file, "computed") == 0) {
502         keymap->flags |= AutoKeyNames;
503         info->explicitMin = 0;
504         info->explicitMax = XKB_KEYCODE_MAX;
505         return (info->errorCount == 0);
506     } /* parse file, store returned info in the xkb struct */
507     else if (ProcessIncludeFile(keymap->ctx, stmt, FILE_TYPE_KEYCODES, &rtrn,
508                                 &newMerge)) {
509         InitKeyNamesInfo(&included, rtrn->id);
510         HandleKeycodesFile(rtrn, keymap, MERGE_OVERRIDE, &included);
511         if (stmt->stmt != NULL) {
512             free(included.name);
513             included.name = stmt->stmt;
514             stmt->stmt = NULL;
515         }
516         FreeXKBFile(rtrn);
517     }
518     else {
519         info->errorCount += 10; /* XXX: why 10?? */
520         return false;
521     }
522     /* Do we have more than one include statement? */
523     if ((stmt->next != NULL) && (included.errorCount < 1)) {
524         IncludeStmt *next;
525         unsigned op;
526         KeyNamesInfo next_incl;
527
528         for (next = stmt->next; next != NULL; next = next->next) {
529             if ((next->file == NULL) && (next->map == NULL)) {
530                 haveSelf = true;
531                 MergeIncludedKeycodes(&included, keymap, info, next->merge);
532                 ClearKeyNamesInfo(info);
533             }
534             else if (ProcessIncludeFile(keymap->ctx, next, FILE_TYPE_KEYCODES,
535                                         &rtrn, &op)) {
536                 InitKeyNamesInfo(&next_incl, rtrn->id);
537                 HandleKeycodesFile(rtrn, keymap, MERGE_OVERRIDE, &next_incl);
538                 MergeIncludedKeycodes(&included, keymap, &next_incl, op);
539                 ClearKeyNamesInfo(&next_incl);
540                 FreeXKBFile(rtrn);
541             }
542             else {
543                 info->errorCount += 10; /* XXX: Why 10?? */
544                 ClearKeyNamesInfo(&included);
545                 return false;
546             }
547         }
548     }
549     if (haveSelf)
550         *info = included;
551     else {
552         MergeIncludedKeycodes(info, keymap, &included, newMerge);
553         ClearKeyNamesInfo(&included);
554     }
555     return (info->errorCount == 0);
556 }
557
558 /**
559  * Parse the given statement and store the output in the info struct.
560  * e.g. <ESC> = 9
561  */
562 static int
563 HandleKeycodeDef(KeycodeDef *stmt, enum merge_mode merge, KeyNamesInfo *info)
564 {
565     if ((info->explicitMin != 0 && stmt->value < info->explicitMin) ||
566         (info->explicitMax != 0 && stmt->value > info->explicitMax)) {
567         ERROR("Illegal keycode %lu for name <%s>\n", stmt->value, stmt->name);
568         ACTION("Must be in the range %d-%d inclusive\n",
569                info->explicitMin,
570                info->explicitMax ? info->explicitMax : XKB_KEYCODE_MAX);
571         return 0;
572     }
573     if (stmt->merge != MERGE_DEFAULT) {
574         if (stmt->merge == MERGE_REPLACE)
575             merge = MERGE_OVERRIDE;
576         else
577             merge = stmt->merge;
578     }
579     return AddKeyName(info, stmt->value, stmt->name, merge, info->file_id,
580                       true);
581 }
582
583 static void
584 HandleAliasCollision(AliasInfo *old, AliasInfo *new)
585 {
586     if (strncmp(new->real, old->real, XkbKeyNameLength) == 0) {
587         if ((new->file_id == old->file_id && warningLevel > 0) ||
588             warningLevel > 9) {
589             WARN("Alias of %s for %s declared more than once\n",
590                   XkbcKeyNameText(new->alias), XkbcKeyNameText(new->real));
591             ACTION("First definition ignored\n");
592         }
593     }
594     else {
595         char *use, *ignore;
596
597         if (new->merge == MERGE_AUGMENT) {
598             use = old->real;
599             ignore = new->real;
600         }
601         else {
602             use = new->real;
603             ignore = old->real;
604         }
605
606         if ((old->file_id == new->file_id && warningLevel > 0) ||
607             warningLevel > 9) {
608             WARN("Multiple definitions for alias %s\n",
609                  XkbcKeyNameText(old->alias));
610             ACTION("Using %s, ignoring %s\n",
611                    XkbcKeyNameText(use), XkbcKeyNameText(ignore));
612         }
613
614         if (use != old->real)
615             memcpy(old->real, use, XkbKeyNameLength);
616     }
617
618     old->file_id = new->file_id;
619     old->merge = new->merge;
620 }
621
622 static int
623 HandleAliasDef(KeyAliasDef *def, enum merge_mode merge, unsigned file_id,
624                KeyNamesInfo *info)
625 {
626     AliasInfo *alias;
627
628     list_foreach(alias, &info->aliases, entry) {
629         if (strncmp(alias->alias, def->alias, XkbKeyNameLength) == 0) {
630             AliasInfo new;
631             InitAliasInfo(&new, merge, file_id, def->alias, def->real);
632             HandleAliasCollision(alias, &new);
633             return true;
634         }
635     }
636
637     alias = calloc(1, sizeof(*alias));
638     if (!alias) {
639         WSGO("Allocation failure in HandleAliasDef\n");
640         return false;
641     }
642
643     alias->file_id = file_id;
644     alias->merge = merge;
645     memcpy(alias->alias, def->alias, XkbKeyNameLength);
646     memcpy(alias->real, def->real, XkbKeyNameLength);
647     list_append(&alias->entry, &info->aliases);
648
649     return true;
650 }
651
652 #define MIN_KEYCODE_DEF 0
653 #define MAX_KEYCODE_DEF 1
654
655 /**
656  * Handle the minimum/maximum statement of the xkb file.
657  * Sets explicitMin/Max of the info struct.
658  *
659  * @return 1 on success, 0 otherwise.
660  */
661 static int
662 HandleKeyNameVar(VarDef *stmt, struct xkb_keymap *keymap, KeyNamesInfo *info)
663 {
664     ExprResult tmp, field;
665     ExprDef *arrayNdx;
666     int which;
667
668     if (ExprResolveLhs(keymap, stmt->name, &tmp, &field, &arrayNdx) == 0)
669         return 0;               /* internal error, already reported */
670
671     if (tmp.str != NULL) {
672         ERROR("Unknown element %s encountered\n", tmp.str);
673         ACTION("Default for field %s ignored\n", field.str);
674         goto err_out;
675     }
676     if (strcasecmp(field.str, "minimum") == 0)
677         which = MIN_KEYCODE_DEF;
678     else if (strcasecmp(field.str, "maximum") == 0)
679         which = MAX_KEYCODE_DEF;
680     else {
681         ERROR("Unknown field encountered\n");
682         ACTION("Assigment to field %s ignored\n", field.str);
683         goto err_out;
684     }
685     if (arrayNdx != NULL) {
686         ERROR("The %s setting is not an array\n", field.str);
687         ACTION("Illegal array reference ignored\n");
688         goto err_out;
689     }
690
691     if (ExprResolveKeyCode(keymap->ctx, stmt->value, &tmp) == 0) {
692         ACTION("Assignment to field %s ignored\n", field.str);
693         goto err_out;
694     }
695     if (tmp.uval > XKB_KEYCODE_MAX) {
696         ERROR
697             ("Illegal keycode %d (must be in the range %d-%d inclusive)\n",
698             tmp.uval, 0, XKB_KEYCODE_MAX);
699         ACTION("Value of \"%s\" not changed\n", field.str);
700         goto err_out;
701     }
702     if (which == MIN_KEYCODE_DEF) {
703         if ((info->explicitMax > 0) && (info->explicitMax < tmp.uval)) {
704             ERROR
705                 ("Minimum key code (%d) must be <= maximum key code (%d)\n",
706                 tmp.uval, info->explicitMax);
707             ACTION("Minimum key code value not changed\n");
708             goto err_out;
709         }
710         if ((info->computedMax > 0) && (info->computedMin < tmp.uval)) {
711             ERROR
712                 ("Minimum key code (%d) must be <= lowest defined key (%d)\n",
713                 tmp.uval, info->computedMin);
714             ACTION("Minimum key code value not changed\n");
715             goto err_out;
716         }
717         info->explicitMin = tmp.uval;
718     }
719     if (which == MAX_KEYCODE_DEF) {
720         if ((info->explicitMin > 0) && (info->explicitMin > tmp.uval)) {
721             ERROR("Maximum code (%d) must be >= minimum key code (%d)\n",
722                   tmp.uval, info->explicitMin);
723             ACTION("Maximum code value not changed\n");
724             goto err_out;
725         }
726         if ((info->computedMax > 0) && (info->computedMax > tmp.uval)) {
727             ERROR
728                 ("Maximum code (%d) must be >= highest defined key (%d)\n",
729                 tmp.uval, info->computedMax);
730             ACTION("Maximum code value not changed\n");
731             goto err_out;
732         }
733         info->explicitMax = tmp.uval;
734     }
735
736     free(field.str);
737     return 1;
738
739 err_out:
740     free(field.str);
741     return 0;
742 }
743
744 static int
745 HandleIndicatorNameDef(IndicatorNameDef *def, struct xkb_keymap *keymap,
746                        enum merge_mode merge, KeyNamesInfo *info)
747 {
748     IndicatorNameInfo ii;
749     ExprResult tmp;
750
751     if ((def->ndx < 1) || (def->ndx > XkbNumIndicators)) {
752         info->errorCount++;
753         ERROR("Name specified for illegal indicator index %d\n", def->ndx);
754         ACTION("Ignored\n");
755         return false;
756     }
757     InitIndicatorNameInfo(&ii, info);
758     ii.ndx = def->ndx;
759     if (!ExprResolveString(keymap->ctx, def->name, &tmp)) {
760         char buf[20];
761         snprintf(buf, sizeof(buf), "%d", def->ndx);
762         info->errorCount++;
763         return ReportBadType("indicator", "name", buf, "string");
764     }
765     ii.name = xkb_atom_intern(keymap->ctx, tmp.str);
766     free(tmp.str);
767     ii.virtual = def->virtual;
768     if (!AddIndicatorName(info, keymap, merge, &ii))
769         return false;
770     return true;
771 }
772
773 /**
774  * Handle the xkb_keycodes section of a xkb file.
775  * All information about parsed keys is stored in the info struct.
776  *
777  * Such a section may have include statements, in which case this function is
778  * semi-recursive (it calls HandleIncludeKeycodes, which may call
779  * HandleKeycodesFile again).
780  *
781  * @param file The input file (parsed xkb_keycodes section)
782  * @param xkb Necessary to pass down, may have flags changed.
783  * @param merge Merge strategy (MERGE_OVERRIDE, etc.)
784  * @param info Struct to contain the fully parsed key information.
785  */
786 static void
787 HandleKeycodesFile(XkbFile *file, struct xkb_keymap *keymap,
788                    enum merge_mode merge, KeyNamesInfo *info)
789 {
790     ParseCommon *stmt;
791
792     free(info->name);
793     info->name = uDupString(file->name);
794     stmt = file->defs;
795     while (stmt)
796     {
797         switch (stmt->stmtType) {
798         case StmtInclude:    /* e.g. include "evdev+aliases(qwerty)" */
799             if (!HandleIncludeKeycodes((IncludeStmt *) stmt, keymap, info))
800                 info->errorCount++;
801             break;
802         case StmtKeycodeDef: /* e.g. <ESC> = 9; */
803             if (!HandleKeycodeDef((KeycodeDef *) stmt, merge, info))
804                 info->errorCount++;
805             break;
806         case StmtKeyAliasDef: /* e.g. alias <MENU> = <COMP>; */
807             if (!HandleAliasDef((KeyAliasDef *) stmt, merge, info->file_id,
808                                 info))
809                 info->errorCount++;
810             break;
811         case StmtVarDef: /* e.g. minimum, maximum */
812             if (!HandleKeyNameVar((VarDef *) stmt, keymap, info))
813                 info->errorCount++;
814             break;
815         case StmtIndicatorNameDef: /* e.g. indicator 1 = "Caps Lock"; */
816             if (!HandleIndicatorNameDef((IndicatorNameDef *) stmt, keymap,
817                                         merge, info))
818                 info->errorCount++;
819             break;
820         case StmtInterpDef:
821         case StmtVModDef:
822             ERROR("Keycode files may define key and indicator names only\n");
823             ACTION("Ignoring definition of %s\n",
824                    ((stmt->stmtType ==
825                      StmtInterpDef) ? "a symbol interpretation" :
826                     "virtual modifiers"));
827             info->errorCount++;
828             break;
829         default:
830             WSGO("Unexpected statement type %d in HandleKeycodesFile\n",
831                  stmt->stmtType);
832             break;
833         }
834         stmt = stmt->next;
835         if (info->errorCount > 10) {
836 #ifdef NOISY
837             ERROR("Too many errors\n");
838 #endif
839             ACTION("Abandoning keycodes file \"%s\"\n", file->topName);
840             break;
841         }
842     }
843 }
844
845 static int
846 ApplyAliases(struct xkb_keymap *keymap, KeyNamesInfo *info)
847 {
848     int i;
849     struct xkb_key *key;
850     struct xkb_key_alias *old, *a;
851     AliasInfo *alias, *next;
852     int nNew = 0, nOld;
853
854     nOld = darray_size(keymap->key_aliases);
855     old = &darray_item(keymap->key_aliases, 0);
856
857     list_foreach(alias, &info->aliases, entry) {
858         unsigned long lname;
859
860         lname = KeyNameToLong(alias->real);
861         key = FindNamedKey(keymap, lname, false, CreateKeyNames(keymap), 0);
862         if (!key) {
863             if (warningLevel > 4) {
864                 WARN("Attempt to alias %s to non-existent key %s\n",
865                      XkbcKeyNameText(alias->alias),
866                      XkbcKeyNameText(alias->real));
867                 ACTION("Ignored\n");
868             }
869             alias->alias[0] = '\0';
870             continue;
871         }
872
873         lname = KeyNameToLong(alias->alias);
874         key = FindNamedKey(keymap, lname, false, false, 0);
875         if (key) {
876             if (warningLevel > 4) {
877                 WARN("Attempt to create alias with the name of a real key\n");
878                 ACTION("Alias \"%s = %s\" ignored\n",
879                        XkbcKeyNameText(alias->alias),
880                        XkbcKeyNameText(alias->real));
881             }
882             alias->alias[0] = '\0';
883             continue;
884         }
885
886         nNew++;
887
888         if (!old)
889             continue;
890
891         for (i = 0, a = old; i < nOld; i++, a++) {
892             AliasInfo old_alias;
893
894             if (strncmp(a->alias, alias->alias, XkbKeyNameLength) != 0)
895                 continue;
896
897             InitAliasInfo(&old_alias, MERGE_AUGMENT, 0, a->alias, a->real);
898             HandleAliasCollision(&old_alias, alias);
899             memcpy(old_alias.real, a->real, XkbKeyNameLength);
900             alias->alias[0] = '\0';
901             nNew--;
902             break;
903         }
904     }
905
906     if (nNew == 0)
907         goto out;
908
909     darray_resize0(keymap->key_aliases, nOld + nNew);
910
911     a = &darray_item(keymap->key_aliases, nOld);
912     list_foreach(alias, &info->aliases, entry) {
913         if (alias->alias[0] != '\0') {
914             strncpy(a->alias, alias->alias, XkbKeyNameLength);
915             strncpy(a->real, alias->real, XkbKeyNameLength);
916             a++;
917         }
918     }
919
920 out:
921     list_foreach_safe(alias, next, &info->aliases, entry)
922         free(alias);
923     list_init(&info->aliases);
924     return true;
925 }
926
927 /**
928  * Compile the xkb_keycodes section, parse it's output, return the results.
929  *
930  * @param file The parsed XKB file (may have include statements requiring
931  * further parsing)
932  * @param result The effective keycodes, as gathered from the file.
933  * @param merge Merge strategy.
934  *
935  * @return true on success, false otherwise.
936  */
937 bool
938 CompileKeycodes(XkbFile *file, struct xkb_keymap *keymap,
939                 enum merge_mode merge)
940 {
941     xkb_keycode_t kc;
942     KeyNamesInfo info; /* contains all the info after parsing */
943
944     InitKeyNamesInfo(&info, file->id);
945
946     HandleKeycodesFile(file, keymap, merge, &info);
947
948     /* all the keys are now stored in info */
949
950     if (info.errorCount != 0)
951         goto err_info;
952
953     if (info.explicitMin > 0) /* if "minimum" statement was present */
954         keymap->min_key_code = info.explicitMin;
955     else
956         keymap->min_key_code = info.computedMin;
957
958     if (info.explicitMax > 0) /* if "maximum" statement was present */
959         keymap->max_key_code = info.explicitMax;
960     else
961         keymap->max_key_code = info.computedMax;
962
963     darray_resize0(keymap->keys, keymap->max_key_code + 1);
964     for (kc = info.computedMin; kc <= info.computedMax; kc++)
965         LongToKeyName(darray_item(info.names, kc),
966                       XkbKey(keymap, kc)->name);
967
968     if (info.name)
969         keymap->keycodes_section_name = strdup(info.name);
970
971     if (info.leds) {
972         IndicatorNameInfo *ii;
973
974         for (ii = info.leds; ii; ii = (IndicatorNameInfo *) ii->defs.next) {
975             free(keymap->indicator_names[ii->ndx - 1]);
976             keymap->indicator_names[ii->ndx - 1] =
977                 xkb_atom_strdup(keymap->ctx, ii->name);
978         }
979     }
980
981     ApplyAliases(keymap, &info);
982
983     ClearKeyNamesInfo(&info);
984     return true;
985
986 err_info:
987     ClearKeyNamesInfo(&info);
988     return false;
989 }