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 ********************************************************/
34 /***====================================================================***/
36 typedef Bool(*IdentLookupFunc) (const void * /* priv */ ,
37 xkb_atom_t /* field */ ,
39 ExprResult * /* val_rtrn */
42 /***====================================================================***/
45 exprOpText(unsigned type)
52 strcpy(buf, "literal");
55 strcpy(buf, "identifier");
58 strcpy(buf, "action declaration");
61 strcpy(buf, "field reference");
64 strcpy(buf, "array reference");
67 strcpy(buf, "list of keysyms");
70 strcpy(buf, "list of actions");
73 strcpy(buf, "addition");
76 strcpy(buf, "subtraction");
79 strcpy(buf, "multiplication");
82 strcpy(buf, "division");
85 strcpy(buf, "assignment");
88 strcpy(buf, "logical not");
91 strcpy(buf, "arithmetic negation");
94 strcpy(buf, "bitwise inversion");
97 strcpy(buf, "plus sign");
100 snprintf(buf, sizeof(buf), "illegal(%d)", type);
107 exprTypeText(unsigned type)
114 strcpy(buf, "unknown");
117 strcpy(buf, "boolean");
123 strcpy(buf, "string");
126 strcpy(buf, "action");
129 strcpy(buf, "keyname");
132 snprintf(buf, sizeof(buf), "illegal(%d)", type);
139 ExprResolveLhs(ExprDef * expr,
140 ExprResult * elem_rtrn,
141 ExprResult * field_rtrn, ExprDef ** index_rtrn)
146 elem_rtrn->str = NULL;
147 field_rtrn->str = XkbcAtomGetString(expr->value.str);
151 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
152 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
156 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
157 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
158 *index_rtrn = expr->value.array.entry;
161 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
166 SimpleLookup(const void * priv, xkb_atom_t field, unsigned type,
167 ExprResult * val_rtrn)
169 const LookupEntry *entry;
172 if ((priv == NULL) || (field == None) || (type != TypeInt))
176 str = XkbcAtomText(field);
177 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
179 if (strcasecmp(str, entry->name) == 0)
181 val_rtrn->uval = entry->result;
188 static const LookupEntry modIndexNames[] = {
189 {"shift", ShiftMapIndex},
190 {"control", ControlMapIndex},
191 {"lock", LockMapIndex},
192 {"mod1", Mod1MapIndex},
193 {"mod2", Mod2MapIndex},
194 {"mod3", Mod3MapIndex},
195 {"mod4", Mod4MapIndex},
196 {"mod5", Mod5MapIndex},
197 {"none", XkbNoModifier},
202 LookupModIndex(const void * priv, xkb_atom_t field, unsigned type,
203 ExprResult * val_rtrn)
205 return SimpleLookup(modIndexNames, field, type, val_rtrn);
209 LookupModMask(const void * priv, xkb_atom_t field, unsigned type,
210 ExprResult * val_rtrn)
217 str = XkbcAtomText(field);
220 if (strcasecmp(str, "all") == 0)
221 val_rtrn->uval = 0xff;
222 else if (strcasecmp(str, "none") == 0)
224 else if (LookupModIndex(priv, field, type, val_rtrn))
225 val_rtrn->uval = (1 << val_rtrn->uval);
232 ExprResolveBoolean(ExprDef * expr,
233 ExprResult * val_rtrn)
236 const char *bogus = NULL;
241 if (expr->type != TypeBoolean)
244 ("Found constant of type %s where boolean was expected\n",
245 exprTypeText(expr->type));
248 val_rtrn->ival = expr->value.ival;
251 bogus = XkbcAtomText(expr->value.str);
254 if ((strcasecmp(bogus, "true") == 0) ||
255 (strcasecmp(bogus, "yes") == 0) ||
256 (strcasecmp(bogus, "on") == 0))
261 else if ((strcasecmp(bogus, "false") == 0) ||
262 (strcasecmp(bogus, "no") == 0) ||
263 (strcasecmp(bogus, "off") == 0))
269 ERROR("Identifier \"%s\" of type int is unknown\n",
270 XkbcAtomText(expr->value.str));
273 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
274 XkbcAtomText(expr->value.field.element),
275 XkbcAtomText(expr->value.field.field));
279 ok = ExprResolveBoolean(expr, val_rtrn);
281 val_rtrn->uval = !val_rtrn->uval;
288 bogus = "Subtraction";
291 bogus = "Multiplication";
297 bogus = "Assignment";
301 ERROR("%s of boolean values not permitted\n", bogus);
304 ERROR("Unary \"+\" operator not permitted for boolean values\n");
307 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
314 ExprResolveFloat(ExprDef * expr,
315 ExprResult * val_rtrn)
318 ExprResult leftRtrn, rightRtrn;
319 ExprDef *left, *right;
324 if (expr->type == TypeString)
327 str = XkbcAtomText(expr->value.str);
328 if ((str != NULL) && (strlen(str) == 1))
330 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
334 if (expr->type != TypeInt)
336 ERROR("Found constant of type %s, expected a number\n",
337 exprTypeText(expr->type));
340 val_rtrn->ival = expr->value.ival;
341 if (expr->type == TypeInt)
342 val_rtrn->ival *= XkbGeomPtsPerMM;
345 ERROR("Numeric identifier \"%s\" unknown\n",
346 XkbcAtomText(expr->value.str));
349 ERROR("Numeric default \"%s.%s\" unknown\n",
350 XkbcAtomText(expr->value.field.element),
351 XkbcAtomText(expr->value.field.field));
357 left = expr->value.binary.left;
358 right = expr->value.binary.right;
359 if (ExprResolveFloat(left, &leftRtrn) &&
360 ExprResolveFloat(right, &rightRtrn))
365 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
368 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
371 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
374 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
381 WSGO("Assignment operator not implemented yet\n");
384 ERROR("The ! operator cannot be applied to a number\n");
388 left = expr->value.child;
389 if (ExprResolveFloat(left, &leftRtrn))
391 if (expr->op == OpNegate)
392 val_rtrn->ival = -leftRtrn.ival;
394 val_rtrn->ival = ~leftRtrn.ival;
399 left = expr->value.child;
400 return ExprResolveFloat(left, val_rtrn);
402 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
409 ExprResolveKeyCode(ExprDef * expr,
410 ExprResult * val_rtrn)
412 ExprResult leftRtrn, rightRtrn;
413 ExprDef *left, *right;
418 if (expr->type != TypeInt)
421 ("Found constant of type %s where an int was expected\n",
422 exprTypeText(expr->type));
425 val_rtrn->uval = expr->value.uval;
431 left = expr->value.binary.left;
432 right = expr->value.binary.right;
433 if (ExprResolveKeyCode(left, &leftRtrn) &&
434 ExprResolveKeyCode(right, &rightRtrn))
439 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
442 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
445 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
448 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
455 left = expr->value.child;
456 if (ExprResolveKeyCode(left, &leftRtrn))
458 val_rtrn->uval = ~leftRtrn.uval;
463 left = expr->value.child;
464 return ExprResolveKeyCode(left, val_rtrn);
466 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
473 * This function returns ... something. It's a bit of a guess, really.
475 * If a string is given in value context, its first character will be
476 * returned in uval. If an integer is given in value context, it will be
477 * returned in ival. If a float is given in value context, it will be
478 * returned as millimetres (rather than points) in ival.
480 * If an ident or field reference is given, the lookup function (if given)
481 * will be called. At the moment, only SimpleLookup use this, and they both
482 * return the results in uval. And don't support field references.
487 ExprResolveIntegerLookup(ExprDef * expr,
488 ExprResult * val_rtrn,
489 IdentLookupFunc lookup, const void * lookupPriv)
492 ExprResult leftRtrn, rightRtrn;
493 ExprDef *left, *right;
498 if (expr->type == TypeString)
501 str = XkbcAtomText(expr->value.str);
509 val_rtrn->uval = str[0];
515 if (expr->type != TypeInt)
518 ("Found constant of type %s where an int was expected\n",
519 exprTypeText(expr->type));
522 val_rtrn->ival = expr->value.ival;
527 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
530 ERROR("Identifier \"%s\" of type int is unknown\n",
531 XkbcAtomText(expr->value.str));
534 ERROR("Default \"%s.%s\" of type int is unknown\n",
535 XkbcAtomText(expr->value.field.element),
536 XkbcAtomText(expr->value.field.field));
542 left = expr->value.binary.left;
543 right = expr->value.binary.right;
544 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
545 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
550 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
553 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
556 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
559 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
566 WSGO("Assignment operator not implemented yet\n");
569 ERROR("The ! operator cannot be applied to an integer\n");
573 left = expr->value.child;
574 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
576 if (expr->op == OpNegate)
577 val_rtrn->ival = -leftRtrn.ival;
579 val_rtrn->ival = ~leftRtrn.ival;
584 left = expr->value.child;
585 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
587 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
594 ExprResolveInteger(ExprDef * expr,
595 ExprResult * val_rtrn)
597 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
601 ExprResolveGroup(ExprDef * expr,
602 ExprResult * val_rtrn)
605 static const LookupEntry group_names[] = {
617 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
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(ExprDef * expr,
632 ExprResult * val_rtrn)
635 static const LookupEntry level_names[] = {
647 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, level_names);
651 if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) {
652 ERROR("Shift level %d is out of range (1..%d)\n", val_rtrn->ival,
661 ExprResolveButton(ExprDef * expr,
662 ExprResult * val_rtrn)
664 static const LookupEntry button_names[] = {
674 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
679 ExprResolveString(ExprDef * expr,
680 ExprResult * val_rtrn)
682 ExprResult leftRtrn, rightRtrn;
685 const char *bogus = NULL;
690 if (expr->type != TypeString)
692 ERROR("Found constant of type %s, expected a string\n",
693 exprTypeText(expr->type));
696 val_rtrn->str = XkbcAtomGetString(expr->value.str);
697 if (val_rtrn->str == NULL)
698 val_rtrn->str = strdup("");
701 ERROR("Identifier \"%s\" of type string not found\n",
702 XkbcAtomText(expr->value.str));
705 ERROR("Default \"%s.%s\" of type string not found\n",
706 XkbcAtomText(expr->value.field.element),
707 XkbcAtomText(expr->value.field.field));
710 left = expr->value.binary.left;
711 right = expr->value.binary.right;
712 if (ExprResolveString(left, &leftRtrn) &&
713 ExprResolveString(right, &rightRtrn))
717 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
720 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
732 bogus = "Subtraction";
735 bogus = "Multiplication";
741 bogus = "Assignment";
747 bogus = "Bitwise complement";
748 ERROR("%s of string values not permitted\n", bogus);
751 ERROR("The ! operator cannot be applied to a string\n");
754 ERROR("The + operator cannot be applied to a string\n");
757 WSGO("Unknown operator %d in ResolveString\n", expr->op);
764 ExprResolveKeyName(ExprDef * expr,
765 ExprResult * val_rtrn)
767 const char *bogus = NULL;
772 if (expr->type != TypeKeyName)
774 ERROR("Found constant of type %s, expected a key name\n",
775 exprTypeText(expr->type));
778 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
781 ERROR("Identifier \"%s\" of type string not found\n",
782 XkbcAtomText(expr->value.str));
785 ERROR("Default \"%s.%s\" of type key name not found\n",
786 XkbcAtomText(expr->value.field.element),
787 XkbcAtomText(expr->value.field.field));
794 bogus = "Subtraction";
797 bogus = "Multiplication";
803 bogus = "Assignment";
809 bogus = "Bitwise complement";
810 ERROR("%s of key name values not permitted\n", bogus);
813 ERROR("The ! operator cannot be applied to a key name\n");
816 ERROR("The + operator cannot be applied to a key name\n");
819 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
825 /***====================================================================***/
828 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, const LookupEntry * values)
830 if (expr->op != ExprIdent)
832 ERROR("Found a %s where an enumerated value was expected\n",
833 exprOpText(expr->op));
836 if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
839 ERROR("Illegal identifier %s (expected one of: ",
840 XkbcAtomText(expr->value.str));
841 while (values && values->name)
844 INFO(", %s", values->name);
846 INFO("%s", values->name);
857 ExprResolveMaskLookup(ExprDef * expr,
858 ExprResult * val_rtrn,
859 IdentLookupFunc lookup,
860 const void * lookupPriv)
863 ExprResult leftRtrn, rightRtrn;
864 ExprDef *left, *right;
865 const char *bogus = NULL;
870 if (expr->type != TypeInt)
873 ("Found constant of type %s where a mask was expected\n",
874 exprTypeText(expr->type));
877 val_rtrn->ival = expr->value.ival;
880 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
882 ERROR("Identifier \"%s\" of type int is unknown\n",
883 XkbcAtomText(expr->value.str));
886 ERROR("Default \"%s.%s\" of type int is unknown\n",
887 XkbcAtomText(expr->value.field.element),
888 XkbcAtomText(expr->value.field.field));
891 bogus = "array reference";
894 bogus = "function use";
895 ERROR("Unexpected %s in mask expression\n", bogus);
896 ACTION("Expression ignored\n");
902 left = expr->value.binary.left;
903 right = expr->value.binary.right;
904 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
905 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
910 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
913 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
917 ERROR("Cannot %s masks\n",
918 expr->op == OpDivide ? "divide" : "multiply");
919 ACTION("Illegal operation ignored\n");
926 WSGO("Assignment operator not implemented yet\n");
929 left = expr->value.child;
930 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
932 val_rtrn->ival = ~leftRtrn.ival;
939 left = expr->value.child;
940 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
942 ERROR("The %s operator cannot be used with a mask\n",
943 (expr->op == OpNegate ? "-" : "!"));
947 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
954 ExprResolveMask(ExprDef * expr,
955 ExprResult * val_rtrn,
956 const LookupEntry * values)
958 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
962 ExprResolveModMask(ExprDef * expr,
963 ExprResult * val_rtrn)
965 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
969 ExprResolveVModMask(ExprDef * expr,
970 ExprResult * val_rtrn,
971 struct xkb_desc *xkb)
973 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, xkb);
977 ExprResolveKeySym(ExprDef * expr,
978 ExprResult * val_rtrn)
983 if (expr->op == ExprIdent)
986 str = XkbcAtomText(expr->value.str);
987 if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
989 val_rtrn->uval = sym;
993 ok = ExprResolveInteger(expr, val_rtrn);
994 if ((ok) && (val_rtrn->uval < 10))
995 val_rtrn->uval += '0';