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