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