#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)
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;
}