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