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