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