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) (char * /* priv */ ,
38 uint32_t /* field */ ,
40 ExprResult * /* val_rtrn */
43 typedef struct _LookupPriv
45 IdentLookupFunc chain;
49 /***====================================================================***/
52 exprOpText(unsigned type)
59 strcpy(buf, "literal");
62 strcpy(buf, "identifier");
65 strcpy(buf, "action declaration");
68 strcpy(buf, "field reference");
71 strcpy(buf, "array reference");
74 strcpy(buf, "list of keysyms");
77 strcpy(buf, "list of actions");
80 strcpy(buf, "addition");
83 strcpy(buf, "subtraction");
86 strcpy(buf, "multiplication");
89 strcpy(buf, "division");
92 strcpy(buf, "assignment");
95 strcpy(buf, "logical not");
98 strcpy(buf, "arithmetic negation");
101 strcpy(buf, "bitwise inversion");
104 strcpy(buf, "plus sign");
107 snprintf(buf, sizeof(buf), "illegal(%d)", type);
114 exprTypeText(unsigned type)
121 strcpy(buf, "unknown");
124 strcpy(buf, "boolean");
130 strcpy(buf, "string");
133 strcpy(buf, "action");
136 strcpy(buf, "keyname");
139 snprintf(buf, sizeof(buf), "illegal(%d)", type);
146 ExprResolveLhs(ExprDef * expr,
147 ExprResult * elem_rtrn,
148 ExprResult * field_rtrn, ExprDef ** index_rtrn)
153 elem_rtrn->str = NULL;
154 field_rtrn->str = XkbcAtomGetString(expr->value.str);
158 elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
159 field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
163 elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
164 field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
165 *index_rtrn = expr->value.array.entry;
168 WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
173 SimpleLookup(char * priv, uint32_t field, unsigned type,
174 ExprResult * val_rtrn)
179 if ((priv == NULL) || (field == None) ||
180 ((type != TypeInt) && (type != TypeFloat)))
184 str = XkbcAtomText(field);
185 for (entry = (LookupEntry *) priv;
186 (entry != NULL) && (entry->name != NULL); entry++)
188 if (uStrCaseCmp(str, entry->name) == 0)
190 val_rtrn->uval = entry->result;
191 if (type == TypeFloat)
192 val_rtrn->uval *= XkbGeomPtsPerMM;
200 RadioLookup(char * priv, uint32_t field, unsigned type, ExprResult * val_rtrn)
205 if ((field == None) || (type != TypeInt))
207 str = XkbcAtomText(field);
210 if (uStrCasePrefix("group", str))
211 str += strlen("group");
212 else if (uStrCasePrefix("radiogroup", str))
213 str += strlen("radiogroup");
214 else if (uStrCasePrefix("rg", str))
216 else if (!isdigit(str[0]))
219 if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
220 || (rg > XkbMaxRadioGroups))
226 static LookupEntry modIndexNames[] = {
227 {"shift", ShiftMapIndex},
228 {"control", ControlMapIndex},
229 {"lock", LockMapIndex},
230 {"mod1", Mod1MapIndex},
231 {"mod2", Mod2MapIndex},
232 {"mod3", Mod3MapIndex},
233 {"mod4", Mod4MapIndex},
234 {"mod5", Mod5MapIndex},
235 {"none", XkbNoModifier},
240 LookupModIndex(char * priv, uint32_t field, unsigned type,
241 ExprResult * val_rtrn)
243 return SimpleLookup((char *) modIndexNames, field, type, val_rtrn);
247 LookupModMask(char * priv, uint32_t field, unsigned type,
248 ExprResult * val_rtrn)
255 str = XkbcAtomGetString(field);
258 if (uStrCaseCmp(str, "all") == 0)
259 val_rtrn->uval = 0xff;
260 else if (uStrCaseCmp(str, "none") == 0)
262 else if (LookupModIndex(priv, field, type, val_rtrn))
263 val_rtrn->uval = (1 << val_rtrn->uval);
264 else if (priv != NULL)
266 LookupPriv *lpriv = (LookupPriv *) priv;
267 if ((lpriv->chain == NULL) ||
268 (!(*lpriv->chain) (lpriv->chainPriv, field, type, val_rtrn)))
278 ExprResolveBoolean(ExprDef * expr,
279 ExprResult * val_rtrn)
282 const char *bogus = NULL;
287 if (expr->type != TypeBoolean)
290 ("Found constant of type %s where boolean was expected\n",
291 exprTypeText(expr->type));
294 val_rtrn->ival = expr->value.ival;
297 bogus = XkbcAtomText(expr->value.str);
300 if ((uStrCaseCmp(bogus, "true") == 0) ||
301 (uStrCaseCmp(bogus, "yes") == 0) ||
302 (uStrCaseCmp(bogus, "on") == 0))
307 else if ((uStrCaseCmp(bogus, "false") == 0) ||
308 (uStrCaseCmp(bogus, "no") == 0) ||
309 (uStrCaseCmp(bogus, "off") == 0))
315 ERROR("Identifier \"%s\" of type int is unknown\n",
316 XkbcAtomText(expr->value.str));
319 ERROR("Default \"%s.%s\" of type boolean is unknown\n",
320 XkbcAtomText(expr->value.field.element),
321 XkbcAtomText(expr->value.field.field));
325 ok = ExprResolveBoolean(expr, val_rtrn);
327 val_rtrn->uval = !val_rtrn->uval;
334 bogus = "Subtraction";
337 bogus = "Multiplication";
343 bogus = "Assignment";
347 ERROR("%s of boolean values not permitted\n", bogus);
350 ERROR("Unary \"+\" operator not permitted for boolean values\n");
353 WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
360 ExprResolveFloat(ExprDef * expr,
361 ExprResult * val_rtrn)
364 ExprResult leftRtrn, rightRtrn;
365 ExprDef *left, *right;
370 if (expr->type == TypeString)
373 str = XkbcAtomText(expr->value.str);
374 if ((str != NULL) && (strlen(str) == 1))
376 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
380 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
382 ERROR("Found constant of type %s, expected a number\n",
383 exprTypeText(expr->type));
386 val_rtrn->ival = expr->value.ival;
387 if (expr->type == TypeInt)
388 val_rtrn->ival *= XkbGeomPtsPerMM;
391 ERROR("Numeric identifier \"%s\" unknown\n",
392 XkbcAtomText(expr->value.str));
395 ERROR("Numeric default \"%s.%s\" unknown\n",
396 XkbcAtomText(expr->value.field.element),
397 XkbcAtomText(expr->value.field.field));
403 left = expr->value.binary.left;
404 right = expr->value.binary.right;
405 if (ExprResolveFloat(left, &leftRtrn) &&
406 ExprResolveFloat(right, &rightRtrn))
411 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
414 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
417 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
420 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
427 WSGO("Assignment operator not implemented yet\n");
430 ERROR("The ! operator cannot be applied to a number\n");
434 left = expr->value.child;
435 if (ExprResolveFloat(left, &leftRtrn))
437 if (expr->op == OpNegate)
438 val_rtrn->ival = -leftRtrn.ival;
440 val_rtrn->ival = ~leftRtrn.ival;
445 left = expr->value.child;
446 return ExprResolveFloat(left, val_rtrn);
448 WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
455 ExprResolveKeyCode(ExprDef * expr,
456 ExprResult * val_rtrn)
458 ExprResult leftRtrn, rightRtrn;
459 ExprDef *left, *right;
464 if (expr->type != TypeInt)
467 ("Found constant of type %s where an int was expected\n",
468 exprTypeText(expr->type));
471 val_rtrn->uval = expr->value.uval;
477 left = expr->value.binary.left;
478 right = expr->value.binary.right;
479 if (ExprResolveKeyCode(left, &leftRtrn) &&
480 ExprResolveKeyCode(right, &rightRtrn))
485 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
488 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
491 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
494 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
501 left = expr->value.child;
502 if (ExprResolveKeyCode(left, &leftRtrn))
504 val_rtrn->uval = ~leftRtrn.uval;
509 left = expr->value.child;
510 return ExprResolveKeyCode(left, val_rtrn);
512 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
519 * This function returns ... something. It's a bit of a guess, really.
521 * If a string is given in value context, its first character will be
522 * returned in uval. If an integer is given in value context, it will be
523 * returned in ival. If a float is given in value context, it will be
524 * returned as millimetres (rather than points) in ival.
526 * If an ident or field reference is given, the lookup function (if given)
527 * will be called. At the moment, only RadioLookup and SimpleLookup use
528 * this, and they both return the results in uval. And don't support field
534 ExprResolveIntegerLookup(ExprDef * expr,
535 ExprResult * val_rtrn,
536 IdentLookupFunc lookup, char * lookupPriv)
539 ExprResult leftRtrn, rightRtrn;
540 ExprDef *left, *right;
545 if (expr->type == TypeString)
548 str = XkbcAtomText(expr->value.str);
556 val_rtrn->uval = str[0];
562 if ((expr->type != TypeInt) && (expr->type != TypeFloat))
565 ("Found constant of type %s where an int was expected\n",
566 exprTypeText(expr->type));
569 val_rtrn->ival = expr->value.ival;
570 if (expr->type == TypeFloat)
571 val_rtrn->ival /= XkbGeomPtsPerMM;
576 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
579 ERROR("Identifier \"%s\" of type int is unknown\n",
580 XkbcAtomText(expr->value.str));
583 ERROR("Default \"%s.%s\" of type int is unknown\n",
584 XkbcAtomText(expr->value.field.element),
585 XkbcAtomText(expr->value.field.field));
591 left = expr->value.binary.left;
592 right = expr->value.binary.right;
593 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
594 ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
599 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
602 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
605 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
608 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
615 WSGO("Assignment operator not implemented yet\n");
618 ERROR("The ! operator cannot be applied to an integer\n");
622 left = expr->value.child;
623 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
625 if (expr->op == OpNegate)
626 val_rtrn->ival = -leftRtrn.ival;
628 val_rtrn->ival = ~leftRtrn.ival;
633 left = expr->value.child;
634 return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
636 WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
643 ExprResolveInteger(ExprDef * expr,
644 ExprResult * val_rtrn)
646 return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
650 ExprResolveRadioGroup(ExprDef * expr,
651 ExprResult * val_rtrn)
653 return ExprResolveIntegerLookup(expr, val_rtrn, RadioLookup, NULL);
657 ExprResolveGroup(ExprDef * expr,
658 ExprResult * val_rtrn)
660 static LookupEntry group_names[] = {
672 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
673 (char *) group_names);
677 ExprResolveLevel(ExprDef * expr,
678 ExprResult * val_rtrn)
680 static LookupEntry level_names[] = {
692 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
693 (char *) level_names);
697 ExprResolveButton(ExprDef * expr,
698 ExprResult * val_rtrn)
700 static LookupEntry button_names[] = {
710 return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
711 (char *) button_names);
715 ExprResolveString(ExprDef * expr,
716 ExprResult * val_rtrn)
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)
734 val_rtrn->str = strdup("");
737 ERROR("Identifier \"%s\" of type string not found\n",
738 XkbcAtomText(expr->value.str));
741 ERROR("Default \"%s.%s\" of type string not found\n",
742 XkbcAtomText(expr->value.field.element),
743 XkbcAtomText(expr->value.field.field));
746 left = expr->value.binary.left;
747 right = expr->value.binary.right;
748 if (ExprResolveString(left, &leftRtrn) &&
749 ExprResolveString(right, &rightRtrn))
753 len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
754 new = (char *) malloc(len);
756 { sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
768 bogus = "Subtraction";
771 bogus = "Multiplication";
777 bogus = "Assignment";
783 bogus = "Bitwise complement";
784 ERROR("%s of string values not permitted\n", bogus);
787 ERROR("The ! operator cannot be applied to a string\n");
790 ERROR("The + operator cannot be applied to a string\n");
793 WSGO("Unknown operator %d in ResolveString\n", expr->op);
800 ExprResolveKeyName(ExprDef * expr,
801 ExprResult * val_rtrn)
808 if (expr->type != TypeKeyName)
810 ERROR("Found constant of type %s, expected a key name\n",
811 exprTypeText(expr->type));
814 memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
817 ERROR("Identifier \"%s\" of type string not found\n",
818 XkbcAtomText(expr->value.str));
821 ERROR("Default \"%s.%s\" of type key name not found\n",
822 XkbcAtomText(expr->value.field.element),
823 XkbcAtomText(expr->value.field.field));
830 bogus = "Subtraction";
833 bogus = "Multiplication";
839 bogus = "Assignment";
845 bogus = "Bitwise complement";
846 ERROR("%s of key name values not permitted\n", bogus);
849 ERROR("The ! operator cannot be applied to a key name\n");
852 ERROR("The + operator cannot be applied to a key name\n");
855 WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
861 /***====================================================================***/
864 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
866 if (expr->op != ExprIdent)
868 ERROR("Found a %s where an enumerated value was expected\n",
869 exprOpText(expr->op));
872 if (!SimpleLookup((char *) values, expr->value.str, TypeInt, val_rtrn))
875 ERROR("Illegal identifier %s (expected one of: ",
876 XkbcAtomText(expr->value.str));
877 while (values && values->name)
880 INFO(", %s", values->name);
882 INFO("%s", values->name);
893 ExprResolveMaskLookup(ExprDef * expr,
894 ExprResult * val_rtrn,
895 IdentLookupFunc lookup,
899 ExprResult leftRtrn, rightRtrn;
900 ExprDef *left, *right;
906 if (expr->type != TypeInt)
909 ("Found constant of type %s where a mask was expected\n",
910 exprTypeText(expr->type));
913 val_rtrn->ival = expr->value.ival;
916 ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
918 ERROR("Identifier \"%s\" of type int is unknown\n",
919 XkbcAtomText(expr->value.str));
922 ERROR("Default \"%s.%s\" of type int is unknown\n",
923 XkbcAtomText(expr->value.field.element),
924 XkbcAtomText(expr->value.field.field));
927 bogus = "array reference";
930 bogus = "function use";
931 ERROR("Unexpected %s in mask expression\n", bogus);
932 ACTION("Expression ignored\n");
938 left = expr->value.binary.left;
939 right = expr->value.binary.right;
940 if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
941 ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
946 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
949 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
953 ERROR("Cannot %s masks\n",
954 expr->op == OpDivide ? "divide" : "multiply");
955 ACTION("Illegal operation ignored\n");
962 WSGO("Assignment operator not implemented yet\n");
965 left = expr->value.child;
966 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
968 val_rtrn->ival = ~leftRtrn.ival;
975 left = expr->value.child;
976 if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
978 ERROR("The %s operator cannot be used with a mask\n",
979 (expr->op == OpNegate ? "-" : "!"));
983 WSGO("Unknown operator %d in ResolveMask\n", expr->op);
990 ExprResolveMask(ExprDef * expr,
991 ExprResult * val_rtrn,
992 LookupEntry * values)
994 return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup,
999 ExprResolveModMask(ExprDef * expr,
1000 ExprResult * val_rtrn)
1002 return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
1006 ExprResolveVModMask(ExprDef * expr,
1007 ExprResult * val_rtrn,
1008 struct xkb_desc *xkb)
1010 return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask,
1015 ExprResolveKeySym(ExprDef * expr,
1016 ExprResult * val_rtrn)
1021 if (expr->op == ExprIdent)
1024 str = XkbcAtomText(expr->value.str);
1025 if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
1027 val_rtrn->uval = sym;
1031 ok = ExprResolveInteger(expr, val_rtrn);
1032 if ((ok) && (val_rtrn->uval < 10))
1033 val_rtrn->uval += '0';