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