1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
29 #include "parseutils.h"
33 longText(unsigned long val)
37 LongToKeyName(val, buf);
38 return XkbcKeyNameText(buf);
41 /***====================================================================***/
44 LongToKeyName(unsigned long val, char *name)
46 name[0] = ((val >> 24) & 0xff);
47 name[1] = ((val >> 16) & 0xff);
48 name[2] = ((val >> 8) & 0xff);
49 name[3] = (val & 0xff);
52 /***====================================================================***/
54 typedef struct _IndicatorNameInfo
62 typedef struct _KeyNamesInfo
64 char *name; /* e.g. evdev+aliases(qwerty) */
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;
79 static void HandleKeycodesFile(XkbFile *file, struct xkb_keymap *keymap,
80 unsigned merge, KeyNamesInfo *info);
83 ResizeKeyNameArrays(KeyNamesInfo *info, int newMax)
85 if (newMax < darray_size(info->names))
88 darray_resize0(info->names, newMax + 1);
89 darray_resize0(info->files, newMax + 1);
90 darray_resize0(info->has_alt_forms, newMax + 1);
94 InitIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
97 ii->defs.merge = info->merge;
98 ii->defs.fileID = info->fileID;
101 ii->name = XKB_ATOM_NONE;
106 ClearIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
108 if (ii == info->leds)
110 ClearCommonInfo(&ii->defs);
115 static IndicatorNameInfo *
116 NextIndicatorName(KeyNamesInfo * info)
118 IndicatorNameInfo *ii;
120 ii = uTypedAlloc(IndicatorNameInfo);
123 InitIndicatorNameInfo(ii, info);
124 info->leds = (IndicatorNameInfo *) AddCommonInfo(&info->leds->defs,
130 static IndicatorNameInfo *
131 FindIndicatorByIndex(KeyNamesInfo * info, int ndx)
133 IndicatorNameInfo *old;
135 for (old = info->leds; old != NULL;
136 old = (IndicatorNameInfo *) old->defs.next)
144 static IndicatorNameInfo *
145 FindIndicatorByName(KeyNamesInfo * info, xkb_atom_t name)
147 IndicatorNameInfo *old;
149 for (old = info->leds; old != NULL;
150 old = (IndicatorNameInfo *) old->defs.next)
152 if (old->name == name)
159 AddIndicatorName(KeyNamesInfo *info, struct xkb_keymap *keymap,
160 IndicatorNameInfo *new)
162 IndicatorNameInfo *old;
165 replace = (new->defs.merge == MergeReplace) ||
166 (new->defs.merge == MergeOverride);
167 old = FindIndicatorByName(info, new->name);
170 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
171 || (warningLevel > 9))
173 WARN("Multiple indicators named %s\n",
174 xkb_atom_text(keymap->ctx, new->name));
175 if (old->ndx == new->ndx)
177 if (old->virtual != new->virtual)
180 old->virtual = new->virtual;
181 ACTION("Using %s instead of %s\n",
182 (old->virtual ? "virtual" : "real"),
183 (old->virtual ? "real" : "virtual"));
187 ACTION("Identical definitions ignored\n");
194 ACTION("Ignoring %d, using %d\n", old->ndx, new->ndx);
196 ACTION("Using %d, ignoring %d\n", old->ndx, new->ndx);
200 if (info->leds == old)
201 info->leds = (IndicatorNameInfo *) old->defs.next;
204 IndicatorNameInfo *tmp;
207 tmp = (IndicatorNameInfo *) tmp->defs.next)
209 if (tmp->defs.next == (CommonInfo *) old)
211 tmp->defs.next = old->defs.next;
220 old = FindIndicatorByIndex(info, new->ndx);
223 if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
224 || (warningLevel > 9))
226 WARN("Multiple names for indicator %d\n", new->ndx);
227 if ((old->name == new->name) && (old->virtual == new->virtual))
228 ACTION("Identical definitions ignored\n");
231 const char *oldType, *newType;
232 xkb_atom_t using, ignoring;
234 oldType = "virtual indicator";
236 oldType = "real indicator";
238 newType = "virtual indicator";
240 newType = "real indicator";
244 ignoring = old->name;
249 ignoring = new->name;
251 ACTION("Using %s %s, ignoring %s %s\n",
252 oldType, xkb_atom_text(keymap->ctx, using),
253 newType, xkb_atom_text(keymap->ctx, ignoring));
258 old->name = new->name;
259 old->virtual = new->virtual;
264 new = NextIndicatorName(info);
267 WSGO("Couldn't allocate name for indicator %d\n", old->ndx);
271 new->name = old->name;
273 new->virtual = old->virtual;
278 ClearKeyNamesInfo(KeyNamesInfo * info)
282 info->computedMax = info->explicitMax = info->explicitMin = 0;
283 info->computedMin = XKB_KEYCODE_MAX;
284 darray_free(info->names);
285 darray_init(info->names);
286 darray_free(info->files);
287 darray_init(info->files);
288 darray_free(info->has_alt_forms);
289 darray_init(info->has_alt_forms);
291 ClearIndicatorNameInfo(info->leds, info);
293 ClearAliases(&info->aliases);
297 InitKeyNamesInfo(KeyNamesInfo * info)
301 info->aliases = NULL;
302 darray_init(info->names);
303 darray_init(info->files);
304 darray_init(info->has_alt_forms);
305 ClearKeyNamesInfo(info);
306 info->errorCount = 0;
310 FindKeyByLong(KeyNamesInfo * info, unsigned long name)
314 for (i = info->computedMin; i <= info->computedMax; i++)
315 if (darray_item(info->names, i) == name)
322 * Store the name of the key as a long in the info struct under the given
323 * keycode. If the same keys is referred to twice, print a warning.
324 * Note that the key's name is stored as a long, the keycode is the index.
327 AddKeyName(KeyNamesInfo * info,
329 char *name, unsigned merge, unsigned fileID, bool reportCollisions)
334 ResizeKeyNameArrays(info, kc);
336 if (kc < info->computedMin)
337 info->computedMin = kc;
338 if (kc > info->computedMax)
339 info->computedMax = kc;
340 lval = KeyNameToLong(name);
342 if (reportCollisions)
344 reportCollisions = (warningLevel > 7 ||
346 fileID == darray_item(info->files, kc)));
349 if (darray_item(info->names, kc) != 0)
353 LongToKeyName(darray_item(info->names, kc), buf);
355 if (darray_item(info->names, kc) == lval)
357 if (darray_item(info->has_alt_forms, kc) || (merge == MergeAltForm)) {
358 darray_item(info->has_alt_forms, kc) = true;
360 else if (reportCollisions) {
361 WARN("Multiple identical key name definitions\n");
362 ACTION("Later occurences of \"<%s> = %d\" ignored\n",
367 if (merge == MergeAugment)
369 if (reportCollisions)
371 WARN("Multiple names for keycode %d\n", kc);
372 ACTION("Using <%s>, ignoring <%s>\n", buf, name);
378 if (reportCollisions)
380 WARN("Multiple names for keycode %d\n", kc);
381 ACTION("Using <%s>, ignoring <%s>\n", name, buf);
383 darray_item(info->names, kc) = 0;
384 darray_item(info->files, kc) = 0;
387 old = FindKeyByLong(info, lval);
388 if ((old != 0) && (old != kc))
390 if (merge == MergeOverride)
392 darray_item(info->names, old) = 0;
393 darray_item(info->files, old) = 0;
394 darray_item(info->has_alt_forms, old) = true;
395 if (reportCollisions)
397 WARN("Key name <%s> assigned to multiple keys\n", name);
398 ACTION("Using %d, ignoring %d\n", kc, old);
401 else if (merge != MergeAltForm)
403 if ((reportCollisions) && (warningLevel > 3))
405 WARN("Key name <%s> assigned to multiple keys\n", name);
406 ACTION("Using %d, ignoring %d\n", old, kc);
408 ("Use 'alternate' keyword to assign the same name to multiple keys\n");
414 darray_item(info->has_alt_forms, old) = true;
417 darray_item(info->names, kc) = lval;
418 darray_item(info->files, kc) = fileID;
419 darray_item(info->has_alt_forms, kc) = (merge == MergeAltForm);
423 /***====================================================================***/
426 MergeIncludedKeycodes(KeyNamesInfo *into, struct xkb_keymap *keymap,
427 KeyNamesInfo *from, unsigned merge)
432 if (from->errorCount > 0)
434 into->errorCount += from->errorCount;
437 if (into->name == NULL)
439 into->name = from->name;
443 ResizeKeyNameArrays(into, from->computedMax);
445 for (i = from->computedMin; i <= from->computedMax; i++)
448 if (darray_item(from->names, i) == 0)
450 LongToKeyName(darray_item(from->names, i), buf);
452 if (darray_item(from->has_alt_forms, i))
453 thisMerge = MergeAltForm;
456 if (!AddKeyName(into, i, buf, thisMerge, from->fileID, false))
461 IndicatorNameInfo *led, *next;
462 for (led = from->leds; led != NULL; led = next)
464 if (merge != MergeDefault)
465 led->defs.merge = merge;
466 if (!AddIndicatorName(into, keymap, led))
468 next = (IndicatorNameInfo *) led->defs.next;
471 if (!MergeAliases(&into->aliases, &from->aliases, merge))
473 if (from->explicitMin != 0)
475 if ((into->explicitMin == 0)
476 || (into->explicitMin > from->explicitMin))
477 into->explicitMin = from->explicitMin;
479 if (from->explicitMax > 0)
481 if ((into->explicitMax == 0)
482 || (into->explicitMax < from->explicitMax))
483 into->explicitMax = from->explicitMax;
488 * Handle the given include statement (e.g. "include "evdev+aliases(qwerty)").
490 * @param stmt The include statement from the keymap file.
491 * @param keymap Unused for all but the keymap->flags.
492 * @param info Struct to store the key info in.
495 HandleIncludeKeycodes(IncludeStmt *stmt, struct xkb_keymap *keymap,
500 KeyNamesInfo included;
503 memset(&included, 0, sizeof(included));
506 if ((stmt->file == NULL) && (stmt->map == NULL))
510 memset(info, 0, sizeof(KeyNamesInfo));
512 else if (stmt->file && strcmp(stmt->file, "computed") == 0)
514 keymap->flags |= AutoKeyNames;
515 info->explicitMin = 0;
516 info->explicitMax = XKB_KEYCODE_MAX;
517 return (info->errorCount == 0);
518 } /* parse file, store returned info in the xkb struct */
519 else if (ProcessIncludeFile(keymap->ctx, stmt, XkmKeyNamesIndex, &rtrn,
522 InitKeyNamesInfo(&included);
523 HandleKeycodesFile(rtrn, keymap, MergeOverride, &included);
524 if (stmt->stmt != NULL)
527 included.name = stmt->stmt;
534 info->errorCount += 10; /* XXX: why 10?? */
537 /* Do we have more than one include statement? */
538 if ((stmt->next != NULL) && (included.errorCount < 1))
542 KeyNamesInfo next_incl;
544 for (next = stmt->next; next != NULL; next = next->next)
546 if ((next->file == NULL) && (next->map == NULL))
549 MergeIncludedKeycodes(&included, keymap, info, next->merge);
550 ClearKeyNamesInfo(info);
552 else if (ProcessIncludeFile(keymap->ctx, next, XkmKeyNamesIndex,
555 InitKeyNamesInfo(&next_incl);
556 HandleKeycodesFile(rtrn, keymap, MergeOverride, &next_incl);
557 MergeIncludedKeycodes(&included, keymap, &next_incl, op);
558 ClearKeyNamesInfo(&next_incl);
563 info->errorCount += 10; /* XXX: Why 10?? */
564 ClearKeyNamesInfo(&included);
573 MergeIncludedKeycodes(info, keymap, &included, newMerge);
574 ClearKeyNamesInfo(&included);
576 return (info->errorCount == 0);
580 * Parse the given statement and store the output in the info struct.
584 HandleKeycodeDef(KeycodeDef *stmt, unsigned merge, KeyNamesInfo *info)
586 if ((info->explicitMin != 0 && stmt->value < info->explicitMin) ||
587 (info->explicitMax != 0 && stmt->value > info->explicitMax))
589 ERROR("Illegal keycode %lu for name <%s>\n", stmt->value, stmt->name);
590 ACTION("Must be in the range %d-%d inclusive\n",
592 info->explicitMax ? info->explicitMax : XKB_KEYCODE_MAX);
595 if (stmt->merge != MergeDefault)
597 if (stmt->merge == MergeReplace)
598 merge = MergeOverride;
602 return AddKeyName(info, stmt->value, stmt->name, merge, info->fileID,
606 #define MIN_KEYCODE_DEF 0
607 #define MAX_KEYCODE_DEF 1
610 * Handle the minimum/maximum statement of the xkb file.
611 * Sets explicitMin/Max of the info struct.
613 * @return 1 on success, 0 otherwise.
616 HandleKeyNameVar(VarDef *stmt, struct xkb_keymap *keymap, KeyNamesInfo *info)
618 ExprResult tmp, field;
622 if (ExprResolveLhs(keymap, stmt->name, &tmp, &field, &arrayNdx) == 0)
623 return 0; /* internal error, already reported */
627 ERROR("Unknown element %s encountered\n", tmp.str);
628 ACTION("Default for field %s ignored\n", field.str);
631 if (strcasecmp(field.str, "minimum") == 0)
632 which = MIN_KEYCODE_DEF;
633 else if (strcasecmp(field.str, "maximum") == 0)
634 which = MAX_KEYCODE_DEF;
637 ERROR("Unknown field encountered\n");
638 ACTION("Assigment to field %s ignored\n", field.str);
641 if (arrayNdx != NULL)
643 ERROR("The %s setting is not an array\n", field.str);
644 ACTION("Illegal array reference ignored\n");
648 if (ExprResolveKeyCode(keymap->ctx, stmt->value, &tmp) == 0)
650 ACTION("Assignment to field %s ignored\n", field.str);
653 if (tmp.uval > XKB_KEYCODE_MAX)
656 ("Illegal keycode %d (must be in the range %d-%d inclusive)\n",
657 tmp.uval, 0, XKB_KEYCODE_MAX);
658 ACTION("Value of \"%s\" not changed\n", field.str);
661 if (which == MIN_KEYCODE_DEF)
663 if ((info->explicitMax > 0) && (info->explicitMax < tmp.uval))
666 ("Minimum key code (%d) must be <= maximum key code (%d)\n",
667 tmp.uval, info->explicitMax);
668 ACTION("Minimum key code value not changed\n");
671 if ((info->computedMax > 0) && (info->computedMin < tmp.uval))
674 ("Minimum key code (%d) must be <= lowest defined key (%d)\n",
675 tmp.uval, info->computedMin);
676 ACTION("Minimum key code value not changed\n");
679 info->explicitMin = tmp.uval;
681 if (which == MAX_KEYCODE_DEF)
683 if ((info->explicitMin > 0) && (info->explicitMin > tmp.uval))
685 ERROR("Maximum code (%d) must be >= minimum key code (%d)\n",
686 tmp.uval, info->explicitMin);
687 ACTION("Maximum code value not changed\n");
690 if ((info->computedMax > 0) && (info->computedMax > tmp.uval))
693 ("Maximum code (%d) must be >= highest defined key (%d)\n",
694 tmp.uval, info->computedMax);
695 ACTION("Maximum code value not changed\n");
698 info->explicitMax = tmp.uval;
710 HandleIndicatorNameDef(IndicatorNameDef *def, struct xkb_keymap *keymap,
713 IndicatorNameInfo ii;
716 if ((def->ndx < 1) || (def->ndx > XkbNumIndicators))
719 ERROR("Name specified for illegal indicator index %d\n", def->ndx);
723 InitIndicatorNameInfo(&ii, info);
725 if (!ExprResolveString(keymap->ctx, def->name, &tmp))
728 snprintf(buf, sizeof(buf), "%d", def->ndx);
730 return ReportBadType("indicator", "name", buf, "string");
732 ii.name = xkb_atom_intern(keymap->ctx, tmp.str);
734 ii.virtual = def->virtual;
735 if (!AddIndicatorName(info, keymap, &ii))
741 * Handle the xkb_keycodes section of a xkb file.
742 * All information about parsed keys is stored in the info struct.
744 * Such a section may have include statements, in which case this function is
745 * semi-recursive (it calls HandleIncludeKeycodes, which may call
746 * HandleKeycodesFile again).
748 * @param file The input file (parsed xkb_keycodes section)
749 * @param xkb Necessary to pass down, may have flags changed.
750 * @param merge Merge strategy (MergeOverride, etc.)
751 * @param info Struct to contain the fully parsed key information.
754 HandleKeycodesFile(XkbFile *file, struct xkb_keymap *keymap,
755 unsigned merge, KeyNamesInfo *info)
760 info->name = uDupString(file->name);
764 switch (stmt->stmtType)
766 case StmtInclude: /* e.g. include "evdev+aliases(qwerty)" */
767 if (!HandleIncludeKeycodes((IncludeStmt *) stmt, keymap, info))
770 case StmtKeycodeDef: /* e.g. <ESC> = 9; */
771 if (!HandleKeycodeDef((KeycodeDef *) stmt, merge, info))
774 case StmtKeyAliasDef: /* e.g. alias <MENU> = <COMP>; */
775 if (!HandleAliasDef((KeyAliasDef *) stmt, merge, info->fileID,
779 case StmtVarDef: /* e.g. minimum, maximum */
780 if (!HandleKeyNameVar((VarDef *) stmt, keymap, info))
783 case StmtIndicatorNameDef: /* e.g. indicator 1 = "Caps Lock"; */
784 if (!HandleIndicatorNameDef((IndicatorNameDef *) stmt, keymap, info))
789 ERROR("Keycode files may define key and indicator names only\n");
790 ACTION("Ignoring definition of %s\n",
792 StmtInterpDef) ? "a symbol interpretation" :
793 "virtual modifiers"));
797 WSGO("Unexpected statement type %d in HandleKeycodesFile\n",
802 if (info->errorCount > 10)
805 ERROR("Too many errors\n");
807 ACTION("Abandoning keycodes file \"%s\"\n", file->topName);
814 * Compile the xkb_keycodes section, parse it's output, return the results.
816 * @param file The parsed XKB file (may have include statements requiring
818 * @param result The effective keycodes, as gathered from the file.
819 * @param merge Merge strategy.
821 * @return true on success, false otherwise.
824 CompileKeycodes(XkbFile *file, struct xkb_keymap *keymap, unsigned merge)
826 KeyNamesInfo info; /* contains all the info after parsing */
828 InitKeyNamesInfo(&info);
830 HandleKeycodesFile(file, keymap, merge, &info);
832 /* all the keys are now stored in info */
834 if (info.errorCount != 0)
837 if (info.explicitMin > 0) /* if "minimum" statement was present */
838 keymap->min_key_code = info.explicitMin;
840 keymap->min_key_code = info.computedMin;
842 if (info.explicitMax > 0) /* if "maximum" statement was present */
843 keymap->max_key_code = info.explicitMax;
845 keymap->max_key_code = info.computedMax;
847 if (XkbcAllocNames(keymap, XkbKeyNamesMask | XkbIndicatorNamesMask, 0)
850 for (i = info.computedMin; i <= info.computedMax; i++)
851 LongToKeyName(darray_item(info.names, i),
852 darray_item(keymap->names->keys, i).name);
854 WSGO("Cannot create struct xkb_names in CompileKeycodes\n");
859 IndicatorNameInfo *ii;
860 if (XkbcAllocIndicatorMaps(keymap) != Success) {
861 WSGO("Couldn't allocate IndicatorRec in CompileKeycodes\n");
862 ACTION("Physical indicators not set\n");
865 for (ii = info.leds; ii; ii = (IndicatorNameInfo *)ii->defs.next) {
866 free(UNCONSTIFY(keymap->names->indicators[ii->ndx - 1]));
867 keymap->names->indicators[ii->ndx - 1] =
868 xkb_atom_strdup(keymap->ctx, ii->name);
872 ApplyAliases(keymap, &info.aliases);
874 ClearKeyNamesInfo(&info);
878 ClearKeyNamesInfo(&info);