aboutsummaryrefslogtreecommitdiff
path: root/xkbcomp/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'xkbcomp/expr.c')
-rw-r--r--xkbcomp/expr.c2130
1 files changed, 1065 insertions, 1065 deletions
diff --git a/xkbcomp/expr.c b/xkbcomp/expr.c
index 96fd95675..33a2dddee 100644
--- a/xkbcomp/expr.c
+++ b/xkbcomp/expr.c
@@ -1,1065 +1,1065 @@
-/************************************************************
- Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
-
- Permission to use, copy, modify, and distribute this
- software and its documentation for any purpose and without
- fee is hereby granted, provided that the above copyright
- notice appear in all copies and that both that copyright
- notice and this permission notice appear in supporting
- documentation, and that the name of Silicon Graphics not be
- used in advertising or publicity pertaining to distribution
- of the software without specific prior written permission.
- Silicon Graphics makes no representation about the suitability
- of this software for any purpose. It is provided "as is"
- without any express or implied warranty.
-
- SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
- THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ********************************************************/
-
-#include "xkbcomp.h"
-#include "tokens.h"
-#include "expr.h"
-
-#include <ctype.h>
-
-/***====================================================================***/
-
-char *
-exprOpText(unsigned type)
-{
- static char buf[32];
-
- switch (type)
- {
- case ExprValue:
- strcpy(buf, "literal");
- break;
- case ExprIdent:
- strcpy(buf, "identifier");
- break;
- case ExprActionDecl:
- strcpy(buf, "action declaration");
- break;
- case ExprFieldRef:
- strcpy(buf, "field reference");
- break;
- case ExprArrayRef:
- strcpy(buf, "array reference");
- break;
- case ExprKeysymList:
- strcpy(buf, "list of keysyms");
- break;
- case ExprActionList:
- strcpy(buf, "list of actions");
- break;
- case OpAdd:
- strcpy(buf, "addition");
- break;
- case OpSubtract:
- strcpy(buf, "subtraction");
- break;
- case OpMultiply:
- strcpy(buf, "multiplication");
- break;
- case OpDivide:
- strcpy(buf, "division");
- break;
- case OpAssign:
- strcpy(buf, "assignment");
- break;
- case OpNot:
- strcpy(buf, "logical not");
- break;
- case OpNegate:
- strcpy(buf, "arithmetic negation");
- break;
- case OpInvert:
- strcpy(buf, "bitwise inversion");
- break;
- case OpUnaryPlus:
- strcpy(buf, "plus sign");
- break;
- default:
- snprintf(buf, sizeof(buf), "illegal(%d)", type);
- break;
- }
- return buf;
-}
-
-char *
-exprTypeText(unsigned type)
-{
- static char buf[20];
-
- switch (type)
- {
- case TypeUnknown:
- strcpy(buf, "unknown");
- break;
- case TypeBoolean:
- strcpy(buf, "boolean");
- break;
- case TypeInt:
- strcpy(buf, "int");
- break;
- case TypeString:
- strcpy(buf, "string");
- break;
- case TypeAction:
- strcpy(buf, "action");
- break;
- case TypeKeyName:
- strcpy(buf, "keyname");
- break;
- default:
- snprintf(buf, sizeof(buf), "illegal(%d)", type);
- break;
- }
- return buf;
-}
-
-int
-ExprResolveLhs(ExprDef * expr,
- ExprResult * elem_rtrn,
- ExprResult * field_rtrn, ExprDef ** index_rtrn)
-{
- switch (expr->op)
- {
- case ExprIdent:
- elem_rtrn->str = NULL;
- field_rtrn->str = XkbAtomGetString(NULL, expr->value.str);
- *index_rtrn = NULL;
- return True;
- case ExprFieldRef:
- elem_rtrn->str = XkbAtomGetString(NULL, expr->value.field.element);
- field_rtrn->str = XkbAtomGetString(NULL, expr->value.field.field);
- *index_rtrn = NULL;
- return True;
- case ExprArrayRef:
- elem_rtrn->str = XkbAtomGetString(NULL, expr->value.array.element);
- field_rtrn->str = XkbAtomGetString(NULL, expr->value.array.field);
- *index_rtrn = expr->value.array.entry;
- return True;
- }
- WSGO1("Unexpected operator %d in ResolveLhs\n", expr->op);
- return False;
-}
-
-Bool
-SimpleLookup(XPointer priv,
- Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
-{
- LookupEntry *entry;
- register char *str;
-
- if ((priv == NULL) ||
- (field == None) || (elem != None) ||
- ((type != TypeInt) && (type != TypeFloat)))
- {
- return False;
- }
- str = XkbAtomGetString(NULL, field);
- for (entry = (LookupEntry *) priv;
- (entry != NULL) && (entry->name != NULL); entry++)
- {
- if (uStrCaseCmp(str, entry->name) == 0)
- {
- val_rtrn->uval = entry->result;
- if (type == TypeFloat)
- val_rtrn->uval *= XkbGeomPtsPerMM;
- return True;
- }
- }
- return False;
-}
-
-Bool
-RadioLookup(XPointer priv,
- Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
-{
- register char *str;
- int rg;
-
- if ((field == None) || (elem != None) || (type != TypeInt))
- return False;
- str = XkbAtomGetString(NULL, field);
- if (str)
- {
- if (uStrCasePrefix("group", str))
- str += strlen("group");
- else if (uStrCasePrefix("radiogroup", str))
- str += strlen("radiogroup");
- else if (uStrCasePrefix("rg", str))
- str += strlen("rg");
- else if (!isdigit(str[0]))
- str = NULL;
- }
- if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
- || (rg > XkbMaxRadioGroups))
- return False;
- val_rtrn->uval = rg;
- return True;
-}
-
-int
-TableLookup(XPointer priv,
- Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
-{
- LookupTable *tbl = (LookupTable *) priv;
- register char *str;
-
- if ((priv == NULL) || (field == None) || (type != TypeInt))
- return False;
- str = XkbAtomGetString(NULL, elem);
- while (tbl)
- {
- if (((str == NULL) && (tbl->element == NULL)) ||
- ((str != NULL) && (tbl->element != NULL) &&
- (uStrCaseCmp(str, tbl->element) == 0)))
- {
- break;
- }
- tbl = tbl->nextElement;
- }
- if (tbl == NULL) /* didn't find a matching element */
- return False;
- priv = (XPointer) tbl->entries;
- return SimpleLookup(priv, (Atom) None, field, type, val_rtrn);
-}
-
-static LookupEntry modIndexNames[] = {
- {"shift", ShiftMapIndex},
- {"control", ControlMapIndex},
- {"lock", LockMapIndex},
- {"mod1", Mod1MapIndex},
- {"mod2", Mod2MapIndex},
- {"mod3", Mod3MapIndex},
- {"mod4", Mod4MapIndex},
- {"mod5", Mod5MapIndex},
- {"none", XkbNoModifier},
- {NULL, 0}
-};
-
-int
-LookupModIndex(XPointer priv,
- Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
-{
- return SimpleLookup((XPointer) modIndexNames, elem, field, type,
- val_rtrn);
-}
-
-int
-LookupModMask(XPointer priv,
- Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
-{
- char *str;
-
- if ((elem != None) || (type != TypeInt))
- return False;
- str = XkbAtomGetString(NULL, field);
- if (str == NULL)
- return False;
- if (uStrCaseCmp(str, "all") == 0)
- val_rtrn->uval = 0xff;
- else if (uStrCaseCmp(str, "none") == 0)
- val_rtrn->uval = 0;
- else if (LookupModIndex(priv, elem, field, type, val_rtrn))
- val_rtrn->uval = (1 << val_rtrn->uval);
- else if (priv != NULL)
- {
- LookupPriv *lpriv = (LookupPriv *) priv;
- if ((lpriv->chain == NULL) ||
- (!(*lpriv->chain) (lpriv->chainPriv, elem, field, type,
- val_rtrn)))
- return False;
- }
- else
- return False;
- return True;
-}
-
-int
-ExprResolveModIndex(ExprDef * expr,
- ExprResult * val_rtrn,
- IdentLookupFunc lookup, XPointer lookupPriv)
-{
- int ok = 0;
- char *bogus = NULL;
-
- switch (expr->op)
- {
- case ExprValue:
- if (expr->type != TypeInt)
- {
- ERROR1
- ("Found constant of type %s where a modifier mask was expected\n",
- exprTypeText(expr->type));
- return False;
- }
- else if ((expr->value.ival >= XkbNumModifiers)
- || (expr->value.ival < 0))
- {
- ERROR2("Illegal modifier index (%d, must be 0..%d)\n",
- expr->value.ival, XkbNumModifiers - 1);
- return False;
- }
- val_rtrn->ival = expr->value.ival;
- return True;
- case ExprIdent:
- if (LookupModIndex(lookupPriv, (Atom) None, expr->value.str,
- (unsigned) TypeInt, val_rtrn))
- {
- return True;
- }
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- None, expr->value.str, TypeInt, val_rtrn);
- }
- if (!ok)
- ERROR1("Cannot determine modifier index for \"%s\"\n",
- XkbAtomText(NULL, expr->value.str, XkbMessage));
- break;
- case ExprFieldRef:
- bogus = "field reference";
- break;
- case ExprArrayRef:
- bogus = "array reference";
- break;
- case ExprActionDecl:
- bogus = "function";
- break;
- case OpAdd:
- case OpSubtract:
- case OpMultiply:
- case OpDivide:
- case OpInvert:
- case OpNegate:
- case OpNot:
- case OpUnaryPlus:
- bogus = "arithmetic operations";
- break;
- case OpAssign:
- bogus = "assignment";
- break;
- default:
- WSGO1("Unknown operator %d in ResolveModIndex\n", expr->op);
- return False;
- }
- if (bogus)
- {
- ERROR1("Modifier index must be a name or number, %s ignored\n",
- bogus);
- return False;
- }
- return ok;
-}
-
-int
-ExprResolveModMask(ExprDef * expr,
- ExprResult * val_rtrn,
- IdentLookupFunc lookup, XPointer lookupPriv)
-{
- LookupPriv priv;
-
- priv.priv = NULL;
- priv.chain = lookup;
- priv.chainPriv = lookupPriv;
- return ExprResolveMask(expr, val_rtrn, LookupModMask, (XPointer) & priv);
-}
-
-int
-ExprResolveBoolean(ExprDef * expr,
- ExprResult * val_rtrn,
- IdentLookupFunc lookup, XPointer lookupPriv)
-{
- int ok = 0;
- char *bogus = NULL;
-
- switch (expr->op)
- {
- case ExprValue:
- if (expr->type != TypeBoolean)
- {
- ERROR1
- ("Found constant of type %s where boolean was expected\n",
- exprTypeText(expr->type));
- return False;
- }
- val_rtrn->ival = expr->value.ival;
- return True;
- case ExprIdent:
- bogus = XkbAtomGetString(NULL, expr->value.str);
- if (bogus)
- {
- if ((uStrCaseCmp(bogus, "true") == 0) ||
- (uStrCaseCmp(bogus, "yes") == 0) ||
- (uStrCaseCmp(bogus, "on") == 0))
- {
- val_rtrn->uval = 1;
- return True;
- }
- else if ((uStrCaseCmp(bogus, "false") == 0) ||
- (uStrCaseCmp(bogus, "no") == 0) ||
- (uStrCaseCmp(bogus, "off") == 0))
- {
- val_rtrn->uval = 0;
- return True;
- }
- }
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- None, expr->value.str, TypeBoolean, val_rtrn);
- }
- if (!ok)
- ERROR1("Identifier \"%s\" of type int is unknown\n",
- XkbAtomText(NULL, expr->value.str, XkbMessage));
- return ok;
- case ExprFieldRef:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- expr->value.field.element,
- expr->value.field.field, TypeBoolean, val_rtrn);
- }
- if (!ok)
- ERROR2("Default \"%s.%s\" of type boolean is unknown\n",
- XkbAtomText(NULL, expr->value.field.element, XkbMessage),
- XkbAtomText(NULL, expr->value.field.field, XkbMessage));
- return ok;
- case OpInvert:
- case OpNot:
- ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv);
- if (ok)
- val_rtrn->uval = !val_rtrn->uval;
- return ok;
- case OpAdd:
- if (bogus == NULL)
- bogus = "Addition";
- case OpSubtract:
- if (bogus == NULL)
- bogus = "Subtraction";
- case OpMultiply:
- if (bogus == NULL)
- bogus = "Multiplication";
- case OpDivide:
- if (bogus == NULL)
- bogus = "Division";
- case OpAssign:
- if (bogus == NULL)
- bogus = "Assignment";
- case OpNegate:
- if (bogus == NULL)
- bogus = "Negation";
- ERROR1("%s of boolean values not permitted\n", bogus);
- break;
- case OpUnaryPlus:
- ERROR("Unary \"+\" operator not permitted for boolean values\n");
- break;
- default:
- WSGO1("Unknown operator %d in ResolveBoolean\n", expr->op);
- break;
- }
- return False;
-}
-
-int
-ExprResolveFloat(ExprDef * expr,
- ExprResult * val_rtrn,
- IdentLookupFunc lookup, XPointer lookupPriv)
-{
- int ok = 0;
- ExprResult leftRtrn, rightRtrn;
- ExprDef *left, *right;
-
- switch (expr->op)
- {
- case ExprValue:
- if (expr->type == TypeString)
- {
- register char *str;
- str = XkbAtomGetString(NULL, expr->value.str);
- if ((str != NULL) && (strlen(str) == 1))
- {
- val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
- return True;
- }
- }
- if ((expr->type != TypeInt) && (expr->type != TypeFloat))
- {
- ERROR1("Found constant of type %s, expected a number\n",
- exprTypeText(expr->type));
- return False;
- }
- val_rtrn->ival = expr->value.ival;
- if (expr->type == TypeInt)
- val_rtrn->ival *= XkbGeomPtsPerMM;
- return True;
- case ExprIdent:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- None, expr->value.str, TypeFloat, val_rtrn);
- }
- if (!ok)
- ERROR1("Numeric identifier \"%s\" unknown\n",
- XkbAtomText(NULL, expr->value.str, XkbMessage));
- return ok;
- case ExprFieldRef:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- expr->value.field.element,
- expr->value.field.field, TypeFloat, val_rtrn);
- }
- if (!ok)
- ERROR2("Numeric default \"%s.%s\" unknown\n",
- XkbAtomText(NULL, expr->value.field.element, XkbMessage),
- XkbAtomText(NULL, expr->value.field.field, XkbMessage));
- return ok;
- case OpAdd:
- case OpSubtract:
- case OpMultiply:
- case OpDivide:
- left = expr->value.binary.left;
- right = expr->value.binary.right;
- if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) &&
- ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv))
- {
- switch (expr->op)
- {
- case OpAdd:
- val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
- break;
- case OpSubtract:
- val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
- break;
- case OpMultiply:
- val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
- break;
- case OpDivide:
- val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
- break;
- }
- return True;
- }
- return False;
- case OpAssign:
- WSGO("Assignment operator not implemented yet\n");
- break;
- case OpNot:
- left = expr->value.child;
- if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
- {
- ERROR("The ! operator cannot be applied to a number\n");
- }
- return False;
- case OpInvert:
- case OpNegate:
- left = expr->value.child;
- if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
- {
- if (expr->op == OpNegate)
- val_rtrn->ival = -leftRtrn.ival;
- else
- val_rtrn->ival = ~leftRtrn.ival;
- return True;
- }
- return False;
- case OpUnaryPlus:
- left = expr->value.child;
- return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv);
- default:
- WSGO1("Unknown operator %d in ResolveFloat\n", expr->op);
- break;
- }
- return False;
-}
-
-int
-ExprResolveInteger(ExprDef * expr,
- ExprResult * val_rtrn,
- IdentLookupFunc lookup, XPointer lookupPriv)
-{
- int ok = 0;
- ExprResult leftRtrn, rightRtrn;
- ExprDef *left, *right;
-
- switch (expr->op)
- {
- case ExprValue:
- if (expr->type == TypeString)
- {
- register char *str;
- str = XkbAtomGetString(NULL, expr->value.str);
- if (str != NULL)
- switch (strlen(str))
- {
- case 0:
- val_rtrn->uval = 0;
- return True;
- case 1:
- val_rtrn->uval = str[0];
- return True;
- default:
- break;
- }
- }
- if ((expr->type != TypeInt) && (expr->type != TypeFloat))
- {
- ERROR1
- ("Found constant of type %s where an int was expected\n",
- exprTypeText(expr->type));
- return False;
- }
- val_rtrn->ival = expr->value.ival;
- if (expr->type == TypeFloat)
- val_rtrn->ival /= XkbGeomPtsPerMM;
- return True;
- case ExprIdent:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- None, expr->value.str, TypeInt, val_rtrn);
- }
- if (!ok)
- ERROR1("Identifier \"%s\" of type int is unknown\n",
- XkbAtomText(NULL, expr->value.str, XkbMessage));
- return ok;
- case ExprFieldRef:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- expr->value.field.element,
- expr->value.field.field, TypeInt, val_rtrn);
- }
- if (!ok)
- ERROR2("Default \"%s.%s\" of type int is unknown\n",
- XkbAtomText(NULL, expr->value.field.element, XkbMessage),
- XkbAtomText(NULL, expr->value.field.field, XkbMessage));
- return ok;
- case OpAdd:
- case OpSubtract:
- case OpMultiply:
- case OpDivide:
- left = expr->value.binary.left;
- right = expr->value.binary.right;
- if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv) &&
- ExprResolveInteger(right, &rightRtrn, lookup, lookupPriv))
- {
- switch (expr->op)
- {
- case OpAdd:
- val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
- break;
- case OpSubtract:
- val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
- break;
- case OpMultiply:
- val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
- break;
- case OpDivide:
- val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
- break;
- }
- return True;
- }
- return False;
- case OpAssign:
- WSGO("Assignment operator not implemented yet\n");
- break;
- case OpNot:
- left = expr->value.child;
- if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
- {
- ERROR("The ! operator cannot be applied to an integer\n");
- }
- return False;
- case OpInvert:
- case OpNegate:
- left = expr->value.child;
- if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
- {
- if (expr->op == OpNegate)
- val_rtrn->ival = -leftRtrn.ival;
- else
- val_rtrn->ival = ~leftRtrn.ival;
- return True;
- }
- return False;
- case OpUnaryPlus:
- left = expr->value.child;
- return ExprResolveInteger(left, val_rtrn, lookup, lookupPriv);
- default:
- WSGO1("Unknown operator %d in ResolveInteger\n", expr->op);
- break;
- }
- return False;
-}
-
-int
-ExprResolveString(ExprDef * expr,
- ExprResult * val_rtrn,
- IdentLookupFunc lookup, XPointer lookupPriv)
-{
- int ok = 0;
- ExprResult leftRtrn, rightRtrn;
- ExprDef *left;
- ExprDef *right;
- char *bogus = NULL;
-
- switch (expr->op)
- {
- case ExprValue:
- if (expr->type != TypeString)
- {
- ERROR1("Found constant of type %s, expected a string\n",
- exprTypeText(expr->type));
- return False;
- }
- val_rtrn->str = XkbAtomGetString(NULL, expr->value.str);
- if (val_rtrn->str == NULL)
- {
- static char *empty = "";
- val_rtrn->str = empty;
- }
- return True;
- case ExprIdent:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- None, expr->value.str, TypeString, val_rtrn);
- }
- if (!ok)
- ERROR1("Identifier \"%s\" of type string not found\n",
- XkbAtomText(NULL, expr->value.str, XkbMessage));
- return ok;
- case ExprFieldRef:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- expr->value.field.element,
- expr->value.field.field, TypeString, val_rtrn);
- }
- if (!ok)
- ERROR2("Default \"%s.%s\" of type string not found\n",
- XkbAtomText(NULL, expr->value.field.element, XkbMessage),
- XkbAtomText(NULL, expr->value.field.field, XkbMessage));
- return ok;
- case OpAdd:
- left = expr->value.binary.left;
- right = expr->value.binary.right;
- if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) &&
- ExprResolveString(right, &rightRtrn, lookup, lookupPriv))
- {
- int len;
- char *new;
- len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
- new = (char *) uAlloc(len);
- if (new)
- {
- sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
- val_rtrn->str = new;
- return True;
- }
- }
- return False;
- case OpSubtract:
- if (bogus == NULL)
- bogus = "Subtraction";
- case OpMultiply:
- if (bogus == NULL)
- bogus = "Multiplication";
- case OpDivide:
- if (bogus == NULL)
- bogus = "Division";
- case OpAssign:
- if (bogus == NULL)
- bogus = "Assignment";
- case OpNegate:
- if (bogus == NULL)
- bogus = "Negation";
- case OpInvert:
- if (bogus == NULL)
- bogus = "Bitwise complement";
- ERROR1("%s of string values not permitted\n", bogus);
- return False;
- case OpNot:
- left = expr->value.child;
- if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
- {
- ERROR("The ! operator cannot be applied to a string\n");
- }
- return False;
- case OpUnaryPlus:
- left = expr->value.child;
- if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
- {
- ERROR("The + operator cannot be applied to a string\n");
- }
- return False;
- default:
- WSGO1("Unknown operator %d in ResolveString\n", expr->op);
- break;
- }
- return False;
-}
-
-int
-ExprResolveKeyName(ExprDef * expr,
- ExprResult * val_rtrn,
- IdentLookupFunc lookup, XPointer lookupPriv)
-{
- int ok = 0;
- ExprDef *left;
- ExprResult leftRtrn;
- char *bogus = NULL;
-
- switch (expr->op)
- {
- case ExprValue:
- if (expr->type != TypeKeyName)
- {
- ERROR1("Found constant of type %s, expected a key name\n",
- exprTypeText(expr->type));
- return False;
- }
- memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
- return True;
- case ExprIdent:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- None, expr->value.str, TypeString, val_rtrn);
- }
- if (!ok)
- ERROR1("Identifier \"%s\" of type string not found\n",
- XkbAtomText(NULL, expr->value.str, XkbMessage));
- return ok;
- case ExprFieldRef:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- expr->value.field.element,
- expr->value.field.field, TypeString, val_rtrn);
- }
- if (!ok)
- ERROR2("Default \"%s.%s\" of type key name not found\n",
- XkbAtomText(NULL, expr->value.field.element, XkbMessage),
- XkbAtomText(NULL, expr->value.field.field, XkbMessage));
- return ok;
- case OpAdd:
- if (bogus == NULL)
- bogus = "Addition";
- case OpSubtract:
- if (bogus == NULL)
- bogus = "Subtraction";
- case OpMultiply:
- if (bogus == NULL)
- bogus = "Multiplication";
- case OpDivide:
- if (bogus == NULL)
- bogus = "Division";
- case OpAssign:
- if (bogus == NULL)
- bogus = "Assignment";
- case OpNegate:
- if (bogus == NULL)
- bogus = "Negation";
- case OpInvert:
- if (bogus == NULL)
- bogus = "Bitwise complement";
- ERROR1("%s of key name values not permitted\n", bogus);
- return False;
- case OpNot:
- left = expr->value.binary.left;
- if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
- {
- ERROR("The ! operator cannot be applied to a key name\n");
- }
- return False;
- case OpUnaryPlus:
- left = expr->value.binary.left;
- if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
- {
- ERROR("The + operator cannot be applied to a key name\n");
- }
- return False;
- default:
- WSGO1("Unknown operator %d in ResolveKeyName\n", expr->op);
- break;
- }
- return False;
-}
-
-/***====================================================================***/
-
-int
-ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
-{
- if (expr->op != ExprIdent)
- {
- ERROR1("Found a %s where an enumerated value was expected\n",
- exprOpText(expr->op));
- return False;
- }
- if (!SimpleLookup((XPointer) values, (Atom) None, expr->value.str,
- (unsigned) TypeInt, val_rtrn))
- {
- int nOut = 0;
- ERROR1("Illegal identifier %s (expected one of: ",
- XkbAtomText(NULL, expr->value.str, XkbMessage));
- while (values && values->name)
- {
- if (nOut != 0)
- INFO1(", %s", values->name);
- else
- INFO1("%s", values->name);
- values++;
- nOut++;
- }
- INFO(")\n");
- return False;
- }
- return True;
-}
-
-int
-ExprResolveMask(ExprDef * expr,
- ExprResult * val_rtrn,
- IdentLookupFunc lookup, XPointer lookupPriv)
-{
- int ok = 0;
- ExprResult leftRtrn, rightRtrn;
- ExprDef *left, *right;
- char *bogus = NULL;
-
- switch (expr->op)
- {
- case ExprValue:
- if (expr->type != TypeInt)
- {
- ERROR1
- ("Found constant of type %s where a mask was expected\n",
- exprTypeText(expr->type));
- return False;
- }
- val_rtrn->ival = expr->value.ival;
- return True;
- case ExprIdent:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- None, expr->value.str, TypeInt, val_rtrn);
- }
- if (!ok)
- ERROR1("Identifier \"%s\" of type int is unknown\n",
- XkbAtomText(NULL, expr->value.str, XkbMessage));
- return ok;
- case ExprFieldRef:
- if (lookup)
- {
- ok = (*lookup) (lookupPriv,
- expr->value.field.element,
- expr->value.field.field, TypeInt, val_rtrn);
- }
- if (!ok)
- ERROR2("Default \"%s.%s\" of type int is unknown\n",
- XkbAtomText(NULL, expr->value.field.element, XkbMessage),
- XkbAtomText(NULL, expr->value.field.field, XkbMessage));
- return ok;
- case ExprArrayRef:
- bogus = "array reference";
- case ExprActionDecl:
- if (bogus == NULL)
- bogus = "function use";
- ERROR1("Unexpected %s in mask expression\n", bogus);
- ACTION("Expression ignored\n");
- return False;
- case OpAdd:
- case OpSubtract:
- case OpMultiply:
- case OpDivide:
- left = expr->value.binary.left;
- right = expr->value.binary.right;
- if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) &&
- ExprResolveMask(right, &rightRtrn, lookup, lookupPriv))
- {
- switch (expr->op)
- {
- case OpAdd:
- val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
- break;
- case OpSubtract:
- val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
- break;
- case OpMultiply:
- case OpDivide:
- ERROR1("Cannot %s masks\n",
- expr->op == OpDivide ? "divide" : "multiply");
- ACTION("Illegal operation ignored\n");
- return False;
- }
- return True;
- }
- return False;
- case OpAssign:
- WSGO("Assignment operator not implemented yet\n");
- break;
- case OpInvert:
- left = expr->value.child;
- if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
- {
- val_rtrn->ival = ~leftRtrn.ival;
- return True;
- }
- return False;
- case OpUnaryPlus:
- case OpNegate:
- case OpNot:
- left = expr->value.child;
- if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
- {
- ERROR1("The %s operator cannot be used with a mask\n",
- (expr->op == OpNegate ? "-" : "!"));
- }
- return False;
- default:
- WSGO1("Unknown operator %d in ResolveMask\n", expr->op);
- break;
- }
- return False;
-}
-
-int
-ExprResolveKeySym(ExprDef * expr,
- ExprResult * val_rtrn,
- IdentLookupFunc lookup, XPointer lookupPriv)
-{
- int ok = 0;
- KeySym sym;
-
- if (expr->op == ExprIdent)
- {
- char *str;
- str = XkbAtomGetString(NULL, expr->value.str);
- if ((str != NULL) && ((sym = XStringToKeysym(str)) != NoSymbol))
- {
- val_rtrn->uval = sym;
- return True;
- }
- }
- ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv);
- if ((ok) && (val_rtrn->uval < 10))
- val_rtrn->uval += '0';
- return ok;
-}
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+
+#include <ctype.h>
+
+/***====================================================================***/
+
+char *
+exprOpText(unsigned type)
+{
+ static char buf[32];
+
+ switch (type)
+ {
+ case ExprValue:
+ strcpy(buf, "literal");
+ break;
+ case ExprIdent:
+ strcpy(buf, "identifier");
+ break;
+ case ExprActionDecl:
+ strcpy(buf, "action declaration");
+ break;
+ case ExprFieldRef:
+ strcpy(buf, "field reference");
+ break;
+ case ExprArrayRef:
+ strcpy(buf, "array reference");
+ break;
+ case ExprKeysymList:
+ strcpy(buf, "list of keysyms");
+ break;
+ case ExprActionList:
+ strcpy(buf, "list of actions");
+ break;
+ case OpAdd:
+ strcpy(buf, "addition");
+ break;
+ case OpSubtract:
+ strcpy(buf, "subtraction");
+ break;
+ case OpMultiply:
+ strcpy(buf, "multiplication");
+ break;
+ case OpDivide:
+ strcpy(buf, "division");
+ break;
+ case OpAssign:
+ strcpy(buf, "assignment");
+ break;
+ case OpNot:
+ strcpy(buf, "logical not");
+ break;
+ case OpNegate:
+ strcpy(buf, "arithmetic negation");
+ break;
+ case OpInvert:
+ strcpy(buf, "bitwise inversion");
+ break;
+ case OpUnaryPlus:
+ strcpy(buf, "plus sign");
+ break;
+ default:
+ snprintf(buf, sizeof(buf), "illegal(%d)", type);
+ break;
+ }
+ return buf;
+}
+
+char *
+exprTypeText(unsigned type)
+{
+ static char buf[20];
+
+ switch (type)
+ {
+ case TypeUnknown:
+ strcpy(buf, "unknown");
+ break;
+ case TypeBoolean:
+ strcpy(buf, "boolean");
+ break;
+ case TypeInt:
+ strcpy(buf, "int");
+ break;
+ case TypeString:
+ strcpy(buf, "string");
+ break;
+ case TypeAction:
+ strcpy(buf, "action");
+ break;
+ case TypeKeyName:
+ strcpy(buf, "keyname");
+ break;
+ default:
+ snprintf(buf, sizeof(buf), "illegal(%d)", type);
+ break;
+ }
+ return buf;
+}
+
+int
+ExprResolveLhs(ExprDef * expr,
+ ExprResult * elem_rtrn,
+ ExprResult * field_rtrn, ExprDef ** index_rtrn)
+{
+ switch (expr->op)
+ {
+ case ExprIdent:
+ elem_rtrn->str = NULL;
+ field_rtrn->str = XkbAtomGetString(NULL, expr->value.str);
+ *index_rtrn = NULL;
+ return True;
+ case ExprFieldRef:
+ elem_rtrn->str = XkbAtomGetString(NULL, expr->value.field.element);
+ field_rtrn->str = XkbAtomGetString(NULL, expr->value.field.field);
+ *index_rtrn = NULL;
+ return True;
+ case ExprArrayRef:
+ elem_rtrn->str = XkbAtomGetString(NULL, expr->value.array.element);
+ field_rtrn->str = XkbAtomGetString(NULL, expr->value.array.field);
+ *index_rtrn = expr->value.array.entry;
+ return True;
+ }
+ WSGO1("Unexpected operator %d in ResolveLhs\n", expr->op);
+ return False;
+}
+
+Bool
+SimpleLookup(XPointer priv,
+ Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
+{
+ LookupEntry *entry;
+ register char *str;
+
+ if ((priv == NULL) ||
+ (field == None) || (elem != None) ||
+ ((type != TypeInt) && (type != TypeFloat)))
+ {
+ return False;
+ }
+ str = XkbAtomGetString(NULL, field);
+ for (entry = (LookupEntry *) priv;
+ (entry != NULL) && (entry->name != NULL); entry++)
+ {
+ if (uStrCaseCmp(str, entry->name) == 0)
+ {
+ val_rtrn->uval = entry->result;
+ if (type == TypeFloat)
+ val_rtrn->uval *= XkbGeomPtsPerMM;
+ return True;
+ }
+ }
+ return False;
+}
+
+Bool
+RadioLookup(XPointer priv,
+ Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
+{
+ register char *str;
+ int rg;
+
+ if ((field == None) || (elem != None) || (type != TypeInt))
+ return False;
+ str = XkbAtomGetString(NULL, field);
+ if (str)
+ {
+ if (uStrCasePrefix("group", str))
+ str += strlen("group");
+ else if (uStrCasePrefix("radiogroup", str))
+ str += strlen("radiogroup");
+ else if (uStrCasePrefix("rg", str))
+ str += strlen("rg");
+ else if (!isdigit(str[0]))
+ str = NULL;
+ }
+ if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
+ || (rg > XkbMaxRadioGroups))
+ return False;
+ val_rtrn->uval = rg;
+ return True;
+}
+
+int
+TableLookup(XPointer priv,
+ Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
+{
+ LookupTable *tbl = (LookupTable *) priv;
+ register char *str;
+
+ if ((priv == NULL) || (field == None) || (type != TypeInt))
+ return False;
+ str = XkbAtomGetString(NULL, elem);
+ while (tbl)
+ {
+ if (((str == NULL) && (tbl->element == NULL)) ||
+ ((str != NULL) && (tbl->element != NULL) &&
+ (uStrCaseCmp(str, tbl->element) == 0)))
+ {
+ break;
+ }
+ tbl = tbl->nextElement;
+ }
+ if (tbl == NULL) /* didn't find a matching element */
+ return False;
+ priv = (XPointer) tbl->entries;
+ return SimpleLookup(priv, (Atom) None, field, type, val_rtrn);
+}
+
+static LookupEntry modIndexNames[] = {
+ {"shift", ShiftMapIndex},
+ {"control", ControlMapIndex},
+ {"lock", LockMapIndex},
+ {"mod1", Mod1MapIndex},
+ {"mod2", Mod2MapIndex},
+ {"mod3", Mod3MapIndex},
+ {"mod4", Mod4MapIndex},
+ {"mod5", Mod5MapIndex},
+ {"none", XkbNoModifier},
+ {NULL, 0}
+};
+
+int
+LookupModIndex(XPointer priv,
+ Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
+{
+ return SimpleLookup((XPointer) modIndexNames, elem, field, type,
+ val_rtrn);
+}
+
+int
+LookupModMask(XPointer priv,
+ Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
+{
+ char *str;
+
+ if ((elem != None) || (type != TypeInt))
+ return False;
+ str = XkbAtomGetString(NULL, field);
+ if (str == NULL)
+ return False;
+ if (uStrCaseCmp(str, "all") == 0)
+ val_rtrn->uval = 0xff;
+ else if (uStrCaseCmp(str, "none") == 0)
+ val_rtrn->uval = 0;
+ else if (LookupModIndex(priv, elem, field, type, val_rtrn))
+ val_rtrn->uval = (1 << val_rtrn->uval);
+ else if (priv != NULL)
+ {
+ LookupPriv *lpriv = (LookupPriv *) priv;
+ if ((lpriv->chain == NULL) ||
+ (!(*lpriv->chain) (lpriv->chainPriv, elem, field, type,
+ val_rtrn)))
+ return False;
+ }
+ else
+ return False;
+ return True;
+}
+
+int
+ExprResolveModIndex(ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup, XPointer lookupPriv)
+{
+ int ok = 0;
+ char *bogus = NULL;
+
+ switch (expr->op)
+ {
+ case ExprValue:
+ if (expr->type != TypeInt)
+ {
+ ERROR1
+ ("Found constant of type %s where a modifier mask was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ else if ((expr->value.ival >= XkbNumModifiers)
+ || (expr->value.ival < 0))
+ {
+ ERROR2("Illegal modifier index (%d, must be 0..%d)\n",
+ expr->value.ival, XkbNumModifiers - 1);
+ return False;
+ }
+ val_rtrn->ival = expr->value.ival;
+ return True;
+ case ExprIdent:
+ if (LookupModIndex(lookupPriv, (Atom) None, expr->value.str,
+ (unsigned) TypeInt, val_rtrn))
+ {
+ return True;
+ }
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ None, expr->value.str, TypeInt, val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Cannot determine modifier index for \"%s\"\n",
+ XkbAtomText(NULL, expr->value.str, XkbMessage));
+ break;
+ case ExprFieldRef:
+ bogus = "field reference";
+ break;
+ case ExprArrayRef:
+ bogus = "array reference";
+ break;
+ case ExprActionDecl:
+ bogus = "function";
+ break;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ case OpInvert:
+ case OpNegate:
+ case OpNot:
+ case OpUnaryPlus:
+ bogus = "arithmetic operations";
+ break;
+ case OpAssign:
+ bogus = "assignment";
+ break;
+ default:
+ WSGO1("Unknown operator %d in ResolveModIndex\n", expr->op);
+ return False;
+ }
+ if (bogus)
+ {
+ ERROR1("Modifier index must be a name or number, %s ignored\n",
+ bogus);
+ return False;
+ }
+ return ok;
+}
+
+int
+ExprResolveModMask(ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup, XPointer lookupPriv)
+{
+ LookupPriv priv;
+
+ priv.priv = NULL;
+ priv.chain = lookup;
+ priv.chainPriv = lookupPriv;
+ return ExprResolveMask(expr, val_rtrn, LookupModMask, (XPointer) & priv);
+}
+
+int
+ExprResolveBoolean(ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup, XPointer lookupPriv)
+{
+ int ok = 0;
+ char *bogus = NULL;
+
+ switch (expr->op)
+ {
+ case ExprValue:
+ if (expr->type != TypeBoolean)
+ {
+ ERROR1
+ ("Found constant of type %s where boolean was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival = expr->value.ival;
+ return True;
+ case ExprIdent:
+ bogus = XkbAtomGetString(NULL, expr->value.str);
+ if (bogus)
+ {
+ if ((uStrCaseCmp(bogus, "true") == 0) ||
+ (uStrCaseCmp(bogus, "yes") == 0) ||
+ (uStrCaseCmp(bogus, "on") == 0))
+ {
+ val_rtrn->uval = 1;
+ return True;
+ }
+ else if ((uStrCaseCmp(bogus, "false") == 0) ||
+ (uStrCaseCmp(bogus, "no") == 0) ||
+ (uStrCaseCmp(bogus, "off") == 0))
+ {
+ val_rtrn->uval = 0;
+ return True;
+ }
+ }
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ None, expr->value.str, TypeBoolean, val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type int is unknown\n",
+ XkbAtomText(NULL, expr->value.str, XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ expr->value.field.element,
+ expr->value.field.field, TypeBoolean, val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type boolean is unknown\n",
+ XkbAtomText(NULL, expr->value.field.element, XkbMessage),
+ XkbAtomText(NULL, expr->value.field.field, XkbMessage));
+ return ok;
+ case OpInvert:
+ case OpNot:
+ ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv);
+ if (ok)
+ val_rtrn->uval = !val_rtrn->uval;
+ return ok;
+ case OpAdd:
+ if (bogus == NULL)
+ bogus = "Addition";
+ case OpSubtract:
+ if (bogus == NULL)
+ bogus = "Subtraction";
+ case OpMultiply:
+ if (bogus == NULL)
+ bogus = "Multiplication";
+ case OpDivide:
+ if (bogus == NULL)
+ bogus = "Division";
+ case OpAssign:
+ if (bogus == NULL)
+ bogus = "Assignment";
+ case OpNegate:
+ if (bogus == NULL)
+ bogus = "Negation";
+ ERROR1("%s of boolean values not permitted\n", bogus);
+ break;
+ case OpUnaryPlus:
+ ERROR("Unary \"+\" operator not permitted for boolean values\n");
+ break;
+ default:
+ WSGO1("Unknown operator %d in ResolveBoolean\n", expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+ExprResolveFloat(ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup, XPointer lookupPriv)
+{
+ int ok = 0;
+ ExprResult leftRtrn, rightRtrn;
+ ExprDef *left, *right;
+
+ switch (expr->op)
+ {
+ case ExprValue:
+ if (expr->type == TypeString)
+ {
+ register char *str;
+ str = XkbAtomGetString(NULL, expr->value.str);
+ if ((str != NULL) && (strlen(str) == 1))
+ {
+ val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
+ return True;
+ }
+ }
+ if ((expr->type != TypeInt) && (expr->type != TypeFloat))
+ {
+ ERROR1("Found constant of type %s, expected a number\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival = expr->value.ival;
+ if (expr->type == TypeInt)
+ val_rtrn->ival *= XkbGeomPtsPerMM;
+ return True;
+ case ExprIdent:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ None, expr->value.str, TypeFloat, val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Numeric identifier \"%s\" unknown\n",
+ XkbAtomText(NULL, expr->value.str, XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ expr->value.field.element,
+ expr->value.field.field, TypeFloat, val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Numeric default \"%s.%s\" unknown\n",
+ XkbAtomText(NULL, expr->value.field.element, XkbMessage),
+ XkbAtomText(NULL, expr->value.field.field, XkbMessage));
+ return ok;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ left = expr->value.binary.left;
+ right = expr->value.binary.right;
+ if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) &&
+ ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv))
+ {
+ switch (expr->op)
+ {
+ case OpAdd:
+ val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
+ break;
+ case OpSubtract:
+ val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
+ break;
+ case OpMultiply:
+ val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
+ break;
+ case OpDivide:
+ val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
+ break;
+ }
+ return True;
+ }
+ return False;
+ case OpAssign:
+ WSGO("Assignment operator not implemented yet\n");
+ break;
+ case OpNot:
+ left = expr->value.child;
+ if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
+ {
+ ERROR("The ! operator cannot be applied to a number\n");
+ }
+ return False;
+ case OpInvert:
+ case OpNegate:
+ left = expr->value.child;
+ if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
+ {
+ if (expr->op == OpNegate)
+ val_rtrn->ival = -leftRtrn.ival;
+ else
+ val_rtrn->ival = ~leftRtrn.ival;
+ return True;
+ }
+ return False;
+ case OpUnaryPlus:
+ left = expr->value.child;
+ return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv);
+ default:
+ WSGO1("Unknown operator %d in ResolveFloat\n", expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+ExprResolveInteger(ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup, XPointer lookupPriv)
+{
+ int ok = 0;
+ ExprResult leftRtrn, rightRtrn;
+ ExprDef *left, *right;
+
+ switch (expr->op)
+ {
+ case ExprValue:
+ if (expr->type == TypeString)
+ {
+ register char *str;
+ str = XkbAtomGetString(NULL, expr->value.str);
+ if (str != NULL)
+ switch (strlen(str))
+ {
+ case 0:
+ val_rtrn->uval = 0;
+ return True;
+ case 1:
+ val_rtrn->uval = str[0];
+ return True;
+ default:
+ break;
+ }
+ }
+ if ((expr->type != TypeInt) && (expr->type != TypeFloat))
+ {
+ ERROR1
+ ("Found constant of type %s where an int was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival = expr->value.ival;
+ if (expr->type == TypeFloat)
+ val_rtrn->ival /= XkbGeomPtsPerMM;
+ return True;
+ case ExprIdent:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ None, expr->value.str, TypeInt, val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type int is unknown\n",
+ XkbAtomText(NULL, expr->value.str, XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ expr->value.field.element,
+ expr->value.field.field, TypeInt, val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type int is unknown\n",
+ XkbAtomText(NULL, expr->value.field.element, XkbMessage),
+ XkbAtomText(NULL, expr->value.field.field, XkbMessage));
+ return ok;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ left = expr->value.binary.left;
+ right = expr->value.binary.right;
+ if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv) &&
+ ExprResolveInteger(right, &rightRtrn, lookup, lookupPriv))
+ {
+ switch (expr->op)
+ {
+ case OpAdd:
+ val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
+ break;
+ case OpSubtract:
+ val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
+ break;
+ case OpMultiply:
+ val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
+ break;
+ case OpDivide:
+ val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
+ break;
+ }
+ return True;
+ }
+ return False;
+ case OpAssign:
+ WSGO("Assignment operator not implemented yet\n");
+ break;
+ case OpNot:
+ left = expr->value.child;
+ if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
+ {
+ ERROR("The ! operator cannot be applied to an integer\n");
+ }
+ return False;
+ case OpInvert:
+ case OpNegate:
+ left = expr->value.child;
+ if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
+ {
+ if (expr->op == OpNegate)
+ val_rtrn->ival = -leftRtrn.ival;
+ else
+ val_rtrn->ival = ~leftRtrn.ival;
+ return True;
+ }
+ return False;
+ case OpUnaryPlus:
+ left = expr->value.child;
+ return ExprResolveInteger(left, val_rtrn, lookup, lookupPriv);
+ default:
+ WSGO1("Unknown operator %d in ResolveInteger\n", expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+ExprResolveString(ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup, XPointer lookupPriv)
+{
+ int ok = 0;
+ ExprResult leftRtrn, rightRtrn;
+ ExprDef *left;
+ ExprDef *right;
+ char *bogus = NULL;
+
+ switch (expr->op)
+ {
+ case ExprValue:
+ if (expr->type != TypeString)
+ {
+ ERROR1("Found constant of type %s, expected a string\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->str = XkbAtomGetString(NULL, expr->value.str);
+ if (val_rtrn->str == NULL)
+ {
+ static char *empty = "";
+ val_rtrn->str = empty;
+ }
+ return True;
+ case ExprIdent:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ None, expr->value.str, TypeString, val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type string not found\n",
+ XkbAtomText(NULL, expr->value.str, XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ expr->value.field.element,
+ expr->value.field.field, TypeString, val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type string not found\n",
+ XkbAtomText(NULL, expr->value.field.element, XkbMessage),
+ XkbAtomText(NULL, expr->value.field.field, XkbMessage));
+ return ok;
+ case OpAdd:
+ left = expr->value.binary.left;
+ right = expr->value.binary.right;
+ if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) &&
+ ExprResolveString(right, &rightRtrn, lookup, lookupPriv))
+ {
+ int len;
+ char *new;
+ len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
+ new = (char *) uAlloc(len);
+ if (new)
+ {
+ sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
+ val_rtrn->str = new;
+ return True;
+ }
+ }
+ return False;
+ case OpSubtract:
+ if (bogus == NULL)
+ bogus = "Subtraction";
+ case OpMultiply:
+ if (bogus == NULL)
+ bogus = "Multiplication";
+ case OpDivide:
+ if (bogus == NULL)
+ bogus = "Division";
+ case OpAssign:
+ if (bogus == NULL)
+ bogus = "Assignment";
+ case OpNegate:
+ if (bogus == NULL)
+ bogus = "Negation";
+ case OpInvert:
+ if (bogus == NULL)
+ bogus = "Bitwise complement";
+ ERROR1("%s of string values not permitted\n", bogus);
+ return False;
+ case OpNot:
+ left = expr->value.child;
+ if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
+ {
+ ERROR("The ! operator cannot be applied to a string\n");
+ }
+ return False;
+ case OpUnaryPlus:
+ left = expr->value.child;
+ if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
+ {
+ ERROR("The + operator cannot be applied to a string\n");
+ }
+ return False;
+ default:
+ WSGO1("Unknown operator %d in ResolveString\n", expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+ExprResolveKeyName(ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup, XPointer lookupPriv)
+{
+ int ok = 0;
+ ExprDef *left;
+ ExprResult leftRtrn;
+ char *bogus = NULL;
+
+ switch (expr->op)
+ {
+ case ExprValue:
+ if (expr->type != TypeKeyName)
+ {
+ ERROR1("Found constant of type %s, expected a key name\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
+ return True;
+ case ExprIdent:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ None, expr->value.str, TypeString, val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type string not found\n",
+ XkbAtomText(NULL, expr->value.str, XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ expr->value.field.element,
+ expr->value.field.field, TypeString, val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type key name not found\n",
+ XkbAtomText(NULL, expr->value.field.element, XkbMessage),
+ XkbAtomText(NULL, expr->value.field.field, XkbMessage));
+ return ok;
+ case OpAdd:
+ if (bogus == NULL)
+ bogus = "Addition";
+ case OpSubtract:
+ if (bogus == NULL)
+ bogus = "Subtraction";
+ case OpMultiply:
+ if (bogus == NULL)
+ bogus = "Multiplication";
+ case OpDivide:
+ if (bogus == NULL)
+ bogus = "Division";
+ case OpAssign:
+ if (bogus == NULL)
+ bogus = "Assignment";
+ case OpNegate:
+ if (bogus == NULL)
+ bogus = "Negation";
+ case OpInvert:
+ if (bogus == NULL)
+ bogus = "Bitwise complement";
+ ERROR1("%s of key name values not permitted\n", bogus);
+ return False;
+ case OpNot:
+ left = expr->value.binary.left;
+ if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
+ {
+ ERROR("The ! operator cannot be applied to a key name\n");
+ }
+ return False;
+ case OpUnaryPlus:
+ left = expr->value.binary.left;
+ if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
+ {
+ ERROR("The + operator cannot be applied to a key name\n");
+ }
+ return False;
+ default:
+ WSGO1("Unknown operator %d in ResolveKeyName\n", expr->op);
+ break;
+ }
+ return False;
+}
+
+/***====================================================================***/
+
+int
+ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
+{
+ if (expr->op != ExprIdent)
+ {
+ ERROR1("Found a %s where an enumerated value was expected\n",
+ exprOpText(expr->op));
+ return False;
+ }
+ if (!SimpleLookup((XPointer) values, (Atom) None, expr->value.str,
+ (unsigned) TypeInt, val_rtrn))
+ {
+ int nOut = 0;
+ ERROR1("Illegal identifier %s (expected one of: ",
+ XkbAtomText(NULL, expr->value.str, XkbMessage));
+ while (values && values->name)
+ {
+ if (nOut != 0)
+ INFO1(", %s", values->name);
+ else
+ INFO1("%s", values->name);
+ values++;
+ nOut++;
+ }
+ INFO(")\n");
+ return False;
+ }
+ return True;
+}
+
+int
+ExprResolveMask(ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup, XPointer lookupPriv)
+{
+ int ok = 0;
+ ExprResult leftRtrn, rightRtrn;
+ ExprDef *left, *right;
+ char *bogus = NULL;
+
+ switch (expr->op)
+ {
+ case ExprValue:
+ if (expr->type != TypeInt)
+ {
+ ERROR1
+ ("Found constant of type %s where a mask was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival = expr->value.ival;
+ return True;
+ case ExprIdent:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ None, expr->value.str, TypeInt, val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type int is unknown\n",
+ XkbAtomText(NULL, expr->value.str, XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup)
+ {
+ ok = (*lookup) (lookupPriv,
+ expr->value.field.element,
+ expr->value.field.field, TypeInt, val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type int is unknown\n",
+ XkbAtomText(NULL, expr->value.field.element, XkbMessage),
+ XkbAtomText(NULL, expr->value.field.field, XkbMessage));
+ return ok;
+ case ExprArrayRef:
+ bogus = "array reference";
+ case ExprActionDecl:
+ if (bogus == NULL)
+ bogus = "function use";
+ ERROR1("Unexpected %s in mask expression\n", bogus);
+ ACTION("Expression ignored\n");
+ return False;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ left = expr->value.binary.left;
+ right = expr->value.binary.right;
+ if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) &&
+ ExprResolveMask(right, &rightRtrn, lookup, lookupPriv))
+ {
+ switch (expr->op)
+ {
+ case OpAdd:
+ val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
+ break;
+ case OpSubtract:
+ val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
+ break;
+ case OpMultiply:
+ case OpDivide:
+ ERROR1("Cannot %s masks\n",
+ expr->op == OpDivide ? "divide" : "multiply");
+ ACTION("Illegal operation ignored\n");
+ return False;
+ }
+ return True;
+ }
+ return False;
+ case OpAssign:
+ WSGO("Assignment operator not implemented yet\n");
+ break;
+ case OpInvert:
+ left = expr->value.child;
+ if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
+ {
+ val_rtrn->ival = ~leftRtrn.ival;
+ return True;
+ }
+ return False;
+ case OpUnaryPlus:
+ case OpNegate:
+ case OpNot:
+ left = expr->value.child;
+ if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
+ {
+ ERROR1("The %s operator cannot be used with a mask\n",
+ (expr->op == OpNegate ? "-" : "!"));
+ }
+ return False;
+ default:
+ WSGO1("Unknown operator %d in ResolveMask\n", expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+ExprResolveKeySym(ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup, XPointer lookupPriv)
+{
+ int ok = 0;
+ KeySym sym;
+
+ if (expr->op == ExprIdent)
+ {
+ char *str;
+ str = XkbAtomGetString(NULL, expr->value.str);
+ if ((str != NULL) && ((sym = XStringToKeysym(str)) != NoSymbol))
+ {
+ val_rtrn->uval = sym;
+ return True;
+ }
+ }
+ ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv);
+ if ((ok) && (val_rtrn->uval < 10))
+ val_rtrn->uval += '0';
+ return ok;
+}