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(ExprDef * expr,
132 ExprResult * elem_rtrn,
133 ExprResult * field_rtrn, ExprDef ** index_rtrn)
138 elem_rtrn->str = NULL;
139 field_rtrn->str = XkbcAtomGetString(expr->value.str);
143 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
144 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
148 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
149 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
150 *index_rtrn = expr->value.array.entry;
153 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
158 SimpleLookup(const void * priv, xkb_atom_t field, unsigned type,
159 ExprResult * val_rtrn)
161 const LookupEntry *entry;
164 if ((priv == NULL) || (field == XKB_ATOM_NONE) || (type != TypeInt))
168 str = XkbcAtomText(field);
169 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
171 if (strcasecmp(str, entry->name) == 0)
173 val_rtrn->uval = entry->result;
180 static const LookupEntry modIndexNames[] = {
181 {"shift", ShiftMapIndex},
182 {"control", ControlMapIndex},
183 {"lock", LockMapIndex},
184 {"mod1", Mod1MapIndex},
185 {"mod2", Mod2MapIndex},
186 {"mod3", Mod3MapIndex},
187 {"mod4", Mod4MapIndex},
188 {"mod5", Mod5MapIndex},
189 {"none", XkbNoModifier},
194 LookupModIndex(const void * priv, xkb_atom_t field, unsigned type,
195 ExprResult * val_rtrn)
197 return SimpleLookup(modIndexNames, field, type, val_rtrn);
201 LookupModMask(const void * priv, xkb_atom_t field, unsigned type,
202 ExprResult * val_rtrn)
209 str = XkbcAtomText(field);
212 if (strcasecmp(str, "all") == 0)
213 val_rtrn->uval = 0xff;
214 else if (strcasecmp(str, "none") == 0)
216 else if (LookupModIndex(priv, field, type, val_rtrn))
217 val_rtrn->uval = (1 << val_rtrn->uval);
224 ExprResolveBoolean(ExprDef * expr,
225 ExprResult * val_rtrn)
228 const char *bogus = NULL;
233 if (expr->type != TypeBoolean)
236 ("Found constant of type %s where boolean was expected\n",
237 exprTypeText(expr->type));
240 val_rtrn->ival = expr->value.ival;
243 bogus = XkbcAtomText(expr->value.str);
246 if ((strcasecmp(bogus, "true") == 0) ||
247 (strcasecmp(bogus, "yes") == 0) ||
248 (strcasecmp(bogus, "on") == 0))
253 else if ((strcasecmp(bogus, "false") == 0) ||
254 (strcasecmp(bogus, "no") == 0) ||
255 (strcasecmp(bogus, "off") == 0))
261 ERROR("Identifier \"%s\" of type int is unknown\n",
262 XkbcAtomText(expr->value.str));
265 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
266 XkbcAtomText(expr->value.field.element),
267 XkbcAtomText(expr->value.field.field));
271 ok = ExprResolveBoolean(expr, val_rtrn);
273 val_rtrn->uval = !val_rtrn->uval;
280 bogus = "Subtraction";
283 bogus = "Multiplication";
289 bogus = "Assignment";
293 ERROR("%s of boolean values not permitted\n", bogus);
296 ERROR("Unary \"+\" operator not permitted for boolean values\n");
299 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
306 ExprResolveFloat(ExprDef * expr,
307 ExprResult * val_rtrn)
310 ExprResult leftRtrn, rightRtrn;
311 ExprDef *left, *right;
316 if (expr->type == TypeString)
319 str = XkbcAtomText(expr->value.str);
320 if ((str != NULL) && (strlen(str) == 1))
322 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
326 if (expr->type != TypeInt)
328 ERROR("Found constant of type %s, expected a number\n",
329 exprTypeText(expr->type));
332 val_rtrn->ival = expr->value.ival;
333 if (expr->type == TypeInt)
334 val_rtrn->ival *= XkbGeomPtsPerMM;
337 ERROR("Numeric identifier \"%s\" unknown\n",
338 XkbcAtomText(expr->value.str));
341 ERROR("Numeric default \"%s.%s\" unknown\n",
342 XkbcAtomText(expr->value.field.element),
343 XkbcAtomText(expr->value.field.field));
349 left = expr->value.binary.left;
350 right = expr->value.binary.right;
351 if (ExprResolveFloat(left, &leftRtrn) &&
352 ExprResolveFloat(right, &rightRtrn))
357 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
360 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
363 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
366 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
373 WSGO("Assignment operator not implemented yet\n");
376 ERROR("The ! operator cannot be applied to a number\n");
380 left = expr->value.child;
381 if (ExprResolveFloat(left, &leftRtrn))
383 if (expr->op == OpNegate)
384 val_rtrn->ival = -leftRtrn.ival;
386 val_rtrn->ival = ~leftRtrn.ival;
391 left = expr->value.child;
392 return ExprResolveFloat(left, val_rtrn);
394 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
401 ExprResolveKeyCode(ExprDef * expr,
402 ExprResult * val_rtrn)
404 ExprResult leftRtrn, rightRtrn;
405 ExprDef *left, *right;
410 if (expr->type != TypeInt)
413 ("Found constant of type %s where an int was expected\n",
414 exprTypeText(expr->type));
417 val_rtrn->uval = expr->value.uval;
423 left = expr->value.binary.left;
424 right = expr->value.binary.right;
425 if (ExprResolveKeyCode(left, &leftRtrn) &&
426 ExprResolveKeyCode(right, &rightRtrn))
431 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
434 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
437 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
440 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
447 left = expr->value.child;
448 if (ExprResolveKeyCode(left, &leftRtrn))
450 val_rtrn->uval = ~leftRtrn.uval;
455 left = expr->value.child;
456 return ExprResolveKeyCode(left, val_rtrn);
458 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
465 * This function returns ... something. It's a bit of a guess, really.
467 * If a string is given in value context, its first character will be
468 * returned in uval. If an integer is given in value context, it will be
469 * returned in ival. If a float is given in value context, it will be
470 * returned as millimetres (rather than points) in ival.
472 * If an ident or field reference is given, the lookup function (if given)
473 * will be called. At the moment, only SimpleLookup use this, and they both
474 * return the results in uval. And don't support field references.
479 ExprResolveIntegerLookup(ExprDef * expr,
480 ExprResult * val_rtrn,
481 IdentLookupFunc lookup, const void * lookupPriv)
484 ExprResult leftRtrn, rightRtrn;
485 ExprDef *left, *right;
490 if (expr->type == TypeString)
493 str = XkbcAtomText(expr->value.str);
501 val_rtrn->uval = str[0];
507 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) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
522 ERROR("Identifier \"%s\" of type int is unknown\n",
523 XkbcAtomText(expr->value.str));
526 ERROR("Default \"%s.%s\" of type int is unknown\n",
527 XkbcAtomText(expr->value.field.element),
528 XkbcAtomText(expr->value.field.field));
534 left = expr->value.binary.left;
535 right = expr->value.binary.right;
536 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
537 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
542 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
545 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
548 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
551 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
558 WSGO("Assignment operator not implemented yet\n");
561 ERROR("The ! operator cannot be applied to an integer\n");
565 left = expr->value.child;
566 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
568 if (expr->op == OpNegate)
569 val_rtrn->ival = -leftRtrn.ival;
571 val_rtrn->ival = ~leftRtrn.ival;
576 left = expr->value.child;
577 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
579 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
586 ExprResolveInteger(ExprDef * expr,
587 ExprResult * val_rtrn)
589 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
593 ExprResolveGroup(ExprDef * expr,
594 ExprResult * val_rtrn)
597 static const LookupEntry group_names[] = {
609 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
613 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
614 ERROR("Group index %d is out of range (1..%d)\n",
615 val_rtrn->uval, XkbNumKbdGroups);
623 ExprResolveLevel(ExprDef * expr,
624 ExprResult * val_rtrn)
627 static const LookupEntry level_names[] = {
639 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, level_names);
643 if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) {
644 ERROR("Shift level %d is out of range (1..%d)\n", val_rtrn->ival,
653 ExprResolveButton(ExprDef * expr,
654 ExprResult * val_rtrn)
656 static const LookupEntry button_names[] = {
666 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
671 ExprResolveString(ExprDef * expr,
672 ExprResult * val_rtrn)
674 ExprResult leftRtrn, rightRtrn;
677 const char *bogus = NULL;
682 if (expr->type != TypeString)
684 ERROR("Found constant of type %s, expected a string\n",
685 exprTypeText(expr->type));
688 val_rtrn->str = XkbcAtomGetString(expr->value.str);
689 if (val_rtrn->str == NULL)
690 val_rtrn->str = strdup("");
693 ERROR("Identifier \"%s\" of type string not found\n",
694 XkbcAtomText(expr->value.str));
697 ERROR("Default \"%s.%s\" of type string not found\n",
698 XkbcAtomText(expr->value.field.element),
699 XkbcAtomText(expr->value.field.field));
702 left = expr->value.binary.left;
703 right = expr->value.binary.right;
704 if (ExprResolveString(left, &leftRtrn) &&
705 ExprResolveString(right, &rightRtrn))
709 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
712 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
724 bogus = "Subtraction";
727 bogus = "Multiplication";
733 bogus = "Assignment";
739 bogus = "Bitwise complement";
740 ERROR("%s of string values not permitted\n", bogus);
743 ERROR("The ! operator cannot be applied to a string\n");
746 ERROR("The + operator cannot be applied to a string\n");
749 WSGO("Unknown operator %d in ResolveString\n", expr->op);
756 ExprResolveKeyName(ExprDef * expr,
757 ExprResult * val_rtrn)
759 const char *bogus = NULL;
764 if (expr->type != TypeKeyName)
766 ERROR("Found constant of type %s, expected a key name\n",
767 exprTypeText(expr->type));
770 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
773 ERROR("Identifier \"%s\" of type string not found\n",
774 XkbcAtomText(expr->value.str));
777 ERROR("Default \"%s.%s\" of type key name not found\n",
778 XkbcAtomText(expr->value.field.element),
779 XkbcAtomText(expr->value.field.field));
786 bogus = "Subtraction";
789 bogus = "Multiplication";
795 bogus = "Assignment";
801 bogus = "Bitwise complement";
802 ERROR("%s of key name values not permitted\n", bogus);
805 ERROR("The ! operator cannot be applied to a key name\n");
808 ERROR("The + operator cannot be applied to a key name\n");
811 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
817 /***====================================================================***/
820 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, const LookupEntry * values)
822 if (expr->op != ExprIdent)
824 ERROR("Found a %s where an enumerated value was expected\n",
825 exprOpText(expr->op));
828 if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
831 ERROR("Illegal identifier %s (expected one of: ",
832 XkbcAtomText(expr->value.str));
833 while (values && values->name)
836 INFO(", %s", values->name);
838 INFO("%s", values->name);
849 ExprResolveMaskLookup(ExprDef * expr,
850 ExprResult * val_rtrn,
851 IdentLookupFunc lookup,
852 const void * lookupPriv)
855 ExprResult leftRtrn, rightRtrn;
856 ExprDef *left, *right;
857 const char *bogus = NULL;
862 if (expr->type != TypeInt)
865 ("Found constant of type %s where a mask was expected\n",
866 exprTypeText(expr->type));
869 val_rtrn->ival = expr->value.ival;
872 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
874 ERROR("Identifier \"%s\" of type int is unknown\n",
875 XkbcAtomText(expr->value.str));
878 ERROR("Default \"%s.%s\" of type int is unknown\n",
879 XkbcAtomText(expr->value.field.element),
880 XkbcAtomText(expr->value.field.field));
883 bogus = "array reference";
886 bogus = "function use";
887 ERROR("Unexpected %s in mask expression\n", bogus);
888 ACTION("Expression ignored\n");
894 left = expr->value.binary.left;
895 right = expr->value.binary.right;
896 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
897 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
902 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
905 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
909 ERROR("Cannot %s masks\n",
910 expr->op == OpDivide ? "divide" : "multiply");
911 ACTION("Illegal operation ignored\n");
918 WSGO("Assignment operator not implemented yet\n");
921 left = expr->value.child;
922 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
924 val_rtrn->ival = ~leftRtrn.ival;
931 left = expr->value.child;
932 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
934 ERROR("The %s operator cannot be used with a mask\n",
935 (expr->op == OpNegate ? "-" : "!"));
939 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
946 ExprResolveMask(ExprDef * expr,
947 ExprResult * val_rtrn,
948 const LookupEntry * values)
950 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
954 ExprResolveModMask(ExprDef * expr,
955 ExprResult * val_rtrn)
957 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
961 ExprResolveVModMask(ExprDef * expr,
962 ExprResult * val_rtrn,
963 struct xkb_keymap *xkb)
965 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, xkb);
969 ExprResolveKeySym(ExprDef * expr,
970 ExprResult * val_rtrn)
975 if (expr->op == ExprIdent)
978 str = XkbcAtomText(expr->value.str);
980 sym = xkb_string_to_keysym(str);
981 if (sym != XKB_KEYSYM_NO_SYMBOL) {
982 val_rtrn->uval = sym;
987 ok = ExprResolveInteger(expr, val_rtrn);
988 if ((ok) && (val_rtrn->uval < 10))
989 val_rtrn->uval += '0';