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 ********************************************************/
36 /***====================================================================***/
38 typedef bool (*IdentLookupFunc) (const void *priv, xkb_atom_t field,
39 unsigned type, ExprResult *val_rtrn);
41 /***====================================================================***/
44 exprOpText(unsigned type)
51 strcpy(buf, "literal");
54 strcpy(buf, "identifier");
57 strcpy(buf, "action declaration");
60 strcpy(buf, "field reference");
63 strcpy(buf, "array reference");
66 strcpy(buf, "list of keysyms");
69 strcpy(buf, "list of actions");
72 strcpy(buf, "addition");
75 strcpy(buf, "subtraction");
78 strcpy(buf, "multiplication");
81 strcpy(buf, "division");
84 strcpy(buf, "assignment");
87 strcpy(buf, "logical not");
90 strcpy(buf, "arithmetic negation");
93 strcpy(buf, "bitwise inversion");
96 strcpy(buf, "plus sign");
99 snprintf(buf, sizeof(buf), "illegal(%d)", type);
106 exprTypeText(unsigned type)
113 strcpy(buf, "unknown");
116 strcpy(buf, "boolean");
122 strcpy(buf, "string");
125 strcpy(buf, "action");
128 strcpy(buf, "keyname");
131 snprintf(buf, sizeof(buf), "illegal(%d)", type);
138 ExprResolveLhs(ExprDef * expr,
139 ExprResult * elem_rtrn,
140 ExprResult * field_rtrn, ExprDef ** index_rtrn)
145 elem_rtrn->str = NULL;
146 field_rtrn->str = XkbcAtomGetString(expr->value.str);
150 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
151 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
155 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
156 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
157 *index_rtrn = expr->value.array.entry;
160 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
165 SimpleLookup(const void * priv, xkb_atom_t field, unsigned type,
166 ExprResult * val_rtrn)
168 const LookupEntry *entry;
171 if ((priv == NULL) || (field == XKB_ATOM_NONE) || (type != TypeInt))
175 str = XkbcAtomText(field);
176 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
178 if (strcasecmp(str, entry->name) == 0)
180 val_rtrn->uval = entry->result;
187 static const LookupEntry modIndexNames[] = {
188 {"shift", ShiftMapIndex},
189 {"control", ControlMapIndex},
190 {"lock", LockMapIndex},
191 {"mod1", Mod1MapIndex},
192 {"mod2", Mod2MapIndex},
193 {"mod3", Mod3MapIndex},
194 {"mod4", Mod4MapIndex},
195 {"mod5", Mod5MapIndex},
196 {"none", XkbNoModifier},
201 LookupModIndex(const void * priv, xkb_atom_t field, unsigned type,
202 ExprResult * val_rtrn)
204 return SimpleLookup(modIndexNames, field, type, val_rtrn);
208 LookupModMask(const void * priv, xkb_atom_t field, unsigned type,
209 ExprResult * val_rtrn)
216 str = XkbcAtomText(field);
219 if (strcasecmp(str, "all") == 0)
220 val_rtrn->uval = 0xff;
221 else if (strcasecmp(str, "none") == 0)
223 else if (LookupModIndex(priv, field, type, val_rtrn))
224 val_rtrn->uval = (1 << val_rtrn->uval);
231 ExprResolveBoolean(ExprDef * expr,
232 ExprResult * val_rtrn)
235 const char *bogus = NULL;
240 if (expr->type != TypeBoolean)
243 ("Found constant of type %s where boolean was expected\n",
244 exprTypeText(expr->type));
247 val_rtrn->ival = expr->value.ival;
250 bogus = XkbcAtomText(expr->value.str);
253 if ((strcasecmp(bogus, "true") == 0) ||
254 (strcasecmp(bogus, "yes") == 0) ||
255 (strcasecmp(bogus, "on") == 0))
260 else if ((strcasecmp(bogus, "false") == 0) ||
261 (strcasecmp(bogus, "no") == 0) ||
262 (strcasecmp(bogus, "off") == 0))
268 ERROR("Identifier \"%s\" of type int is unknown\n",
269 XkbcAtomText(expr->value.str));
272 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
273 XkbcAtomText(expr->value.field.element),
274 XkbcAtomText(expr->value.field.field));
278 ok = ExprResolveBoolean(expr, val_rtrn);
280 val_rtrn->uval = !val_rtrn->uval;
287 bogus = "Subtraction";
290 bogus = "Multiplication";
296 bogus = "Assignment";
300 ERROR("%s of boolean values not permitted\n", bogus);
303 ERROR("Unary \"+\" operator not permitted for boolean values\n");
306 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
313 ExprResolveFloat(ExprDef * expr,
314 ExprResult * val_rtrn)
317 ExprResult leftRtrn, rightRtrn;
318 ExprDef *left, *right;
323 if (expr->type == TypeString)
326 str = XkbcAtomText(expr->value.str);
327 if ((str != NULL) && (strlen(str) == 1))
329 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
333 if (expr->type != TypeInt)
335 ERROR("Found constant of type %s, expected a number\n",
336 exprTypeText(expr->type));
339 val_rtrn->ival = expr->value.ival;
340 if (expr->type == TypeInt)
341 val_rtrn->ival *= XkbGeomPtsPerMM;
344 ERROR("Numeric identifier \"%s\" unknown\n",
345 XkbcAtomText(expr->value.str));
348 ERROR("Numeric default \"%s.%s\" unknown\n",
349 XkbcAtomText(expr->value.field.element),
350 XkbcAtomText(expr->value.field.field));
356 left = expr->value.binary.left;
357 right = expr->value.binary.right;
358 if (ExprResolveFloat(left, &leftRtrn) &&
359 ExprResolveFloat(right, &rightRtrn))
364 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
367 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
370 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
373 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
380 WSGO("Assignment operator not implemented yet\n");
383 ERROR("The ! operator cannot be applied to a number\n");
387 left = expr->value.child;
388 if (ExprResolveFloat(left, &leftRtrn))
390 if (expr->op == OpNegate)
391 val_rtrn->ival = -leftRtrn.ival;
393 val_rtrn->ival = ~leftRtrn.ival;
398 left = expr->value.child;
399 return ExprResolveFloat(left, val_rtrn);
401 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
408 ExprResolveKeyCode(ExprDef * expr,
409 ExprResult * val_rtrn)
411 ExprResult leftRtrn, rightRtrn;
412 ExprDef *left, *right;
417 if (expr->type != TypeInt)
420 ("Found constant of type %s where an int was expected\n",
421 exprTypeText(expr->type));
424 val_rtrn->uval = expr->value.uval;
430 left = expr->value.binary.left;
431 right = expr->value.binary.right;
432 if (ExprResolveKeyCode(left, &leftRtrn) &&
433 ExprResolveKeyCode(right, &rightRtrn))
438 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
441 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
444 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
447 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
454 left = expr->value.child;
455 if (ExprResolveKeyCode(left, &leftRtrn))
457 val_rtrn->uval = ~leftRtrn.uval;
462 left = expr->value.child;
463 return ExprResolveKeyCode(left, val_rtrn);
465 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
472 * This function returns ... something. It's a bit of a guess, really.
474 * If a string is given in value context, its first character will be
475 * returned in uval. If an integer is given in value context, it will be
476 * returned in ival. If a float is given in value context, it will be
477 * returned as millimetres (rather than points) in ival.
479 * If an ident or field reference is given, the lookup function (if given)
480 * will be called. At the moment, only SimpleLookup use this, and they both
481 * return the results in uval. And don't support field references.
486 ExprResolveIntegerLookup(ExprDef * expr,
487 ExprResult * val_rtrn,
488 IdentLookupFunc lookup, const void * lookupPriv)
491 ExprResult leftRtrn, rightRtrn;
492 ExprDef *left, *right;
497 if (expr->type == TypeString)
500 str = XkbcAtomText(expr->value.str);
508 val_rtrn->uval = str[0];
514 if (expr->type != TypeInt)
517 ("Found constant of type %s where an int was expected\n",
518 exprTypeText(expr->type));
521 val_rtrn->ival = expr->value.ival;
526 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
529 ERROR("Identifier \"%s\" of type int is unknown\n",
530 XkbcAtomText(expr->value.str));
533 ERROR("Default \"%s.%s\" of type int is unknown\n",
534 XkbcAtomText(expr->value.field.element),
535 XkbcAtomText(expr->value.field.field));
541 left = expr->value.binary.left;
542 right = expr->value.binary.right;
543 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
544 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
549 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
552 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
555 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
558 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
565 WSGO("Assignment operator not implemented yet\n");
568 ERROR("The ! operator cannot be applied to an integer\n");
572 left = expr->value.child;
573 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
575 if (expr->op == OpNegate)
576 val_rtrn->ival = -leftRtrn.ival;
578 val_rtrn->ival = ~leftRtrn.ival;
583 left = expr->value.child;
584 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
586 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
593 ExprResolveInteger(ExprDef * expr,
594 ExprResult * val_rtrn)
596 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
600 ExprResolveGroup(ExprDef * expr,
601 ExprResult * val_rtrn)
604 static const LookupEntry group_names[] = {
616 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
620 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
621 ERROR("Group index %d is out of range (1..%d)\n",
622 val_rtrn->uval, XkbNumKbdGroups);
630 ExprResolveLevel(ExprDef * expr,
631 ExprResult * val_rtrn)
634 static const LookupEntry level_names[] = {
646 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, level_names);
650 if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) {
651 ERROR("Shift level %d is out of range (1..%d)\n", val_rtrn->ival,
660 ExprResolveButton(ExprDef * expr,
661 ExprResult * val_rtrn)
663 static const LookupEntry button_names[] = {
673 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
678 ExprResolveString(ExprDef * expr,
679 ExprResult * val_rtrn)
681 ExprResult leftRtrn, rightRtrn;
684 const char *bogus = NULL;
689 if (expr->type != TypeString)
691 ERROR("Found constant of type %s, expected a string\n",
692 exprTypeText(expr->type));
695 val_rtrn->str = XkbcAtomGetString(expr->value.str);
696 if (val_rtrn->str == NULL)
697 val_rtrn->str = strdup("");
700 ERROR("Identifier \"%s\" of type string not found\n",
701 XkbcAtomText(expr->value.str));
704 ERROR("Default \"%s.%s\" of type string not found\n",
705 XkbcAtomText(expr->value.field.element),
706 XkbcAtomText(expr->value.field.field));
709 left = expr->value.binary.left;
710 right = expr->value.binary.right;
711 if (ExprResolveString(left, &leftRtrn) &&
712 ExprResolveString(right, &rightRtrn))
716 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
719 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
731 bogus = "Subtraction";
734 bogus = "Multiplication";
740 bogus = "Assignment";
746 bogus = "Bitwise complement";
747 ERROR("%s of string values not permitted\n", bogus);
750 ERROR("The ! operator cannot be applied to a string\n");
753 ERROR("The + operator cannot be applied to a string\n");
756 WSGO("Unknown operator %d in ResolveString\n", expr->op);
763 ExprResolveKeyName(ExprDef * expr,
764 ExprResult * val_rtrn)
766 const char *bogus = NULL;
771 if (expr->type != TypeKeyName)
773 ERROR("Found constant of type %s, expected a key name\n",
774 exprTypeText(expr->type));
777 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
780 ERROR("Identifier \"%s\" of type string not found\n",
781 XkbcAtomText(expr->value.str));
784 ERROR("Default \"%s.%s\" of type key name not found\n",
785 XkbcAtomText(expr->value.field.element),
786 XkbcAtomText(expr->value.field.field));
793 bogus = "Subtraction";
796 bogus = "Multiplication";
802 bogus = "Assignment";
808 bogus = "Bitwise complement";
809 ERROR("%s of key name values not permitted\n", bogus);
812 ERROR("The ! operator cannot be applied to a key name\n");
815 ERROR("The + operator cannot be applied to a key name\n");
818 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
824 /***====================================================================***/
827 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, const LookupEntry * values)
829 if (expr->op != ExprIdent)
831 ERROR("Found a %s where an enumerated value was expected\n",
832 exprOpText(expr->op));
835 if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
838 ERROR("Illegal identifier %s (expected one of: ",
839 XkbcAtomText(expr->value.str));
840 while (values && values->name)
843 INFO(", %s", values->name);
845 INFO("%s", values->name);
856 ExprResolveMaskLookup(ExprDef * expr,
857 ExprResult * val_rtrn,
858 IdentLookupFunc lookup,
859 const void * lookupPriv)
862 ExprResult leftRtrn, rightRtrn;
863 ExprDef *left, *right;
864 const char *bogus = NULL;
869 if (expr->type != TypeInt)
872 ("Found constant of type %s where a mask was expected\n",
873 exprTypeText(expr->type));
876 val_rtrn->ival = expr->value.ival;
879 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
881 ERROR("Identifier \"%s\" of type int is unknown\n",
882 XkbcAtomText(expr->value.str));
885 ERROR("Default \"%s.%s\" of type int is unknown\n",
886 XkbcAtomText(expr->value.field.element),
887 XkbcAtomText(expr->value.field.field));
890 bogus = "array reference";
893 bogus = "function use";
894 ERROR("Unexpected %s in mask expression\n", bogus);
895 ACTION("Expression ignored\n");
901 left = expr->value.binary.left;
902 right = expr->value.binary.right;
903 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
904 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
909 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
912 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
916 ERROR("Cannot %s masks\n",
917 expr->op == OpDivide ? "divide" : "multiply");
918 ACTION("Illegal operation ignored\n");
925 WSGO("Assignment operator not implemented yet\n");
928 left = expr->value.child;
929 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
931 val_rtrn->ival = ~leftRtrn.ival;
938 left = expr->value.child;
939 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
941 ERROR("The %s operator cannot be used with a mask\n",
942 (expr->op == OpNegate ? "-" : "!"));
946 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
953 ExprResolveMask(ExprDef * expr,
954 ExprResult * val_rtrn,
955 const LookupEntry * values)
957 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
961 ExprResolveModMask(ExprDef * expr,
962 ExprResult * val_rtrn)
964 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
968 ExprResolveVModMask(ExprDef * expr,
969 ExprResult * val_rtrn,
970 struct xkb_keymap *xkb)
972 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, xkb);
976 ExprResolveKeySym(ExprDef * expr,
977 ExprResult * val_rtrn)
982 if (expr->op == ExprIdent)
985 str = XkbcAtomText(expr->value.str);
987 sym = xkb_string_to_keysym(str);
988 if (sym != XKB_KEYSYM_NO_SYMBOL) {
989 val_rtrn->uval = sym;
994 ok = ExprResolveInteger(expr, val_rtrn);
995 if ((ok) && (val_rtrn->uval < 10))
996 val_rtrn->uval += '0';