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,
295 IdentLookupFunc lookup, char * lookupPriv)
298 const char *bogus = NULL;
303 if (expr->type != TypeBoolean)
306 ("Found constant of type %s where boolean was expected\n",
307 exprTypeText(expr->type));
310 val_rtrn->ival = expr->value.ival;
313 bogus = XkbcAtomText(expr->value.str);
316 if ((uStrCaseCmp(bogus, "true") == 0) ||
317 (uStrCaseCmp(bogus, "yes") == 0) ||
318 (uStrCaseCmp(bogus, "on") == 0))
323 else if ((uStrCaseCmp(bogus, "false") == 0) ||
324 (uStrCaseCmp(bogus, "no") == 0) ||
325 (uStrCaseCmp(bogus, "off") == 0))
333 ok = (*lookup) (lookupPriv,
334 None, expr->value.str, TypeBoolean, val_rtrn);
337 ERROR("Identifier \"%s\" of type int is unknown\n",
338 XkbcAtomText(expr->value.str));
343 ok = (*lookup) (lookupPriv,
344 expr->value.field.element,
345 expr->value.field.field, TypeBoolean, val_rtrn);
348 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
349 XkbcAtomText(expr->value.field.element),
350 XkbcAtomText(expr->value.field.field));
354 ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv);
356 val_rtrn->uval = !val_rtrn->uval;
363 bogus = "Subtraction";
366 bogus = "Multiplication";
372 bogus = "Assignment";
376 ERROR("%s of boolean values not permitted\n", bogus);
379 ERROR("Unary \"+\" operator not permitted for boolean values\n");
382 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
389 ExprResolveFloat(ExprDef * expr,
390 ExprResult * val_rtrn,
391 IdentLookupFunc lookup, char * lookupPriv)
394 ExprResult leftRtrn, rightRtrn;
395 ExprDef *left, *right;
400 if (expr->type == TypeString)
403 str = XkbcAtomText(expr->value.str);
404 if ((str != NULL) && (strlen(str) == 1))
406 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
410 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
412 ERROR("Found constant of type %s, expected a number\n",
413 exprTypeText(expr->type));
416 val_rtrn->ival = expr->value.ival;
417 if (expr->type == TypeInt)
418 val_rtrn->ival *= XkbGeomPtsPerMM;
423 ok = (*lookup) (lookupPriv,
424 None, expr->value.str, TypeFloat, val_rtrn);
427 ERROR("Numeric identifier \"%s\" unknown\n",
428 XkbcAtomText(expr->value.str));
433 ok = (*lookup) (lookupPriv,
434 expr->value.field.element,
435 expr->value.field.field, TypeFloat, val_rtrn);
438 ERROR("Numeric default \"%s.%s\" unknown\n",
439 XkbcAtomText(expr->value.field.element),
440 XkbcAtomText(expr->value.field.field));
446 left = expr->value.binary.left;
447 right = expr->value.binary.right;
448 if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) &&
449 ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv))
454 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
457 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
460 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
463 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
470 WSGO("Assignment operator not implemented yet\n");
473 left = expr->value.child;
474 if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
476 ERROR("The ! operator cannot be applied to a number\n");
481 left = expr->value.child;
482 if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
484 if (expr->op == OpNegate)
485 val_rtrn->ival = -leftRtrn.ival;
487 val_rtrn->ival = ~leftRtrn.ival;
492 left = expr->value.child;
493 return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv);
495 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
502 ExprResolveKeyCode(ExprDef * expr,
503 ExprResult * val_rtrn)
505 ExprResult leftRtrn, rightRtrn;
506 ExprDef *left, *right;
511 if (expr->type != TypeInt)
514 ("Found constant of type %s where an int was expected\n",
515 exprTypeText(expr->type));
518 val_rtrn->uval = expr->value.uval;
524 left = expr->value.binary.left;
525 right = expr->value.binary.right;
526 if (ExprResolveKeyCode(left, &leftRtrn) &&
527 ExprResolveKeyCode(right, &rightRtrn))
532 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
535 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
538 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
541 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
548 left = expr->value.child;
549 if (ExprResolveKeyCode(left, &leftRtrn))
551 val_rtrn->uval = ~leftRtrn.uval;
556 left = expr->value.child;
557 return ExprResolveKeyCode(left, val_rtrn);
559 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
565 ExprResolveInteger(ExprDef * expr,
566 ExprResult * val_rtrn,
567 IdentLookupFunc lookup, char * lookupPriv)
570 ExprResult leftRtrn, rightRtrn;
571 ExprDef *left, *right;
576 if (expr->type == TypeString)
579 str = XkbcAtomText(expr->value.str);
587 val_rtrn->uval = str[0];
593 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
596 ("Found constant of type %s where an int was expected\n",
597 exprTypeText(expr->type));
600 val_rtrn->ival = expr->value.ival;
601 if (expr->type == TypeFloat)
602 val_rtrn->ival /= XkbGeomPtsPerMM;
607 ok = (*lookup) (lookupPriv,
608 None, expr->value.str, TypeInt, val_rtrn);
611 ERROR("Identifier \"%s\" of type int is unknown\n",
612 XkbcAtomText(expr->value.str));
617 ok = (*lookup) (lookupPriv,
618 expr->value.field.element,
619 expr->value.field.field, TypeInt, val_rtrn);
622 ERROR("Default \"%s.%s\" of type int is unknown\n",
623 XkbcAtomText(expr->value.field.element),
624 XkbcAtomText(expr->value.field.field));
630 left = expr->value.binary.left;
631 right = expr->value.binary.right;
632 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv) &&
633 ExprResolveInteger(right, &rightRtrn, lookup, lookupPriv))
638 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
641 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
644 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
647 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
654 WSGO("Assignment operator not implemented yet\n");
657 left = expr->value.child;
658 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
660 ERROR("The ! operator cannot be applied to an integer\n");
665 left = expr->value.child;
666 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
668 if (expr->op == OpNegate)
669 val_rtrn->ival = -leftRtrn.ival;
671 val_rtrn->ival = ~leftRtrn.ival;
676 left = expr->value.child;
677 return ExprResolveInteger(left, val_rtrn, lookup, lookupPriv);
679 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
686 ExprResolveString(ExprDef * expr,
687 ExprResult * val_rtrn,
688 IdentLookupFunc lookup, char * lookupPriv)
691 ExprResult leftRtrn, rightRtrn;
699 if (expr->type != TypeString)
701 ERROR("Found constant of type %s, expected a string\n",
702 exprTypeText(expr->type));
705 val_rtrn->str = XkbcAtomGetString(expr->value.str);
706 if (val_rtrn->str == NULL)
707 val_rtrn->str = strdup("");
712 ok = (*lookup) (lookupPriv,
713 None, expr->value.str, TypeString, val_rtrn);
716 ERROR("Identifier \"%s\" of type string not found\n",
717 XkbcAtomText(expr->value.str));
722 ok = (*lookup) (lookupPriv,
723 expr->value.field.element,
724 expr->value.field.field, TypeString, val_rtrn);
727 ERROR("Default \"%s.%s\" of type string not found\n",
728 XkbcAtomText(expr->value.field.element),
729 XkbcAtomText(expr->value.field.field));
732 left = expr->value.binary.left;
733 right = expr->value.binary.right;
734 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) &&
735 ExprResolveString(right, &rightRtrn, lookup, lookupPriv))
739 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
740 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 left = expr->value.child;
775 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
777 ERROR("The ! operator cannot be applied to a string\n");
781 left = expr->value.child;
782 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
784 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,
797 IdentLookupFunc lookup, char * lookupPriv)
807 if (expr->type != TypeKeyName)
809 ERROR("Found constant of type %s, expected a key name\n",
810 exprTypeText(expr->type));
813 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
818 ok = (*lookup) (lookupPriv,
819 None, expr->value.str, TypeString, val_rtrn);
822 ERROR("Identifier \"%s\" of type string not found\n",
823 XkbcAtomText(expr->value.str));
828 ok = (*lookup) (lookupPriv,
829 expr->value.field.element,
830 expr->value.field.field, TypeString, val_rtrn);
833 ERROR("Default \"%s.%s\" of type key name not found\n",
834 XkbcAtomText(expr->value.field.element),
835 XkbcAtomText(expr->value.field.field));
842 bogus = "Subtraction";
845 bogus = "Multiplication";
851 bogus = "Assignment";
857 bogus = "Bitwise complement";
858 ERROR("%s of key name values not permitted\n", bogus);
861 left = expr->value.binary.left;
862 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
864 ERROR("The ! operator cannot be applied to a key name\n");
868 left = expr->value.binary.left;
869 if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
871 ERROR("The + operator cannot be applied to a key name\n");
875 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
881 /***====================================================================***/
884 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
886 if (expr->op != ExprIdent)
888 ERROR("Found a %s where an enumerated value was expected\n",
889 exprOpText(expr->op));
892 if (!SimpleLookup((char *) values, (uint32_t) None, expr->value.str,
893 (unsigned) TypeInt, val_rtrn))
896 ERROR("Illegal identifier %s (expected one of: ",
897 XkbcAtomText(expr->value.str));
898 while (values && values->name)
901 INFO(", %s", values->name);
903 INFO("%s", values->name);
914 ExprResolveMask(ExprDef * expr,
915 ExprResult * val_rtrn,
916 IdentLookupFunc lookup, char * lookupPriv)
919 ExprResult leftRtrn, rightRtrn;
920 ExprDef *left, *right;
926 if (expr->type != TypeInt)
929 ("Found constant of type %s where a mask was expected\n",
930 exprTypeText(expr->type));
933 val_rtrn->ival = expr->value.ival;
938 ok = (*lookup) (lookupPriv,
939 None, expr->value.str, TypeInt, val_rtrn);
942 ERROR("Identifier \"%s\" of type int is unknown\n",
943 XkbcAtomText(expr->value.str));
948 ok = (*lookup) (lookupPriv,
949 expr->value.field.element,
950 expr->value.field.field, TypeInt, val_rtrn);
953 ERROR("Default \"%s.%s\" of type int is unknown\n",
954 XkbcAtomText(expr->value.field.element),
955 XkbcAtomText(expr->value.field.field));
958 bogus = "array reference";
961 bogus = "function use";
962 ERROR("Unexpected %s in mask expression\n", bogus);
963 ACTION("Expression ignored\n");
969 left = expr->value.binary.left;
970 right = expr->value.binary.right;
971 if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) &&
972 ExprResolveMask(right, &rightRtrn, lookup, lookupPriv))
977 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
980 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
984 ERROR("Cannot %s masks\n",
985 expr->op == OpDivide ? "divide" : "multiply");
986 ACTION("Illegal operation ignored\n");
993 WSGO("Assignment operator not implemented yet\n");
996 left = expr->value.child;
997 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
999 val_rtrn->ival = ~leftRtrn.ival;
1006 left = expr->value.child;
1007 if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
1009 ERROR("The %s operator cannot be used with a mask\n",
1010 (expr->op == OpNegate ? "-" : "!"));
1014 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
1021 ExprResolveKeySym(ExprDef * expr,
1022 ExprResult * val_rtrn,
1023 IdentLookupFunc lookup, char * lookupPriv)
1028 if (expr->op == ExprIdent)
1031 str = XkbcAtomText(expr->value.str);
1032 if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
1034 val_rtrn->uval = sym;
1038 ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv);
1039 if ((ok) && (val_rtrn->uval < 10))
1040 val_rtrn->uval += '0';