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 ********************************************************/
35 /***====================================================================***/
38 exprOpText(unsigned type)
45 strcpy(buf, "literal");
48 strcpy(buf, "identifier");
51 strcpy(buf, "action declaration");
54 strcpy(buf, "field reference");
57 strcpy(buf, "array reference");
60 strcpy(buf, "list of keysyms");
63 strcpy(buf, "list of actions");
66 strcpy(buf, "addition");
69 strcpy(buf, "subtraction");
72 strcpy(buf, "multiplication");
75 strcpy(buf, "division");
78 strcpy(buf, "assignment");
81 strcpy(buf, "logical not");
84 strcpy(buf, "arithmetic negation");
87 strcpy(buf, "bitwise inversion");
90 strcpy(buf, "plus sign");
93 snprintf(buf, sizeof(buf), "illegal(%d)", type);
100 exprTypeText(unsigned type)
107 strcpy(buf, "unknown");
110 strcpy(buf, "boolean");
116 strcpy(buf, "string");
119 strcpy(buf, "action");
122 strcpy(buf, "keyname");
125 snprintf(buf, sizeof(buf), "illegal(%d)", type);
132 ExprResolveLhs(ExprDef * expr,
133 ExprResult * elem_rtrn,
134 ExprResult * field_rtrn, ExprDef ** index_rtrn)
139 elem_rtrn->str = NULL;
140 field_rtrn->str = XkbcAtomGetString(expr->value.str);
144 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
145 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
149 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
150 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
151 *index_rtrn = expr->value.array.entry;
154 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
159 SimpleLookup(char * priv,
160 uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
165 if ((priv == NULL) ||
166 (field == None) || (elem != None) ||
167 ((type != TypeInt) && (type != TypeFloat)))
171 str = XkbcAtomText(field);
172 for (entry = (LookupEntry *) priv;
173 (entry != NULL) && (entry->name != NULL); entry++)
175 if (uStrCaseCmp(str, entry->name) == 0)
177 val_rtrn->uval = entry->result;
178 if (type == TypeFloat)
179 val_rtrn->uval *= XkbGeomPtsPerMM;
187 RadioLookup(char * priv,
188 uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
193 if ((field == None) || (elem != None) || (type != TypeInt))
195 str = XkbcAtomText(field);
198 if (uStrCasePrefix("group", str))
199 str += strlen("group");
200 else if (uStrCasePrefix("radiogroup", str))
201 str += strlen("radiogroup");
202 else if (uStrCasePrefix("rg", str))
204 else if (!isdigit(str[0]))
207 if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
208 || (rg > XkbMaxRadioGroups))
214 static LookupEntry modIndexNames[] = {
215 {"shift", ShiftMapIndex},
216 {"control", ControlMapIndex},
217 {"lock", LockMapIndex},
218 {"mod1", Mod1MapIndex},
219 {"mod2", Mod2MapIndex},
220 {"mod3", Mod3MapIndex},
221 {"mod4", Mod4MapIndex},
222 {"mod5", Mod5MapIndex},
223 {"none", XkbNoModifier},
228 LookupModIndex(char * priv,
229 uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
231 return SimpleLookup((char *) modIndexNames, elem, field, type,
236 LookupModMask(char * priv,
237 uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
242 if ((elem != None) || (type != TypeInt))
244 str = XkbcAtomGetString(field);
247 if (uStrCaseCmp(str, "all") == 0)
248 val_rtrn->uval = 0xff;
249 else if (uStrCaseCmp(str, "none") == 0)
251 else if (LookupModIndex(priv, elem, field, type, val_rtrn))
252 val_rtrn->uval = (1 << val_rtrn->uval);
253 else if (priv != NULL)
255 LookupPriv *lpriv = (LookupPriv *) priv;
256 if ((lpriv->chain == NULL) ||
257 (!(*lpriv->chain) (lpriv->chainPriv, elem, field, type,
268 ExprResolveModMask(ExprDef * expr,
269 ExprResult * val_rtrn)
275 priv.chainPriv = NULL;
276 return ExprResolveMask(expr, val_rtrn, LookupModMask, (char *) & priv);
280 ExprResolveVModMask(ExprDef * expr,
281 ExprResult * val_rtrn,
282 struct xkb_desc *xkb)
287 priv.chain = LookupVModMask;
288 priv.chainPriv = (char *) xkb;
289 return ExprResolveMask(expr, val_rtrn, LookupModMask, (char *) & priv);
293 ExprResolveBoolean(ExprDef * expr,
294 ExprResult * val_rtrn)
297 const char *bogus = NULL;
302 if (expr->type != TypeBoolean)
305 ("Found constant of type %s where boolean was expected\n",
306 exprTypeText(expr->type));
309 val_rtrn->ival = expr->value.ival;
312 bogus = XkbcAtomText(expr->value.str);
315 if ((uStrCaseCmp(bogus, "true") == 0) ||
316 (uStrCaseCmp(bogus, "yes") == 0) ||
317 (uStrCaseCmp(bogus, "on") == 0))
322 else if ((uStrCaseCmp(bogus, "false") == 0) ||
323 (uStrCaseCmp(bogus, "no") == 0) ||
324 (uStrCaseCmp(bogus, "off") == 0))
330 ERROR("Identifier \"%s\" of type int is unknown\n",
331 XkbcAtomText(expr->value.str));
334 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
335 XkbcAtomText(expr->value.field.element),
336 XkbcAtomText(expr->value.field.field));
340 ok = ExprResolveBoolean(expr, val_rtrn);
342 val_rtrn->uval = !val_rtrn->uval;
349 bogus = "Subtraction";
352 bogus = "Multiplication";
358 bogus = "Assignment";
362 ERROR("%s of boolean values not permitted\n", bogus);
365 ERROR("Unary \"+\" operator not permitted for boolean values\n");
368 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
375 ExprResolveFloat(ExprDef * expr,
376 ExprResult * val_rtrn)
379 ExprResult leftRtrn, rightRtrn;
380 ExprDef *left, *right;
385 if (expr->type == TypeString)
388 str = XkbcAtomText(expr->value.str);
389 if ((str != NULL) && (strlen(str) == 1))
391 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
395 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
397 ERROR("Found constant of type %s, expected a number\n",
398 exprTypeText(expr->type));
401 val_rtrn->ival = expr->value.ival;
402 if (expr->type == TypeInt)
403 val_rtrn->ival *= XkbGeomPtsPerMM;
406 ERROR("Numeric identifier \"%s\" unknown\n",
407 XkbcAtomText(expr->value.str));
410 ERROR("Numeric default \"%s.%s\" unknown\n",
411 XkbcAtomText(expr->value.field.element),
412 XkbcAtomText(expr->value.field.field));
418 left = expr->value.binary.left;
419 right = expr->value.binary.right;
420 if (ExprResolveFloat(left, &leftRtrn) &&
421 ExprResolveFloat(right, &rightRtrn))
426 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
429 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
432 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
435 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
442 WSGO("Assignment operator not implemented yet\n");
445 ERROR("The ! operator cannot be applied to a number\n");
449 left = expr->value.child;
450 if (ExprResolveFloat(left, &leftRtrn))
452 if (expr->op == OpNegate)
453 val_rtrn->ival = -leftRtrn.ival;
455 val_rtrn->ival = ~leftRtrn.ival;
460 left = expr->value.child;
461 return ExprResolveFloat(left, val_rtrn);
463 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
470 ExprResolveKeyCode(ExprDef * expr,
471 ExprResult * val_rtrn)
473 ExprResult leftRtrn, rightRtrn;
474 ExprDef *left, *right;
479 if (expr->type != TypeInt)
482 ("Found constant of type %s where an int was expected\n",
483 exprTypeText(expr->type));
486 val_rtrn->uval = expr->value.uval;
492 left = expr->value.binary.left;
493 right = expr->value.binary.right;
494 if (ExprResolveKeyCode(left, &leftRtrn) &&
495 ExprResolveKeyCode(right, &rightRtrn))
500 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
503 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
506 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
509 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
516 left = expr->value.child;
517 if (ExprResolveKeyCode(left, &leftRtrn))
519 val_rtrn->uval = ~leftRtrn.uval;
524 left = expr->value.child;
525 return ExprResolveKeyCode(left, val_rtrn);
527 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
534 * This function returns ... something. It's a bit of a guess, really.
536 * If a string is given in value context, its first character will be
537 * returned in uval. If an integer is given in value context, it will be
538 * returned in ival. If a float is given in value context, it will be
539 * returned as millimetres (rather than points) in ival.
541 * If an ident or field reference is given, the lookup function (if given)
542 * will be called. At the moment, only RadioLookup and SimpleLookup use
543 * this, and they both return the results in uval. And don't support field
549 ExprResolveIntegerLookup(ExprDef * expr,
550 ExprResult * val_rtrn,
551 IdentLookupFunc lookup, char * lookupPriv)
554 ExprResult leftRtrn, rightRtrn;
555 ExprDef *left, *right;
560 if (expr->type == TypeString)
563 str = XkbcAtomText(expr->value.str);
571 val_rtrn->uval = str[0];
577 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
580 ("Found constant of type %s where an int was expected\n",
581 exprTypeText(expr->type));
584 val_rtrn->ival = expr->value.ival;
585 if (expr->type == TypeFloat)
586 val_rtrn->ival /= XkbGeomPtsPerMM;
591 ok = (*lookup) (lookupPriv,
592 None, expr->value.str, TypeInt, val_rtrn);
595 ERROR("Identifier \"%s\" of type int is unknown\n",
596 XkbcAtomText(expr->value.str));
601 ok = (*lookup) (lookupPriv,
602 expr->value.field.element,
603 expr->value.field.field, TypeInt, val_rtrn);
606 ERROR("Default \"%s.%s\" of type int is unknown\n",
607 XkbcAtomText(expr->value.field.element),
608 XkbcAtomText(expr->value.field.field));
614 left = expr->value.binary.left;
615 right = expr->value.binary.right;
616 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
617 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
622 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
625 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
628 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
631 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
638 WSGO("Assignment operator not implemented yet\n");
641 ERROR("The ! operator cannot be applied to an integer\n");
645 left = expr->value.child;
646 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
648 if (expr->op == OpNegate)
649 val_rtrn->ival = -leftRtrn.ival;
651 val_rtrn->ival = ~leftRtrn.ival;
656 left = expr->value.child;
657 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
659 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
666 ExprResolveInteger(ExprDef * expr,
667 ExprResult * val_rtrn)
669 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
673 ExprResolveRadioGroup(ExprDef * expr,
674 ExprResult * val_rtrn)
676 return ExprResolveIntegerLookup(expr, val_rtrn, RadioLookup, NULL);
680 ExprResolveGroup(ExprDef * expr,
681 ExprResult * val_rtrn)
683 static LookupEntry group_names[] = {
695 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
696 (char *) group_names);
700 ExprResolveLevel(ExprDef * expr,
701 ExprResult * val_rtrn)
703 static LookupEntry level_names[] = {
715 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
716 (char *) level_names);
720 ExprResolveButton(ExprDef * expr,
721 ExprResult * val_rtrn)
723 static LookupEntry button_names[] = {
733 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
734 (char *) button_names);
738 ExprResolveString(ExprDef * expr,
739 ExprResult * val_rtrn)
741 ExprResult leftRtrn, rightRtrn;
749 if (expr->type != TypeString)
751 ERROR("Found constant of type %s, expected a string\n",
752 exprTypeText(expr->type));
755 val_rtrn->str = XkbcAtomGetString(expr->value.str);
756 if (val_rtrn->str == NULL)
757 val_rtrn->str = strdup("");
760 ERROR("Identifier \"%s\" of type string not found\n",
761 XkbcAtomText(expr->value.str));
764 ERROR("Default \"%s.%s\" of type string not found\n",
765 XkbcAtomText(expr->value.field.element),
766 XkbcAtomText(expr->value.field.field));
769 left = expr->value.binary.left;
770 right = expr->value.binary.right;
771 if (ExprResolveString(left, &leftRtrn) &&
772 ExprResolveString(right, &rightRtrn))
776 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
777 new = (char *) malloc(len);
779 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
791 bogus = "Subtraction";
794 bogus = "Multiplication";
800 bogus = "Assignment";
806 bogus = "Bitwise complement";
807 ERROR("%s of string values not permitted\n", bogus);
810 ERROR("The ! operator cannot be applied to a string\n");
813 ERROR("The + operator cannot be applied to a string\n");
816 WSGO("Unknown operator %d in ResolveString\n", expr->op);
823 ExprResolveKeyName(ExprDef * expr,
824 ExprResult * val_rtrn)
831 if (expr->type != TypeKeyName)
833 ERROR("Found constant of type %s, expected a key name\n",
834 exprTypeText(expr->type));
837 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
840 ERROR("Identifier \"%s\" of type string not found\n",
841 XkbcAtomText(expr->value.str));
844 ERROR("Default \"%s.%s\" of type key name not found\n",
845 XkbcAtomText(expr->value.field.element),
846 XkbcAtomText(expr->value.field.field));
853 bogus = "Subtraction";
856 bogus = "Multiplication";
862 bogus = "Assignment";
868 bogus = "Bitwise complement";
869 ERROR("%s of key name values not permitted\n", bogus);
872 ERROR("The ! operator cannot be applied to a key name\n");
875 ERROR("The + operator cannot be applied to a key name\n");
878 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
884 /***====================================================================***/
887 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
889 if (expr->op != ExprIdent)
891 ERROR("Found a %s where an enumerated value was expected\n",
892 exprOpText(expr->op));
895 if (!SimpleLookup((char *) values, (uint32_t) None, expr->value.str,
896 (unsigned) TypeInt, val_rtrn))
899 ERROR("Illegal identifier %s (expected one of: ",
900 XkbcAtomText(expr->value.str));
901 while (values && values->name)
904 INFO(", %s", values->name);
906 INFO("%s", values->name);
917 ExprResolveMask(ExprDef * expr,
918 ExprResult * val_rtrn,
919 IdentLookupFunc lookup, char * lookupPriv)
922 ExprResult leftRtrn, rightRtrn;
923 ExprDef *left, *right;
929 if (expr->type != TypeInt)
932 ("Found constant of type %s where a mask was expected\n",
933 exprTypeText(expr->type));
936 val_rtrn->ival = expr->value.ival;
941 ok = (*lookup) (lookupPriv,
942 None, expr->value.str, TypeInt, val_rtrn);
945 ERROR("Identifier \"%s\" of type int is unknown\n",
946 XkbcAtomText(expr->value.str));
951 ok = (*lookup) (lookupPriv,
952 expr->value.field.element,
953 expr->value.field.field, TypeInt, val_rtrn);
956 ERROR("Default \"%s.%s\" of type int is unknown\n",
957 XkbcAtomText(expr->value.field.element),
958 XkbcAtomText(expr->value.field.field));
961 bogus = "array reference";
964 bogus = "function use";
965 ERROR("Unexpected %s in mask expression\n", bogus);
966 ACTION("Expression ignored\n");
972 left = expr->value.binary.left;
973 right = expr->value.binary.right;
974 if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) &&
975 ExprResolveMask(right, &rightRtrn, lookup, lookupPriv))
980 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
983 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
987 ERROR("Cannot %s masks\n",
988 expr->op == OpDivide ? "divide" : "multiply");
989 ACTION("Illegal operation ignored\n");
996 WSGO("Assignment operator not implemented yet\n");
999 left = expr->value.child;
1000 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
1002 val_rtrn->ival = ~leftRtrn.ival;
1009 left = expr->value.child;
1010 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
1012 ERROR("The %s operator cannot be used with a mask\n",
1013 (expr->op == OpNegate ? "-" : "!"));
1017 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
1024 ExprResolveKeySym(ExprDef * expr,
1025 ExprResult * val_rtrn)
1030 if (expr->op == ExprIdent)
1033 str = XkbcAtomText(expr->value.str);
1034 if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
1036 val_rtrn->uval = sym;
1040 ok = ExprResolveInteger(expr, val_rtrn);
1041 if ((ok) && (val_rtrn->uval < 10))
1042 val_rtrn->uval += '0';