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 */ ,
39 xkb_atom_t /* field */ ,
41 ExprResult * /* val_rtrn */
44 /***====================================================================***/
47 exprOpText(unsigned type)
54 strcpy(buf, "literal");
57 strcpy(buf, "identifier");
60 strcpy(buf, "action declaration");
63 strcpy(buf, "field reference");
66 strcpy(buf, "array reference");
69 strcpy(buf, "list of keysyms");
72 strcpy(buf, "list of actions");
75 strcpy(buf, "addition");
78 strcpy(buf, "subtraction");
81 strcpy(buf, "multiplication");
84 strcpy(buf, "division");
87 strcpy(buf, "assignment");
90 strcpy(buf, "logical not");
93 strcpy(buf, "arithmetic negation");
96 strcpy(buf, "bitwise inversion");
99 strcpy(buf, "plus sign");
102 snprintf(buf, sizeof(buf), "illegal(%d)", type);
109 exprTypeText(unsigned type)
116 strcpy(buf, "unknown");
119 strcpy(buf, "boolean");
125 strcpy(buf, "string");
128 strcpy(buf, "action");
131 strcpy(buf, "keyname");
134 snprintf(buf, sizeof(buf), "illegal(%d)", type);
141 ExprResolveLhs(ExprDef * expr,
142 ExprResult * elem_rtrn,
143 ExprResult * field_rtrn, ExprDef ** index_rtrn)
148 elem_rtrn->str = NULL;
149 field_rtrn->str = XkbcAtomGetString(expr->value.str);
153 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
154 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
158 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
159 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
160 *index_rtrn = expr->value.array.entry;
163 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
168 SimpleLookup(const void * priv, xkb_atom_t field, unsigned type,
169 ExprResult * val_rtrn)
171 const LookupEntry *entry;
174 if ((priv == NULL) || (field == XKB_ATOM_NONE) || (type != TypeInt))
178 str = XkbcAtomText(field);
179 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
181 if (strcasecmp(str, entry->name) == 0)
183 val_rtrn->uval = entry->result;
190 static const LookupEntry modIndexNames[] = {
191 {"shift", ShiftMapIndex},
192 {"control", ControlMapIndex},
193 {"lock", LockMapIndex},
194 {"mod1", Mod1MapIndex},
195 {"mod2", Mod2MapIndex},
196 {"mod3", Mod3MapIndex},
197 {"mod4", Mod4MapIndex},
198 {"mod5", Mod5MapIndex},
199 {"none", XkbNoModifier},
204 LookupModIndex(const void * priv, xkb_atom_t field, unsigned type,
205 ExprResult * val_rtrn)
207 return SimpleLookup(modIndexNames, field, type, val_rtrn);
211 LookupModMask(const void * priv, xkb_atom_t field, unsigned type,
212 ExprResult * val_rtrn)
219 str = XkbcAtomText(field);
222 if (strcasecmp(str, "all") == 0)
223 val_rtrn->uval = 0xff;
224 else if (strcasecmp(str, "none") == 0)
226 else if (LookupModIndex(priv, field, type, val_rtrn))
227 val_rtrn->uval = (1 << val_rtrn->uval);
234 ExprResolveBoolean(ExprDef * expr,
235 ExprResult * val_rtrn)
238 const char *bogus = NULL;
243 if (expr->type != TypeBoolean)
246 ("Found constant of type %s where boolean was expected\n",
247 exprTypeText(expr->type));
250 val_rtrn->ival = expr->value.ival;
253 bogus = XkbcAtomText(expr->value.str);
256 if ((strcasecmp(bogus, "true") == 0) ||
257 (strcasecmp(bogus, "yes") == 0) ||
258 (strcasecmp(bogus, "on") == 0))
263 else if ((strcasecmp(bogus, "false") == 0) ||
264 (strcasecmp(bogus, "no") == 0) ||
265 (strcasecmp(bogus, "off") == 0))
271 ERROR("Identifier \"%s\" of type int is unknown\n",
272 XkbcAtomText(expr->value.str));
275 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
276 XkbcAtomText(expr->value.field.element),
277 XkbcAtomText(expr->value.field.field));
281 ok = ExprResolveBoolean(expr, val_rtrn);
283 val_rtrn->uval = !val_rtrn->uval;
290 bogus = "Subtraction";
293 bogus = "Multiplication";
299 bogus = "Assignment";
303 ERROR("%s of boolean values not permitted\n", bogus);
306 ERROR("Unary \"+\" operator not permitted for boolean values\n");
309 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
316 ExprResolveFloat(ExprDef * expr,
317 ExprResult * val_rtrn)
320 ExprResult leftRtrn, rightRtrn;
321 ExprDef *left, *right;
326 if (expr->type == TypeString)
329 str = XkbcAtomText(expr->value.str);
330 if ((str != NULL) && (strlen(str) == 1))
332 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
336 if (expr->type != TypeInt)
338 ERROR("Found constant of type %s, expected a number\n",
339 exprTypeText(expr->type));
342 val_rtrn->ival = expr->value.ival;
343 if (expr->type == TypeInt)
344 val_rtrn->ival *= XkbGeomPtsPerMM;
347 ERROR("Numeric identifier \"%s\" unknown\n",
348 XkbcAtomText(expr->value.str));
351 ERROR("Numeric default \"%s.%s\" unknown\n",
352 XkbcAtomText(expr->value.field.element),
353 XkbcAtomText(expr->value.field.field));
359 left = expr->value.binary.left;
360 right = expr->value.binary.right;
361 if (ExprResolveFloat(left, &leftRtrn) &&
362 ExprResolveFloat(right, &rightRtrn))
367 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
370 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
373 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
376 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
383 WSGO("Assignment operator not implemented yet\n");
386 ERROR("The ! operator cannot be applied to a number\n");
390 left = expr->value.child;
391 if (ExprResolveFloat(left, &leftRtrn))
393 if (expr->op == OpNegate)
394 val_rtrn->ival = -leftRtrn.ival;
396 val_rtrn->ival = ~leftRtrn.ival;
401 left = expr->value.child;
402 return ExprResolveFloat(left, val_rtrn);
404 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
411 ExprResolveKeyCode(ExprDef * expr,
412 ExprResult * val_rtrn)
414 ExprResult leftRtrn, rightRtrn;
415 ExprDef *left, *right;
420 if (expr->type != TypeInt)
423 ("Found constant of type %s where an int was expected\n",
424 exprTypeText(expr->type));
427 val_rtrn->uval = expr->value.uval;
433 left = expr->value.binary.left;
434 right = expr->value.binary.right;
435 if (ExprResolveKeyCode(left, &leftRtrn) &&
436 ExprResolveKeyCode(right, &rightRtrn))
441 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
444 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
447 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
450 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
457 left = expr->value.child;
458 if (ExprResolveKeyCode(left, &leftRtrn))
460 val_rtrn->uval = ~leftRtrn.uval;
465 left = expr->value.child;
466 return ExprResolveKeyCode(left, val_rtrn);
468 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
475 * This function returns ... something. It's a bit of a guess, really.
477 * If a string is given in value context, its first character will be
478 * returned in uval. If an integer is given in value context, it will be
479 * returned in ival. If a float is given in value context, it will be
480 * returned as millimetres (rather than points) in ival.
482 * If an ident or field reference is given, the lookup function (if given)
483 * will be called. At the moment, only SimpleLookup use this, and they both
484 * return the results in uval. And don't support field references.
489 ExprResolveIntegerLookup(ExprDef * expr,
490 ExprResult * val_rtrn,
491 IdentLookupFunc lookup, const void * lookupPriv)
494 ExprResult leftRtrn, rightRtrn;
495 ExprDef *left, *right;
500 if (expr->type == TypeString)
503 str = XkbcAtomText(expr->value.str);
511 val_rtrn->uval = str[0];
517 if (expr->type != TypeInt)
520 ("Found constant of type %s where an int was expected\n",
521 exprTypeText(expr->type));
524 val_rtrn->ival = expr->value.ival;
529 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
532 ERROR("Identifier \"%s\" of type int is unknown\n",
533 XkbcAtomText(expr->value.str));
536 ERROR("Default \"%s.%s\" of type int is unknown\n",
537 XkbcAtomText(expr->value.field.element),
538 XkbcAtomText(expr->value.field.field));
544 left = expr->value.binary.left;
545 right = expr->value.binary.right;
546 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
547 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
552 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
555 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
558 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
561 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
568 WSGO("Assignment operator not implemented yet\n");
571 ERROR("The ! operator cannot be applied to an integer\n");
575 left = expr->value.child;
576 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
578 if (expr->op == OpNegate)
579 val_rtrn->ival = -leftRtrn.ival;
581 val_rtrn->ival = ~leftRtrn.ival;
586 left = expr->value.child;
587 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
589 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
596 ExprResolveInteger(ExprDef * expr,
597 ExprResult * val_rtrn)
599 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
603 ExprResolveGroup(ExprDef * expr,
604 ExprResult * val_rtrn)
607 static const LookupEntry group_names[] = {
619 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
623 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
624 ERROR("Group index %d is out of range (1..%d)\n",
625 val_rtrn->uval, XkbNumKbdGroups);
633 ExprResolveLevel(ExprDef * expr,
634 ExprResult * val_rtrn)
637 static const LookupEntry level_names[] = {
649 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, level_names);
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(ExprDef * expr,
664 ExprResult * val_rtrn)
666 static const LookupEntry button_names[] = {
676 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
681 ExprResolveString(ExprDef * expr,
682 ExprResult * val_rtrn)
684 ExprResult leftRtrn, rightRtrn;
687 const char *bogus = NULL;
692 if (expr->type != TypeString)
694 ERROR("Found constant of type %s, expected a string\n",
695 exprTypeText(expr->type));
698 val_rtrn->str = XkbcAtomGetString(expr->value.str);
699 if (val_rtrn->str == NULL)
700 val_rtrn->str = strdup("");
703 ERROR("Identifier \"%s\" of type string not found\n",
704 XkbcAtomText(expr->value.str));
707 ERROR("Default \"%s.%s\" of type string not found\n",
708 XkbcAtomText(expr->value.field.element),
709 XkbcAtomText(expr->value.field.field));
712 left = expr->value.binary.left;
713 right = expr->value.binary.right;
714 if (ExprResolveString(left, &leftRtrn) &&
715 ExprResolveString(right, &rightRtrn))
719 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
722 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
734 bogus = "Subtraction";
737 bogus = "Multiplication";
743 bogus = "Assignment";
749 bogus = "Bitwise complement";
750 ERROR("%s of string values not permitted\n", bogus);
753 ERROR("The ! operator cannot be applied to a string\n");
756 ERROR("The + operator cannot be applied to a string\n");
759 WSGO("Unknown operator %d in ResolveString\n", expr->op);
766 ExprResolveKeyName(ExprDef * expr,
767 ExprResult * val_rtrn)
769 const char *bogus = NULL;
774 if (expr->type != TypeKeyName)
776 ERROR("Found constant of type %s, expected a key name\n",
777 exprTypeText(expr->type));
780 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
783 ERROR("Identifier \"%s\" of type string not found\n",
784 XkbcAtomText(expr->value.str));
787 ERROR("Default \"%s.%s\" of type key name not found\n",
788 XkbcAtomText(expr->value.field.element),
789 XkbcAtomText(expr->value.field.field));
796 bogus = "Subtraction";
799 bogus = "Multiplication";
805 bogus = "Assignment";
811 bogus = "Bitwise complement";
812 ERROR("%s of key name values not permitted\n", bogus);
815 ERROR("The ! operator cannot be applied to a key name\n");
818 ERROR("The + operator cannot be applied to a key name\n");
821 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
827 /***====================================================================***/
830 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, const LookupEntry * values)
832 if (expr->op != ExprIdent)
834 ERROR("Found a %s where an enumerated value was expected\n",
835 exprOpText(expr->op));
838 if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
841 ERROR("Illegal identifier %s (expected one of: ",
842 XkbcAtomText(expr->value.str));
843 while (values && values->name)
846 INFO(", %s", values->name);
848 INFO("%s", values->name);
859 ExprResolveMaskLookup(ExprDef * expr,
860 ExprResult * val_rtrn,
861 IdentLookupFunc lookup,
862 const void * lookupPriv)
865 ExprResult leftRtrn, rightRtrn;
866 ExprDef *left, *right;
867 const char *bogus = NULL;
872 if (expr->type != TypeInt)
875 ("Found constant of type %s where a mask was expected\n",
876 exprTypeText(expr->type));
879 val_rtrn->ival = expr->value.ival;
882 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
884 ERROR("Identifier \"%s\" of type int is unknown\n",
885 XkbcAtomText(expr->value.str));
888 ERROR("Default \"%s.%s\" of type int is unknown\n",
889 XkbcAtomText(expr->value.field.element),
890 XkbcAtomText(expr->value.field.field));
893 bogus = "array reference";
896 bogus = "function use";
897 ERROR("Unexpected %s in mask expression\n", bogus);
898 ACTION("Expression ignored\n");
904 left = expr->value.binary.left;
905 right = expr->value.binary.right;
906 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
907 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
912 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
915 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
919 ERROR("Cannot %s masks\n",
920 expr->op == OpDivide ? "divide" : "multiply");
921 ACTION("Illegal operation ignored\n");
928 WSGO("Assignment operator not implemented yet\n");
931 left = expr->value.child;
932 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
934 val_rtrn->ival = ~leftRtrn.ival;
941 left = expr->value.child;
942 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
944 ERROR("The %s operator cannot be used with a mask\n",
945 (expr->op == OpNegate ? "-" : "!"));
949 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
956 ExprResolveMask(ExprDef * expr,
957 ExprResult * val_rtrn,
958 const LookupEntry * values)
960 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
964 ExprResolveModMask(ExprDef * expr,
965 ExprResult * val_rtrn)
967 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
971 ExprResolveVModMask(ExprDef * expr,
972 ExprResult * val_rtrn,
973 struct xkb_desc *xkb)
975 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, xkb);
979 ExprResolveKeySym(ExprDef * expr,
980 ExprResult * val_rtrn)
985 if (expr->op == ExprIdent)
988 str = XkbcAtomText(expr->value.str);
990 sym = xkb_string_to_keysym(str);
991 if (sym != XKB_KEYSYM_NO_SYMBOL) {
992 val_rtrn->uval = sym;
997 ok = ExprResolveInteger(expr, val_rtrn);
998 if ((ok) && (val_rtrn->uval < 10))
999 val_rtrn->uval += '0';