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