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 ********************************************************/
35 /***====================================================================***/
37 typedef Bool(*IdentLookupFunc) (const void * /* priv */ ,
38 xkb_atom_t /* field */ ,
40 ExprResult * /* val_rtrn */
43 /***====================================================================***/
46 exprOpText(unsigned type)
53 strcpy(buf, "literal");
56 strcpy(buf, "identifier");
59 strcpy(buf, "action declaration");
62 strcpy(buf, "field reference");
65 strcpy(buf, "array reference");
68 strcpy(buf, "list of keysyms");
71 strcpy(buf, "list of actions");
74 strcpy(buf, "addition");
77 strcpy(buf, "subtraction");
80 strcpy(buf, "multiplication");
83 strcpy(buf, "division");
86 strcpy(buf, "assignment");
89 strcpy(buf, "logical not");
92 strcpy(buf, "arithmetic negation");
95 strcpy(buf, "bitwise inversion");
98 strcpy(buf, "plus sign");
101 snprintf(buf, sizeof(buf), "illegal(%d)", type);
108 exprTypeText(unsigned type)
115 strcpy(buf, "unknown");
118 strcpy(buf, "boolean");
124 strcpy(buf, "string");
127 strcpy(buf, "action");
130 strcpy(buf, "keyname");
133 snprintf(buf, sizeof(buf), "illegal(%d)", type);
140 ExprResolveLhs(ExprDef * expr,
141 ExprResult * elem_rtrn,
142 ExprResult * field_rtrn, ExprDef ** index_rtrn)
147 elem_rtrn->str = NULL;
148 field_rtrn->str = XkbcAtomGetString(expr->value.str);
152 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
153 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
157 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
158 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
159 *index_rtrn = expr->value.array.entry;
162 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
167 SimpleLookup(const void * priv, xkb_atom_t field, unsigned type,
168 ExprResult * val_rtrn)
170 const LookupEntry *entry;
173 if ((priv == NULL) || (field == XKB_ATOM_NONE) || (type != TypeInt))
177 str = XkbcAtomText(field);
178 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
180 if (strcasecmp(str, entry->name) == 0)
182 val_rtrn->uval = entry->result;
189 static const LookupEntry modIndexNames[] = {
190 {"shift", ShiftMapIndex},
191 {"control", ControlMapIndex},
192 {"lock", LockMapIndex},
193 {"mod1", Mod1MapIndex},
194 {"mod2", Mod2MapIndex},
195 {"mod3", Mod3MapIndex},
196 {"mod4", Mod4MapIndex},
197 {"mod5", Mod5MapIndex},
198 {"none", XkbNoModifier},
203 LookupModIndex(const void * priv, xkb_atom_t field, unsigned type,
204 ExprResult * val_rtrn)
206 return SimpleLookup(modIndexNames, field, type, val_rtrn);
210 LookupModMask(const void * priv, xkb_atom_t field, unsigned type,
211 ExprResult * val_rtrn)
218 str = XkbcAtomText(field);
221 if (strcasecmp(str, "all") == 0)
222 val_rtrn->uval = 0xff;
223 else if (strcasecmp(str, "none") == 0)
225 else if (LookupModIndex(priv, field, type, val_rtrn))
226 val_rtrn->uval = (1 << val_rtrn->uval);
233 ExprResolveBoolean(ExprDef * expr,
234 ExprResult * val_rtrn)
237 const char *bogus = NULL;
242 if (expr->type != TypeBoolean)
245 ("Found constant of type %s where boolean was expected\n",
246 exprTypeText(expr->type));
249 val_rtrn->ival = expr->value.ival;
252 bogus = XkbcAtomText(expr->value.str);
255 if ((strcasecmp(bogus, "true") == 0) ||
256 (strcasecmp(bogus, "yes") == 0) ||
257 (strcasecmp(bogus, "on") == 0))
262 else if ((strcasecmp(bogus, "false") == 0) ||
263 (strcasecmp(bogus, "no") == 0) ||
264 (strcasecmp(bogus, "off") == 0))
270 ERROR("Identifier \"%s\" of type int is unknown\n",
271 XkbcAtomText(expr->value.str));
274 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
275 XkbcAtomText(expr->value.field.element),
276 XkbcAtomText(expr->value.field.field));
280 ok = ExprResolveBoolean(expr, val_rtrn);
282 val_rtrn->uval = !val_rtrn->uval;
289 bogus = "Subtraction";
292 bogus = "Multiplication";
298 bogus = "Assignment";
302 ERROR("%s of boolean values not permitted\n", bogus);
305 ERROR("Unary \"+\" operator not permitted for boolean values\n");
308 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
315 ExprResolveFloat(ExprDef * expr,
316 ExprResult * val_rtrn)
319 ExprResult leftRtrn, rightRtrn;
320 ExprDef *left, *right;
325 if (expr->type == TypeString)
328 str = XkbcAtomText(expr->value.str);
329 if ((str != NULL) && (strlen(str) == 1))
331 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
335 if (expr->type != TypeInt)
337 ERROR("Found constant of type %s, expected a number\n",
338 exprTypeText(expr->type));
341 val_rtrn->ival = expr->value.ival;
342 if (expr->type == TypeInt)
343 val_rtrn->ival *= XkbGeomPtsPerMM;
346 ERROR("Numeric identifier \"%s\" unknown\n",
347 XkbcAtomText(expr->value.str));
350 ERROR("Numeric default \"%s.%s\" unknown\n",
351 XkbcAtomText(expr->value.field.element),
352 XkbcAtomText(expr->value.field.field));
358 left = expr->value.binary.left;
359 right = expr->value.binary.right;
360 if (ExprResolveFloat(left, &leftRtrn) &&
361 ExprResolveFloat(right, &rightRtrn))
366 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
369 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
372 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
375 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
382 WSGO("Assignment operator not implemented yet\n");
385 ERROR("The ! operator cannot be applied to a number\n");
389 left = expr->value.child;
390 if (ExprResolveFloat(left, &leftRtrn))
392 if (expr->op == OpNegate)
393 val_rtrn->ival = -leftRtrn.ival;
395 val_rtrn->ival = ~leftRtrn.ival;
400 left = expr->value.child;
401 return ExprResolveFloat(left, val_rtrn);
403 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
410 ExprResolveKeyCode(ExprDef * expr,
411 ExprResult * val_rtrn)
413 ExprResult leftRtrn, rightRtrn;
414 ExprDef *left, *right;
419 if (expr->type != TypeInt)
422 ("Found constant of type %s where an int was expected\n",
423 exprTypeText(expr->type));
426 val_rtrn->uval = expr->value.uval;
432 left = expr->value.binary.left;
433 right = expr->value.binary.right;
434 if (ExprResolveKeyCode(left, &leftRtrn) &&
435 ExprResolveKeyCode(right, &rightRtrn))
440 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
443 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
446 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
449 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
456 left = expr->value.child;
457 if (ExprResolveKeyCode(left, &leftRtrn))
459 val_rtrn->uval = ~leftRtrn.uval;
464 left = expr->value.child;
465 return ExprResolveKeyCode(left, val_rtrn);
467 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
474 * This function returns ... something. It's a bit of a guess, really.
476 * If a string is given in value context, its first character will be
477 * returned in uval. If an integer is given in value context, it will be
478 * returned in ival. If a float is given in value context, it will be
479 * returned as millimetres (rather than points) in ival.
481 * If an ident or field reference is given, the lookup function (if given)
482 * will be called. At the moment, only SimpleLookup use this, and they both
483 * return the results in uval. And don't support field references.
488 ExprResolveIntegerLookup(ExprDef * expr,
489 ExprResult * val_rtrn,
490 IdentLookupFunc lookup, const void * lookupPriv)
493 ExprResult leftRtrn, rightRtrn;
494 ExprDef *left, *right;
499 if (expr->type == TypeString)
502 str = XkbcAtomText(expr->value.str);
510 val_rtrn->uval = str[0];
516 if (expr->type != TypeInt)
519 ("Found constant of type %s where an int was expected\n",
520 exprTypeText(expr->type));
523 val_rtrn->ival = expr->value.ival;
528 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
531 ERROR("Identifier \"%s\" of type int is unknown\n",
532 XkbcAtomText(expr->value.str));
535 ERROR("Default \"%s.%s\" of type int is unknown\n",
536 XkbcAtomText(expr->value.field.element),
537 XkbcAtomText(expr->value.field.field));
543 left = expr->value.binary.left;
544 right = expr->value.binary.right;
545 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
546 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
551 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
554 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
557 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
560 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
567 WSGO("Assignment operator not implemented yet\n");
570 ERROR("The ! operator cannot be applied to an integer\n");
574 left = expr->value.child;
575 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
577 if (expr->op == OpNegate)
578 val_rtrn->ival = -leftRtrn.ival;
580 val_rtrn->ival = ~leftRtrn.ival;
585 left = expr->value.child;
586 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
588 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
595 ExprResolveInteger(ExprDef * expr,
596 ExprResult * val_rtrn)
598 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
602 ExprResolveGroup(ExprDef * expr,
603 ExprResult * val_rtrn)
606 static const LookupEntry group_names[] = {
618 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
622 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
623 ERROR("Group index %d is out of range (1..%d)\n",
624 val_rtrn->uval, XkbNumKbdGroups);
632 ExprResolveLevel(ExprDef * expr,
633 ExprResult * val_rtrn)
636 static const LookupEntry level_names[] = {
648 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, level_names);
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(ExprDef * expr,
663 ExprResult * val_rtrn)
665 static const LookupEntry button_names[] = {
675 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
680 ExprResolveString(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 = XkbcAtomGetString(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 XkbcAtomText(expr->value.str));
706 ERROR("Default \"%s.%s\" of type string not found\n",
707 XkbcAtomText(expr->value.field.element),
708 XkbcAtomText(expr->value.field.field));
711 left = expr->value.binary.left;
712 right = expr->value.binary.right;
713 if (ExprResolveString(left, &leftRtrn) &&
714 ExprResolveString(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(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 XkbcAtomText(expr->value.str));
786 ERROR("Default \"%s.%s\" of type key name not found\n",
787 XkbcAtomText(expr->value.field.element),
788 XkbcAtomText(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(ExprDef * expr, ExprResult * val_rtrn, const LookupEntry * values)
831 if (expr->op != ExprIdent)
833 ERROR("Found a %s where an enumerated value was expected\n",
834 exprOpText(expr->op));
837 if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
840 ERROR("Illegal identifier %s (expected one of: ",
841 XkbcAtomText(expr->value.str));
842 while (values && values->name)
845 INFO(", %s", values->name);
847 INFO("%s", values->name);
858 ExprResolveMaskLookup(ExprDef * expr,
859 ExprResult * val_rtrn,
860 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) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
883 ERROR("Identifier \"%s\" of type int is unknown\n",
884 XkbcAtomText(expr->value.str));
887 ERROR("Default \"%s.%s\" of type int is unknown\n",
888 XkbcAtomText(expr->value.field.element),
889 XkbcAtomText(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(left, &leftRtrn, lookup, lookupPriv) &&
906 ExprResolveMaskLookup(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(left, &leftRtrn, lookup, lookupPriv))
933 val_rtrn->ival = ~leftRtrn.ival;
940 left = expr->value.child;
941 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
943 ERROR("The %s operator cannot be used with a mask\n",
944 (expr->op == OpNegate ? "-" : "!"));
948 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
955 ExprResolveMask(ExprDef * expr,
956 ExprResult * val_rtrn,
957 const LookupEntry * values)
959 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
963 ExprResolveModMask(ExprDef * expr,
964 ExprResult * val_rtrn)
966 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
970 ExprResolveVModMask(ExprDef * expr,
971 ExprResult * val_rtrn,
972 struct xkb_desc *xkb)
974 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, xkb);
978 ExprResolveKeySym(ExprDef * expr,
979 ExprResult * val_rtrn)
984 if (expr->op == ExprIdent)
987 str = XkbcAtomText(expr->value.str);
988 if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
990 val_rtrn->uval = sym;
994 ok = ExprResolveInteger(expr, val_rtrn);
995 if ((ok) && (val_rtrn->uval < 10))
996 val_rtrn->uval += '0';