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