expr.c revision 319fa471
1f46a6179Smrg/************************************************************ 2f46a6179Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3f46a6179Smrg 4f46a6179Smrg Permission to use, copy, modify, and distribute this 5f46a6179Smrg software and its documentation for any purpose and without 6f46a6179Smrg fee is hereby granted, provided that the above copyright 7f46a6179Smrg notice appear in all copies and that both that copyright 8f46a6179Smrg notice and this permission notice appear in supporting 9f46a6179Smrg documentation, and that the name of Silicon Graphics not be 10f46a6179Smrg used in advertising or publicity pertaining to distribution 11f46a6179Smrg of the software without specific prior written permission. 12f46a6179Smrg Silicon Graphics makes no representation about the suitability 13f46a6179Smrg of this software for any purpose. It is provided "as is" 14f46a6179Smrg without any express or implied warranty. 15f46a6179Smrg 16f46a6179Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17f46a6179Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19f46a6179Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20f46a6179Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21f46a6179Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 24f46a6179Smrg 25f46a6179Smrg ********************************************************/ 26f46a6179Smrg 27f46a6179Smrg#include "xkbcomp.h" 28f46a6179Smrg#include "tokens.h" 29f46a6179Smrg#include "expr.h" 30f46a6179Smrg 31f46a6179Smrg#include <ctype.h> 32f46a6179Smrg 33f46a6179Smrg/***====================================================================***/ 34f46a6179Smrg 35f46a6179Smrgchar * 36f46a6179SmrgexprOpText(unsigned type) 37f46a6179Smrg{ 3834345a63Smrg static char buf[32]; 3934345a63Smrg 4034345a63Smrg switch (type) 4134345a63Smrg { 4234345a63Smrg case ExprValue: 4334345a63Smrg strcpy(buf, "literal"); 4434345a63Smrg break; 4534345a63Smrg case ExprIdent: 4634345a63Smrg strcpy(buf, "identifier"); 4734345a63Smrg break; 4834345a63Smrg case ExprActionDecl: 4934345a63Smrg strcpy(buf, "action declaration"); 5034345a63Smrg break; 5134345a63Smrg case ExprFieldRef: 5234345a63Smrg strcpy(buf, "field reference"); 5334345a63Smrg break; 5434345a63Smrg case ExprArrayRef: 5534345a63Smrg strcpy(buf, "array reference"); 5634345a63Smrg break; 5734345a63Smrg case ExprKeysymList: 5834345a63Smrg strcpy(buf, "list of keysyms"); 5934345a63Smrg break; 6034345a63Smrg case ExprActionList: 6134345a63Smrg strcpy(buf, "list of actions"); 6234345a63Smrg break; 6334345a63Smrg case OpAdd: 6434345a63Smrg strcpy(buf, "addition"); 6534345a63Smrg break; 6634345a63Smrg case OpSubtract: 6734345a63Smrg strcpy(buf, "subtraction"); 6834345a63Smrg break; 6934345a63Smrg case OpMultiply: 7034345a63Smrg strcpy(buf, "multiplication"); 7134345a63Smrg break; 7234345a63Smrg case OpDivide: 7334345a63Smrg strcpy(buf, "division"); 7434345a63Smrg break; 7534345a63Smrg case OpAssign: 7634345a63Smrg strcpy(buf, "assignment"); 7734345a63Smrg break; 7834345a63Smrg case OpNot: 7934345a63Smrg strcpy(buf, "logical not"); 8034345a63Smrg break; 8134345a63Smrg case OpNegate: 8234345a63Smrg strcpy(buf, "arithmetic negation"); 8334345a63Smrg break; 8434345a63Smrg case OpInvert: 8534345a63Smrg strcpy(buf, "bitwise inversion"); 8634345a63Smrg break; 8734345a63Smrg case OpUnaryPlus: 8834345a63Smrg strcpy(buf, "plus sign"); 8934345a63Smrg break; 9034345a63Smrg default: 9134345a63Smrg snprintf(buf, sizeof(buf), "illegal(%d)", type); 9234345a63Smrg break; 9334345a63Smrg } 9434345a63Smrg return buf; 95f46a6179Smrg} 96f46a6179Smrg 97f46a6179Smrgchar * 98f46a6179SmrgexprTypeText(unsigned type) 99f46a6179Smrg{ 10034345a63Smrg static char buf[20]; 10134345a63Smrg 10234345a63Smrg switch (type) 10334345a63Smrg { 10434345a63Smrg case TypeUnknown: 10534345a63Smrg strcpy(buf, "unknown"); 10634345a63Smrg break; 10734345a63Smrg case TypeBoolean: 10834345a63Smrg strcpy(buf, "boolean"); 10934345a63Smrg break; 11034345a63Smrg case TypeInt: 11134345a63Smrg strcpy(buf, "int"); 11234345a63Smrg break; 11334345a63Smrg case TypeString: 11434345a63Smrg strcpy(buf, "string"); 11534345a63Smrg break; 11634345a63Smrg case TypeAction: 11734345a63Smrg strcpy(buf, "action"); 11834345a63Smrg break; 11934345a63Smrg case TypeKeyName: 12034345a63Smrg strcpy(buf, "keyname"); 12134345a63Smrg break; 12234345a63Smrg default: 12334345a63Smrg snprintf(buf, sizeof(buf), "illegal(%d)", type); 12434345a63Smrg break; 12534345a63Smrg } 12634345a63Smrg return buf; 127f46a6179Smrg} 128f46a6179Smrg 129f46a6179Smrgint 13034345a63SmrgExprResolveLhs(ExprDef * expr, 13134345a63Smrg ExprResult * elem_rtrn, 13234345a63Smrg ExprResult * field_rtrn, ExprDef ** index_rtrn) 133f46a6179Smrg{ 13434345a63Smrg switch (expr->op) 13534345a63Smrg { 13634345a63Smrg case ExprIdent: 13734345a63Smrg elem_rtrn->str = NULL; 13834345a63Smrg field_rtrn->str = XkbAtomGetString(NULL, expr->value.str); 13934345a63Smrg *index_rtrn = NULL; 14034345a63Smrg return True; 14134345a63Smrg case ExprFieldRef: 14234345a63Smrg elem_rtrn->str = XkbAtomGetString(NULL, expr->value.field.element); 14334345a63Smrg field_rtrn->str = XkbAtomGetString(NULL, expr->value.field.field); 14434345a63Smrg *index_rtrn = NULL; 14534345a63Smrg return True; 14634345a63Smrg case ExprArrayRef: 14734345a63Smrg elem_rtrn->str = XkbAtomGetString(NULL, expr->value.array.element); 14834345a63Smrg field_rtrn->str = XkbAtomGetString(NULL, expr->value.array.field); 14934345a63Smrg *index_rtrn = expr->value.array.entry; 15034345a63Smrg return True; 151f46a6179Smrg } 15234345a63Smrg WSGO1("Unexpected operator %d in ResolveLhs\n", expr->op); 153f46a6179Smrg return False; 154f46a6179Smrg} 155f46a6179Smrg 156f46a6179SmrgBool 15734345a63SmrgSimpleLookup(XPointer priv, 15834345a63Smrg Atom elem, Atom field, unsigned type, ExprResult * val_rtrn) 159f46a6179Smrg{ 16034345a63Smrg LookupEntry *entry; 16134345a63Smrg register char *str; 162f46a6179Smrg 16334345a63Smrg if ((priv == NULL) || 16434345a63Smrg (field == None) || (elem != None) || 16534345a63Smrg ((type != TypeInt) && (type != TypeFloat))) 16634345a63Smrg { 16734345a63Smrg return False; 168f46a6179Smrg } 16934345a63Smrg str = XkbAtomGetString(NULL, field); 17034345a63Smrg for (entry = (LookupEntry *) priv; 17134345a63Smrg (entry != NULL) && (entry->name != NULL); entry++) 17234345a63Smrg { 17334345a63Smrg if (uStrCaseCmp(str, entry->name) == 0) 17434345a63Smrg { 17534345a63Smrg val_rtrn->uval = entry->result; 17634345a63Smrg if (type == TypeFloat) 17734345a63Smrg val_rtrn->uval *= XkbGeomPtsPerMM; 17834345a63Smrg return True; 17934345a63Smrg } 180f46a6179Smrg } 181f46a6179Smrg return False; 182f46a6179Smrg} 183f46a6179Smrg 184f46a6179SmrgBool 18534345a63SmrgRadioLookup(XPointer priv, 18634345a63Smrg Atom elem, Atom field, unsigned type, ExprResult * val_rtrn) 187f46a6179Smrg{ 18834345a63Smrg register char *str; 18934345a63Smrg int rg; 19034345a63Smrg 19134345a63Smrg if ((field == None) || (elem != None) || (type != TypeInt)) 19234345a63Smrg return False; 19334345a63Smrg str = XkbAtomGetString(NULL, field); 19434345a63Smrg if (str) 19534345a63Smrg { 19634345a63Smrg if (uStrCasePrefix("group", str)) 19734345a63Smrg str += strlen("group"); 19834345a63Smrg else if (uStrCasePrefix("radiogroup", str)) 19934345a63Smrg str += strlen("radiogroup"); 20034345a63Smrg else if (uStrCasePrefix("rg", str)) 20134345a63Smrg str += strlen("rg"); 20234345a63Smrg else if (!isdigit(str[0])) 20334345a63Smrg str = NULL; 204f46a6179Smrg } 20534345a63Smrg if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1) 20634345a63Smrg || (rg > XkbMaxRadioGroups)) 20734345a63Smrg return False; 20834345a63Smrg val_rtrn->uval = rg; 209f46a6179Smrg return True; 210f46a6179Smrg} 211f46a6179Smrg 212f46a6179Smrgint 21334345a63SmrgTableLookup(XPointer priv, 21434345a63Smrg Atom elem, Atom field, unsigned type, ExprResult * val_rtrn) 215f46a6179Smrg{ 21634345a63Smrg LookupTable *tbl = (LookupTable *) priv; 21734345a63Smrg register char *str; 21834345a63Smrg 21934345a63Smrg if ((priv == NULL) || (field == None) || (type != TypeInt)) 22034345a63Smrg return False; 22134345a63Smrg str = XkbAtomGetString(NULL, elem); 22234345a63Smrg while (tbl) 22334345a63Smrg { 22434345a63Smrg if (((str == NULL) && (tbl->element == NULL)) || 22534345a63Smrg ((str != NULL) && (tbl->element != NULL) && 22634345a63Smrg (uStrCaseCmp(str, tbl->element) == 0))) 22734345a63Smrg { 22834345a63Smrg break; 22934345a63Smrg } 23034345a63Smrg tbl = tbl->nextElement; 231f46a6179Smrg } 23234345a63Smrg if (tbl == NULL) /* didn't find a matching element */ 23334345a63Smrg return False; 23434345a63Smrg priv = (XPointer) tbl->entries; 23534345a63Smrg return SimpleLookup(priv, (Atom) None, field, type, val_rtrn); 236f46a6179Smrg} 237f46a6179Smrg 238f46a6179Smrgstatic LookupEntry modIndexNames[] = { 23934345a63Smrg {"shift", ShiftMapIndex}, 24034345a63Smrg {"control", ControlMapIndex}, 24134345a63Smrg {"lock", LockMapIndex}, 24234345a63Smrg {"mod1", Mod1MapIndex}, 24334345a63Smrg {"mod2", Mod2MapIndex}, 24434345a63Smrg {"mod3", Mod3MapIndex}, 24534345a63Smrg {"mod4", Mod4MapIndex}, 24634345a63Smrg {"mod5", Mod5MapIndex}, 24734345a63Smrg {"none", XkbNoModifier}, 24834345a63Smrg {NULL, 0} 249f46a6179Smrg}; 250f46a6179Smrg 251f46a6179Smrgint 25234345a63SmrgLookupModIndex(XPointer priv, 25334345a63Smrg Atom elem, Atom field, unsigned type, ExprResult * val_rtrn) 254f46a6179Smrg{ 25534345a63Smrg return SimpleLookup((XPointer) modIndexNames, elem, field, type, 25634345a63Smrg val_rtrn); 257f46a6179Smrg} 258f46a6179Smrg 259f46a6179Smrgint 26034345a63SmrgLookupModMask(XPointer priv, 26134345a63Smrg Atom elem, Atom field, unsigned type, ExprResult * val_rtrn) 262f46a6179Smrg{ 26334345a63Smrg char *str; 26434345a63Smrg 26534345a63Smrg if ((elem != None) || (type != TypeInt)) 26634345a63Smrg return False; 26734345a63Smrg str = XkbAtomGetString(NULL, field); 26834345a63Smrg if (str == NULL) 26934345a63Smrg return False; 27034345a63Smrg if (uStrCaseCmp(str, "all") == 0) 27134345a63Smrg val_rtrn->uval = 0xff; 27234345a63Smrg else if (uStrCaseCmp(str, "none") == 0) 27334345a63Smrg val_rtrn->uval = 0; 27434345a63Smrg else if (LookupModIndex(priv, elem, field, type, val_rtrn)) 27534345a63Smrg val_rtrn->uval = (1 << val_rtrn->uval); 27634345a63Smrg else if (priv != NULL) 27734345a63Smrg { 27834345a63Smrg LookupPriv *lpriv = (LookupPriv *) priv; 27934345a63Smrg if ((lpriv->chain == NULL) || 28034345a63Smrg (!(*lpriv->chain) (lpriv->chainPriv, elem, field, type, 28134345a63Smrg val_rtrn))) 28234345a63Smrg return False; 283f46a6179Smrg } 28434345a63Smrg else 28534345a63Smrg return False; 286f46a6179Smrg return True; 287f46a6179Smrg} 288f46a6179Smrg 289f46a6179Smrgint 29034345a63SmrgExprResolveModIndex(ExprDef * expr, 29134345a63Smrg ExprResult * val_rtrn, 29234345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 293f46a6179Smrg{ 29434345a63Smrg int ok = 0; 295c82dfdfbSmrg const char *bogus = NULL; 29634345a63Smrg 29734345a63Smrg switch (expr->op) 29834345a63Smrg { 29934345a63Smrg case ExprValue: 30034345a63Smrg if (expr->type != TypeInt) 30134345a63Smrg { 30234345a63Smrg ERROR1 30334345a63Smrg ("Found constant of type %s where a modifier mask was expected\n", 30434345a63Smrg exprTypeText(expr->type)); 30534345a63Smrg return False; 30634345a63Smrg } 30734345a63Smrg else if ((expr->value.ival >= XkbNumModifiers) 30834345a63Smrg || (expr->value.ival < 0)) 30934345a63Smrg { 31034345a63Smrg ERROR2("Illegal modifier index (%d, must be 0..%d)\n", 31134345a63Smrg expr->value.ival, XkbNumModifiers - 1); 31234345a63Smrg return False; 31334345a63Smrg } 31434345a63Smrg val_rtrn->ival = expr->value.ival; 31534345a63Smrg return True; 31634345a63Smrg case ExprIdent: 31734345a63Smrg if (LookupModIndex(lookupPriv, (Atom) None, expr->value.str, 31834345a63Smrg (unsigned) TypeInt, val_rtrn)) 31934345a63Smrg { 32034345a63Smrg return True; 32134345a63Smrg } 32234345a63Smrg if (lookup) 32334345a63Smrg { 32434345a63Smrg ok = (*lookup) (lookupPriv, 32534345a63Smrg None, expr->value.str, TypeInt, val_rtrn); 32634345a63Smrg } 32734345a63Smrg if (!ok) 32834345a63Smrg ERROR1("Cannot determine modifier index for \"%s\"\n", 32934345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 33034345a63Smrg break; 33134345a63Smrg case ExprFieldRef: 33234345a63Smrg bogus = "field reference"; 33334345a63Smrg break; 33434345a63Smrg case ExprArrayRef: 33534345a63Smrg bogus = "array reference"; 33634345a63Smrg break; 33734345a63Smrg case ExprActionDecl: 33834345a63Smrg bogus = "function"; 33934345a63Smrg break; 34034345a63Smrg case OpAdd: 34134345a63Smrg case OpSubtract: 34234345a63Smrg case OpMultiply: 34334345a63Smrg case OpDivide: 34434345a63Smrg case OpInvert: 34534345a63Smrg case OpNegate: 34634345a63Smrg case OpNot: 34734345a63Smrg case OpUnaryPlus: 34834345a63Smrg bogus = "arithmetic operations"; 34934345a63Smrg break; 35034345a63Smrg case OpAssign: 35134345a63Smrg bogus = "assignment"; 35234345a63Smrg break; 35334345a63Smrg default: 35434345a63Smrg WSGO1("Unknown operator %d in ResolveModIndex\n", expr->op); 35534345a63Smrg return False; 356f46a6179Smrg } 35734345a63Smrg if (bogus) 35834345a63Smrg { 35934345a63Smrg ERROR1("Modifier index must be a name or number, %s ignored\n", 36034345a63Smrg bogus); 36134345a63Smrg return False; 362f46a6179Smrg } 363f46a6179Smrg return ok; 364f46a6179Smrg} 365f46a6179Smrg 366f46a6179Smrgint 36734345a63SmrgExprResolveModMask(ExprDef * expr, 36834345a63Smrg ExprResult * val_rtrn, 36934345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 370f46a6179Smrg{ 37134345a63Smrg LookupPriv priv; 372f46a6179Smrg 37334345a63Smrg priv.priv = NULL; 37434345a63Smrg priv.chain = lookup; 37534345a63Smrg priv.chainPriv = lookupPriv; 37634345a63Smrg return ExprResolveMask(expr, val_rtrn, LookupModMask, (XPointer) & priv); 377f46a6179Smrg} 378f46a6179Smrg 379f46a6179Smrgint 38034345a63SmrgExprResolveBoolean(ExprDef * expr, 38134345a63Smrg ExprResult * val_rtrn, 38234345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 383f46a6179Smrg{ 38434345a63Smrg int ok = 0; 385c82dfdfbSmrg const char *bogus = NULL; 38634345a63Smrg 38734345a63Smrg switch (expr->op) 38834345a63Smrg { 38934345a63Smrg case ExprValue: 39034345a63Smrg if (expr->type != TypeBoolean) 39134345a63Smrg { 39234345a63Smrg ERROR1 39334345a63Smrg ("Found constant of type %s where boolean was expected\n", 39434345a63Smrg exprTypeText(expr->type)); 39534345a63Smrg return False; 39634345a63Smrg } 39734345a63Smrg val_rtrn->ival = expr->value.ival; 39834345a63Smrg return True; 39934345a63Smrg case ExprIdent: 40034345a63Smrg bogus = XkbAtomGetString(NULL, expr->value.str); 40134345a63Smrg if (bogus) 40234345a63Smrg { 40334345a63Smrg if ((uStrCaseCmp(bogus, "true") == 0) || 40434345a63Smrg (uStrCaseCmp(bogus, "yes") == 0) || 40534345a63Smrg (uStrCaseCmp(bogus, "on") == 0)) 40634345a63Smrg { 40734345a63Smrg val_rtrn->uval = 1; 40834345a63Smrg return True; 40934345a63Smrg } 41034345a63Smrg else if ((uStrCaseCmp(bogus, "false") == 0) || 41134345a63Smrg (uStrCaseCmp(bogus, "no") == 0) || 41234345a63Smrg (uStrCaseCmp(bogus, "off") == 0)) 41334345a63Smrg { 41434345a63Smrg val_rtrn->uval = 0; 41534345a63Smrg return True; 41634345a63Smrg } 41734345a63Smrg } 41834345a63Smrg if (lookup) 41934345a63Smrg { 42034345a63Smrg ok = (*lookup) (lookupPriv, 42134345a63Smrg None, expr->value.str, TypeBoolean, val_rtrn); 42234345a63Smrg } 42334345a63Smrg if (!ok) 42434345a63Smrg ERROR1("Identifier \"%s\" of type int is unknown\n", 42534345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 42634345a63Smrg return ok; 42734345a63Smrg case ExprFieldRef: 42834345a63Smrg if (lookup) 42934345a63Smrg { 43034345a63Smrg ok = (*lookup) (lookupPriv, 43134345a63Smrg expr->value.field.element, 43234345a63Smrg expr->value.field.field, TypeBoolean, val_rtrn); 43334345a63Smrg } 43434345a63Smrg if (!ok) 43534345a63Smrg ERROR2("Default \"%s.%s\" of type boolean is unknown\n", 43634345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 43734345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 43834345a63Smrg return ok; 43934345a63Smrg case OpInvert: 44034345a63Smrg case OpNot: 44134345a63Smrg ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv); 44234345a63Smrg if (ok) 44334345a63Smrg val_rtrn->uval = !val_rtrn->uval; 44434345a63Smrg return ok; 44534345a63Smrg case OpAdd: 44634345a63Smrg if (bogus == NULL) 44734345a63Smrg bogus = "Addition"; 44834345a63Smrg case OpSubtract: 44934345a63Smrg if (bogus == NULL) 45034345a63Smrg bogus = "Subtraction"; 45134345a63Smrg case OpMultiply: 45234345a63Smrg if (bogus == NULL) 45334345a63Smrg bogus = "Multiplication"; 45434345a63Smrg case OpDivide: 45534345a63Smrg if (bogus == NULL) 45634345a63Smrg bogus = "Division"; 45734345a63Smrg case OpAssign: 45834345a63Smrg if (bogus == NULL) 45934345a63Smrg bogus = "Assignment"; 46034345a63Smrg case OpNegate: 46134345a63Smrg if (bogus == NULL) 46234345a63Smrg bogus = "Negation"; 46334345a63Smrg ERROR1("%s of boolean values not permitted\n", bogus); 46434345a63Smrg break; 46534345a63Smrg case OpUnaryPlus: 46634345a63Smrg ERROR("Unary \"+\" operator not permitted for boolean values\n"); 46734345a63Smrg break; 46834345a63Smrg default: 46934345a63Smrg WSGO1("Unknown operator %d in ResolveBoolean\n", expr->op); 47034345a63Smrg break; 471f46a6179Smrg } 472f46a6179Smrg return False; 473f46a6179Smrg} 474f46a6179Smrg 475f46a6179Smrgint 47634345a63SmrgExprResolveFloat(ExprDef * expr, 47734345a63Smrg ExprResult * val_rtrn, 47834345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 479f46a6179Smrg{ 48034345a63Smrg int ok = 0; 48134345a63Smrg ExprResult leftRtrn, rightRtrn; 48234345a63Smrg ExprDef *left, *right; 48334345a63Smrg 48434345a63Smrg switch (expr->op) 48534345a63Smrg { 48634345a63Smrg case ExprValue: 48734345a63Smrg if (expr->type == TypeString) 48834345a63Smrg { 48934345a63Smrg register char *str; 49034345a63Smrg str = XkbAtomGetString(NULL, expr->value.str); 49134345a63Smrg if ((str != NULL) && (strlen(str) == 1)) 49234345a63Smrg { 49334345a63Smrg val_rtrn->uval = str[0] * XkbGeomPtsPerMM; 49434345a63Smrg return True; 49534345a63Smrg } 49634345a63Smrg } 49734345a63Smrg if ((expr->type != TypeInt) && (expr->type != TypeFloat)) 49834345a63Smrg { 49934345a63Smrg ERROR1("Found constant of type %s, expected a number\n", 50034345a63Smrg exprTypeText(expr->type)); 50134345a63Smrg return False; 50234345a63Smrg } 50334345a63Smrg val_rtrn->ival = expr->value.ival; 50434345a63Smrg if (expr->type == TypeInt) 50534345a63Smrg val_rtrn->ival *= XkbGeomPtsPerMM; 50634345a63Smrg return True; 50734345a63Smrg case ExprIdent: 50834345a63Smrg if (lookup) 50934345a63Smrg { 51034345a63Smrg ok = (*lookup) (lookupPriv, 51134345a63Smrg None, expr->value.str, TypeFloat, val_rtrn); 51234345a63Smrg } 51334345a63Smrg if (!ok) 51434345a63Smrg ERROR1("Numeric identifier \"%s\" unknown\n", 51534345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 51634345a63Smrg return ok; 51734345a63Smrg case ExprFieldRef: 51834345a63Smrg if (lookup) 51934345a63Smrg { 52034345a63Smrg ok = (*lookup) (lookupPriv, 52134345a63Smrg expr->value.field.element, 52234345a63Smrg expr->value.field.field, TypeFloat, val_rtrn); 52334345a63Smrg } 52434345a63Smrg if (!ok) 52534345a63Smrg ERROR2("Numeric default \"%s.%s\" unknown\n", 52634345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 52734345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 52834345a63Smrg return ok; 52934345a63Smrg case OpAdd: 53034345a63Smrg case OpSubtract: 53134345a63Smrg case OpMultiply: 53234345a63Smrg case OpDivide: 53334345a63Smrg left = expr->value.binary.left; 53434345a63Smrg right = expr->value.binary.right; 53534345a63Smrg if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) && 53634345a63Smrg ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv)) 53734345a63Smrg { 53834345a63Smrg switch (expr->op) 53934345a63Smrg { 54034345a63Smrg case OpAdd: 54134345a63Smrg val_rtrn->ival = leftRtrn.ival + rightRtrn.ival; 54234345a63Smrg break; 54334345a63Smrg case OpSubtract: 54434345a63Smrg val_rtrn->ival = leftRtrn.ival - rightRtrn.ival; 54534345a63Smrg break; 54634345a63Smrg case OpMultiply: 54734345a63Smrg val_rtrn->ival = leftRtrn.ival * rightRtrn.ival; 54834345a63Smrg break; 54934345a63Smrg case OpDivide: 55034345a63Smrg val_rtrn->ival = leftRtrn.ival / rightRtrn.ival; 55134345a63Smrg break; 55234345a63Smrg } 55334345a63Smrg return True; 55434345a63Smrg } 55534345a63Smrg return False; 55634345a63Smrg case OpAssign: 55734345a63Smrg WSGO("Assignment operator not implemented yet\n"); 55834345a63Smrg break; 55934345a63Smrg case OpNot: 56034345a63Smrg left = expr->value.child; 56134345a63Smrg if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv)) 56234345a63Smrg { 56334345a63Smrg ERROR("The ! operator cannot be applied to a number\n"); 56434345a63Smrg } 56534345a63Smrg return False; 56634345a63Smrg case OpInvert: 56734345a63Smrg case OpNegate: 56834345a63Smrg left = expr->value.child; 56934345a63Smrg if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv)) 57034345a63Smrg { 57134345a63Smrg if (expr->op == OpNegate) 57234345a63Smrg val_rtrn->ival = -leftRtrn.ival; 57334345a63Smrg else 57434345a63Smrg val_rtrn->ival = ~leftRtrn.ival; 57534345a63Smrg return True; 57634345a63Smrg } 57734345a63Smrg return False; 57834345a63Smrg case OpUnaryPlus: 57934345a63Smrg left = expr->value.child; 58034345a63Smrg return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv); 58134345a63Smrg default: 58234345a63Smrg WSGO1("Unknown operator %d in ResolveFloat\n", expr->op); 58334345a63Smrg break; 584f46a6179Smrg } 585f46a6179Smrg return False; 586f46a6179Smrg} 587f46a6179Smrg 588f46a6179Smrgint 58934345a63SmrgExprResolveInteger(ExprDef * expr, 59034345a63Smrg ExprResult * val_rtrn, 59134345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 592f46a6179Smrg{ 59334345a63Smrg int ok = 0; 59434345a63Smrg ExprResult leftRtrn, rightRtrn; 59534345a63Smrg ExprDef *left, *right; 59634345a63Smrg 59734345a63Smrg switch (expr->op) 59834345a63Smrg { 59934345a63Smrg case ExprValue: 60034345a63Smrg if (expr->type == TypeString) 60134345a63Smrg { 60234345a63Smrg register char *str; 60334345a63Smrg str = XkbAtomGetString(NULL, expr->value.str); 60434345a63Smrg if (str != NULL) 60534345a63Smrg switch (strlen(str)) 60634345a63Smrg { 60734345a63Smrg case 0: 60834345a63Smrg val_rtrn->uval = 0; 60934345a63Smrg return True; 61034345a63Smrg case 1: 61134345a63Smrg val_rtrn->uval = str[0]; 61234345a63Smrg return True; 61334345a63Smrg default: 61434345a63Smrg break; 61534345a63Smrg } 61634345a63Smrg } 61734345a63Smrg if ((expr->type != TypeInt) && (expr->type != TypeFloat)) 61834345a63Smrg { 61934345a63Smrg ERROR1 62034345a63Smrg ("Found constant of type %s where an int was expected\n", 62134345a63Smrg exprTypeText(expr->type)); 62234345a63Smrg return False; 62334345a63Smrg } 62434345a63Smrg val_rtrn->ival = expr->value.ival; 62534345a63Smrg if (expr->type == TypeFloat) 62634345a63Smrg val_rtrn->ival /= XkbGeomPtsPerMM; 62734345a63Smrg return True; 62834345a63Smrg case ExprIdent: 62934345a63Smrg if (lookup) 63034345a63Smrg { 63134345a63Smrg ok = (*lookup) (lookupPriv, 63234345a63Smrg None, expr->value.str, TypeInt, val_rtrn); 63334345a63Smrg } 63434345a63Smrg if (!ok) 63534345a63Smrg ERROR1("Identifier \"%s\" of type int is unknown\n", 63634345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 63734345a63Smrg return ok; 63834345a63Smrg case ExprFieldRef: 63934345a63Smrg if (lookup) 64034345a63Smrg { 64134345a63Smrg ok = (*lookup) (lookupPriv, 64234345a63Smrg expr->value.field.element, 64334345a63Smrg expr->value.field.field, TypeInt, val_rtrn); 64434345a63Smrg } 64534345a63Smrg if (!ok) 64634345a63Smrg ERROR2("Default \"%s.%s\" of type int is unknown\n", 64734345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 64834345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 64934345a63Smrg return ok; 65034345a63Smrg case OpAdd: 65134345a63Smrg case OpSubtract: 65234345a63Smrg case OpMultiply: 65334345a63Smrg case OpDivide: 65434345a63Smrg left = expr->value.binary.left; 65534345a63Smrg right = expr->value.binary.right; 65634345a63Smrg if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv) && 65734345a63Smrg ExprResolveInteger(right, &rightRtrn, lookup, lookupPriv)) 65834345a63Smrg { 65934345a63Smrg switch (expr->op) 66034345a63Smrg { 66134345a63Smrg case OpAdd: 66234345a63Smrg val_rtrn->ival = leftRtrn.ival + rightRtrn.ival; 66334345a63Smrg break; 66434345a63Smrg case OpSubtract: 66534345a63Smrg val_rtrn->ival = leftRtrn.ival - rightRtrn.ival; 66634345a63Smrg break; 66734345a63Smrg case OpMultiply: 66834345a63Smrg val_rtrn->ival = leftRtrn.ival * rightRtrn.ival; 66934345a63Smrg break; 67034345a63Smrg case OpDivide: 67134345a63Smrg val_rtrn->ival = leftRtrn.ival / rightRtrn.ival; 67234345a63Smrg break; 67334345a63Smrg } 67434345a63Smrg return True; 67534345a63Smrg } 67634345a63Smrg return False; 67734345a63Smrg case OpAssign: 67834345a63Smrg WSGO("Assignment operator not implemented yet\n"); 67934345a63Smrg break; 68034345a63Smrg case OpNot: 68134345a63Smrg left = expr->value.child; 68234345a63Smrg if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv)) 68334345a63Smrg { 68434345a63Smrg ERROR("The ! operator cannot be applied to an integer\n"); 68534345a63Smrg } 68634345a63Smrg return False; 68734345a63Smrg case OpInvert: 68834345a63Smrg case OpNegate: 68934345a63Smrg left = expr->value.child; 69034345a63Smrg if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv)) 69134345a63Smrg { 69234345a63Smrg if (expr->op == OpNegate) 69334345a63Smrg val_rtrn->ival = -leftRtrn.ival; 69434345a63Smrg else 69534345a63Smrg val_rtrn->ival = ~leftRtrn.ival; 69634345a63Smrg return True; 69734345a63Smrg } 69834345a63Smrg return False; 69934345a63Smrg case OpUnaryPlus: 70034345a63Smrg left = expr->value.child; 70134345a63Smrg return ExprResolveInteger(left, val_rtrn, lookup, lookupPriv); 70234345a63Smrg default: 70334345a63Smrg WSGO1("Unknown operator %d in ResolveInteger\n", expr->op); 70434345a63Smrg break; 705f46a6179Smrg } 706f46a6179Smrg return False; 707f46a6179Smrg} 708f46a6179Smrg 709f46a6179Smrgint 71034345a63SmrgExprResolveString(ExprDef * expr, 71134345a63Smrg ExprResult * val_rtrn, 71234345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 713f46a6179Smrg{ 71434345a63Smrg int ok = 0; 71534345a63Smrg ExprResult leftRtrn, rightRtrn; 71634345a63Smrg ExprDef *left; 71734345a63Smrg ExprDef *right; 718c82dfdfbSmrg const char *bogus = NULL; 71934345a63Smrg 72034345a63Smrg switch (expr->op) 72134345a63Smrg { 72234345a63Smrg case ExprValue: 72334345a63Smrg if (expr->type != TypeString) 72434345a63Smrg { 72534345a63Smrg ERROR1("Found constant of type %s, expected a string\n", 72634345a63Smrg exprTypeText(expr->type)); 72734345a63Smrg return False; 72834345a63Smrg } 72934345a63Smrg val_rtrn->str = XkbAtomGetString(NULL, expr->value.str); 73034345a63Smrg if (val_rtrn->str == NULL) 73134345a63Smrg { 732319fa471Smrg static char empty_char = '\0'; 733319fa471Smrg val_rtrn->str = &empty_char; 73434345a63Smrg } 73534345a63Smrg return True; 73634345a63Smrg case ExprIdent: 73734345a63Smrg if (lookup) 73834345a63Smrg { 73934345a63Smrg ok = (*lookup) (lookupPriv, 74034345a63Smrg None, expr->value.str, TypeString, val_rtrn); 74134345a63Smrg } 74234345a63Smrg if (!ok) 74334345a63Smrg ERROR1("Identifier \"%s\" of type string not found\n", 74434345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 74534345a63Smrg return ok; 74634345a63Smrg case ExprFieldRef: 74734345a63Smrg if (lookup) 74834345a63Smrg { 74934345a63Smrg ok = (*lookup) (lookupPriv, 75034345a63Smrg expr->value.field.element, 75134345a63Smrg expr->value.field.field, TypeString, val_rtrn); 75234345a63Smrg } 75334345a63Smrg if (!ok) 75434345a63Smrg ERROR2("Default \"%s.%s\" of type string not found\n", 75534345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 75634345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 75734345a63Smrg return ok; 75834345a63Smrg case OpAdd: 75934345a63Smrg left = expr->value.binary.left; 76034345a63Smrg right = expr->value.binary.right; 76134345a63Smrg if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) && 76234345a63Smrg ExprResolveString(right, &rightRtrn, lookup, lookupPriv)) 76334345a63Smrg { 76434345a63Smrg int len; 76534345a63Smrg char *new; 76634345a63Smrg len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1; 76734345a63Smrg new = (char *) uAlloc(len); 76834345a63Smrg if (new) 76934345a63Smrg { 770c82dfdfbSmrg snprintf(new, len, "%s%s", leftRtrn.str, rightRtrn.str); 77134345a63Smrg val_rtrn->str = new; 77234345a63Smrg return True; 77334345a63Smrg } 77434345a63Smrg } 77534345a63Smrg return False; 77634345a63Smrg case OpSubtract: 77734345a63Smrg if (bogus == NULL) 77834345a63Smrg bogus = "Subtraction"; 77934345a63Smrg case OpMultiply: 78034345a63Smrg if (bogus == NULL) 78134345a63Smrg bogus = "Multiplication"; 78234345a63Smrg case OpDivide: 78334345a63Smrg if (bogus == NULL) 78434345a63Smrg bogus = "Division"; 78534345a63Smrg case OpAssign: 78634345a63Smrg if (bogus == NULL) 78734345a63Smrg bogus = "Assignment"; 78834345a63Smrg case OpNegate: 78934345a63Smrg if (bogus == NULL) 79034345a63Smrg bogus = "Negation"; 79134345a63Smrg case OpInvert: 79234345a63Smrg if (bogus == NULL) 79334345a63Smrg bogus = "Bitwise complement"; 79434345a63Smrg ERROR1("%s of string values not permitted\n", bogus); 79534345a63Smrg return False; 79634345a63Smrg case OpNot: 79734345a63Smrg left = expr->value.child; 79834345a63Smrg if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv)) 79934345a63Smrg { 80034345a63Smrg ERROR("The ! operator cannot be applied to a string\n"); 80134345a63Smrg } 80234345a63Smrg return False; 80334345a63Smrg case OpUnaryPlus: 80434345a63Smrg left = expr->value.child; 80534345a63Smrg if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv)) 80634345a63Smrg { 80734345a63Smrg ERROR("The + operator cannot be applied to a string\n"); 80834345a63Smrg } 80934345a63Smrg return False; 81034345a63Smrg default: 81134345a63Smrg WSGO1("Unknown operator %d in ResolveString\n", expr->op); 81234345a63Smrg break; 813f46a6179Smrg } 814f46a6179Smrg return False; 815f46a6179Smrg} 816f46a6179Smrg 817f46a6179Smrgint 81834345a63SmrgExprResolveKeyName(ExprDef * expr, 81934345a63Smrg ExprResult * val_rtrn, 82034345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 821f46a6179Smrg{ 82234345a63Smrg int ok = 0; 82334345a63Smrg ExprDef *left; 82434345a63Smrg ExprResult leftRtrn; 825c82dfdfbSmrg const char *bogus = NULL; 82634345a63Smrg 82734345a63Smrg switch (expr->op) 82834345a63Smrg { 82934345a63Smrg case ExprValue: 83034345a63Smrg if (expr->type != TypeKeyName) 83134345a63Smrg { 83234345a63Smrg ERROR1("Found constant of type %s, expected a key name\n", 83334345a63Smrg exprTypeText(expr->type)); 83434345a63Smrg return False; 83534345a63Smrg } 83634345a63Smrg memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength); 83734345a63Smrg return True; 83834345a63Smrg case ExprIdent: 83934345a63Smrg if (lookup) 84034345a63Smrg { 84134345a63Smrg ok = (*lookup) (lookupPriv, 84234345a63Smrg None, expr->value.str, TypeString, val_rtrn); 84334345a63Smrg } 84434345a63Smrg if (!ok) 84534345a63Smrg ERROR1("Identifier \"%s\" of type string not found\n", 84634345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 84734345a63Smrg return ok; 84834345a63Smrg case ExprFieldRef: 84934345a63Smrg if (lookup) 85034345a63Smrg { 85134345a63Smrg ok = (*lookup) (lookupPriv, 85234345a63Smrg expr->value.field.element, 85334345a63Smrg expr->value.field.field, TypeString, val_rtrn); 85434345a63Smrg } 85534345a63Smrg if (!ok) 85634345a63Smrg ERROR2("Default \"%s.%s\" of type key name not found\n", 85734345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 85834345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 85934345a63Smrg return ok; 86034345a63Smrg case OpAdd: 86134345a63Smrg if (bogus == NULL) 86234345a63Smrg bogus = "Addition"; 86334345a63Smrg case OpSubtract: 86434345a63Smrg if (bogus == NULL) 86534345a63Smrg bogus = "Subtraction"; 86634345a63Smrg case OpMultiply: 86734345a63Smrg if (bogus == NULL) 86834345a63Smrg bogus = "Multiplication"; 86934345a63Smrg case OpDivide: 87034345a63Smrg if (bogus == NULL) 87134345a63Smrg bogus = "Division"; 87234345a63Smrg case OpAssign: 87334345a63Smrg if (bogus == NULL) 87434345a63Smrg bogus = "Assignment"; 87534345a63Smrg case OpNegate: 87634345a63Smrg if (bogus == NULL) 87734345a63Smrg bogus = "Negation"; 87834345a63Smrg case OpInvert: 87934345a63Smrg if (bogus == NULL) 88034345a63Smrg bogus = "Bitwise complement"; 88134345a63Smrg ERROR1("%s of key name values not permitted\n", bogus); 88234345a63Smrg return False; 88334345a63Smrg case OpNot: 88434345a63Smrg left = expr->value.binary.left; 88534345a63Smrg if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv)) 88634345a63Smrg { 88734345a63Smrg ERROR("The ! operator cannot be applied to a key name\n"); 88834345a63Smrg } 88934345a63Smrg return False; 89034345a63Smrg case OpUnaryPlus: 89134345a63Smrg left = expr->value.binary.left; 89234345a63Smrg if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv)) 89334345a63Smrg { 89434345a63Smrg ERROR("The + operator cannot be applied to a key name\n"); 89534345a63Smrg } 89634345a63Smrg return False; 89734345a63Smrg default: 89834345a63Smrg WSGO1("Unknown operator %d in ResolveKeyName\n", expr->op); 89934345a63Smrg break; 900f46a6179Smrg } 901f46a6179Smrg return False; 902f46a6179Smrg} 903f46a6179Smrg 904f46a6179Smrg/***====================================================================***/ 905f46a6179Smrg 906f46a6179Smrgint 90734345a63SmrgExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values) 908f46a6179Smrg{ 90934345a63Smrg if (expr->op != ExprIdent) 91034345a63Smrg { 91134345a63Smrg ERROR1("Found a %s where an enumerated value was expected\n", 91234345a63Smrg exprOpText(expr->op)); 91334345a63Smrg return False; 914f46a6179Smrg } 91534345a63Smrg if (!SimpleLookup((XPointer) values, (Atom) None, expr->value.str, 91634345a63Smrg (unsigned) TypeInt, val_rtrn)) 91734345a63Smrg { 91834345a63Smrg int nOut = 0; 91934345a63Smrg ERROR1("Illegal identifier %s (expected one of: ", 92034345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 92134345a63Smrg while (values && values->name) 92234345a63Smrg { 92334345a63Smrg if (nOut != 0) 92434345a63Smrg INFO1(", %s", values->name); 92534345a63Smrg else 92634345a63Smrg INFO1("%s", values->name); 92734345a63Smrg values++; 92834345a63Smrg nOut++; 92934345a63Smrg } 93034345a63Smrg INFO(")\n"); 93134345a63Smrg return False; 932f46a6179Smrg } 933f46a6179Smrg return True; 934f46a6179Smrg} 935f46a6179Smrg 936f46a6179Smrgint 93734345a63SmrgExprResolveMask(ExprDef * expr, 93834345a63Smrg ExprResult * val_rtrn, 93934345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 940f46a6179Smrg{ 94134345a63Smrg int ok = 0; 94234345a63Smrg ExprResult leftRtrn, rightRtrn; 94334345a63Smrg ExprDef *left, *right; 944c82dfdfbSmrg const char *bogus = NULL; 94534345a63Smrg 94634345a63Smrg switch (expr->op) 94734345a63Smrg { 94834345a63Smrg case ExprValue: 94934345a63Smrg if (expr->type != TypeInt) 95034345a63Smrg { 95134345a63Smrg ERROR1 95234345a63Smrg ("Found constant of type %s where a mask was expected\n", 95334345a63Smrg exprTypeText(expr->type)); 95434345a63Smrg return False; 95534345a63Smrg } 95634345a63Smrg val_rtrn->ival = expr->value.ival; 95734345a63Smrg return True; 95834345a63Smrg case ExprIdent: 95934345a63Smrg if (lookup) 96034345a63Smrg { 96134345a63Smrg ok = (*lookup) (lookupPriv, 96234345a63Smrg None, expr->value.str, TypeInt, val_rtrn); 96334345a63Smrg } 96434345a63Smrg if (!ok) 96534345a63Smrg ERROR1("Identifier \"%s\" of type int is unknown\n", 96634345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 96734345a63Smrg return ok; 96834345a63Smrg case ExprFieldRef: 96934345a63Smrg if (lookup) 97034345a63Smrg { 97134345a63Smrg ok = (*lookup) (lookupPriv, 97234345a63Smrg expr->value.field.element, 97334345a63Smrg expr->value.field.field, TypeInt, val_rtrn); 97434345a63Smrg } 97534345a63Smrg if (!ok) 97634345a63Smrg ERROR2("Default \"%s.%s\" of type int is unknown\n", 97734345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 97834345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 97934345a63Smrg return ok; 98034345a63Smrg case ExprArrayRef: 98134345a63Smrg bogus = "array reference"; 98234345a63Smrg case ExprActionDecl: 98334345a63Smrg if (bogus == NULL) 98434345a63Smrg bogus = "function use"; 98534345a63Smrg ERROR1("Unexpected %s in mask expression\n", bogus); 98634345a63Smrg ACTION("Expression ignored\n"); 98734345a63Smrg return False; 98834345a63Smrg case OpAdd: 98934345a63Smrg case OpSubtract: 99034345a63Smrg case OpMultiply: 99134345a63Smrg case OpDivide: 99234345a63Smrg left = expr->value.binary.left; 99334345a63Smrg right = expr->value.binary.right; 99434345a63Smrg if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) && 99534345a63Smrg ExprResolveMask(right, &rightRtrn, lookup, lookupPriv)) 99634345a63Smrg { 99734345a63Smrg switch (expr->op) 99834345a63Smrg { 99934345a63Smrg case OpAdd: 100034345a63Smrg val_rtrn->ival = leftRtrn.ival | rightRtrn.ival; 100134345a63Smrg break; 100234345a63Smrg case OpSubtract: 100334345a63Smrg val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival); 100434345a63Smrg break; 100534345a63Smrg case OpMultiply: 100634345a63Smrg case OpDivide: 100734345a63Smrg ERROR1("Cannot %s masks\n", 100834345a63Smrg expr->op == OpDivide ? "divide" : "multiply"); 100934345a63Smrg ACTION("Illegal operation ignored\n"); 101034345a63Smrg return False; 101134345a63Smrg } 101234345a63Smrg return True; 101334345a63Smrg } 101434345a63Smrg return False; 101534345a63Smrg case OpAssign: 101634345a63Smrg WSGO("Assignment operator not implemented yet\n"); 101734345a63Smrg break; 101834345a63Smrg case OpInvert: 101934345a63Smrg left = expr->value.child; 102034345a63Smrg if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv)) 102134345a63Smrg { 102234345a63Smrg val_rtrn->ival = ~leftRtrn.ival; 102334345a63Smrg return True; 102434345a63Smrg } 102534345a63Smrg return False; 102634345a63Smrg case OpUnaryPlus: 102734345a63Smrg case OpNegate: 102834345a63Smrg case OpNot: 102934345a63Smrg left = expr->value.child; 103034345a63Smrg if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv)) 103134345a63Smrg { 103234345a63Smrg ERROR1("The %s operator cannot be used with a mask\n", 103334345a63Smrg (expr->op == OpNegate ? "-" : "!")); 103434345a63Smrg } 103534345a63Smrg return False; 103634345a63Smrg default: 103734345a63Smrg WSGO1("Unknown operator %d in ResolveMask\n", expr->op); 103834345a63Smrg break; 1039f46a6179Smrg } 1040f46a6179Smrg return False; 1041f46a6179Smrg} 1042f46a6179Smrg 1043f46a6179Smrgint 104434345a63SmrgExprResolveKeySym(ExprDef * expr, 104534345a63Smrg ExprResult * val_rtrn, 104634345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 1047f46a6179Smrg{ 104834345a63Smrg int ok = 0; 104934345a63Smrg KeySym sym; 105034345a63Smrg 105134345a63Smrg if (expr->op == ExprIdent) 105234345a63Smrg { 105334345a63Smrg char *str; 105434345a63Smrg str = XkbAtomGetString(NULL, expr->value.str); 105534345a63Smrg if ((str != NULL) && ((sym = XStringToKeysym(str)) != NoSymbol)) 105634345a63Smrg { 105734345a63Smrg val_rtrn->uval = sym; 105834345a63Smrg return True; 105934345a63Smrg } 1060f46a6179Smrg } 106134345a63Smrg ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv); 106234345a63Smrg if ((ok) && (val_rtrn->uval < 10)) 106334345a63Smrg val_rtrn->uval += '0'; 1064f46a6179Smrg return ok; 1065f46a6179Smrg} 1066