#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:
sprintf(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:
sprintf(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!=None)&&(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!=None)
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;
}