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) (void * /* 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(void * 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 = priv; (entry != NULL) && (entry->name != NULL); entry++)
181 if (uStrCaseCmp(str, entry->name) == 0)
183 val_rtrn->uval = entry->result;
184 if (type == TypeFloat)
185 val_rtrn->uval *= XkbGeomPtsPerMM;
193 RadioLookup(void * priv, uint32_t field, unsigned type, ExprResult * val_rtrn)
198 if ((field == None) || (type != TypeInt))
200 str = XkbcAtomText(field);
203 if (uStrCasePrefix("group", str))
204 str += strlen("group");
205 else if (uStrCasePrefix("radiogroup", str))
206 str += strlen("radiogroup");
207 else if (uStrCasePrefix("rg", str))
209 else if (!isdigit(str[0]))
212 if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
213 || (rg > XkbMaxRadioGroups))
219 static LookupEntry modIndexNames[] = {
220 {"shift", ShiftMapIndex},
221 {"control", ControlMapIndex},
222 {"lock", LockMapIndex},
223 {"mod1", Mod1MapIndex},
224 {"mod2", Mod2MapIndex},
225 {"mod3", Mod3MapIndex},
226 {"mod4", Mod4MapIndex},
227 {"mod5", Mod5MapIndex},
228 {"none", XkbNoModifier},
233 LookupModIndex(void * priv, uint32_t field, unsigned type,
234 ExprResult * val_rtrn)
236 return SimpleLookup(modIndexNames, field, type, val_rtrn);
240 LookupModMask(void * priv, uint32_t field, unsigned type,
241 ExprResult * val_rtrn)
248 str = XkbcAtomGetString(field);
251 if (uStrCaseCmp(str, "all") == 0)
252 val_rtrn->uval = 0xff;
253 else if (uStrCaseCmp(str, "none") == 0)
255 else if (LookupModIndex(priv, field, type, val_rtrn))
256 val_rtrn->uval = (1 << val_rtrn->uval);
264 ExprResolveBoolean(ExprDef * expr,
265 ExprResult * val_rtrn)
268 const char *bogus = NULL;
273 if (expr->type != TypeBoolean)
276 ("Found constant of type %s where boolean was expected\n",
277 exprTypeText(expr->type));
280 val_rtrn->ival = expr->value.ival;
283 bogus = XkbcAtomText(expr->value.str);
286 if ((uStrCaseCmp(bogus, "true") == 0) ||
287 (uStrCaseCmp(bogus, "yes") == 0) ||
288 (uStrCaseCmp(bogus, "on") == 0))
293 else if ((uStrCaseCmp(bogus, "false") == 0) ||
294 (uStrCaseCmp(bogus, "no") == 0) ||
295 (uStrCaseCmp(bogus, "off") == 0))
301 ERROR("Identifier \"%s\" of type int is unknown\n",
302 XkbcAtomText(expr->value.str));
305 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
306 XkbcAtomText(expr->value.field.element),
307 XkbcAtomText(expr->value.field.field));
311 ok = ExprResolveBoolean(expr, val_rtrn);
313 val_rtrn->uval = !val_rtrn->uval;
320 bogus = "Subtraction";
323 bogus = "Multiplication";
329 bogus = "Assignment";
333 ERROR("%s of boolean values not permitted\n", bogus);
336 ERROR("Unary \"+\" operator not permitted for boolean values\n");
339 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
346 ExprResolveFloat(ExprDef * expr,
347 ExprResult * val_rtrn)
350 ExprResult leftRtrn, rightRtrn;
351 ExprDef *left, *right;
356 if (expr->type == TypeString)
359 str = XkbcAtomText(expr->value.str);
360 if ((str != NULL) && (strlen(str) == 1))
362 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
366 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
368 ERROR("Found constant of type %s, expected a number\n",
369 exprTypeText(expr->type));
372 val_rtrn->ival = expr->value.ival;
373 if (expr->type == TypeInt)
374 val_rtrn->ival *= XkbGeomPtsPerMM;
377 ERROR("Numeric identifier \"%s\" unknown\n",
378 XkbcAtomText(expr->value.str));
381 ERROR("Numeric default \"%s.%s\" unknown\n",
382 XkbcAtomText(expr->value.field.element),
383 XkbcAtomText(expr->value.field.field));
389 left = expr->value.binary.left;
390 right = expr->value.binary.right;
391 if (ExprResolveFloat(left, &leftRtrn) &&
392 ExprResolveFloat(right, &rightRtrn))
397 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
400 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
403 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
406 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
413 WSGO("Assignment operator not implemented yet\n");
416 ERROR("The ! operator cannot be applied to a number\n");
420 left = expr->value.child;
421 if (ExprResolveFloat(left, &leftRtrn))
423 if (expr->op == OpNegate)
424 val_rtrn->ival = -leftRtrn.ival;
426 val_rtrn->ival = ~leftRtrn.ival;
431 left = expr->value.child;
432 return ExprResolveFloat(left, val_rtrn);
434 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
441 ExprResolveKeyCode(ExprDef * expr,
442 ExprResult * val_rtrn)
444 ExprResult leftRtrn, rightRtrn;
445 ExprDef *left, *right;
450 if (expr->type != TypeInt)
453 ("Found constant of type %s where an int was expected\n",
454 exprTypeText(expr->type));
457 val_rtrn->uval = expr->value.uval;
463 left = expr->value.binary.left;
464 right = expr->value.binary.right;
465 if (ExprResolveKeyCode(left, &leftRtrn) &&
466 ExprResolveKeyCode(right, &rightRtrn))
471 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
474 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
477 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
480 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
487 left = expr->value.child;
488 if (ExprResolveKeyCode(left, &leftRtrn))
490 val_rtrn->uval = ~leftRtrn.uval;
495 left = expr->value.child;
496 return ExprResolveKeyCode(left, val_rtrn);
498 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
505 * This function returns ... something. It's a bit of a guess, really.
507 * If a string is given in value context, its first character will be
508 * returned in uval. If an integer is given in value context, it will be
509 * returned in ival. If a float is given in value context, it will be
510 * returned as millimetres (rather than points) in ival.
512 * If an ident or field reference is given, the lookup function (if given)
513 * will be called. At the moment, only RadioLookup and SimpleLookup use
514 * this, and they both return the results in uval. And don't support field
520 ExprResolveIntegerLookup(ExprDef * expr,
521 ExprResult * val_rtrn,
522 IdentLookupFunc lookup, void * lookupPriv)
525 ExprResult leftRtrn, rightRtrn;
526 ExprDef *left, *right;
531 if (expr->type == TypeString)
534 str = XkbcAtomText(expr->value.str);
542 val_rtrn->uval = str[0];
548 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
551 ("Found constant of type %s where an int was expected\n",
552 exprTypeText(expr->type));
555 val_rtrn->ival = expr->value.ival;
556 if (expr->type == TypeFloat)
557 val_rtrn->ival /= XkbGeomPtsPerMM;
562 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
565 ERROR("Identifier \"%s\" of type int is unknown\n",
566 XkbcAtomText(expr->value.str));
569 ERROR("Default \"%s.%s\" of type int is unknown\n",
570 XkbcAtomText(expr->value.field.element),
571 XkbcAtomText(expr->value.field.field));
577 left = expr->value.binary.left;
578 right = expr->value.binary.right;
579 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
580 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
585 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
588 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
591 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
594 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
601 WSGO("Assignment operator not implemented yet\n");
604 ERROR("The ! operator cannot be applied to an integer\n");
608 left = expr->value.child;
609 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
611 if (expr->op == OpNegate)
612 val_rtrn->ival = -leftRtrn.ival;
614 val_rtrn->ival = ~leftRtrn.ival;
619 left = expr->value.child;
620 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
622 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
629 ExprResolveInteger(ExprDef * expr,
630 ExprResult * val_rtrn)
632 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
636 ExprResolveRadioGroup(ExprDef * expr,
637 ExprResult * val_rtrn)
639 return ExprResolveIntegerLookup(expr, val_rtrn, RadioLookup, NULL);
643 ExprResolveGroup(ExprDef * expr,
644 ExprResult * val_rtrn)
647 static LookupEntry group_names[] = {
659 ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
663 if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
664 ERROR("Group index %d is out of range (1..%d)\n",
665 val_rtrn->uval, XkbNumKbdGroups);
673 ExprResolveLevel(ExprDef * expr,
674 ExprResult * val_rtrn)
676 static LookupEntry level_names[] = {
688 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
693 ExprResolveButton(ExprDef * expr,
694 ExprResult * val_rtrn)
696 static LookupEntry button_names[] = {
706 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
711 ExprResolveString(ExprDef * expr,
712 ExprResult * val_rtrn)
714 ExprResult leftRtrn, rightRtrn;
722 if (expr->type != TypeString)
724 ERROR("Found constant of type %s, expected a string\n",
725 exprTypeText(expr->type));
728 val_rtrn->str = XkbcAtomGetString(expr->value.str);
729 if (val_rtrn->str == NULL)
730 val_rtrn->str = strdup("");
733 ERROR("Identifier \"%s\" of type string not found\n",
734 XkbcAtomText(expr->value.str));
737 ERROR("Default \"%s.%s\" of type string not found\n",
738 XkbcAtomText(expr->value.field.element),
739 XkbcAtomText(expr->value.field.field));
742 left = expr->value.binary.left;
743 right = expr->value.binary.right;
744 if (ExprResolveString(left, &leftRtrn) &&
745 ExprResolveString(right, &rightRtrn))
749 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
750 new = (char *) malloc(len);
752 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
764 bogus = "Subtraction";
767 bogus = "Multiplication";
773 bogus = "Assignment";
779 bogus = "Bitwise complement";
780 ERROR("%s of string values not permitted\n", bogus);
783 ERROR("The ! operator cannot be applied to a string\n");
786 ERROR("The + operator cannot be applied to a string\n");
789 WSGO("Unknown operator %d in ResolveString\n", expr->op);
796 ExprResolveKeyName(ExprDef * expr,
797 ExprResult * val_rtrn)
804 if (expr->type != TypeKeyName)
806 ERROR("Found constant of type %s, expected a key name\n",
807 exprTypeText(expr->type));
810 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
813 ERROR("Identifier \"%s\" of type string not found\n",
814 XkbcAtomText(expr->value.str));
817 ERROR("Default \"%s.%s\" of type key name not found\n",
818 XkbcAtomText(expr->value.field.element),
819 XkbcAtomText(expr->value.field.field));
826 bogus = "Subtraction";
829 bogus = "Multiplication";
835 bogus = "Assignment";
841 bogus = "Bitwise complement";
842 ERROR("%s of key name values not permitted\n", bogus);
845 ERROR("The ! operator cannot be applied to a key name\n");
848 ERROR("The + operator cannot be applied to a key name\n");
851 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
857 /***====================================================================***/
860 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
862 if (expr->op != ExprIdent)
864 ERROR("Found a %s where an enumerated value was expected\n",
865 exprOpText(expr->op));
868 if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
871 ERROR("Illegal identifier %s (expected one of: ",
872 XkbcAtomText(expr->value.str));
873 while (values && values->name)
876 INFO(", %s", values->name);
878 INFO("%s", values->name);
889 ExprResolveMaskLookup(ExprDef * expr,
890 ExprResult * val_rtrn,
891 IdentLookupFunc lookup,
895 ExprResult leftRtrn, rightRtrn;
896 ExprDef *left, *right;
902 if (expr->type != TypeInt)
905 ("Found constant of type %s where a mask was expected\n",
906 exprTypeText(expr->type));
909 val_rtrn->ival = expr->value.ival;
912 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
914 ERROR("Identifier \"%s\" of type int is unknown\n",
915 XkbcAtomText(expr->value.str));
918 ERROR("Default \"%s.%s\" of type int is unknown\n",
919 XkbcAtomText(expr->value.field.element),
920 XkbcAtomText(expr->value.field.field));
923 bogus = "array reference";
926 bogus = "function use";
927 ERROR("Unexpected %s in mask expression\n", bogus);
928 ACTION("Expression ignored\n");
934 left = expr->value.binary.left;
935 right = expr->value.binary.right;
936 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
937 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
942 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
945 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
949 ERROR("Cannot %s masks\n",
950 expr->op == OpDivide ? "divide" : "multiply");
951 ACTION("Illegal operation ignored\n");
958 WSGO("Assignment operator not implemented yet\n");
961 left = expr->value.child;
962 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
964 val_rtrn->ival = ~leftRtrn.ival;
971 left = expr->value.child;
972 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
974 ERROR("The %s operator cannot be used with a mask\n",
975 (expr->op == OpNegate ? "-" : "!"));
979 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
986 ExprResolveMask(ExprDef * expr,
987 ExprResult * val_rtrn,
988 LookupEntry * values)
990 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
994 ExprResolveModMask(ExprDef * expr,
995 ExprResult * val_rtrn)
997 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
1001 ExprResolveVModMask(ExprDef * expr,
1002 ExprResult * val_rtrn,
1003 struct xkb_desc *xkb)
1005 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, xkb);
1009 ExprResolveKeySym(ExprDef * expr,
1010 ExprResult * val_rtrn)
1015 if (expr->op == ExprIdent)
1018 str = XkbcAtomText(expr->value.str);
1019 if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
1021 val_rtrn->uval = sym;
1025 ok = ExprResolveInteger(expr, val_rtrn);
1026 if ((ok) && (val_rtrn->uval < 10))
1027 val_rtrn->uval += '0';