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 /***====================================================================***/
37 typedef Bool(*IdentLookupFunc) (char * /* priv */ ,
38 uint32_t /* field */ ,
40 ExprResult * /* val_rtrn */
43 /***====================================================================***/
46 exprOpText(unsigned type)
53 strcpy(buf, "literal");
56 strcpy(buf, "identifier");
59 strcpy(buf, "action declaration");
62 strcpy(buf, "field reference");
65 strcpy(buf, "array reference");
68 strcpy(buf, "list of keysyms");
71 strcpy(buf, "list of actions");
74 strcpy(buf, "addition");
77 strcpy(buf, "subtraction");
80 strcpy(buf, "multiplication");
83 strcpy(buf, "division");
86 strcpy(buf, "assignment");
89 strcpy(buf, "logical not");
92 strcpy(buf, "arithmetic negation");
95 strcpy(buf, "bitwise inversion");
98 strcpy(buf, "plus sign");
101 snprintf(buf, sizeof(buf), "illegal(%d)", type);
108 exprTypeText(unsigned type)
115 strcpy(buf, "unknown");
118 strcpy(buf, "boolean");
124 strcpy(buf, "string");
127 strcpy(buf, "action");
130 strcpy(buf, "keyname");
133 snprintf(buf, sizeof(buf), "illegal(%d)", type);
140 ExprResolveLhs(ExprDef * expr,
141 ExprResult * elem_rtrn,
142 ExprResult * field_rtrn, ExprDef ** index_rtrn)
147 elem_rtrn->str = NULL;
148 field_rtrn->str = XkbcAtomGetString(expr->value.str);
152 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
153 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
157 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
158 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
159 *index_rtrn = expr->value.array.entry;
162 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
167 SimpleLookup(char * priv, uint32_t field, unsigned type,
168 ExprResult * val_rtrn)
173 if ((priv == NULL) || (field == None) ||
174 ((type != TypeInt) && (type != TypeFloat)))
178 str = XkbcAtomText(field);
179 for (entry = (LookupEntry *) priv;
180 (entry != NULL) && (entry->name != NULL); entry++)
182 if (uStrCaseCmp(str, entry->name) == 0)
184 val_rtrn->uval = entry->result;
185 if (type == TypeFloat)
186 val_rtrn->uval *= XkbGeomPtsPerMM;
194 RadioLookup(char * priv, uint32_t field, unsigned type, ExprResult * val_rtrn)
199 if ((field == None) || (type != TypeInt))
201 str = XkbcAtomText(field);
204 if (uStrCasePrefix("group", str))
205 str += strlen("group");
206 else if (uStrCasePrefix("radiogroup", str))
207 str += strlen("radiogroup");
208 else if (uStrCasePrefix("rg", str))
210 else if (!isdigit(str[0]))
213 if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
214 || (rg > XkbMaxRadioGroups))
220 static LookupEntry modIndexNames[] = {
221 {"shift", ShiftMapIndex},
222 {"control", ControlMapIndex},
223 {"lock", LockMapIndex},
224 {"mod1", Mod1MapIndex},
225 {"mod2", Mod2MapIndex},
226 {"mod3", Mod3MapIndex},
227 {"mod4", Mod4MapIndex},
228 {"mod5", Mod5MapIndex},
229 {"none", XkbNoModifier},
234 LookupModIndex(char * priv, uint32_t field, unsigned type,
235 ExprResult * val_rtrn)
237 return SimpleLookup((char *) modIndexNames, field, type, val_rtrn);
241 LookupModMask(char * priv, uint32_t field, unsigned type,
242 ExprResult * val_rtrn)
249 str = XkbcAtomGetString(field);
252 if (uStrCaseCmp(str, "all") == 0)
253 val_rtrn->uval = 0xff;
254 else if (uStrCaseCmp(str, "none") == 0)
256 else if (LookupModIndex(priv, field, type, val_rtrn))
257 val_rtrn->uval = (1 << val_rtrn->uval);
265 ExprResolveBoolean(ExprDef * expr,
266 ExprResult * val_rtrn)
269 const char *bogus = NULL;
274 if (expr->type != TypeBoolean)
277 ("Found constant of type %s where boolean was expected\n",
278 exprTypeText(expr->type));
281 val_rtrn->ival = expr->value.ival;
284 bogus = XkbcAtomText(expr->value.str);
287 if ((uStrCaseCmp(bogus, "true") == 0) ||
288 (uStrCaseCmp(bogus, "yes") == 0) ||
289 (uStrCaseCmp(bogus, "on") == 0))
294 else if ((uStrCaseCmp(bogus, "false") == 0) ||
295 (uStrCaseCmp(bogus, "no") == 0) ||
296 (uStrCaseCmp(bogus, "off") == 0))
302 ERROR("Identifier \"%s\" of type int is unknown\n",
303 XkbcAtomText(expr->value.str));
306 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
307 XkbcAtomText(expr->value.field.element),
308 XkbcAtomText(expr->value.field.field));
312 ok = ExprResolveBoolean(expr, val_rtrn);
314 val_rtrn->uval = !val_rtrn->uval;
321 bogus = "Subtraction";
324 bogus = "Multiplication";
330 bogus = "Assignment";
334 ERROR("%s of boolean values not permitted\n", bogus);
337 ERROR("Unary \"+\" operator not permitted for boolean values\n");
340 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
347 ExprResolveFloat(ExprDef * expr,
348 ExprResult * val_rtrn)
351 ExprResult leftRtrn, rightRtrn;
352 ExprDef *left, *right;
357 if (expr->type == TypeString)
360 str = XkbcAtomText(expr->value.str);
361 if ((str != NULL) && (strlen(str) == 1))
363 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
367 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
369 ERROR("Found constant of type %s, expected a number\n",
370 exprTypeText(expr->type));
373 val_rtrn->ival = expr->value.ival;
374 if (expr->type == TypeInt)
375 val_rtrn->ival *= XkbGeomPtsPerMM;
378 ERROR("Numeric identifier \"%s\" unknown\n",
379 XkbcAtomText(expr->value.str));
382 ERROR("Numeric default \"%s.%s\" unknown\n",
383 XkbcAtomText(expr->value.field.element),
384 XkbcAtomText(expr->value.field.field));
390 left = expr->value.binary.left;
391 right = expr->value.binary.right;
392 if (ExprResolveFloat(left, &leftRtrn) &&
393 ExprResolveFloat(right, &rightRtrn))
398 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
401 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
404 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
407 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
414 WSGO("Assignment operator not implemented yet\n");
417 ERROR("The ! operator cannot be applied to a number\n");
421 left = expr->value.child;
422 if (ExprResolveFloat(left, &leftRtrn))
424 if (expr->op == OpNegate)
425 val_rtrn->ival = -leftRtrn.ival;
427 val_rtrn->ival = ~leftRtrn.ival;
432 left = expr->value.child;
433 return ExprResolveFloat(left, val_rtrn);
435 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
442 ExprResolveKeyCode(ExprDef * expr,
443 ExprResult * val_rtrn)
445 ExprResult leftRtrn, rightRtrn;
446 ExprDef *left, *right;
451 if (expr->type != TypeInt)
454 ("Found constant of type %s where an int was expected\n",
455 exprTypeText(expr->type));
458 val_rtrn->uval = expr->value.uval;
464 left = expr->value.binary.left;
465 right = expr->value.binary.right;
466 if (ExprResolveKeyCode(left, &leftRtrn) &&
467 ExprResolveKeyCode(right, &rightRtrn))
472 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
475 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
478 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
481 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
488 left = expr->value.child;
489 if (ExprResolveKeyCode(left, &leftRtrn))
491 val_rtrn->uval = ~leftRtrn.uval;
496 left = expr->value.child;
497 return ExprResolveKeyCode(left, val_rtrn);
499 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
506 * This function returns ... something. It's a bit of a guess, really.
508 * If a string is given in value context, its first character will be
509 * returned in uval. If an integer is given in value context, it will be
510 * returned in ival. If a float is given in value context, it will be
511 * returned as millimetres (rather than points) in ival.
513 * If an ident or field reference is given, the lookup function (if given)
514 * will be called. At the moment, only RadioLookup and SimpleLookup use
515 * this, and they both return the results in uval. And don't support field
521 ExprResolveIntegerLookup(ExprDef * expr,
522 ExprResult * val_rtrn,
523 IdentLookupFunc lookup, char * lookupPriv)
526 ExprResult leftRtrn, rightRtrn;
527 ExprDef *left, *right;
532 if (expr->type == TypeString)
535 str = XkbcAtomText(expr->value.str);
543 val_rtrn->uval = str[0];
549 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
552 ("Found constant of type %s where an int was expected\n",
553 exprTypeText(expr->type));
556 val_rtrn->ival = expr->value.ival;
557 if (expr->type == TypeFloat)
558 val_rtrn->ival /= XkbGeomPtsPerMM;
563 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
566 ERROR("Identifier \"%s\" of type int is unknown\n",
567 XkbcAtomText(expr->value.str));
570 ERROR("Default \"%s.%s\" of type int is unknown\n",
571 XkbcAtomText(expr->value.field.element),
572 XkbcAtomText(expr->value.field.field));
578 left = expr->value.binary.left;
579 right = expr->value.binary.right;
580 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
581 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
586 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
589 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
592 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
595 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
602 WSGO("Assignment operator not implemented yet\n");
605 ERROR("The ! operator cannot be applied to an integer\n");
609 left = expr->value.child;
610 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
612 if (expr->op == OpNegate)
613 val_rtrn->ival = -leftRtrn.ival;
615 val_rtrn->ival = ~leftRtrn.ival;
620 left = expr->value.child;
621 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
623 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
630 ExprResolveInteger(ExprDef * expr,
631 ExprResult * val_rtrn)
633 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
637 ExprResolveRadioGroup(ExprDef * expr,
638 ExprResult * val_rtrn)
640 return ExprResolveIntegerLookup(expr, val_rtrn, RadioLookup, NULL);
644 ExprResolveGroup(ExprDef * expr,
645 ExprResult * val_rtrn)
647 static LookupEntry group_names[] = {
659 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
660 (char *) group_names);
664 ExprResolveLevel(ExprDef * expr,
665 ExprResult * val_rtrn)
667 static LookupEntry level_names[] = {
679 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
680 (char *) level_names);
684 ExprResolveButton(ExprDef * expr,
685 ExprResult * val_rtrn)
687 static LookupEntry button_names[] = {
697 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
698 (char *) button_names);
702 ExprResolveString(ExprDef * expr,
703 ExprResult * val_rtrn)
705 ExprResult leftRtrn, rightRtrn;
713 if (expr->type != TypeString)
715 ERROR("Found constant of type %s, expected a string\n",
716 exprTypeText(expr->type));
719 val_rtrn->str = XkbcAtomGetString(expr->value.str);
720 if (val_rtrn->str == NULL)
721 val_rtrn->str = strdup("");
724 ERROR("Identifier \"%s\" of type string not found\n",
725 XkbcAtomText(expr->value.str));
728 ERROR("Default \"%s.%s\" of type string not found\n",
729 XkbcAtomText(expr->value.field.element),
730 XkbcAtomText(expr->value.field.field));
733 left = expr->value.binary.left;
734 right = expr->value.binary.right;
735 if (ExprResolveString(left, &leftRtrn) &&
736 ExprResolveString(right, &rightRtrn))
740 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
741 new = (char *) malloc(len);
743 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
755 bogus = "Subtraction";
758 bogus = "Multiplication";
764 bogus = "Assignment";
770 bogus = "Bitwise complement";
771 ERROR("%s of string values not permitted\n", bogus);
774 ERROR("The ! operator cannot be applied to a string\n");
777 ERROR("The + operator cannot be applied to a string\n");
780 WSGO("Unknown operator %d in ResolveString\n", expr->op);
787 ExprResolveKeyName(ExprDef * expr,
788 ExprResult * val_rtrn)
795 if (expr->type != TypeKeyName)
797 ERROR("Found constant of type %s, expected a key name\n",
798 exprTypeText(expr->type));
801 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
804 ERROR("Identifier \"%s\" of type string not found\n",
805 XkbcAtomText(expr->value.str));
808 ERROR("Default \"%s.%s\" of type key name not found\n",
809 XkbcAtomText(expr->value.field.element),
810 XkbcAtomText(expr->value.field.field));
817 bogus = "Subtraction";
820 bogus = "Multiplication";
826 bogus = "Assignment";
832 bogus = "Bitwise complement";
833 ERROR("%s of key name values not permitted\n", bogus);
836 ERROR("The ! operator cannot be applied to a key name\n");
839 ERROR("The + operator cannot be applied to a key name\n");
842 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
848 /***====================================================================***/
851 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
853 if (expr->op != ExprIdent)
855 ERROR("Found a %s where an enumerated value was expected\n",
856 exprOpText(expr->op));
859 if (!SimpleLookup((char *) values, expr->value.str, TypeInt, val_rtrn))
862 ERROR("Illegal identifier %s (expected one of: ",
863 XkbcAtomText(expr->value.str));
864 while (values && values->name)
867 INFO(", %s", values->name);
869 INFO("%s", values->name);
880 ExprResolveMaskLookup(ExprDef * expr,
881 ExprResult * val_rtrn,
882 IdentLookupFunc lookup,
886 ExprResult leftRtrn, rightRtrn;
887 ExprDef *left, *right;
893 if (expr->type != TypeInt)
896 ("Found constant of type %s where a mask was expected\n",
897 exprTypeText(expr->type));
900 val_rtrn->ival = expr->value.ival;
903 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
905 ERROR("Identifier \"%s\" of type int is unknown\n",
906 XkbcAtomText(expr->value.str));
909 ERROR("Default \"%s.%s\" of type int is unknown\n",
910 XkbcAtomText(expr->value.field.element),
911 XkbcAtomText(expr->value.field.field));
914 bogus = "array reference";
917 bogus = "function use";
918 ERROR("Unexpected %s in mask expression\n", bogus);
919 ACTION("Expression ignored\n");
925 left = expr->value.binary.left;
926 right = expr->value.binary.right;
927 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
928 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
933 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
936 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
940 ERROR("Cannot %s masks\n",
941 expr->op == OpDivide ? "divide" : "multiply");
942 ACTION("Illegal operation ignored\n");
949 WSGO("Assignment operator not implemented yet\n");
952 left = expr->value.child;
953 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
955 val_rtrn->ival = ~leftRtrn.ival;
962 left = expr->value.child;
963 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
965 ERROR("The %s operator cannot be used with a mask\n",
966 (expr->op == OpNegate ? "-" : "!"));
970 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
977 ExprResolveMask(ExprDef * expr,
978 ExprResult * val_rtrn,
979 LookupEntry * values)
981 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup,
986 ExprResolveModMask(ExprDef * expr,
987 ExprResult * val_rtrn)
989 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
993 ExprResolveVModMask(ExprDef * expr,
994 ExprResult * val_rtrn,
995 struct xkb_desc *xkb)
997 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask,
1002 ExprResolveKeySym(ExprDef * expr,
1003 ExprResult * val_rtrn)
1008 if (expr->op == ExprIdent)
1011 str = XkbcAtomText(expr->value.str);
1012 if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
1014 val_rtrn->uval = sym;
1018 ok = ExprResolveInteger(expr, val_rtrn);
1019 if ((ok) && (val_rtrn->uval < 10))
1020 val_rtrn->uval += '0';