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