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 ********************************************************/
33 /***====================================================================***/
36 exprOpText(unsigned type)
43 strcpy(buf, "literal");
46 strcpy(buf, "identifier");
49 strcpy(buf, "action declaration");
52 strcpy(buf, "field reference");
55 strcpy(buf, "array reference");
58 strcpy(buf, "list of keysyms");
61 strcpy(buf, "list of actions");
64 strcpy(buf, "addition");
67 strcpy(buf, "subtraction");
70 strcpy(buf, "multiplication");
73 strcpy(buf, "division");
76 strcpy(buf, "assignment");
79 strcpy(buf, "logical not");
82 strcpy(buf, "arithmetic negation");
85 strcpy(buf, "bitwise inversion");
88 strcpy(buf, "plus sign");
91 snprintf(buf, sizeof(buf), "illegal(%d)", type);
98 exprTypeText(unsigned type)
105 strcpy(buf, "unknown");
108 strcpy(buf, "boolean");
114 strcpy(buf, "string");
117 strcpy(buf, "action");
120 strcpy(buf, "keyname");
123 snprintf(buf, sizeof(buf), "illegal(%d)", type);
130 ExprResolveLhs(ExprDef * expr,
131 ExprResult * elem_rtrn,
132 ExprResult * field_rtrn, ExprDef ** index_rtrn)
137 elem_rtrn->str = NULL;
138 field_rtrn->str = XkbcAtomGetString(expr->value.str);
142 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
143 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
147 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
148 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
149 *index_rtrn = expr->value.array.entry;
152 WSGO1("Unexpected operator %d in ResolveLhs\n", expr->op);
157 SimpleLookup(char * priv,
158 Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
163 if ((priv == NULL) ||
164 (field == None) || (elem != None) ||
165 ((type != TypeInt) && (type != TypeFloat)))
169 str = XkbcAtomGetString(field);
170 for (entry = (LookupEntry *) priv;
171 (entry != NULL) && (entry->name != NULL); entry++)
173 if (uStrCaseCmp(str, entry->name) == 0)
175 val_rtrn->uval = entry->result;
176 if (type == TypeFloat)
177 val_rtrn->uval *= XkbGeomPtsPerMM;
185 RadioLookup(char * priv,
186 Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
191 if ((field == None) || (elem != None) || (type != TypeInt))
193 str = XkbcAtomGetString(field);
196 if (uStrCasePrefix("group", str))
197 str += strlen("group");
198 else if (uStrCasePrefix("radiogroup", str))
199 str += strlen("radiogroup");
200 else if (uStrCasePrefix("rg", str))
202 else if (!isdigit(str[0]))
205 if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
206 || (rg > XkbMaxRadioGroups))
213 TableLookup(char * priv,
214 Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
216 LookupTable *tbl = (LookupTable *) priv;
219 if ((priv == NULL) || (field == None) || (type != TypeInt))
221 str = XkbcAtomGetString(elem);
224 if (((str == NULL) && (tbl->element == NULL)) ||
225 ((str != NULL) && (tbl->element != NULL) &&
226 (uStrCaseCmp(str, tbl->element) == 0)))
230 tbl = tbl->nextElement;
232 if (tbl == NULL) /* didn't find a matching element */
234 priv = (char *) tbl->entries;
235 return SimpleLookup(priv, (Atom) None, field, type, val_rtrn);
238 static LookupEntry modIndexNames[] = {
239 {"shift", ShiftMapIndex},
240 {"control", ControlMapIndex},
241 {"lock", LockMapIndex},
242 {"mod1", Mod1MapIndex},
243 {"mod2", Mod2MapIndex},
244 {"mod3", Mod3MapIndex},
245 {"mod4", Mod4MapIndex},
246 {"mod5", Mod5MapIndex},
247 {"none", XkbNoModifier},
252 LookupModIndex(char * priv,
253 Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
255 return SimpleLookup((char *) modIndexNames, elem, field, type,
260 LookupModMask(char * priv,
261 Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
265 if ((elem != None) || (type != TypeInt))
267 str = XkbcAtomGetString(field);
270 if (uStrCaseCmp(str, "all") == 0)
271 val_rtrn->uval = 0xff;
272 else if (uStrCaseCmp(str, "none") == 0)
274 else if (LookupModIndex(priv, elem, field, type, val_rtrn))
275 val_rtrn->uval = (1 << val_rtrn->uval);
276 else if (priv != NULL)
278 LookupPriv *lpriv = (LookupPriv *) priv;
279 if ((lpriv->chain == NULL) ||
280 (!(*lpriv->chain) (lpriv->chainPriv, elem, field, type,
290 ExprResolveModIndex(ExprDef * expr,
291 ExprResult * val_rtrn,
292 IdentLookupFunc lookup, char * lookupPriv)
300 if (expr->type != TypeInt)
303 ("Found constant of type %s where a modifier mask was expected\n",
304 exprTypeText(expr->type));
307 else if ((expr->value.ival >= XkbNumModifiers)
308 || (expr->value.ival < 0))
310 ERROR2("Illegal modifier index (%d, must be 0..%d)\n",
311 expr->value.ival, XkbNumModifiers - 1);
314 val_rtrn->ival = expr->value.ival;
317 if (LookupModIndex(lookupPriv, (Atom) None, expr->value.str,
318 (unsigned) TypeInt, val_rtrn))
324 ok = (*lookup) (lookupPriv,
325 None, expr->value.str, TypeInt, val_rtrn);
328 ERROR1("Cannot determine modifier index for \"%s\"\n",
329 XkbAtomText(NULL, expr->value.str, XkbMessage));
332 bogus = "field reference";
335 bogus = "array reference";
348 bogus = "arithmetic operations";
351 bogus = "assignment";
354 WSGO1("Unknown operator %d in ResolveModIndex\n", expr->op);
359 ERROR1("Modifier index must be a name or number, %s ignored\n",
367 ExprResolveModMask(ExprDef * expr,
368 ExprResult * val_rtrn,
369 IdentLookupFunc lookup, char * lookupPriv)
375 priv.chainPriv = lookupPriv;
376 return ExprResolveMask(expr, val_rtrn, LookupModMask, (char *) & priv);
380 ExprResolveBoolean(ExprDef * expr,
381 ExprResult * val_rtrn,
382 IdentLookupFunc lookup, char * lookupPriv)
390 if (expr->type != TypeBoolean)
393 ("Found constant of type %s where boolean was expected\n",
394 exprTypeText(expr->type));
397 val_rtrn->ival = expr->value.ival;
400 bogus = XkbcAtomGetString(expr->value.str);
403 if ((uStrCaseCmp(bogus, "true") == 0) ||
404 (uStrCaseCmp(bogus, "yes") == 0) ||
405 (uStrCaseCmp(bogus, "on") == 0))
410 else if ((uStrCaseCmp(bogus, "false") == 0) ||
411 (uStrCaseCmp(bogus, "no") == 0) ||
412 (uStrCaseCmp(bogus, "off") == 0))
420 ok = (*lookup) (lookupPriv,
421 None, expr->value.str, TypeBoolean, val_rtrn);
424 ERROR1("Identifier \"%s\" of type int is unknown\n",
425 XkbAtomText(NULL, expr->value.str, XkbMessage));
430 ok = (*lookup) (lookupPriv,
431 expr->value.field.element,
432 expr->value.field.field, TypeBoolean, val_rtrn);
435 ERROR2("Default \"%s.%s\" of type boolean is unknown\n",
436 XkbAtomText(NULL, expr->value.field.element, XkbMessage),
437 XkbAtomText(NULL, expr->value.field.field, XkbMessage));
441 ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv);
443 val_rtrn->uval = !val_rtrn->uval;
450 bogus = "Subtraction";
453 bogus = "Multiplication";
459 bogus = "Assignment";
463 ERROR1("%s of boolean values not permitted\n", bogus);
466 ERROR("Unary \"+\" operator not permitted for boolean values\n");
469 WSGO1("Unknown operator %d in ResolveBoolean\n", expr->op);
476 ExprResolveFloat(ExprDef * expr,
477 ExprResult * val_rtrn,
478 IdentLookupFunc lookup, char * lookupPriv)
481 ExprResult leftRtrn, rightRtrn;
482 ExprDef *left, *right;
487 if (expr->type == TypeString)
490 str = XkbcAtomGetString(expr->value.str);
491 if ((str != NULL) && (strlen(str) == 1))
493 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
497 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
499 ERROR1("Found constant of type %s, expected a number\n",
500 exprTypeText(expr->type));
503 val_rtrn->ival = expr->value.ival;
504 if (expr->type == TypeInt)
505 val_rtrn->ival *= XkbGeomPtsPerMM;
510 ok = (*lookup) (lookupPriv,
511 None, expr->value.str, TypeFloat, val_rtrn);
514 ERROR1("Numeric identifier \"%s\" unknown\n",
515 XkbAtomText(NULL, expr->value.str, XkbMessage));
520 ok = (*lookup) (lookupPriv,
521 expr->value.field.element,
522 expr->value.field.field, TypeFloat, val_rtrn);
525 ERROR2("Numeric default \"%s.%s\" unknown\n",
526 XkbAtomText(NULL, expr->value.field.element, XkbMessage),
527 XkbAtomText(NULL, expr->value.field.field, XkbMessage));
533 left = expr->value.binary.left;
534 right = expr->value.binary.right;
535 if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) &&
536 ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv))
541 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
544 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
547 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
550 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
557 WSGO("Assignment operator not implemented yet\n");
560 left = expr->value.child;
561 if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
563 ERROR("The ! operator cannot be applied to a number\n");
568 left = expr->value.child;
569 if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
571 if (expr->op == OpNegate)
572 val_rtrn->ival = -leftRtrn.ival;
574 val_rtrn->ival = ~leftRtrn.ival;
579 left = expr->value.child;
580 return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv);
582 WSGO1("Unknown operator %d in ResolveFloat\n", expr->op);
589 ExprResolveInteger(ExprDef * expr,
590 ExprResult * val_rtrn,
591 IdentLookupFunc lookup, char * lookupPriv)
594 ExprResult leftRtrn, rightRtrn;
595 ExprDef *left, *right;
600 if (expr->type == TypeString)
603 str = XkbcAtomGetString(expr->value.str);
611 val_rtrn->uval = str[0];
617 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
620 ("Found constant of type %s where an int was expected\n",
621 exprTypeText(expr->type));
624 val_rtrn->ival = expr->value.ival;
625 if (expr->type == TypeFloat)
626 val_rtrn->ival /= XkbGeomPtsPerMM;
631 ok = (*lookup) (lookupPriv,
632 None, expr->value.str, TypeInt, val_rtrn);
635 ERROR1("Identifier \"%s\" of type int is unknown\n",
636 XkbAtomText(NULL, expr->value.str, XkbMessage));
641 ok = (*lookup) (lookupPriv,
642 expr->value.field.element,
643 expr->value.field.field, TypeInt, val_rtrn);
646 ERROR2("Default \"%s.%s\" of type int is unknown\n",
647 XkbAtomText(NULL, expr->value.field.element, XkbMessage),
648 XkbAtomText(NULL, expr->value.field.field, XkbMessage));
654 left = expr->value.binary.left;
655 right = expr->value.binary.right;
656 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv) &&
657 ExprResolveInteger(right, &rightRtrn, lookup, lookupPriv))
662 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
665 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
668 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
671 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
678 WSGO("Assignment operator not implemented yet\n");
681 left = expr->value.child;
682 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
684 ERROR("The ! operator cannot be applied to an integer\n");
689 left = expr->value.child;
690 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
692 if (expr->op == OpNegate)
693 val_rtrn->ival = -leftRtrn.ival;
695 val_rtrn->ival = ~leftRtrn.ival;
700 left = expr->value.child;
701 return ExprResolveInteger(left, val_rtrn, lookup, lookupPriv);
703 WSGO1("Unknown operator %d in ResolveInteger\n", expr->op);
710 ExprResolveString(ExprDef * expr,
711 ExprResult * val_rtrn,
712 IdentLookupFunc lookup, char * lookupPriv)
715 ExprResult leftRtrn, rightRtrn;
723 if (expr->type != TypeString)
725 ERROR1("Found constant of type %s, expected a string\n",
726 exprTypeText(expr->type));
729 val_rtrn->str = XkbcAtomGetString(expr->value.str);
730 if (val_rtrn->str == NULL)
732 static char *empty = "";
733 val_rtrn->str = empty;
739 ok = (*lookup) (lookupPriv,
740 None, expr->value.str, TypeString, val_rtrn);
743 ERROR1("Identifier \"%s\" of type string not found\n",
744 XkbAtomText(NULL, expr->value.str, XkbMessage));
749 ok = (*lookup) (lookupPriv,
750 expr->value.field.element,
751 expr->value.field.field, TypeString, val_rtrn);
754 ERROR2("Default \"%s.%s\" of type string not found\n",
755 XkbAtomText(NULL, expr->value.field.element, XkbMessage),
756 XkbAtomText(NULL, expr->value.field.field, XkbMessage));
759 left = expr->value.binary.left;
760 right = expr->value.binary.right;
761 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) &&
762 ExprResolveString(right, &rightRtrn, lookup, lookupPriv))
766 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
767 new = (char *) uAlloc(len);
770 sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
778 bogus = "Subtraction";
781 bogus = "Multiplication";
787 bogus = "Assignment";
793 bogus = "Bitwise complement";
794 ERROR1("%s of string values not permitted\n", bogus);
797 left = expr->value.child;
798 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
800 ERROR("The ! operator cannot be applied to a string\n");
804 left = expr->value.child;
805 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
807 ERROR("The + operator cannot be applied to a string\n");
811 WSGO1("Unknown operator %d in ResolveString\n", expr->op);
818 ExprResolveKeyName(ExprDef * expr,
819 ExprResult * val_rtrn,
820 IdentLookupFunc lookup, char * lookupPriv)
830 if (expr->type != TypeKeyName)
832 ERROR1("Found constant of type %s, expected a key name\n",
833 exprTypeText(expr->type));
836 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
841 ok = (*lookup) (lookupPriv,
842 None, expr->value.str, TypeString, val_rtrn);
845 ERROR1("Identifier \"%s\" of type string not found\n",
846 XkbAtomText(NULL, expr->value.str, XkbMessage));
851 ok = (*lookup) (lookupPriv,
852 expr->value.field.element,
853 expr->value.field.field, TypeString, val_rtrn);
856 ERROR2("Default \"%s.%s\" of type key name not found\n",
857 XkbAtomText(NULL, expr->value.field.element, XkbMessage),
858 XkbAtomText(NULL, expr->value.field.field, XkbMessage));
865 bogus = "Subtraction";
868 bogus = "Multiplication";
874 bogus = "Assignment";
880 bogus = "Bitwise complement";
881 ERROR1("%s of key name values not permitted\n", bogus);
884 left = expr->value.binary.left;
885 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
887 ERROR("The ! operator cannot be applied to a key name\n");
891 left = expr->value.binary.left;
892 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
894 ERROR("The + operator cannot be applied to a key name\n");
898 WSGO1("Unknown operator %d in ResolveKeyName\n", expr->op);
904 /***====================================================================***/
907 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
909 if (expr->op != ExprIdent)
911 ERROR1("Found a %s where an enumerated value was expected\n",
912 exprOpText(expr->op));
915 if (!SimpleLookup((char *) values, (Atom) None, expr->value.str,
916 (unsigned) TypeInt, val_rtrn))
919 ERROR1("Illegal identifier %s (expected one of: ",
920 XkbAtomText(NULL, expr->value.str, XkbMessage));
921 while (values && values->name)
924 INFO1(", %s", values->name);
926 INFO1("%s", values->name);
937 ExprResolveMask(ExprDef * expr,
938 ExprResult * val_rtrn,
939 IdentLookupFunc lookup, char * lookupPriv)
942 ExprResult leftRtrn, rightRtrn;
943 ExprDef *left, *right;
949 if (expr->type != TypeInt)
952 ("Found constant of type %s where a mask was expected\n",
953 exprTypeText(expr->type));
956 val_rtrn->ival = expr->value.ival;
961 ok = (*lookup) (lookupPriv,
962 None, expr->value.str, TypeInt, val_rtrn);
965 ERROR1("Identifier \"%s\" of type int is unknown\n",
966 XkbAtomText(NULL, expr->value.str, XkbMessage));
971 ok = (*lookup) (lookupPriv,
972 expr->value.field.element,
973 expr->value.field.field, TypeInt, val_rtrn);
976 ERROR2("Default \"%s.%s\" of type int is unknown\n",
977 XkbAtomText(NULL, expr->value.field.element, XkbMessage),
978 XkbAtomText(NULL, expr->value.field.field, XkbMessage));
981 bogus = "array reference";
984 bogus = "function use";
985 ERROR1("Unexpected %s in mask expression\n", bogus);
986 ACTION("Expression ignored\n");
992 left = expr->value.binary.left;
993 right = expr->value.binary.right;
994 if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) &&
995 ExprResolveMask(right, &rightRtrn, lookup, lookupPriv))
1000 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
1003 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
1007 ERROR1("Cannot %s masks\n",
1008 expr->op == OpDivide ? "divide" : "multiply");
1009 ACTION("Illegal operation ignored\n");
1016 WSGO("Assignment operator not implemented yet\n");
1019 left = expr->value.child;
1020 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
1022 val_rtrn->ival = ~leftRtrn.ival;
1029 left = expr->value.child;
1030 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
1032 ERROR1("The %s operator cannot be used with a mask\n",
1033 (expr->op == OpNegate ? "-" : "!"));
1037 WSGO1("Unknown operator %d in ResolveMask\n", expr->op);
1044 ExprResolveKeySym(ExprDef * expr,
1045 ExprResult * val_rtrn,
1046 IdentLookupFunc lookup, char * lookupPriv)
1051 if (expr->op == ExprIdent)
1054 str = XkbcAtomGetString(expr->value.str);
1055 if ((str != NULL) && ((sym = XStringToKeysym(str)) != NoSymbol))
1057 val_rtrn->uval = sym;
1061 ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv);
1062 if ((ok) && (val_rtrn->uval < 10))
1063 val_rtrn->uval += '0';