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