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