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 /***====================================================================***/
36 typedef Bool(*IdentLookupFunc) (const void * /* priv */ ,
37 xkb_atom_t /* field */ ,
39 ExprResult * /* val_rtrn */
42 /***====================================================================***/
45 exprOpText(unsigned type)
52 strcpy(buf, "literal");
55 strcpy(buf, "identifier");
58 strcpy(buf, "action declaration");
61 strcpy(buf, "field reference");
64 strcpy(buf, "array reference");
67 strcpy(buf, "list of keysyms");
70 strcpy(buf, "list of actions");
73 strcpy(buf, "addition");
76 strcpy(buf, "subtraction");
79 strcpy(buf, "multiplication");
82 strcpy(buf, "division");
85 strcpy(buf, "assignment");
88 strcpy(buf, "logical not");
91 strcpy(buf, "arithmetic negation");
94 strcpy(buf, "bitwise inversion");
97 strcpy(buf, "plus sign");
100 snprintf(buf, sizeof(buf), "illegal(%d)", type);
107 exprTypeText(unsigned type)
114 strcpy(buf, "unknown");
117 strcpy(buf, "boolean");
123 strcpy(buf, "string");
126 strcpy(buf, "action");
129 strcpy(buf, "keyname");
132 snprintf(buf, sizeof(buf), "illegal(%d)", type);
139 ExprResolveLhs(ExprDef * expr,
140 ExprResult * elem_rtrn,
141 ExprResult * field_rtrn, ExprDef ** index_rtrn)
146 elem_rtrn->str = NULL;
147 field_rtrn->str = XkbcAtomGetString(expr->value.str);
151 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
152 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
156 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
157 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
158 *index_rtrn = expr->value.array.entry;
161 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
166 SimpleLookup(const void * priv, xkb_atom_t field, unsigned type,
167 ExprResult * val_rtrn)
169 const LookupEntry *entry;
172 if ((priv == NULL) || (field == None) ||
173 ((type != TypeInt) && (type != TypeFloat)))
177 str = XkbcAtomText(field);
178 for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
180 if (uStrCaseCmp(str, entry->name) == 0)
182 val_rtrn->uval = entry->result;
183 if (type == TypeFloat)
184 val_rtrn->uval *= XkbGeomPtsPerMM;
191 static const LookupEntry modIndexNames[] = {
192 {"shift", XKB_COMMON_SHIFT_MASK},
193 {"control", XKB_COMMON_CONTROL_MASK},
194 {"lock", XKB_COMMON_LOCK_MASK},
195 {"mod1", XKB_COMMON_MOD1_MASK},
196 {"mod2", XKB_COMMON_MOD2_MASK},
197 {"mod3", XKB_COMMON_MOD3_MASK},
198 {"mod4", XKB_COMMON_MOD4_MASK},
199 {"mod5", XKB_COMMON_MOD5_MASK},
205 LookupModIndex(const void * priv, xkb_atom_t field, unsigned type,
206 ExprResult * val_rtrn)
208 return SimpleLookup(modIndexNames, field, type, val_rtrn);
212 LookupModMask(const void * priv, xkb_atom_t field, unsigned type,
213 ExprResult * val_rtrn)
220 str = XkbcAtomGetString(field);
223 if (uStrCaseCmp(str, "all") == 0)
224 val_rtrn->uval = 0xff;
225 else if (uStrCaseCmp(str, "none") == 0)
227 else if (LookupModIndex(priv, field, type, val_rtrn))
228 val_rtrn->uval = (1 << val_rtrn->uval);
236 ExprResolveBoolean(ExprDef * expr,
237 ExprResult * val_rtrn)
240 const char *bogus = NULL;
245 if (expr->type != TypeBoolean)
248 ("Found constant of type %s where boolean was expected\n",
249 exprTypeText(expr->type));
252 val_rtrn->ival = expr->value.ival;
255 bogus = XkbcAtomText(expr->value.str);
258 if ((uStrCaseCmp(bogus, "true") == 0) ||
259 (uStrCaseCmp(bogus, "yes") == 0) ||
260 (uStrCaseCmp(bogus, "on") == 0))
265 else if ((uStrCaseCmp(bogus, "false") == 0) ||
266 (uStrCaseCmp(bogus, "no") == 0) ||
267 (uStrCaseCmp(bogus, "off") == 0))
273 ERROR("Identifier \"%s\" of type int is unknown\n",
274 XkbcAtomText(expr->value.str));
277 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
278 XkbcAtomText(expr->value.field.element),
279 XkbcAtomText(expr->value.field.field));
283 ok = ExprResolveBoolean(expr, val_rtrn);
285 val_rtrn->uval = !val_rtrn->uval;
292 bogus = "Subtraction";
295 bogus = "Multiplication";
301 bogus = "Assignment";
305 ERROR("%s of boolean values not permitted\n", bogus);
308 ERROR("Unary \"+\" operator not permitted for boolean values\n");
311 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
318 ExprResolveFloat(ExprDef * expr,
319 ExprResult * val_rtrn)
322 ExprResult leftRtrn, rightRtrn;
323 ExprDef *left, *right;
328 if (expr->type == TypeString)
331 str = XkbcAtomText(expr->value.str);
332 if ((str != NULL) && (strlen(str) == 1))
334 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
338 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
340 ERROR("Found constant of type %s, expected a number\n",
341 exprTypeText(expr->type));
344 val_rtrn->ival = expr->value.ival;
345 if (expr->type == TypeInt)
346 val_rtrn->ival *= XkbGeomPtsPerMM;
349 ERROR("Numeric identifier \"%s\" unknown\n",
350 XkbcAtomText(expr->value.str));
353 ERROR("Numeric default \"%s.%s\" unknown\n",
354 XkbcAtomText(expr->value.field.element),
355 XkbcAtomText(expr->value.field.field));
361 left = expr->value.binary.left;
362 right = expr->value.binary.right;
363 if (ExprResolveFloat(left, &leftRtrn) &&
364 ExprResolveFloat(right, &rightRtrn))
369 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
372 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
375 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
378 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
385 WSGO("Assignment operator not implemented yet\n");
388 ERROR("The ! operator cannot be applied to a number\n");
392 left = expr->value.child;
393 if (ExprResolveFloat(left, &leftRtrn))
395 if (expr->op == OpNegate)
396 val_rtrn->ival = -leftRtrn.ival;
398 val_rtrn->ival = ~leftRtrn.ival;
403 left = expr->value.child;
404 return ExprResolveFloat(left, val_rtrn);
406 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
413 ExprResolveKeyCode(ExprDef * expr,
414 ExprResult * val_rtrn)
416 ExprResult leftRtrn, rightRtrn;
417 ExprDef *left, *right;
422 if (expr->type != TypeInt)
425 ("Found constant of type %s where an int was expected\n",
426 exprTypeText(expr->type));
429 val_rtrn->uval = expr->value.uval;
435 left = expr->value.binary.left;
436 right = expr->value.binary.right;
437 if (ExprResolveKeyCode(left, &leftRtrn) &&
438 ExprResolveKeyCode(right, &rightRtrn))
443 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
446 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
449 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
452 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
459 left = expr->value.child;
460 if (ExprResolveKeyCode(left, &leftRtrn))
462 val_rtrn->uval = ~leftRtrn.uval;
467 left = expr->value.child;
468 return ExprResolveKeyCode(left, val_rtrn);
470 WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
477 * This function returns ... something. It's a bit of a guess, really.
479 * If a string is given in value context, its first character will be
480 * returned in uval. If an integer is given in value context, it will be
481 * returned in ival. If a float is given in value context, it will be
482 * returned as millimetres (rather than points) in ival.
484 * If an ident or field reference is given, the lookup function (if given)
485 * will be called. At the moment, only SimpleLookup use this, and they both
486 * return the results in uval. And don't support field references.
491 ExprResolveIntegerLookup(ExprDef * expr,
492 ExprResult * val_rtrn,
493 IdentLookupFunc lookup, const void * lookupPriv)
496 ExprResult leftRtrn, rightRtrn;
497 ExprDef *left, *right;
502 if (expr->type == TypeString)
505 str = XkbcAtomText(expr->value.str);
513 val_rtrn->uval = str[0];
519 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
522 ("Found constant of type %s where an int was expected\n",
523 exprTypeText(expr->type));
526 val_rtrn->ival = expr->value.ival;
527 if (expr->type == TypeFloat)
528 val_rtrn->ival /= XkbGeomPtsPerMM;
533 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
536 ERROR("Identifier \"%s\" of type int is unknown\n",
537 XkbcAtomText(expr->value.str));
540 ERROR("Default \"%s.%s\" of type int is unknown\n",
541 XkbcAtomText(expr->value.field.element),
542 XkbcAtomText(expr->value.field.field));
548 left = expr->value.binary.left;
549 right = expr->value.binary.right;
550 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
551 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
556 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
559 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
562 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
565 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
572 WSGO("Assignment operator not implemented yet\n");
575 ERROR("The ! operator cannot be applied to an integer\n");
579 left = expr->value.child;
580 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
582 if (expr->op == OpNegate)
583 val_rtrn->ival = -leftRtrn.ival;
585 val_rtrn->ival = ~leftRtrn.ival;
590 left = expr->value.child;
591 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
593 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
600 ExprResolveInteger(ExprDef * expr,
601 ExprResult * val_rtrn)
603 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
607 ExprResolveGroup(ExprDef * expr,
608 ExprResult * val_rtrn)
611 static const LookupEntry group_names[] = {
623 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
627 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
628 ERROR("Group index %d is out of range (1..%d)\n",
629 val_rtrn->uval, XkbNumKbdGroups);
637 ExprResolveLevel(ExprDef * expr,
638 ExprResult * val_rtrn)
641 static const LookupEntry level_names[] = {
653 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, level_names);
657 if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) {
658 ERROR("Shift level %d is out of range (1..%d)\n", val_rtrn->ival,
667 ExprResolveButton(ExprDef * expr,
668 ExprResult * val_rtrn)
670 static const LookupEntry button_names[] = {
680 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
685 ExprResolveString(ExprDef * expr,
686 ExprResult * val_rtrn)
688 ExprResult leftRtrn, rightRtrn;
691 const char *bogus = NULL;
696 if (expr->type != TypeString)
698 ERROR("Found constant of type %s, expected a string\n",
699 exprTypeText(expr->type));
702 val_rtrn->str = XkbcAtomGetString(expr->value.str);
703 if (val_rtrn->str == NULL)
704 val_rtrn->str = strdup("");
707 ERROR("Identifier \"%s\" of type string not found\n",
708 XkbcAtomText(expr->value.str));
711 ERROR("Default \"%s.%s\" of type string not found\n",
712 XkbcAtomText(expr->value.field.element),
713 XkbcAtomText(expr->value.field.field));
716 left = expr->value.binary.left;
717 right = expr->value.binary.right;
718 if (ExprResolveString(left, &leftRtrn) &&
719 ExprResolveString(right, &rightRtrn))
723 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
726 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
738 bogus = "Subtraction";
741 bogus = "Multiplication";
747 bogus = "Assignment";
753 bogus = "Bitwise complement";
754 ERROR("%s of string values not permitted\n", bogus);
757 ERROR("The ! operator cannot be applied to a string\n");
760 ERROR("The + operator cannot be applied to a string\n");
763 WSGO("Unknown operator %d in ResolveString\n", expr->op);
770 ExprResolveKeyName(ExprDef * expr,
771 ExprResult * val_rtrn)
773 const char *bogus = NULL;
778 if (expr->type != TypeKeyName)
780 ERROR("Found constant of type %s, expected a key name\n",
781 exprTypeText(expr->type));
784 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
787 ERROR("Identifier \"%s\" of type string not found\n",
788 XkbcAtomText(expr->value.str));
791 ERROR("Default \"%s.%s\" of type key name not found\n",
792 XkbcAtomText(expr->value.field.element),
793 XkbcAtomText(expr->value.field.field));
800 bogus = "Subtraction";
803 bogus = "Multiplication";
809 bogus = "Assignment";
815 bogus = "Bitwise complement";
816 ERROR("%s of key name values not permitted\n", bogus);
819 ERROR("The ! operator cannot be applied to a key name\n");
822 ERROR("The + operator cannot be applied to a key name\n");
825 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
831 /***====================================================================***/
834 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, const LookupEntry * values)
836 if (expr->op != ExprIdent)
838 ERROR("Found a %s where an enumerated value was expected\n",
839 exprOpText(expr->op));
842 if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
845 ERROR("Illegal identifier %s (expected one of: ",
846 XkbcAtomText(expr->value.str));
847 while (values && values->name)
850 INFO(", %s", values->name);
852 INFO("%s", values->name);
863 ExprResolveMaskLookup(ExprDef * expr,
864 ExprResult * val_rtrn,
865 IdentLookupFunc lookup,
866 const void * lookupPriv)
869 ExprResult leftRtrn, rightRtrn;
870 ExprDef *left, *right;
871 const char *bogus = NULL;
876 if (expr->type != TypeInt)
879 ("Found constant of type %s where a mask was expected\n",
880 exprTypeText(expr->type));
883 val_rtrn->ival = expr->value.ival;
886 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
888 ERROR("Identifier \"%s\" of type int is unknown\n",
889 XkbcAtomText(expr->value.str));
892 ERROR("Default \"%s.%s\" of type int is unknown\n",
893 XkbcAtomText(expr->value.field.element),
894 XkbcAtomText(expr->value.field.field));
897 bogus = "array reference";
900 bogus = "function use";
901 ERROR("Unexpected %s in mask expression\n", bogus);
902 ACTION("Expression ignored\n");
908 left = expr->value.binary.left;
909 right = expr->value.binary.right;
910 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
911 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
916 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
919 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
923 ERROR("Cannot %s masks\n",
924 expr->op == OpDivide ? "divide" : "multiply");
925 ACTION("Illegal operation ignored\n");
932 WSGO("Assignment operator not implemented yet\n");
935 left = expr->value.child;
936 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
938 val_rtrn->ival = ~leftRtrn.ival;
945 left = expr->value.child;
946 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
948 ERROR("The %s operator cannot be used with a mask\n",
949 (expr->op == OpNegate ? "-" : "!"));
953 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
960 ExprResolveMask(ExprDef * expr,
961 ExprResult * val_rtrn,
962 const LookupEntry * values)
964 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
968 ExprResolveModMask(ExprDef * expr,
969 ExprResult * val_rtrn)
971 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
975 ExprResolveVModMask(ExprDef * expr,
976 ExprResult * val_rtrn,
977 struct xkb_desc *xkb)
979 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, xkb);
983 ExprResolveKeySym(ExprDef * expr,
984 ExprResult * val_rtrn)
989 if (expr->op == ExprIdent)
992 str = XkbcAtomText(expr->value.str);
993 if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
995 val_rtrn->uval = sym;
999 ok = ExprResolveInteger(expr, val_rtrn);
1000 if ((ok) && (val_rtrn->uval < 10))
1001 val_rtrn->uval += '0';