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