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 /***====================================================================***/
31 typedef bool (*IdentLookupFunc) (const void *priv, xkb_atom_t field,
32 unsigned type, ExprResult *val_rtrn);
34 /***====================================================================***/
37 exprOpText(unsigned type)
44 strcpy(buf, "literal");
47 strcpy(buf, "identifier");
50 strcpy(buf, "action declaration");
53 strcpy(buf, "field reference");
56 strcpy(buf, "array reference");
59 strcpy(buf, "list of keysyms");
62 strcpy(buf, "list of actions");
65 strcpy(buf, "addition");
68 strcpy(buf, "subtraction");
71 strcpy(buf, "multiplication");
74 strcpy(buf, "division");
77 strcpy(buf, "assignment");
80 strcpy(buf, "logical not");
83 strcpy(buf, "arithmetic negation");
86 strcpy(buf, "bitwise inversion");
89 strcpy(buf, "plus sign");
92 snprintf(buf, sizeof(buf), "illegal(%d)", type);
99 exprTypeText(unsigned type)
106 strcpy(buf, "unknown");
109 strcpy(buf, "boolean");
115 strcpy(buf, "string");
118 strcpy(buf, "action");
121 strcpy(buf, "keyname");
124 snprintf(buf, sizeof(buf), "illegal(%d)", type);
131 ExprResolveLhs(struct xkb_keymap *keymap, ExprDef *expr,
132 ExprResult *elem_rtrn, ExprResult *field_rtrn,
133 ExprDef **index_rtrn)
138 elem_rtrn->str = NULL;
139 field_rtrn->str = xkb_atom_strdup(keymap->context,
144 elem_rtrn->str = xkb_atom_strdup(keymap->context,
145 expr->value.field.element);
146 field_rtrn->str = xkb_atom_strdup(keymap->context,
147 expr->value.field.field);
151 elem_rtrn->str = xkb_atom_strdup(keymap->context,
152 expr->value.array.element);
153 field_rtrn->str = xkb_atom_strdup(keymap->context,
154 expr->value.array.field);
155 *index_rtrn = expr->value.array.entry;
158 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
163 SimpleLookup(const void * priv, xkb_atom_t field, unsigned type,
164 ExprResult * val_rtrn)
166 const LookupEntry *entry;
169 if ((priv == NULL) || (field == XKB_ATOM_NONE) || (type != TypeInt))
173 str = XkbcAtomText(field);
174 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
176 if (strcasecmp(str, entry->name) == 0)
178 val_rtrn->uval = entry->result;
185 static const LookupEntry modIndexNames[] = {
186 {"shift", ShiftMapIndex},
187 {"control", ControlMapIndex},
188 {"lock", LockMapIndex},
189 {"mod1", Mod1MapIndex},
190 {"mod2", Mod2MapIndex},
191 {"mod3", Mod3MapIndex},
192 {"mod4", Mod4MapIndex},
193 {"mod5", Mod5MapIndex},
194 {"none", XkbNoModifier},
199 LookupModIndex(const void * priv, xkb_atom_t field, unsigned type,
200 ExprResult * val_rtrn)
202 return SimpleLookup(modIndexNames, field, type, val_rtrn);
206 LookupModMask(const void * priv, xkb_atom_t field, unsigned type,
207 ExprResult * val_rtrn)
214 str = XkbcAtomText(field);
217 if (strcasecmp(str, "all") == 0)
218 val_rtrn->uval = 0xff;
219 else if (strcasecmp(str, "none") == 0)
221 else if (LookupModIndex(priv, field, type, val_rtrn))
222 val_rtrn->uval = (1 << val_rtrn->uval);
229 ExprResolveBoolean(ExprDef * expr,
230 ExprResult * val_rtrn)
233 const char *bogus = NULL;
238 if (expr->type != TypeBoolean)
241 ("Found constant of type %s where boolean was expected\n",
242 exprTypeText(expr->type));
245 val_rtrn->ival = expr->value.ival;
248 bogus = XkbcAtomText(expr->value.str);
251 if ((strcasecmp(bogus, "true") == 0) ||
252 (strcasecmp(bogus, "yes") == 0) ||
253 (strcasecmp(bogus, "on") == 0))
258 else if ((strcasecmp(bogus, "false") == 0) ||
259 (strcasecmp(bogus, "no") == 0) ||
260 (strcasecmp(bogus, "off") == 0))
266 ERROR("Identifier \"%s\" of type int is unknown\n",
267 XkbcAtomText(expr->value.str));
270 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
271 XkbcAtomText(expr->value.field.element),
272 XkbcAtomText(expr->value.field.field));
276 ok = ExprResolveBoolean(expr, val_rtrn);
278 val_rtrn->uval = !val_rtrn->uval;
285 bogus = "Subtraction";
288 bogus = "Multiplication";
294 bogus = "Assignment";
298 ERROR("%s of boolean values not permitted\n", bogus);
301 ERROR("Unary \"+\" operator not permitted for boolean values\n");
304 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
311 ExprResolveFloat(ExprDef * expr,
312 ExprResult * val_rtrn)
315 ExprResult leftRtrn, rightRtrn;
316 ExprDef *left, *right;
321 if (expr->type == TypeString)
324 str = XkbcAtomText(expr->value.str);
325 if ((str != NULL) && (strlen(str) == 1))
327 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
331 if (expr->type != TypeInt)
333 ERROR("Found constant of type %s, expected a number\n",
334 exprTypeText(expr->type));
337 val_rtrn->ival = expr->value.ival;
338 if (expr->type == TypeInt)
339 val_rtrn->ival *= XkbGeomPtsPerMM;
342 ERROR("Numeric identifier \"%s\" unknown\n",
343 XkbcAtomText(expr->value.str));
346 ERROR("Numeric default \"%s.%s\" unknown\n",
347 XkbcAtomText(expr->value.field.element),
348 XkbcAtomText(expr->value.field.field));
354 left = expr->value.binary.left;
355 right = expr->value.binary.right;
356 if (ExprResolveFloat(left, &leftRtrn) &&
357 ExprResolveFloat(right, &rightRtrn))
362 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
365 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
368 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
371 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
378 WSGO("Assignment operator not implemented yet\n");
381 ERROR("The ! operator cannot be applied to a number\n");
385 left = expr->value.child;
386 if (ExprResolveFloat(left, &leftRtrn))
388 if (expr->op == OpNegate)
389 val_rtrn->ival = -leftRtrn.ival;
391 val_rtrn->ival = ~leftRtrn.ival;
396 left = expr->value.child;
397 return ExprResolveFloat(left, val_rtrn);
399 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
406 ExprResolveKeyCode(ExprDef * expr,
407 ExprResult * val_rtrn)
409 ExprResult leftRtrn, rightRtrn;
410 ExprDef *left, *right;
415 if (expr->type != TypeInt)
418 ("Found constant of type %s where an int was expected\n",
419 exprTypeText(expr->type));
422 val_rtrn->uval = expr->value.uval;
428 left = expr->value.binary.left;
429 right = expr->value.binary.right;
430 if (ExprResolveKeyCode(left, &leftRtrn) &&
431 ExprResolveKeyCode(right, &rightRtrn))
436 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
439 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
442 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
445 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
452 left = expr->value.child;
453 if (ExprResolveKeyCode(left, &leftRtrn))
455 val_rtrn->uval = ~leftRtrn.uval;
460 left = expr->value.child;
461 return ExprResolveKeyCode(left, val_rtrn);
463 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
470 * This function returns ... something. It's a bit of a guess, really.
472 * If a string is given in value context, its first character will be
473 * returned in uval. If an integer is given in value context, it will be
474 * returned in ival. If a float is given in value context, it will be
475 * returned as millimetres (rather than points) in ival.
477 * If an ident or field reference is given, the lookup function (if given)
478 * will be called. At the moment, only SimpleLookup use this, and they both
479 * return the results in uval. And don't support field references.
484 ExprResolveIntegerLookup(ExprDef * expr,
485 ExprResult * val_rtrn,
486 IdentLookupFunc lookup, const void * lookupPriv)
489 ExprResult leftRtrn, rightRtrn;
490 ExprDef *left, *right;
495 if (expr->type == TypeString)
498 str = XkbcAtomText(expr->value.str);
506 val_rtrn->uval = str[0];
512 if (expr->type != TypeInt)
515 ("Found constant of type %s where an int was expected\n",
516 exprTypeText(expr->type));
519 val_rtrn->ival = expr->value.ival;
524 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
527 ERROR("Identifier \"%s\" of type int is unknown\n",
528 XkbcAtomText(expr->value.str));
531 ERROR("Default \"%s.%s\" of type int is unknown\n",
532 XkbcAtomText(expr->value.field.element),
533 XkbcAtomText(expr->value.field.field));
539 left = expr->value.binary.left;
540 right = expr->value.binary.right;
541 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
542 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
547 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
550 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
553 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
556 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
563 WSGO("Assignment operator not implemented yet\n");
566 ERROR("The ! operator cannot be applied to an integer\n");
570 left = expr->value.child;
571 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
573 if (expr->op == OpNegate)
574 val_rtrn->ival = -leftRtrn.ival;
576 val_rtrn->ival = ~leftRtrn.ival;
581 left = expr->value.child;
582 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
584 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
591 ExprResolveInteger(ExprDef * expr,
592 ExprResult * val_rtrn)
594 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
598 ExprResolveGroup(ExprDef * expr,
599 ExprResult * val_rtrn)
602 static const LookupEntry group_names[] = {
614 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
618 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
619 ERROR("Group index %d is out of range (1..%d)\n",
620 val_rtrn->uval, XkbNumKbdGroups);
628 ExprResolveLevel(ExprDef * expr,
629 ExprResult * val_rtrn)
632 static const LookupEntry level_names[] = {
644 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, level_names);
648 if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) {
649 ERROR("Shift level %d is out of range (1..%d)\n", val_rtrn->ival,
658 ExprResolveButton(ExprDef * expr,
659 ExprResult * val_rtrn)
661 static const LookupEntry button_names[] = {
671 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
676 ExprResolveString(struct xkb_keymap *keymap, ExprDef *expr,
677 ExprResult *val_rtrn)
679 ExprResult leftRtrn, rightRtrn;
682 const char *bogus = NULL;
687 if (expr->type != TypeString)
689 ERROR("Found constant of type %s, expected a string\n",
690 exprTypeText(expr->type));
693 val_rtrn->str = xkb_atom_strdup(keymap->context, expr->value.str);
694 if (val_rtrn->str == NULL)
695 val_rtrn->str = strdup("");
698 ERROR("Identifier \"%s\" of type string not found\n",
699 XkbcAtomText(expr->value.str));
702 ERROR("Default \"%s.%s\" of type string not found\n",
703 XkbcAtomText(expr->value.field.element),
704 XkbcAtomText(expr->value.field.field));
707 left = expr->value.binary.left;
708 right = expr->value.binary.right;
709 if (ExprResolveString(keymap, left, &leftRtrn) &&
710 ExprResolveString(keymap, right, &rightRtrn))
714 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
717 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
729 bogus = "Subtraction";
732 bogus = "Multiplication";
738 bogus = "Assignment";
744 bogus = "Bitwise complement";
745 ERROR("%s of string values not permitted\n", bogus);
748 ERROR("The ! operator cannot be applied to a string\n");
751 ERROR("The + operator cannot be applied to a string\n");
754 WSGO("Unknown operator %d in ResolveString\n", expr->op);
761 ExprResolveKeyName(ExprDef * expr,
762 ExprResult * val_rtrn)
764 const char *bogus = NULL;
769 if (expr->type != TypeKeyName)
771 ERROR("Found constant of type %s, expected a key name\n",
772 exprTypeText(expr->type));
775 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
778 ERROR("Identifier \"%s\" of type string not found\n",
779 XkbcAtomText(expr->value.str));
782 ERROR("Default \"%s.%s\" of type key name not found\n",
783 XkbcAtomText(expr->value.field.element),
784 XkbcAtomText(expr->value.field.field));
791 bogus = "Subtraction";
794 bogus = "Multiplication";
800 bogus = "Assignment";
806 bogus = "Bitwise complement";
807 ERROR("%s of key name values not permitted\n", bogus);
810 ERROR("The ! operator cannot be applied to a key name\n");
813 ERROR("The + operator cannot be applied to a key name\n");
816 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
822 /***====================================================================***/
825 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, const LookupEntry * values)
827 if (expr->op != ExprIdent)
829 ERROR("Found a %s where an enumerated value was expected\n",
830 exprOpText(expr->op));
833 if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
836 ERROR("Illegal identifier %s (expected one of: ",
837 XkbcAtomText(expr->value.str));
838 while (values && values->name)
841 INFO(", %s", values->name);
843 INFO("%s", values->name);
854 ExprResolveMaskLookup(ExprDef * expr,
855 ExprResult * val_rtrn,
856 IdentLookupFunc lookup,
857 const void * lookupPriv)
860 ExprResult leftRtrn, rightRtrn;
861 ExprDef *left, *right;
862 const char *bogus = NULL;
867 if (expr->type != TypeInt)
870 ("Found constant of type %s where a mask was expected\n",
871 exprTypeText(expr->type));
874 val_rtrn->ival = expr->value.ival;
877 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
879 ERROR("Identifier \"%s\" of type int is unknown\n",
880 XkbcAtomText(expr->value.str));
883 ERROR("Default \"%s.%s\" of type int is unknown\n",
884 XkbcAtomText(expr->value.field.element),
885 XkbcAtomText(expr->value.field.field));
888 bogus = "array reference";
891 bogus = "function use";
892 ERROR("Unexpected %s in mask expression\n", bogus);
893 ACTION("Expression ignored\n");
899 left = expr->value.binary.left;
900 right = expr->value.binary.right;
901 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
902 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
907 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
910 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
914 ERROR("Cannot %s masks\n",
915 expr->op == OpDivide ? "divide" : "multiply");
916 ACTION("Illegal operation ignored\n");
923 WSGO("Assignment operator not implemented yet\n");
926 left = expr->value.child;
927 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
929 val_rtrn->ival = ~leftRtrn.ival;
936 left = expr->value.child;
937 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
939 ERROR("The %s operator cannot be used with a mask\n",
940 (expr->op == OpNegate ? "-" : "!"));
944 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
951 ExprResolveMask(ExprDef *expr, ExprResult *val_rtrn,
952 const LookupEntry * values)
954 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
958 ExprResolveModMask(ExprDef *expr, ExprResult *val_rtrn)
960 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
964 ExprResolveVModMask(ExprDef *expr, ExprResult *val_rtrn,
965 struct xkb_keymap *keymap)
967 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, keymap);
971 ExprResolveKeySym(ExprDef *expr, ExprResult *val_rtrn)
976 if (expr->op == ExprIdent)
979 str = XkbcAtomText(expr->value.str);
981 sym = xkb_keysym_from_name(str);
982 if (sym != XKB_KEYSYM_NO_SYMBOL) {
983 val_rtrn->uval = sym;
988 ok = ExprResolveInteger(expr, val_rtrn);
989 if ((ok) && (val_rtrn->uval < 10))
990 val_rtrn->uval += '0';