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