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) (void * /* priv */ ,
37 uint32_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(void * priv, uint32_t field, unsigned type,
167 ExprResult * val_rtrn)
172 if ((priv == NULL) || (field == None) ||
173 ((type != TypeInt) && (type != TypeFloat)))
177 str = XkbcAtomText(field);
178 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
180 if (uStrCaseCmp(str, entry->name) == 0)
182 val_rtrn->uval = entry->result;
183 if (type == TypeFloat)
184 val_rtrn->uval *= XkbGeomPtsPerMM;
192 RadioLookup(void * priv, uint32_t field, unsigned type, ExprResult * val_rtrn)
197 if ((field == None) || (type != TypeInt))
199 str = XkbcAtomText(field);
202 if (uStrCasePrefix("group", str))
203 str += strlen("group");
204 else if (uStrCasePrefix("radiogroup", str))
205 str += strlen("radiogroup");
206 else if (uStrCasePrefix("rg", str))
208 else if (!isdigit(str[0]))
211 if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
212 || (rg > XkbMaxRadioGroups))
218 static LookupEntry modIndexNames[] = {
219 {"shift", ShiftMapIndex},
220 {"control", ControlMapIndex},
221 {"lock", LockMapIndex},
222 {"mod1", Mod1MapIndex},
223 {"mod2", Mod2MapIndex},
224 {"mod3", Mod3MapIndex},
225 {"mod4", Mod4MapIndex},
226 {"mod5", Mod5MapIndex},
227 {"none", XkbNoModifier},
232 LookupModIndex(void * priv, uint32_t field, unsigned type,
233 ExprResult * val_rtrn)
235 return SimpleLookup(modIndexNames, field, type, val_rtrn);
239 LookupModMask(void * priv, uint32_t field, unsigned type,
240 ExprResult * val_rtrn)
247 str = XkbcAtomGetString(field);
250 if (uStrCaseCmp(str, "all") == 0)
251 val_rtrn->uval = 0xff;
252 else if (uStrCaseCmp(str, "none") == 0)
254 else if (LookupModIndex(priv, field, type, val_rtrn))
255 val_rtrn->uval = (1 << val_rtrn->uval);
263 ExprResolveBoolean(ExprDef * expr,
264 ExprResult * val_rtrn)
267 const char *bogus = NULL;
272 if (expr->type != TypeBoolean)
275 ("Found constant of type %s where boolean was expected\n",
276 exprTypeText(expr->type));
279 val_rtrn->ival = expr->value.ival;
282 bogus = XkbcAtomText(expr->value.str);
285 if ((uStrCaseCmp(bogus, "true") == 0) ||
286 (uStrCaseCmp(bogus, "yes") == 0) ||
287 (uStrCaseCmp(bogus, "on") == 0))
292 else if ((uStrCaseCmp(bogus, "false") == 0) ||
293 (uStrCaseCmp(bogus, "no") == 0) ||
294 (uStrCaseCmp(bogus, "off") == 0))
300 ERROR("Identifier \"%s\" of type int is unknown\n",
301 XkbcAtomText(expr->value.str));
304 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
305 XkbcAtomText(expr->value.field.element),
306 XkbcAtomText(expr->value.field.field));
310 ok = ExprResolveBoolean(expr, val_rtrn);
312 val_rtrn->uval = !val_rtrn->uval;
319 bogus = "Subtraction";
322 bogus = "Multiplication";
328 bogus = "Assignment";
332 ERROR("%s of boolean values not permitted\n", bogus);
335 ERROR("Unary \"+\" operator not permitted for boolean values\n");
338 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
345 ExprResolveFloat(ExprDef * expr,
346 ExprResult * val_rtrn)
349 ExprResult leftRtrn, rightRtrn;
350 ExprDef *left, *right;
355 if (expr->type == TypeString)
358 str = XkbcAtomText(expr->value.str);
359 if ((str != NULL) && (strlen(str) == 1))
361 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
365 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
367 ERROR("Found constant of type %s, expected a number\n",
368 exprTypeText(expr->type));
371 val_rtrn->ival = expr->value.ival;
372 if (expr->type == TypeInt)
373 val_rtrn->ival *= XkbGeomPtsPerMM;
376 ERROR("Numeric identifier \"%s\" unknown\n",
377 XkbcAtomText(expr->value.str));
380 ERROR("Numeric default \"%s.%s\" unknown\n",
381 XkbcAtomText(expr->value.field.element),
382 XkbcAtomText(expr->value.field.field));
388 left = expr->value.binary.left;
389 right = expr->value.binary.right;
390 if (ExprResolveFloat(left, &leftRtrn) &&
391 ExprResolveFloat(right, &rightRtrn))
396 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
399 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
402 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
405 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
412 WSGO("Assignment operator not implemented yet\n");
415 ERROR("The ! operator cannot be applied to a number\n");
419 left = expr->value.child;
420 if (ExprResolveFloat(left, &leftRtrn))
422 if (expr->op == OpNegate)
423 val_rtrn->ival = -leftRtrn.ival;
425 val_rtrn->ival = ~leftRtrn.ival;
430 left = expr->value.child;
431 return ExprResolveFloat(left, val_rtrn);
433 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
440 ExprResolveKeyCode(ExprDef * expr,
441 ExprResult * val_rtrn)
443 ExprResult leftRtrn, rightRtrn;
444 ExprDef *left, *right;
449 if (expr->type != TypeInt)
452 ("Found constant of type %s where an int was expected\n",
453 exprTypeText(expr->type));
456 val_rtrn->uval = expr->value.uval;
462 left = expr->value.binary.left;
463 right = expr->value.binary.right;
464 if (ExprResolveKeyCode(left, &leftRtrn) &&
465 ExprResolveKeyCode(right, &rightRtrn))
470 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
473 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
476 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
479 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
486 left = expr->value.child;
487 if (ExprResolveKeyCode(left, &leftRtrn))
489 val_rtrn->uval = ~leftRtrn.uval;
494 left = expr->value.child;
495 return ExprResolveKeyCode(left, val_rtrn);
497 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
504 * This function returns ... something. It's a bit of a guess, really.
506 * If a string is given in value context, its first character will be
507 * returned in uval. If an integer is given in value context, it will be
508 * returned in ival. If a float is given in value context, it will be
509 * returned as millimetres (rather than points) in ival.
511 * If an ident or field reference is given, the lookup function (if given)
512 * will be called. At the moment, only RadioLookup and SimpleLookup use
513 * this, and they both return the results in uval. And don't support field
519 ExprResolveIntegerLookup(ExprDef * expr,
520 ExprResult * val_rtrn,
521 IdentLookupFunc lookup, void * lookupPriv)
524 ExprResult leftRtrn, rightRtrn;
525 ExprDef *left, *right;
530 if (expr->type == TypeString)
533 str = XkbcAtomText(expr->value.str);
541 val_rtrn->uval = str[0];
547 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
550 ("Found constant of type %s where an int was expected\n",
551 exprTypeText(expr->type));
554 val_rtrn->ival = expr->value.ival;
555 if (expr->type == TypeFloat)
556 val_rtrn->ival /= XkbGeomPtsPerMM;
561 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
564 ERROR("Identifier \"%s\" of type int is unknown\n",
565 XkbcAtomText(expr->value.str));
568 ERROR("Default \"%s.%s\" of type int is unknown\n",
569 XkbcAtomText(expr->value.field.element),
570 XkbcAtomText(expr->value.field.field));
576 left = expr->value.binary.left;
577 right = expr->value.binary.right;
578 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
579 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
584 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
587 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
590 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
593 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
600 WSGO("Assignment operator not implemented yet\n");
603 ERROR("The ! operator cannot be applied to an integer\n");
607 left = expr->value.child;
608 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
610 if (expr->op == OpNegate)
611 val_rtrn->ival = -leftRtrn.ival;
613 val_rtrn->ival = ~leftRtrn.ival;
618 left = expr->value.child;
619 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
621 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
628 ExprResolveInteger(ExprDef * expr,
629 ExprResult * val_rtrn)
631 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
635 ExprResolveRadioGroup(ExprDef * expr,
636 ExprResult * val_rtrn)
638 return ExprResolveIntegerLookup(expr, val_rtrn, RadioLookup, NULL);
642 ExprResolveGroup(ExprDef * expr,
643 ExprResult * val_rtrn)
646 static LookupEntry group_names[] = {
658 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
662 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
663 ERROR("Group index %d is out of range (1..%d)\n",
664 val_rtrn->uval, XkbNumKbdGroups);
672 ExprResolveLevel(ExprDef * expr,
673 ExprResult * val_rtrn)
675 static LookupEntry level_names[] = {
687 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
692 ExprResolveButton(ExprDef * expr,
693 ExprResult * val_rtrn)
695 static LookupEntry button_names[] = {
705 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
710 ExprResolveString(ExprDef * expr,
711 ExprResult * val_rtrn)
713 ExprResult leftRtrn, rightRtrn;
716 const char *bogus = NULL;
721 if (expr->type != TypeString)
723 ERROR("Found constant of type %s, expected a string\n",
724 exprTypeText(expr->type));
727 val_rtrn->str = XkbcAtomGetString(expr->value.str);
728 if (val_rtrn->str == NULL)
729 val_rtrn->str = strdup("");
732 ERROR("Identifier \"%s\" of type string not found\n",
733 XkbcAtomText(expr->value.str));
736 ERROR("Default \"%s.%s\" of type string not found\n",
737 XkbcAtomText(expr->value.field.element),
738 XkbcAtomText(expr->value.field.field));
741 left = expr->value.binary.left;
742 right = expr->value.binary.right;
743 if (ExprResolveString(left, &leftRtrn) &&
744 ExprResolveString(right, &rightRtrn))
748 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
749 new = (char *) malloc(len);
751 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
763 bogus = "Subtraction";
766 bogus = "Multiplication";
772 bogus = "Assignment";
778 bogus = "Bitwise complement";
779 ERROR("%s of string values not permitted\n", bogus);
782 ERROR("The ! operator cannot be applied to a string\n");
785 ERROR("The + operator cannot be applied to a string\n");
788 WSGO("Unknown operator %d in ResolveString\n", expr->op);
795 ExprResolveKeyName(ExprDef * expr,
796 ExprResult * val_rtrn)
798 const char *bogus = NULL;
803 if (expr->type != TypeKeyName)
805 ERROR("Found constant of type %s, expected a key name\n",
806 exprTypeText(expr->type));
809 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
812 ERROR("Identifier \"%s\" of type string not found\n",
813 XkbcAtomText(expr->value.str));
816 ERROR("Default \"%s.%s\" of type key name not found\n",
817 XkbcAtomText(expr->value.field.element),
818 XkbcAtomText(expr->value.field.field));
825 bogus = "Subtraction";
828 bogus = "Multiplication";
834 bogus = "Assignment";
840 bogus = "Bitwise complement";
841 ERROR("%s of key name values not permitted\n", bogus);
844 ERROR("The ! operator cannot be applied to a key name\n");
847 ERROR("The + operator cannot be applied to a key name\n");
850 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
856 /***====================================================================***/
859 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
861 if (expr->op != ExprIdent)
863 ERROR("Found a %s where an enumerated value was expected\n",
864 exprOpText(expr->op));
867 if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
870 ERROR("Illegal identifier %s (expected one of: ",
871 XkbcAtomText(expr->value.str));
872 while (values && values->name)
875 INFO(", %s", values->name);
877 INFO("%s", values->name);
888 ExprResolveMaskLookup(ExprDef * expr,
889 ExprResult * val_rtrn,
890 IdentLookupFunc lookup,
894 ExprResult leftRtrn, rightRtrn;
895 ExprDef *left, *right;
896 const char *bogus = NULL;
901 if (expr->type != TypeInt)
904 ("Found constant of type %s where a mask was expected\n",
905 exprTypeText(expr->type));
908 val_rtrn->ival = expr->value.ival;
911 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
913 ERROR("Identifier \"%s\" of type int is unknown\n",
914 XkbcAtomText(expr->value.str));
917 ERROR("Default \"%s.%s\" of type int is unknown\n",
918 XkbcAtomText(expr->value.field.element),
919 XkbcAtomText(expr->value.field.field));
922 bogus = "array reference";
925 bogus = "function use";
926 ERROR("Unexpected %s in mask expression\n", bogus);
927 ACTION("Expression ignored\n");
933 left = expr->value.binary.left;
934 right = expr->value.binary.right;
935 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
936 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
941 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
944 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
948 ERROR("Cannot %s masks\n",
949 expr->op == OpDivide ? "divide" : "multiply");
950 ACTION("Illegal operation ignored\n");
957 WSGO("Assignment operator not implemented yet\n");
960 left = expr->value.child;
961 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
963 val_rtrn->ival = ~leftRtrn.ival;
970 left = expr->value.child;
971 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
973 ERROR("The %s operator cannot be used with a mask\n",
974 (expr->op == OpNegate ? "-" : "!"));
978 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
985 ExprResolveMask(ExprDef * expr,
986 ExprResult * val_rtrn,
987 LookupEntry * values)
989 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
993 ExprResolveModMask(ExprDef * expr,
994 ExprResult * val_rtrn)
996 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
1000 ExprResolveVModMask(ExprDef * expr,
1001 ExprResult * val_rtrn,
1002 struct xkb_desc *xkb)
1004 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, xkb);
1008 ExprResolveKeySym(ExprDef * expr,
1009 ExprResult * val_rtrn)
1014 if (expr->op == ExprIdent)
1017 str = XkbcAtomText(expr->value.str);
1018 if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
1020 val_rtrn->uval = sym;
1024 ok = ExprResolveInteger(expr, val_rtrn);
1025 if ((ok) && (val_rtrn->uval < 10))
1026 val_rtrn->uval += '0';