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 /***====================================================================***/
37 exprOpText(unsigned type)
44 strcpy(buf, "literal");
47 strcpy(buf, "identifier");
50 strcpy(buf, "action declaration");
53 strcpy(buf, "field reference");
56 strcpy(buf, "array reference");
59 strcpy(buf, "list of keysyms");
62 strcpy(buf, "list of actions");
65 strcpy(buf, "addition");
68 strcpy(buf, "subtraction");
71 strcpy(buf, "multiplication");
74 strcpy(buf, "division");
77 strcpy(buf, "assignment");
80 strcpy(buf, "logical not");
83 strcpy(buf, "arithmetic negation");
86 strcpy(buf, "bitwise inversion");
89 strcpy(buf, "plus sign");
92 snprintf(buf, sizeof(buf), "illegal(%d)", type);
99 exprTypeText(unsigned type)
106 strcpy(buf, "unknown");
109 strcpy(buf, "boolean");
115 strcpy(buf, "string");
118 strcpy(buf, "action");
121 strcpy(buf, "keyname");
124 snprintf(buf, sizeof(buf), "illegal(%d)", type);
131 ExprResolveLhs(ExprDef * expr,
132 ExprResult * elem_rtrn,
133 ExprResult * field_rtrn, ExprDef ** index_rtrn)
138 elem_rtrn->str = NULL;
139 field_rtrn->str = XkbcAtomGetString(expr->value.str);
143 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
144 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
148 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
149 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
150 *index_rtrn = expr->value.array.entry;
153 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
158 SimpleLookup(char * priv,
159 uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
164 if ((priv == NULL) ||
165 (field == None) || (elem != None) ||
166 ((type != TypeInt) && (type != TypeFloat)))
170 str = XkbcAtomText(field);
171 for (entry = (LookupEntry *) priv;
172 (entry != NULL) && (entry->name != NULL); entry++)
174 if (uStrCaseCmp(str, entry->name) == 0)
176 val_rtrn->uval = entry->result;
177 if (type == TypeFloat)
178 val_rtrn->uval *= XkbGeomPtsPerMM;
186 RadioLookup(char * priv,
187 uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
192 if ((field == None) || (elem != None) || (type != TypeInt))
194 str = XkbcAtomText(field);
197 if (uStrCasePrefix("group", str))
198 str += strlen("group");
199 else if (uStrCasePrefix("radiogroup", str))
200 str += strlen("radiogroup");
201 else if (uStrCasePrefix("rg", str))
203 else if (!isdigit(str[0]))
206 if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
207 || (rg > XkbMaxRadioGroups))
214 TableLookup(char * priv,
215 uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
217 LookupTable *tbl = (LookupTable *) priv;
220 if ((priv == NULL) || (field == None) || (type != TypeInt))
222 str = XkbcAtomText(elem);
225 if (((str == NULL) && (tbl->element == NULL)) ||
226 ((str != NULL) && (tbl->element != NULL) &&
227 (uStrCaseCmp(str, tbl->element) == 0)))
231 tbl = tbl->nextElement;
233 if (tbl == NULL) /* didn't find a matching element */
235 priv = (char *) tbl->entries;
236 return SimpleLookup(priv, (uint32_t) None, field, type, val_rtrn);
239 static LookupEntry modIndexNames[] = {
240 {"shift", ShiftMapIndex},
241 {"control", ControlMapIndex},
242 {"lock", LockMapIndex},
243 {"mod1", Mod1MapIndex},
244 {"mod2", Mod2MapIndex},
245 {"mod3", Mod3MapIndex},
246 {"mod4", Mod4MapIndex},
247 {"mod5", Mod5MapIndex},
248 {"none", XkbNoModifier},
253 LookupModIndex(char * priv,
254 uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
256 return SimpleLookup((char *) modIndexNames, elem, field, type,
261 LookupModMask(char * priv,
262 uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
267 if ((elem != None) || (type != TypeInt))
269 str = XkbcAtomGetString(field);
272 if (uStrCaseCmp(str, "all") == 0)
273 val_rtrn->uval = 0xff;
274 else if (uStrCaseCmp(str, "none") == 0)
276 else if (LookupModIndex(priv, elem, field, type, val_rtrn))
277 val_rtrn->uval = (1 << val_rtrn->uval);
278 else if (priv != NULL)
280 LookupPriv *lpriv = (LookupPriv *) priv;
281 if ((lpriv->chain == NULL) ||
282 (!(*lpriv->chain) (lpriv->chainPriv, elem, field, type,
293 ExprResolveModIndex(ExprDef * expr,
294 ExprResult * val_rtrn,
295 IdentLookupFunc lookup, char * lookupPriv)
303 if (expr->type != TypeInt)
306 ("Found constant of type %s where a modifier mask was expected\n",
307 exprTypeText(expr->type));
310 else if ((expr->value.ival >= XkbNumModifiers)
311 || (expr->value.ival < 0))
313 ERROR("Illegal modifier index (%d, must be 0..%d)\n",
314 expr->value.ival, XkbNumModifiers - 1);
317 val_rtrn->ival = expr->value.ival;
320 if (LookupModIndex(lookupPriv, (uint32_t) None, expr->value.str,
321 (unsigned) TypeInt, val_rtrn))
327 ok = (*lookup) (lookupPriv,
328 None, expr->value.str, TypeInt, val_rtrn);
331 ERROR("Cannot determine modifier index for \"%s\"\n",
332 XkbcAtomText(expr->value.str));
335 bogus = "field reference";
338 bogus = "array reference";
351 bogus = "arithmetic operations";
354 bogus = "assignment";
357 WSGO("Unknown operator %d in ResolveModIndex\n", expr->op);
362 ERROR("Modifier index must be a name or number, %s ignored\n",
370 ExprResolveModMask(ExprDef * expr,
371 ExprResult * val_rtrn,
372 IdentLookupFunc lookup, char * lookupPriv)
378 priv.chainPriv = lookupPriv;
379 return ExprResolveMask(expr, val_rtrn, LookupModMask, (char *) & priv);
383 ExprResolveBoolean(ExprDef * expr,
384 ExprResult * val_rtrn,
385 IdentLookupFunc lookup, char * lookupPriv)
388 const char *bogus = NULL;
393 if (expr->type != TypeBoolean)
396 ("Found constant of type %s where boolean was expected\n",
397 exprTypeText(expr->type));
400 val_rtrn->ival = expr->value.ival;
403 bogus = XkbcAtomText(expr->value.str);
406 if ((uStrCaseCmp(bogus, "true") == 0) ||
407 (uStrCaseCmp(bogus, "yes") == 0) ||
408 (uStrCaseCmp(bogus, "on") == 0))
413 else if ((uStrCaseCmp(bogus, "false") == 0) ||
414 (uStrCaseCmp(bogus, "no") == 0) ||
415 (uStrCaseCmp(bogus, "off") == 0))
423 ok = (*lookup) (lookupPriv,
424 None, expr->value.str, TypeBoolean, val_rtrn);
427 ERROR("Identifier \"%s\" of type int is unknown\n",
428 XkbcAtomText(expr->value.str));
433 ok = (*lookup) (lookupPriv,
434 expr->value.field.element,
435 expr->value.field.field, TypeBoolean, val_rtrn);
438 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
439 XkbcAtomText(expr->value.field.element),
440 XkbcAtomText(expr->value.field.field));
444 ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv);
446 val_rtrn->uval = !val_rtrn->uval;
453 bogus = "Subtraction";
456 bogus = "Multiplication";
462 bogus = "Assignment";
466 ERROR("%s of boolean values not permitted\n", bogus);
469 ERROR("Unary \"+\" operator not permitted for boolean values\n");
472 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
479 ExprResolveFloat(ExprDef * expr,
480 ExprResult * val_rtrn,
481 IdentLookupFunc lookup, char * lookupPriv)
484 ExprResult leftRtrn, rightRtrn;
485 ExprDef *left, *right;
490 if (expr->type == TypeString)
493 str = XkbcAtomText(expr->value.str);
494 if ((str != NULL) && (strlen(str) == 1))
496 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
500 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
502 ERROR("Found constant of type %s, expected a number\n",
503 exprTypeText(expr->type));
506 val_rtrn->ival = expr->value.ival;
507 if (expr->type == TypeInt)
508 val_rtrn->ival *= XkbGeomPtsPerMM;
513 ok = (*lookup) (lookupPriv,
514 None, expr->value.str, TypeFloat, val_rtrn);
517 ERROR("Numeric identifier \"%s\" unknown\n",
518 XkbcAtomText(expr->value.str));
523 ok = (*lookup) (lookupPriv,
524 expr->value.field.element,
525 expr->value.field.field, TypeFloat, val_rtrn);
528 ERROR("Numeric default \"%s.%s\" unknown\n",
529 XkbcAtomText(expr->value.field.element),
530 XkbcAtomText(expr->value.field.field));
536 left = expr->value.binary.left;
537 right = expr->value.binary.right;
538 if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) &&
539 ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv))
544 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
547 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
550 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
553 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
560 WSGO("Assignment operator not implemented yet\n");
563 left = expr->value.child;
564 if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
566 ERROR("The ! operator cannot be applied to a number\n");
571 left = expr->value.child;
572 if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
574 if (expr->op == OpNegate)
575 val_rtrn->ival = -leftRtrn.ival;
577 val_rtrn->ival = ~leftRtrn.ival;
582 left = expr->value.child;
583 return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv);
585 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
592 ExprResolveInteger(ExprDef * expr,
593 ExprResult * val_rtrn,
594 IdentLookupFunc lookup, char * lookupPriv)
597 ExprResult leftRtrn, rightRtrn;
598 ExprDef *left, *right;
603 if (expr->type == TypeString)
606 str = XkbcAtomText(expr->value.str);
614 val_rtrn->uval = str[0];
620 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
623 ("Found constant of type %s where an int was expected\n",
624 exprTypeText(expr->type));
627 val_rtrn->ival = expr->value.ival;
628 if (expr->type == TypeFloat)
629 val_rtrn->ival /= XkbGeomPtsPerMM;
634 ok = (*lookup) (lookupPriv,
635 None, expr->value.str, TypeInt, val_rtrn);
638 ERROR("Identifier \"%s\" of type int is unknown\n",
639 XkbcAtomText(expr->value.str));
644 ok = (*lookup) (lookupPriv,
645 expr->value.field.element,
646 expr->value.field.field, TypeInt, val_rtrn);
649 ERROR("Default \"%s.%s\" of type int is unknown\n",
650 XkbcAtomText(expr->value.field.element),
651 XkbcAtomText(expr->value.field.field));
657 left = expr->value.binary.left;
658 right = expr->value.binary.right;
659 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv) &&
660 ExprResolveInteger(right, &rightRtrn, lookup, lookupPriv))
665 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
668 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
671 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
674 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
681 WSGO("Assignment operator not implemented yet\n");
684 left = expr->value.child;
685 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
687 ERROR("The ! operator cannot be applied to an integer\n");
692 left = expr->value.child;
693 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
695 if (expr->op == OpNegate)
696 val_rtrn->ival = -leftRtrn.ival;
698 val_rtrn->ival = ~leftRtrn.ival;
703 left = expr->value.child;
704 return ExprResolveInteger(left, val_rtrn, lookup, lookupPriv);
706 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
713 ExprResolveString(ExprDef * expr,
714 ExprResult * val_rtrn,
715 IdentLookupFunc lookup, char * lookupPriv)
718 ExprResult leftRtrn, rightRtrn;
726 if (expr->type != TypeString)
728 ERROR("Found constant of type %s, expected a string\n",
729 exprTypeText(expr->type));
732 val_rtrn->str = XkbcAtomGetString(expr->value.str);
733 if (val_rtrn->str == NULL)
735 static char *empty = "";
736 val_rtrn->str = empty;
742 ok = (*lookup) (lookupPriv,
743 None, expr->value.str, TypeString, val_rtrn);
746 ERROR("Identifier \"%s\" of type string not found\n",
747 XkbcAtomText(expr->value.str));
752 ok = (*lookup) (lookupPriv,
753 expr->value.field.element,
754 expr->value.field.field, TypeString, val_rtrn);
757 ERROR("Default \"%s.%s\" of type string not found\n",
758 XkbcAtomText(expr->value.field.element),
759 XkbcAtomText(expr->value.field.field));
762 left = expr->value.binary.left;
763 right = expr->value.binary.right;
764 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) &&
765 ExprResolveString(right, &rightRtrn, lookup, lookupPriv))
769 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
770 new = (char *) malloc(len);
773 sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
781 bogus = "Subtraction";
784 bogus = "Multiplication";
790 bogus = "Assignment";
796 bogus = "Bitwise complement";
797 ERROR("%s of string values not permitted\n", bogus);
800 left = expr->value.child;
801 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
803 ERROR("The ! operator cannot be applied to a string\n");
807 left = expr->value.child;
808 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
810 ERROR("The + operator cannot be applied to a string\n");
814 WSGO("Unknown operator %d in ResolveString\n", expr->op);
821 ExprResolveKeyName(ExprDef * expr,
822 ExprResult * val_rtrn,
823 IdentLookupFunc lookup, char * lookupPriv)
833 if (expr->type != TypeKeyName)
835 ERROR("Found constant of type %s, expected a key name\n",
836 exprTypeText(expr->type));
839 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
844 ok = (*lookup) (lookupPriv,
845 None, expr->value.str, TypeString, val_rtrn);
848 ERROR("Identifier \"%s\" of type string not found\n",
849 XkbcAtomText(expr->value.str));
854 ok = (*lookup) (lookupPriv,
855 expr->value.field.element,
856 expr->value.field.field, TypeString, val_rtrn);
859 ERROR("Default \"%s.%s\" of type key name not found\n",
860 XkbcAtomText(expr->value.field.element),
861 XkbcAtomText(expr->value.field.field));
868 bogus = "Subtraction";
871 bogus = "Multiplication";
877 bogus = "Assignment";
883 bogus = "Bitwise complement";
884 ERROR("%s of key name values not permitted\n", bogus);
887 left = expr->value.binary.left;
888 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
890 ERROR("The ! operator cannot be applied to a key name\n");
894 left = expr->value.binary.left;
895 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
897 ERROR("The + operator cannot be applied to a key name\n");
901 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
907 /***====================================================================***/
910 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
912 if (expr->op != ExprIdent)
914 ERROR("Found a %s where an enumerated value was expected\n",
915 exprOpText(expr->op));
918 if (!SimpleLookup((char *) values, (uint32_t) None, expr->value.str,
919 (unsigned) TypeInt, val_rtrn))
922 ERROR("Illegal identifier %s (expected one of: ",
923 XkbcAtomText(expr->value.str));
924 while (values && values->name)
927 INFO(", %s", values->name);
929 INFO("%s", values->name);
940 ExprResolveMask(ExprDef * expr,
941 ExprResult * val_rtrn,
942 IdentLookupFunc lookup, char * lookupPriv)
945 ExprResult leftRtrn, rightRtrn;
946 ExprDef *left, *right;
952 if (expr->type != TypeInt)
955 ("Found constant of type %s where a mask was expected\n",
956 exprTypeText(expr->type));
959 val_rtrn->ival = expr->value.ival;
964 ok = (*lookup) (lookupPriv,
965 None, expr->value.str, TypeInt, val_rtrn);
968 ERROR("Identifier \"%s\" of type int is unknown\n",
969 XkbcAtomText(expr->value.str));
974 ok = (*lookup) (lookupPriv,
975 expr->value.field.element,
976 expr->value.field.field, TypeInt, val_rtrn);
979 ERROR("Default \"%s.%s\" of type int is unknown\n",
980 XkbcAtomText(expr->value.field.element),
981 XkbcAtomText(expr->value.field.field));
984 bogus = "array reference";
987 bogus = "function use";
988 ERROR("Unexpected %s in mask expression\n", bogus);
989 ACTION("Expression ignored\n");
995 left = expr->value.binary.left;
996 right = expr->value.binary.right;
997 if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) &&
998 ExprResolveMask(right, &rightRtrn, lookup, lookupPriv))
1003 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
1006 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
1010 ERROR("Cannot %s masks\n",
1011 expr->op == OpDivide ? "divide" : "multiply");
1012 ACTION("Illegal operation ignored\n");
1019 WSGO("Assignment operator not implemented yet\n");
1022 left = expr->value.child;
1023 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
1025 val_rtrn->ival = ~leftRtrn.ival;
1032 left = expr->value.child;
1033 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
1035 ERROR("The %s operator cannot be used with a mask\n",
1036 (expr->op == OpNegate ? "-" : "!"));
1040 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
1047 ExprResolveKeySym(ExprDef * expr,
1048 ExprResult * val_rtrn,
1049 IdentLookupFunc lookup, char * lookupPriv)
1054 if (expr->op == ExprIdent)
1057 str = XkbcAtomText(expr->value.str);
1058 if ((str != NULL) && ((sym = XkbcStringToKeysym(str)) != NoSymbol))
1060 val_rtrn->uval = sym;
1064 ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv);
1065 if ((ok) && (val_rtrn->uval < 10))
1066 val_rtrn->uval += '0';