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) (struct xkb_context *ctx, const void *priv,
32 xkb_atom_t field, unsigned type,
33 ExprResult *val_rtrn);
35 /***====================================================================***/
38 exprOpText(unsigned type)
45 strcpy(buf, "literal");
48 strcpy(buf, "identifier");
51 strcpy(buf, "action declaration");
54 strcpy(buf, "field reference");
57 strcpy(buf, "array reference");
60 strcpy(buf, "list of keysyms");
63 strcpy(buf, "list of actions");
66 strcpy(buf, "addition");
69 strcpy(buf, "subtraction");
72 strcpy(buf, "multiplication");
75 strcpy(buf, "division");
78 strcpy(buf, "assignment");
81 strcpy(buf, "logical not");
84 strcpy(buf, "arithmetic negation");
87 strcpy(buf, "bitwise inversion");
90 strcpy(buf, "plus sign");
93 snprintf(buf, sizeof(buf), "illegal(%d)", type);
100 exprTypeText(unsigned type)
107 strcpy(buf, "unknown");
110 strcpy(buf, "boolean");
116 strcpy(buf, "string");
119 strcpy(buf, "action");
122 strcpy(buf, "keyname");
125 snprintf(buf, sizeof(buf), "illegal(%d)", type);
132 ExprResolveLhs(struct xkb_keymap *keymap, ExprDef *expr,
133 ExprResult *elem_rtrn, ExprResult *field_rtrn,
134 ExprDef **index_rtrn)
139 elem_rtrn->str = NULL;
140 field_rtrn->str = xkb_atom_strdup(keymap->ctx,
145 elem_rtrn->str = xkb_atom_strdup(keymap->ctx,
146 expr->value.field.element);
147 field_rtrn->str = xkb_atom_strdup(keymap->ctx,
148 expr->value.field.field);
152 elem_rtrn->str = xkb_atom_strdup(keymap->ctx,
153 expr->value.array.element);
154 field_rtrn->str = xkb_atom_strdup(keymap->ctx,
155 expr->value.array.field);
156 *index_rtrn = expr->value.array.entry;
159 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
164 SimpleLookup(struct xkb_context *ctx, const void *priv,
165 xkb_atom_t field, unsigned type, ExprResult *val_rtrn)
167 const LookupEntry *entry;
170 if ((priv == NULL) || (field == XKB_ATOM_NONE) || (type != TypeInt))
174 str = xkb_atom_text(ctx, field);
175 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
177 if (strcasecmp(str, entry->name) == 0)
179 val_rtrn->uval = entry->result;
186 static const LookupEntry modIndexNames[] = {
187 {"shift", ShiftMapIndex},
188 {"control", ControlMapIndex},
189 {"lock", LockMapIndex},
190 {"mod1", Mod1MapIndex},
191 {"mod2", Mod2MapIndex},
192 {"mod3", Mod3MapIndex},
193 {"mod4", Mod4MapIndex},
194 {"mod5", Mod5MapIndex},
195 {"none", XkbNoModifier},
200 LookupModIndex(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
201 unsigned type, ExprResult *val_rtrn)
203 return SimpleLookup(ctx, modIndexNames, field, type, val_rtrn);
207 LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
208 unsigned type, ExprResult *val_rtrn)
215 str = xkb_atom_text(ctx, field);
218 if (strcasecmp(str, "all") == 0)
219 val_rtrn->uval = 0xff;
220 else if (strcasecmp(str, "none") == 0)
222 else if (LookupModIndex(ctx, priv, field, type, val_rtrn))
223 val_rtrn->uval = (1 << val_rtrn->uval);
230 ExprResolveBoolean(struct xkb_context *ctx, ExprDef *expr,
231 ExprResult *val_rtrn)
234 const char *bogus = NULL;
239 if (expr->type != TypeBoolean)
242 ("Found constant of type %s where boolean was expected\n",
243 exprTypeText(expr->type));
246 val_rtrn->ival = expr->value.ival;
249 bogus = xkb_atom_text(ctx, expr->value.str);
252 if ((strcasecmp(bogus, "true") == 0) ||
253 (strcasecmp(bogus, "yes") == 0) ||
254 (strcasecmp(bogus, "on") == 0))
259 else if ((strcasecmp(bogus, "false") == 0) ||
260 (strcasecmp(bogus, "no") == 0) ||
261 (strcasecmp(bogus, "off") == 0))
267 ERROR("Identifier \"%s\" of type int is unknown\n",
268 xkb_atom_text(ctx, expr->value.str));
271 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
272 xkb_atom_text(ctx, expr->value.field.element),
273 xkb_atom_text(ctx, expr->value.field.field));
277 ok = ExprResolveBoolean(ctx, expr, val_rtrn);
279 val_rtrn->uval = !val_rtrn->uval;
286 bogus = "Subtraction";
289 bogus = "Multiplication";
295 bogus = "Assignment";
299 ERROR("%s of boolean values not permitted\n", bogus);
302 ERROR("Unary \"+\" operator not permitted for boolean values\n");
305 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
312 ExprResolveFloat(struct xkb_context *ctx, ExprDef *expr,
313 ExprResult *val_rtrn)
316 ExprResult leftRtrn, rightRtrn;
317 ExprDef *left, *right;
322 if (expr->type == TypeString)
325 str = xkb_atom_text(ctx, expr->value.str);
326 if ((str != NULL) && (strlen(str) == 1))
328 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
332 if (expr->type != TypeInt)
334 ERROR("Found constant of type %s, expected a number\n",
335 exprTypeText(expr->type));
338 val_rtrn->ival = expr->value.ival;
339 if (expr->type == TypeInt)
340 val_rtrn->ival *= XkbGeomPtsPerMM;
343 ERROR("Numeric identifier \"%s\" unknown\n",
344 xkb_atom_text(ctx, expr->value.str));
347 ERROR("Numeric default \"%s.%s\" unknown\n",
348 xkb_atom_text(ctx, expr->value.field.element),
349 xkb_atom_text(ctx, expr->value.field.field));
355 left = expr->value.binary.left;
356 right = expr->value.binary.right;
357 if (ExprResolveFloat(ctx, left, &leftRtrn) &&
358 ExprResolveFloat(ctx, right, &rightRtrn))
363 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
366 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
369 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
372 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
379 WSGO("Assignment operator not implemented yet\n");
382 ERROR("The ! operator cannot be applied to a number\n");
386 left = expr->value.child;
387 if (ExprResolveFloat(ctx, left, &leftRtrn))
389 if (expr->op == OpNegate)
390 val_rtrn->ival = -leftRtrn.ival;
392 val_rtrn->ival = ~leftRtrn.ival;
397 left = expr->value.child;
398 return ExprResolveFloat(ctx, left, val_rtrn);
400 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
407 ExprResolveKeyCode(struct xkb_context *ctx, ExprDef *expr,
408 ExprResult *val_rtrn)
410 ExprResult leftRtrn, rightRtrn;
411 ExprDef *left, *right;
416 if (expr->type != TypeInt)
419 ("Found constant of type %s where an int was expected\n",
420 exprTypeText(expr->type));
423 val_rtrn->uval = expr->value.uval;
429 left = expr->value.binary.left;
430 right = expr->value.binary.right;
431 if (ExprResolveKeyCode(ctx, left, &leftRtrn) &&
432 ExprResolveKeyCode(ctx, right, &rightRtrn))
437 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
440 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
443 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
446 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
453 left = expr->value.child;
454 if (ExprResolveKeyCode(ctx, left, &leftRtrn))
456 val_rtrn->uval = ~leftRtrn.uval;
461 left = expr->value.child;
462 return ExprResolveKeyCode(ctx, left, val_rtrn);
464 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
471 * This function returns ... something. It's a bit of a guess, really.
473 * If a string is given in value ctx, its first character will be
474 * returned in uval. If an integer is given in value ctx, it will be
475 * returned in ival. If a float is given in value ctx, it will be
476 * returned as millimetres (rather than points) in ival.
478 * If an ident or field reference is given, the lookup function (if given)
479 * will be called. At the moment, only SimpleLookup use this, and they both
480 * return the results in uval. And don't support field references.
485 ExprResolveIntegerLookup(struct xkb_context *ctx, ExprDef *expr,
486 ExprResult *val_rtrn, IdentLookupFunc lookup,
487 const void *lookupPriv)
490 ExprResult leftRtrn, rightRtrn;
491 ExprDef *left, *right;
496 if (expr->type == TypeString)
499 str = xkb_atom_text(ctx, expr->value.str);
507 val_rtrn->uval = str[0];
513 if (expr->type != TypeInt)
516 ("Found constant of type %s where an int was expected\n",
517 exprTypeText(expr->type));
520 val_rtrn->ival = expr->value.ival;
524 ok = lookup(ctx, lookupPriv, expr->value.str,
527 ERROR("Identifier \"%s\" of type int is unknown\n",
528 xkb_atom_text(ctx, expr->value.str));
531 ERROR("Default \"%s.%s\" of type int is unknown\n",
532 xkb_atom_text(ctx, expr->value.field.element),
533 xkb_atom_text(ctx, expr->value.field.field));
539 left = expr->value.binary.left;
540 right = expr->value.binary.right;
541 if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup, lookupPriv) &&
542 ExprResolveIntegerLookup(ctx, 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(ctx, left, &leftRtrn, lookup,
574 if (expr->op == OpNegate)
575 val_rtrn->ival = -leftRtrn.ival;
577 val_rtrn->ival = ~leftRtrn.ival;
582 left = expr->value.child;
583 return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup,
586 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
593 ExprResolveInteger(struct xkb_context *ctx, ExprDef *expr,
594 ExprResult *val_rtrn)
596 return ExprResolveIntegerLookup(ctx, expr, val_rtrn, NULL, NULL);
600 ExprResolveGroup(struct xkb_context *ctx, ExprDef *expr,
601 ExprResult *val_rtrn)
604 static const LookupEntry group_names[] = {
616 ret = ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup,
621 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
622 ERROR("Group index %d is out of range (1..%d)\n",
623 val_rtrn->uval, XkbNumKbdGroups);
631 ExprResolveLevel(struct xkb_context *ctx, ExprDef *expr,
632 ExprResult *val_rtrn)
635 static const LookupEntry level_names[] = {
647 ret = ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup,
652 if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) {
653 ERROR("Shift level %d is out of range (1..%d)\n", val_rtrn->ival,
662 ExprResolveButton(struct xkb_context *ctx, ExprDef *expr,
663 ExprResult *val_rtrn)
665 static const LookupEntry button_names[] = {
675 return ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup,
680 ExprResolveString(struct xkb_context *ctx, ExprDef *expr,
681 ExprResult *val_rtrn)
683 ExprResult leftRtrn, rightRtrn;
686 const char *bogus = NULL;
691 if (expr->type != TypeString)
693 ERROR("Found constant of type %s, expected a string\n",
694 exprTypeText(expr->type));
697 val_rtrn->str = xkb_atom_strdup(ctx, expr->value.str);
698 if (val_rtrn->str == NULL)
699 val_rtrn->str = strdup("");
702 ERROR("Identifier \"%s\" of type string not found\n",
703 xkb_atom_text(ctx, expr->value.str));
706 ERROR("Default \"%s.%s\" of type string not found\n",
707 xkb_atom_text(ctx, expr->value.field.element),
708 xkb_atom_text(ctx, expr->value.field.field));
711 left = expr->value.binary.left;
712 right = expr->value.binary.right;
713 if (ExprResolveString(ctx, left, &leftRtrn) &&
714 ExprResolveString(ctx, right, &rightRtrn))
718 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
721 sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
733 bogus = "Subtraction";
736 bogus = "Multiplication";
742 bogus = "Assignment";
748 bogus = "Bitwise complement";
749 ERROR("%s of string values not permitted\n", bogus);
752 ERROR("The ! operator cannot be applied to a string\n");
755 ERROR("The + operator cannot be applied to a string\n");
758 WSGO("Unknown operator %d in ResolveString\n", expr->op);
765 ExprResolveKeyName(struct xkb_context *ctx, ExprDef *expr,
766 ExprResult *val_rtrn)
768 const char *bogus = NULL;
773 if (expr->type != TypeKeyName)
775 ERROR("Found constant of type %s, expected a key name\n",
776 exprTypeText(expr->type));
779 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
782 ERROR("Identifier \"%s\" of type string not found\n",
783 xkb_atom_text(ctx, expr->value.str));
786 ERROR("Default \"%s.%s\" of type key name not found\n",
787 xkb_atom_text(ctx, expr->value.field.element),
788 xkb_atom_text(ctx, expr->value.field.field));
795 bogus = "Subtraction";
798 bogus = "Multiplication";
804 bogus = "Assignment";
810 bogus = "Bitwise complement";
811 ERROR("%s of key name values not permitted\n", bogus);
814 ERROR("The ! operator cannot be applied to a key name\n");
817 ERROR("The + operator cannot be applied to a key name\n");
820 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
826 /***====================================================================***/
829 ExprResolveEnum(struct xkb_context *ctx, ExprDef *expr,
830 ExprResult *val_rtrn, const LookupEntry *values)
832 if (expr->op != ExprIdent)
834 ERROR("Found a %s where an enumerated value was expected\n",
835 exprOpText(expr->op));
838 if (!SimpleLookup(ctx, values, expr->value.str, TypeInt, val_rtrn))
841 ERROR("Illegal identifier %s (expected one of: ",
842 xkb_atom_text(ctx, expr->value.str));
843 while (values && values->name)
846 INFO(", %s", values->name);
848 INFO("%s", values->name);
859 ExprResolveMaskLookup(struct xkb_context *ctx, ExprDef *expr,
860 ExprResult *val_rtrn, IdentLookupFunc lookup,
861 const void *lookupPriv)
864 ExprResult leftRtrn, rightRtrn;
865 ExprDef *left, *right;
866 const char *bogus = NULL;
871 if (expr->type != TypeInt)
874 ("Found constant of type %s where a mask was expected\n",
875 exprTypeText(expr->type));
878 val_rtrn->ival = expr->value.ival;
881 ok = lookup(ctx, lookupPriv, expr->value.str, TypeInt, val_rtrn);
883 ERROR("Identifier \"%s\" of type int is unknown\n",
884 xkb_atom_text(ctx, expr->value.str));
887 ERROR("Default \"%s.%s\" of type int is unknown\n",
888 xkb_atom_text(ctx, expr->value.field.element),
889 xkb_atom_text(ctx, expr->value.field.field));
892 bogus = "array reference";
895 bogus = "function use";
896 ERROR("Unexpected %s in mask expression\n", bogus);
897 ACTION("Expression ignored\n");
903 left = expr->value.binary.left;
904 right = expr->value.binary.right;
905 if (ExprResolveMaskLookup(ctx, left, &leftRtrn, lookup, lookupPriv) &&
906 ExprResolveMaskLookup(ctx, right, &rightRtrn, lookup, lookupPriv))
911 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
914 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
918 ERROR("Cannot %s masks\n",
919 expr->op == OpDivide ? "divide" : "multiply");
920 ACTION("Illegal operation ignored\n");
927 WSGO("Assignment operator not implemented yet\n");
930 left = expr->value.child;
931 if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
934 val_rtrn->ival = ~leftRtrn.ival;
941 left = expr->value.child;
942 if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
945 ERROR("The %s operator cannot be used with a mask\n",
946 (expr->op == OpNegate ? "-" : "!"));
950 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
957 ExprResolveMask(struct xkb_context *ctx, ExprDef *expr,
958 ExprResult *val_rtrn, const LookupEntry *values)
960 return ExprResolveMaskLookup(ctx, expr, val_rtrn, SimpleLookup, values);
964 ExprResolveModMask(struct xkb_context *ctx, ExprDef *expr,
965 ExprResult *val_rtrn)
967 return ExprResolveMaskLookup(ctx, expr, val_rtrn, LookupModMask, NULL);
971 ExprResolveVModMask(ExprDef *expr, ExprResult *val_rtrn,
972 struct xkb_keymap *keymap)
974 return ExprResolveMaskLookup(keymap->ctx, expr, val_rtrn, LookupVModMask,
979 ExprResolveKeySym(struct xkb_context *ctx, ExprDef *expr,
980 ExprResult *val_rtrn)
985 if (expr->op == ExprIdent)
988 str = xkb_atom_text(ctx, expr->value.str);
990 sym = xkb_keysym_from_name(str);
991 if (sym != XKB_KEY_NoSymbol) {
992 val_rtrn->uval = sym;
997 ok = ExprResolveInteger(ctx, expr, val_rtrn);
998 if ((ok) && (val_rtrn->uval < 10))
999 val_rtrn->uval += '0';