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)
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)
105 strcpy(buf, "unknown");
108 strcpy(buf, "boolean");
114 strcpy(buf, "string");
117 strcpy(buf, "action");
120 strcpy(buf, "keyname");
123 snprintf(buf, sizeof(buf), "illegal(%d)", type);
130 ExprResolveLhs(struct xkb_keymap *keymap, ExprDef *expr,
131 ExprResult *elem_rtrn, ExprResult *field_rtrn,
132 ExprDef **index_rtrn)
136 elem_rtrn->str = NULL;
137 field_rtrn->str = xkb_atom_strdup(keymap->ctx,
142 elem_rtrn->str = xkb_atom_strdup(keymap->ctx,
143 expr->value.field.element);
144 field_rtrn->str = xkb_atom_strdup(keymap->ctx,
145 expr->value.field.field);
149 elem_rtrn->str = xkb_atom_strdup(keymap->ctx,
150 expr->value.array.element);
151 field_rtrn->str = xkb_atom_strdup(keymap->ctx,
152 expr->value.array.field);
153 *index_rtrn = expr->value.array.entry;
156 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
161 SimpleLookup(struct xkb_context *ctx, const void *priv,
162 xkb_atom_t field, unsigned type, ExprResult *val_rtrn)
164 const LookupEntry *entry;
167 if ((priv == NULL) || (field == XKB_ATOM_NONE) || (type != TypeInt))
170 str = xkb_atom_text(ctx, field);
171 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++) {
172 if (strcasecmp(str, entry->name) == 0) {
173 val_rtrn->uval = entry->result;
181 static const LookupEntry modIndexNames[] = {
182 { "shift", ShiftMapIndex },
183 { "control", ControlMapIndex },
184 { "lock", LockMapIndex },
185 { "mod1", Mod1MapIndex },
186 { "mod2", Mod2MapIndex },
187 { "mod3", Mod3MapIndex },
188 { "mod4", Mod4MapIndex },
189 { "mod5", Mod5MapIndex },
190 { "none", XkbNoModifier },
195 LookupModIndex(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
196 unsigned type, ExprResult *val_rtrn)
198 return SimpleLookup(ctx, modIndexNames, field, type, val_rtrn);
202 LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
203 unsigned type, ExprResult *val_rtrn)
210 str = xkb_atom_text(ctx, field);
213 if (strcasecmp(str, "all") == 0)
214 val_rtrn->uval = 0xff;
215 else if (strcasecmp(str, "none") == 0)
217 else if (LookupModIndex(ctx, priv, field, type, val_rtrn))
218 val_rtrn->uval = (1 << val_rtrn->uval);
225 ExprResolveBoolean(struct xkb_context *ctx, ExprDef *expr,
226 ExprResult *val_rtrn)
229 const char *bogus = NULL;
233 if (expr->type != TypeBoolean) {
235 ("Found constant of type %s where boolean was expected\n",
236 exprTypeText(expr->type));
239 val_rtrn->ival = expr->value.ival;
243 bogus = xkb_atom_text(ctx, expr->value.str);
245 if ((strcasecmp(bogus, "true") == 0) ||
246 (strcasecmp(bogus, "yes") == 0) ||
247 (strcasecmp(bogus, "on") == 0)) {
251 else if ((strcasecmp(bogus, "false") == 0) ||
252 (strcasecmp(bogus, "no") == 0) ||
253 (strcasecmp(bogus, "off") == 0)) {
258 ERROR("Identifier \"%s\" of type int is unknown\n",
259 xkb_atom_text(ctx, expr->value.str));
263 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
264 xkb_atom_text(ctx, expr->value.field.element),
265 xkb_atom_text(ctx, expr->value.field.field));
270 ok = ExprResolveBoolean(ctx, expr, val_rtrn);
272 val_rtrn->uval = !val_rtrn->uval;
279 bogus = "Subtraction";
282 bogus = "Multiplication";
288 bogus = "Assignment";
292 ERROR("%s of boolean values not permitted\n", bogus);
296 ERROR("Unary \"+\" operator not permitted for boolean values\n");
300 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
307 ExprResolveFloat(struct xkb_context *ctx, ExprDef *expr,
308 ExprResult *val_rtrn)
311 ExprResult leftRtrn, rightRtrn;
312 ExprDef *left, *right;
316 if (expr->type == TypeString) {
318 str = xkb_atom_text(ctx, expr->value.str);
319 if ((str != NULL) && (strlen(str) == 1)) {
320 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
324 if (expr->type != TypeInt) {
325 ERROR("Found constant of type %s, expected a number\n",
326 exprTypeText(expr->type));
329 val_rtrn->ival = expr->value.ival;
330 if (expr->type == TypeInt)
331 val_rtrn->ival *= XkbGeomPtsPerMM;
335 ERROR("Numeric identifier \"%s\" unknown\n",
336 xkb_atom_text(ctx, expr->value.str));
340 ERROR("Numeric default \"%s.%s\" unknown\n",
341 xkb_atom_text(ctx, expr->value.field.element),
342 xkb_atom_text(ctx, expr->value.field.field));
349 left = expr->value.binary.left;
350 right = expr->value.binary.right;
351 if (ExprResolveFloat(ctx, left, &leftRtrn) &&
352 ExprResolveFloat(ctx, right, &rightRtrn)) {
355 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
359 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
363 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
367 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
375 WSGO("Assignment operator not implemented yet\n");
379 ERROR("The ! operator cannot be applied to a number\n");
384 left = expr->value.child;
385 if (ExprResolveFloat(ctx, left, &leftRtrn)) {
386 if (expr->op == OpNegate)
387 val_rtrn->ival = -leftRtrn.ival;
389 val_rtrn->ival = ~leftRtrn.ival;
395 left = expr->value.child;
396 return ExprResolveFloat(ctx, left, val_rtrn);
399 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
406 ExprResolveKeyCode(struct xkb_context *ctx, ExprDef *expr,
407 ExprResult *val_rtrn)
409 ExprResult leftRtrn, rightRtrn;
410 ExprDef *left, *right;
414 if (expr->type != TypeInt) {
416 ("Found constant of type %s where an int was expected\n",
417 exprTypeText(expr->type));
420 val_rtrn->uval = expr->value.uval;
427 left = expr->value.binary.left;
428 right = expr->value.binary.right;
429 if (ExprResolveKeyCode(ctx, left, &leftRtrn) &&
430 ExprResolveKeyCode(ctx, right, &rightRtrn)) {
433 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
436 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
439 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
442 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
450 left = expr->value.child;
451 if (ExprResolveKeyCode(ctx, left, &leftRtrn)) {
452 val_rtrn->uval = ~leftRtrn.uval;
458 left = expr->value.child;
459 return ExprResolveKeyCode(ctx, left, val_rtrn);
462 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
469 * This function returns ... something. It's a bit of a guess, really.
471 * If a string is given in value ctx, its first character will be
472 * returned in uval. If an integer is given in value ctx, it will be
473 * returned in ival. If a float is given in value ctx, it will be
474 * returned as millimetres (rather than points) in ival.
476 * If an ident or field reference is given, the lookup function (if given)
477 * will be called. At the moment, only SimpleLookup use this, and they both
478 * return the results in uval. And don't support field references.
483 ExprResolveIntegerLookup(struct xkb_context *ctx, ExprDef *expr,
484 ExprResult *val_rtrn, IdentLookupFunc lookup,
485 const void *lookupPriv)
488 ExprResult leftRtrn, rightRtrn;
489 ExprDef *left, *right;
493 if (expr->type == TypeString) {
495 str = xkb_atom_text(ctx, expr->value.str);
497 switch (strlen(str)) {
502 val_rtrn->uval = str[0];
508 if (expr->type != TypeInt) {
510 ("Found constant of type %s where an int was expected\n",
511 exprTypeText(expr->type));
514 val_rtrn->ival = expr->value.ival;
519 ok = lookup(ctx, lookupPriv, expr->value.str,
522 ERROR("Identifier \"%s\" of type int is unknown\n",
523 xkb_atom_text(ctx, expr->value.str));
527 ERROR("Default \"%s.%s\" of type int is unknown\n",
528 xkb_atom_text(ctx, expr->value.field.element),
529 xkb_atom_text(ctx, expr->value.field.field));
536 left = expr->value.binary.left;
537 right = expr->value.binary.right;
538 if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
540 ExprResolveIntegerLookup(ctx, right, &rightRtrn, lookup,
544 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
547 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
550 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
553 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
561 WSGO("Assignment operator not implemented yet\n");
565 ERROR("The ! operator cannot be applied to an integer\n");
570 left = expr->value.child;
571 if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
573 if (expr->op == OpNegate)
574 val_rtrn->ival = -leftRtrn.ival;
576 val_rtrn->ival = ~leftRtrn.ival;
582 left = expr->value.child;
583 return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup,
587 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
594 ExprResolveInteger(struct xkb_context *ctx, ExprDef *expr,
595 ExprResult *val_rtrn)
597 return ExprResolveIntegerLookup(ctx, expr, val_rtrn, NULL, NULL);
601 ExprResolveGroup(struct xkb_context *ctx, ExprDef *expr,
602 ExprResult *val_rtrn)
605 static const LookupEntry group_names[] = {
617 ret = ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup,
622 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
623 ERROR("Group index %u is out of range (1..%d)\n",
624 val_rtrn->uval, XkbNumKbdGroups);
632 ExprResolveLevel(struct xkb_context *ctx, ExprDef *expr,
633 ExprResult *val_rtrn)
636 static const LookupEntry level_names[] = {
648 ret = ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup,
653 if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) {
654 ERROR("Shift level %d is out of range (1..%d)\n", val_rtrn->ival,
663 ExprResolveButton(struct xkb_context *ctx, ExprDef *expr,
664 ExprResult *val_rtrn)
666 static const LookupEntry button_names[] = {
676 return ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup,
681 ExprResolveString(struct xkb_context *ctx, ExprDef *expr,
682 ExprResult *val_rtrn)
684 ExprResult leftRtrn, rightRtrn;
687 const char *bogus = NULL;
691 if (expr->type != TypeString) {
692 ERROR("Found constant of type %s, expected a string\n",
693 exprTypeText(expr->type));
696 val_rtrn->str = xkb_atom_strdup(ctx, expr->value.str);
697 if (val_rtrn->str == NULL)
698 val_rtrn->str = strdup("");
702 ERROR("Identifier \"%s\" of type string not found\n",
703 xkb_atom_text(ctx, expr->value.str));
707 ERROR("Default \"%s.%s\" of type string not found\n",
708 xkb_atom_text(ctx, expr->value.field.element),
709 xkb_atom_text(ctx, expr->value.field.field));
713 left = expr->value.binary.left;
714 right = expr->value.binary.right;
715 if (ExprResolveString(ctx, left, &leftRtrn) &&
716 ExprResolveString(ctx, right, &rightRtrn)) {
719 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
722 sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
735 bogus = "Subtraction";
738 bogus = "Multiplication";
744 bogus = "Assignment";
750 bogus = "Bitwise complement";
751 ERROR("%s of string values not permitted\n", bogus);
755 ERROR("The ! operator cannot be applied to a string\n");
759 ERROR("The + operator cannot be applied to a string\n");
763 WSGO("Unknown operator %d in ResolveString\n", expr->op);
770 ExprResolveKeyName(struct xkb_context *ctx, ExprDef *expr,
771 ExprResult *val_rtrn)
773 const char *bogus = NULL;
777 if (expr->type != TypeKeyName) {
778 ERROR("Found constant of type %s, expected a key name\n",
779 exprTypeText(expr->type));
782 memcpy(val_rtrn->name, expr->value.keyName, XkbKeyNameLength);
786 ERROR("Identifier \"%s\" of type string not found\n",
787 xkb_atom_text(ctx, expr->value.str));
791 ERROR("Default \"%s.%s\" of type key name not found\n",
792 xkb_atom_text(ctx, expr->value.field.element),
793 xkb_atom_text(ctx, expr->value.field.field));
801 bogus = "Subtraction";
804 bogus = "Multiplication";
810 bogus = "Assignment";
816 bogus = "Bitwise complement";
817 ERROR("%s of key name values not permitted\n", bogus);
821 ERROR("The ! operator cannot be applied to a key name\n");
825 ERROR("The + operator cannot be applied to a key name\n");
829 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
835 /***====================================================================***/
838 ExprResolveEnum(struct xkb_context *ctx, ExprDef *expr,
839 ExprResult *val_rtrn, const LookupEntry *values)
841 if (expr->op != ExprIdent) {
842 ERROR("Found a %s where an enumerated value was expected\n",
843 exprOpText(expr->op));
846 if (!SimpleLookup(ctx, values, expr->value.str, TypeInt, val_rtrn)) {
848 ERROR("Illegal identifier %s (expected one of: ",
849 xkb_atom_text(ctx, expr->value.str));
850 while (values && values->name)
853 INFO(", %s", values->name);
855 INFO("%s", values->name);
866 ExprResolveMaskLookup(struct xkb_context *ctx, ExprDef *expr,
867 ExprResult *val_rtrn, IdentLookupFunc lookup,
868 const void *lookupPriv)
871 ExprResult leftRtrn, rightRtrn;
872 ExprDef *left, *right;
873 const char *bogus = NULL;
877 if (expr->type != TypeInt) {
879 ("Found constant of type %s where a mask was expected\n",
880 exprTypeText(expr->type));
883 val_rtrn->ival = expr->value.ival;
887 ok = lookup(ctx, lookupPriv, expr->value.str, TypeInt, val_rtrn);
889 ERROR("Identifier \"%s\" of type int is unknown\n",
890 xkb_atom_text(ctx, expr->value.str));
894 ERROR("Default \"%s.%s\" of type int is unknown\n",
895 xkb_atom_text(ctx, expr->value.field.element),
896 xkb_atom_text(ctx, expr->value.field.field));
900 bogus = "array reference";
904 bogus = "function use";
905 ERROR("Unexpected %s in mask expression\n", bogus);
906 ACTION("Expression ignored\n");
913 left = expr->value.binary.left;
914 right = expr->value.binary.right;
915 if (ExprResolveMaskLookup(ctx, left, &leftRtrn, lookup,
917 ExprResolveMaskLookup(ctx, right, &rightRtrn, lookup,
921 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
924 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
928 ERROR("Cannot %s masks\n",
929 expr->op == OpDivide ? "divide" : "multiply");
930 ACTION("Illegal operation ignored\n");
938 WSGO("Assignment operator not implemented yet\n");
942 left = expr->value.child;
943 if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
945 val_rtrn->ival = ~leftRtrn.ival;
953 left = expr->value.child;
954 if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
956 ERROR("The %s operator cannot be used with a mask\n",
957 (expr->op == OpNegate ? "-" : "!"));
962 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
969 ExprResolveMask(struct xkb_context *ctx, ExprDef *expr,
970 ExprResult *val_rtrn, const LookupEntry *values)
972 return ExprResolveMaskLookup(ctx, expr, val_rtrn, SimpleLookup, values);
976 ExprResolveModMask(struct xkb_context *ctx, ExprDef *expr,
977 ExprResult *val_rtrn)
979 return ExprResolveMaskLookup(ctx, expr, val_rtrn, LookupModMask, NULL);
983 ExprResolveVModMask(ExprDef *expr, ExprResult *val_rtrn,
984 struct xkb_keymap *keymap)
986 return ExprResolveMaskLookup(keymap->ctx, expr, val_rtrn, LookupVModMask,
991 ExprResolveKeySym(struct xkb_context *ctx, ExprDef *expr,
992 ExprResult *val_rtrn)
997 if (expr->op == ExprIdent) {
999 str = xkb_atom_text(ctx, expr->value.str);
1001 sym = xkb_keysym_from_name(str);
1002 if (sym != XKB_KEY_NoSymbol) {
1003 val_rtrn->uval = sym;
1008 ok = ExprResolveInteger(ctx, expr, val_rtrn);
1009 if ((ok) && (val_rtrn->uval < 10))
1010 val_rtrn->uval += '0';