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 9370d0a5eSmrg documentation, and that the name of Silicon Graphics not be 10370d0a5eSmrg used in advertising or publicity pertaining to distribution 11f46a6179Smrg of the software without specific prior written permission. 12370d0a5eSmrg 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. 15370d0a5eSmrg 16370d0a5eSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17370d0a5eSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19370d0a5eSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20370d0a5eSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21370d0a5eSmrg 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 976ae2c069Smrgstatic char * 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 1306ae2c069SmrgExprResolveLhs(const ExprDef *expr, ExprResult *elem_rtrn, 1316ae2c069Smrg ExprResult *field_rtrn, ExprDef **index_rtrn) 132f46a6179Smrg{ 13334345a63Smrg switch (expr->op) 13434345a63Smrg { 13534345a63Smrg case ExprIdent: 13634345a63Smrg elem_rtrn->str = NULL; 13734345a63Smrg field_rtrn->str = XkbAtomGetString(NULL, expr->value.str); 13834345a63Smrg *index_rtrn = NULL; 13934345a63Smrg return True; 14034345a63Smrg case ExprFieldRef: 14134345a63Smrg elem_rtrn->str = XkbAtomGetString(NULL, expr->value.field.element); 14234345a63Smrg field_rtrn->str = XkbAtomGetString(NULL, expr->value.field.field); 14334345a63Smrg *index_rtrn = NULL; 14434345a63Smrg return True; 14534345a63Smrg case ExprArrayRef: 14634345a63Smrg elem_rtrn->str = XkbAtomGetString(NULL, expr->value.array.element); 14734345a63Smrg field_rtrn->str = XkbAtomGetString(NULL, expr->value.array.field); 14834345a63Smrg *index_rtrn = expr->value.array.entry; 14934345a63Smrg return True; 150f46a6179Smrg } 151370d0a5eSmrg WSGO("Unexpected operator %d in ResolveLhs\n", expr->op); 152f46a6179Smrg return False; 153f46a6179Smrg} 154f46a6179Smrg 155f46a6179SmrgBool 1566ae2c069SmrgSimpleLookup(const XPointer priv, 1576ae2c069Smrg Atom elem, Atom field, unsigned type, ExprResult *val_rtrn) 158f46a6179Smrg{ 1596ae2c069Smrg char *str; 160f46a6179Smrg 16134345a63Smrg if ((priv == NULL) || 16234345a63Smrg (field == None) || (elem != None) || 16334345a63Smrg ((type != TypeInt) && (type != TypeFloat))) 16434345a63Smrg { 16534345a63Smrg return False; 166f46a6179Smrg } 16734345a63Smrg str = XkbAtomGetString(NULL, field); 1686ae2c069Smrg for (const LookupEntry *entry = (const LookupEntry *) priv; 16934345a63Smrg (entry != NULL) && (entry->name != NULL); entry++) 17034345a63Smrg { 17134345a63Smrg if (uStrCaseCmp(str, entry->name) == 0) 17234345a63Smrg { 17334345a63Smrg val_rtrn->uval = entry->result; 17434345a63Smrg if (type == TypeFloat) 17534345a63Smrg val_rtrn->uval *= XkbGeomPtsPerMM; 17634345a63Smrg return True; 17734345a63Smrg } 178f46a6179Smrg } 179f46a6179Smrg return False; 180f46a6179Smrg} 181f46a6179Smrg 182f46a6179SmrgBool 1836ae2c069SmrgRadioLookup(const XPointer priv, 1846ae2c069Smrg Atom elem, Atom field, unsigned type, ExprResult *val_rtrn) 185f46a6179Smrg{ 1866ae2c069Smrg char *str; 18734345a63Smrg int rg; 18834345a63Smrg 18934345a63Smrg if ((field == None) || (elem != None) || (type != TypeInt)) 19034345a63Smrg return False; 19134345a63Smrg str = XkbAtomGetString(NULL, field); 19234345a63Smrg if (str) 19334345a63Smrg { 19434345a63Smrg if (uStrCasePrefix("group", str)) 19534345a63Smrg str += strlen("group"); 19634345a63Smrg else if (uStrCasePrefix("radiogroup", str)) 19734345a63Smrg str += strlen("radiogroup"); 19834345a63Smrg else if (uStrCasePrefix("rg", str)) 19934345a63Smrg str += strlen("rg"); 20034345a63Smrg else if (!isdigit(str[0])) 20134345a63Smrg str = NULL; 202f46a6179Smrg } 20334345a63Smrg if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1) 20434345a63Smrg || (rg > XkbMaxRadioGroups)) 20534345a63Smrg return False; 20634345a63Smrg val_rtrn->uval = rg; 207f46a6179Smrg return True; 208f46a6179Smrg} 209f46a6179Smrg 2106ae2c069Smrg#if 0 2116ae2c069Smrgstatic int 21234345a63SmrgTableLookup(XPointer priv, 21334345a63Smrg Atom elem, Atom field, unsigned type, ExprResult * val_rtrn) 214f46a6179Smrg{ 21534345a63Smrg LookupTable *tbl = (LookupTable *) priv; 2166ae2c069Smrg char *str; 21734345a63Smrg 21834345a63Smrg if ((priv == NULL) || (field == None) || (type != TypeInt)) 21934345a63Smrg return False; 22034345a63Smrg str = XkbAtomGetString(NULL, elem); 22134345a63Smrg while (tbl) 22234345a63Smrg { 22334345a63Smrg if (((str == NULL) && (tbl->element == NULL)) || 22434345a63Smrg ((str != NULL) && (tbl->element != NULL) && 22534345a63Smrg (uStrCaseCmp(str, tbl->element) == 0))) 22634345a63Smrg { 22734345a63Smrg break; 22834345a63Smrg } 22934345a63Smrg tbl = tbl->nextElement; 230f46a6179Smrg } 23134345a63Smrg if (tbl == NULL) /* didn't find a matching element */ 23234345a63Smrg return False; 23334345a63Smrg priv = (XPointer) tbl->entries; 23434345a63Smrg return SimpleLookup(priv, (Atom) None, field, type, val_rtrn); 235f46a6179Smrg} 2366ae2c069Smrg#endif 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 2516ae2c069SmrgBool 2526ae2c069SmrgLookupModIndex(const XPointer priv, 2536ae2c069Smrg Atom elem, Atom field, unsigned type, ExprResult *val_rtrn) 254f46a6179Smrg{ 25534345a63Smrg return SimpleLookup((XPointer) modIndexNames, elem, field, type, 25634345a63Smrg val_rtrn); 257f46a6179Smrg} 258f46a6179Smrg 2596ae2c069Smrgstatic int 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)) 2756ae2c069Smrg val_rtrn->uval = (1U << 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 2896ae2c069Smrg#if 0 290f46a6179Smrgint 2916ae2c069SmrgExprResolveModIndex(const ExprDef *expr, 29234345a63Smrg ExprResult * val_rtrn, 29334345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 294f46a6179Smrg{ 29534345a63Smrg int ok = 0; 296c82dfdfbSmrg const char *bogus = NULL; 29734345a63Smrg 29834345a63Smrg switch (expr->op) 29934345a63Smrg { 30034345a63Smrg case ExprValue: 30134345a63Smrg if (expr->type != TypeInt) 30234345a63Smrg { 303370d0a5eSmrg ERROR 30434345a63Smrg ("Found constant of type %s where a modifier mask was expected\n", 30534345a63Smrg exprTypeText(expr->type)); 30634345a63Smrg return False; 30734345a63Smrg } 30834345a63Smrg else if ((expr->value.ival >= XkbNumModifiers) 30934345a63Smrg || (expr->value.ival < 0)) 31034345a63Smrg { 311370d0a5eSmrg ERROR("Illegal modifier index (%d, must be 0..%d)\n", 31234345a63Smrg expr->value.ival, XkbNumModifiers - 1); 31334345a63Smrg return False; 31434345a63Smrg } 31534345a63Smrg val_rtrn->ival = expr->value.ival; 31634345a63Smrg return True; 31734345a63Smrg case ExprIdent: 31834345a63Smrg if (LookupModIndex(lookupPriv, (Atom) None, expr->value.str, 31934345a63Smrg (unsigned) TypeInt, val_rtrn)) 32034345a63Smrg { 32134345a63Smrg return True; 32234345a63Smrg } 32334345a63Smrg if (lookup) 32434345a63Smrg { 32534345a63Smrg ok = (*lookup) (lookupPriv, 32634345a63Smrg None, expr->value.str, TypeInt, val_rtrn); 32734345a63Smrg } 32834345a63Smrg if (!ok) 329370d0a5eSmrg ERROR("Cannot determine modifier index for \"%s\"\n", 33034345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 33134345a63Smrg break; 33234345a63Smrg case ExprFieldRef: 33334345a63Smrg bogus = "field reference"; 33434345a63Smrg break; 33534345a63Smrg case ExprArrayRef: 33634345a63Smrg bogus = "array reference"; 33734345a63Smrg break; 33834345a63Smrg case ExprActionDecl: 33934345a63Smrg bogus = "function"; 34034345a63Smrg break; 34134345a63Smrg case OpAdd: 34234345a63Smrg case OpSubtract: 34334345a63Smrg case OpMultiply: 34434345a63Smrg case OpDivide: 34534345a63Smrg case OpInvert: 34634345a63Smrg case OpNegate: 34734345a63Smrg case OpNot: 34834345a63Smrg case OpUnaryPlus: 34934345a63Smrg bogus = "arithmetic operations"; 35034345a63Smrg break; 35134345a63Smrg case OpAssign: 35234345a63Smrg bogus = "assignment"; 35334345a63Smrg break; 35434345a63Smrg default: 355370d0a5eSmrg WSGO("Unknown operator %d in ResolveModIndex\n", expr->op); 35634345a63Smrg return False; 357f46a6179Smrg } 35834345a63Smrg if (bogus) 35934345a63Smrg { 360370d0a5eSmrg ERROR("Modifier index must be a name or number, %s ignored\n", 36134345a63Smrg bogus); 36234345a63Smrg return False; 363f46a6179Smrg } 364f46a6179Smrg return ok; 365f46a6179Smrg} 3666ae2c069Smrg#endif 367f46a6179Smrg 368f46a6179Smrgint 3696ae2c069SmrgExprResolveModMask(const ExprDef *expr, ExprResult *val_rtrn, 37034345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 371f46a6179Smrg{ 3726ae2c069Smrg LookupPriv priv = { 3736ae2c069Smrg .priv = NULL, 3746ae2c069Smrg .chain = lookup, 3756ae2c069Smrg .chainPriv = lookupPriv 3766ae2c069Smrg }; 377f46a6179Smrg 3786ae2c069Smrg return ExprResolveMask(expr, val_rtrn, LookupModMask, (XPointer) &priv); 379f46a6179Smrg} 380f46a6179Smrg 381f46a6179Smrgint 3826ae2c069SmrgExprResolveBoolean(const ExprDef *expr, ExprResult *val_rtrn, 38334345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 384f46a6179Smrg{ 38534345a63Smrg int ok = 0; 386c82dfdfbSmrg const char *bogus = NULL; 38734345a63Smrg 38834345a63Smrg switch (expr->op) 38934345a63Smrg { 39034345a63Smrg case ExprValue: 39134345a63Smrg if (expr->type != TypeBoolean) 39234345a63Smrg { 393370d0a5eSmrg ERROR 39434345a63Smrg ("Found constant of type %s where boolean was expected\n", 39534345a63Smrg exprTypeText(expr->type)); 39634345a63Smrg return False; 39734345a63Smrg } 39834345a63Smrg val_rtrn->ival = expr->value.ival; 39934345a63Smrg return True; 40034345a63Smrg case ExprIdent: 40134345a63Smrg bogus = XkbAtomGetString(NULL, expr->value.str); 40234345a63Smrg if (bogus) 40334345a63Smrg { 40434345a63Smrg if ((uStrCaseCmp(bogus, "true") == 0) || 40534345a63Smrg (uStrCaseCmp(bogus, "yes") == 0) || 40634345a63Smrg (uStrCaseCmp(bogus, "on") == 0)) 40734345a63Smrg { 40834345a63Smrg val_rtrn->uval = 1; 40934345a63Smrg return True; 41034345a63Smrg } 41134345a63Smrg else if ((uStrCaseCmp(bogus, "false") == 0) || 41234345a63Smrg (uStrCaseCmp(bogus, "no") == 0) || 41334345a63Smrg (uStrCaseCmp(bogus, "off") == 0)) 41434345a63Smrg { 41534345a63Smrg val_rtrn->uval = 0; 41634345a63Smrg return True; 41734345a63Smrg } 41834345a63Smrg } 41934345a63Smrg if (lookup) 42034345a63Smrg { 42134345a63Smrg ok = (*lookup) (lookupPriv, 42234345a63Smrg None, expr->value.str, TypeBoolean, val_rtrn); 42334345a63Smrg } 42434345a63Smrg if (!ok) 425370d0a5eSmrg ERROR("Identifier \"%s\" of type int is unknown\n", 42634345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 42734345a63Smrg return ok; 42834345a63Smrg case ExprFieldRef: 42934345a63Smrg if (lookup) 43034345a63Smrg { 43134345a63Smrg ok = (*lookup) (lookupPriv, 43234345a63Smrg expr->value.field.element, 43334345a63Smrg expr->value.field.field, TypeBoolean, val_rtrn); 43434345a63Smrg } 43534345a63Smrg if (!ok) 436370d0a5eSmrg ERROR("Default \"%s.%s\" of type boolean is unknown\n", 43734345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 43834345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 43934345a63Smrg return ok; 44034345a63Smrg case OpInvert: 44134345a63Smrg case OpNot: 44234345a63Smrg ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv); 44334345a63Smrg if (ok) 44434345a63Smrg val_rtrn->uval = !val_rtrn->uval; 44534345a63Smrg return ok; 44634345a63Smrg case OpAdd: 4476ae2c069Smrg bogus = "Addition"; 4486ae2c069Smrg goto boolean; 44934345a63Smrg case OpSubtract: 4506ae2c069Smrg bogus = "Subtraction"; 4516ae2c069Smrg goto boolean; 45234345a63Smrg case OpMultiply: 4536ae2c069Smrg bogus = "Multiplication"; 4546ae2c069Smrg goto boolean; 45534345a63Smrg case OpDivide: 4566ae2c069Smrg bogus = "Division"; 4576ae2c069Smrg goto boolean; 45834345a63Smrg case OpAssign: 4596ae2c069Smrg bogus = "Assignment"; 4606ae2c069Smrg goto boolean; 46134345a63Smrg case OpNegate: 4626ae2c069Smrg bogus = "Negation"; 4636ae2c069Smrg goto boolean; 4646ae2c069Smrg boolean: 465370d0a5eSmrg ERROR("%s of boolean values not permitted\n", bogus); 46634345a63Smrg break; 46734345a63Smrg case OpUnaryPlus: 46834345a63Smrg ERROR("Unary \"+\" operator not permitted for boolean values\n"); 46934345a63Smrg break; 47034345a63Smrg default: 471370d0a5eSmrg WSGO("Unknown operator %d in ResolveBoolean\n", expr->op); 47234345a63Smrg break; 473f46a6179Smrg } 474f46a6179Smrg return False; 475f46a6179Smrg} 476f46a6179Smrg 477f46a6179Smrgint 4786ae2c069SmrgExprResolveFloat(const ExprDef *expr, ExprResult *val_rtrn, 47934345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 480f46a6179Smrg{ 48134345a63Smrg int ok = 0; 48234345a63Smrg ExprResult leftRtrn, rightRtrn; 48334345a63Smrg ExprDef *left, *right; 48434345a63Smrg 48534345a63Smrg switch (expr->op) 48634345a63Smrg { 48734345a63Smrg case ExprValue: 48834345a63Smrg if (expr->type == TypeString) 48934345a63Smrg { 4906ae2c069Smrg char *str; 49134345a63Smrg str = XkbAtomGetString(NULL, expr->value.str); 49234345a63Smrg if ((str != NULL) && (strlen(str) == 1)) 49334345a63Smrg { 49434345a63Smrg val_rtrn->uval = str[0] * XkbGeomPtsPerMM; 49534345a63Smrg return True; 49634345a63Smrg } 49734345a63Smrg } 49834345a63Smrg if ((expr->type != TypeInt) && (expr->type != TypeFloat)) 49934345a63Smrg { 500370d0a5eSmrg ERROR("Found constant of type %s, expected a number\n", 50134345a63Smrg exprTypeText(expr->type)); 50234345a63Smrg return False; 50334345a63Smrg } 50434345a63Smrg val_rtrn->ival = expr->value.ival; 50534345a63Smrg if (expr->type == TypeInt) 50634345a63Smrg val_rtrn->ival *= XkbGeomPtsPerMM; 50734345a63Smrg return True; 50834345a63Smrg case ExprIdent: 50934345a63Smrg if (lookup) 51034345a63Smrg { 51134345a63Smrg ok = (*lookup) (lookupPriv, 51234345a63Smrg None, expr->value.str, TypeFloat, val_rtrn); 51334345a63Smrg } 51434345a63Smrg if (!ok) 515370d0a5eSmrg ERROR("Numeric identifier \"%s\" unknown\n", 51634345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 51734345a63Smrg return ok; 51834345a63Smrg case ExprFieldRef: 51934345a63Smrg if (lookup) 52034345a63Smrg { 52134345a63Smrg ok = (*lookup) (lookupPriv, 52234345a63Smrg expr->value.field.element, 52334345a63Smrg expr->value.field.field, TypeFloat, val_rtrn); 52434345a63Smrg } 52534345a63Smrg if (!ok) 526370d0a5eSmrg ERROR("Numeric default \"%s.%s\" unknown\n", 52734345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 52834345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 52934345a63Smrg return ok; 53034345a63Smrg case OpAdd: 53134345a63Smrg case OpSubtract: 53234345a63Smrg case OpMultiply: 53334345a63Smrg case OpDivide: 53434345a63Smrg left = expr->value.binary.left; 53534345a63Smrg right = expr->value.binary.right; 53634345a63Smrg if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) && 53734345a63Smrg ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv)) 53834345a63Smrg { 53934345a63Smrg switch (expr->op) 54034345a63Smrg { 54134345a63Smrg case OpAdd: 54234345a63Smrg val_rtrn->ival = leftRtrn.ival + rightRtrn.ival; 54334345a63Smrg break; 54434345a63Smrg case OpSubtract: 54534345a63Smrg val_rtrn->ival = leftRtrn.ival - rightRtrn.ival; 54634345a63Smrg break; 54734345a63Smrg case OpMultiply: 54834345a63Smrg val_rtrn->ival = leftRtrn.ival * rightRtrn.ival; 54934345a63Smrg break; 55034345a63Smrg case OpDivide: 55134345a63Smrg val_rtrn->ival = leftRtrn.ival / rightRtrn.ival; 55234345a63Smrg break; 55334345a63Smrg } 55434345a63Smrg return True; 55534345a63Smrg } 55634345a63Smrg return False; 55734345a63Smrg case OpAssign: 55834345a63Smrg WSGO("Assignment operator not implemented yet\n"); 55934345a63Smrg break; 56034345a63Smrg case OpNot: 56134345a63Smrg left = expr->value.child; 56234345a63Smrg if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv)) 56334345a63Smrg { 56434345a63Smrg ERROR("The ! operator cannot be applied to a number\n"); 56534345a63Smrg } 56634345a63Smrg return False; 56734345a63Smrg case OpInvert: 56834345a63Smrg case OpNegate: 56934345a63Smrg left = expr->value.child; 57034345a63Smrg if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv)) 57134345a63Smrg { 57234345a63Smrg if (expr->op == OpNegate) 57334345a63Smrg val_rtrn->ival = -leftRtrn.ival; 57434345a63Smrg else 57534345a63Smrg val_rtrn->ival = ~leftRtrn.ival; 57634345a63Smrg return True; 57734345a63Smrg } 57834345a63Smrg return False; 57934345a63Smrg case OpUnaryPlus: 58034345a63Smrg left = expr->value.child; 58134345a63Smrg return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv); 58234345a63Smrg default: 583370d0a5eSmrg WSGO("Unknown operator %d in ResolveFloat\n", expr->op); 58434345a63Smrg break; 585f46a6179Smrg } 586f46a6179Smrg return False; 587f46a6179Smrg} 588f46a6179Smrg 589f46a6179Smrgint 5906ae2c069SmrgExprResolveInteger(const ExprDef *expr, 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 { 6026ae2c069Smrg 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 { 619370d0a5eSmrg ERROR 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) 635370d0a5eSmrg ERROR("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) 646370d0a5eSmrg ERROR("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: 703370d0a5eSmrg WSGO("Unknown operator %d in ResolveInteger\n", expr->op); 70434345a63Smrg break; 705f46a6179Smrg } 706f46a6179Smrg return False; 707f46a6179Smrg} 708f46a6179Smrg 709f46a6179Smrgint 7106ae2c069SmrgExprResolveString(const ExprDef *expr, ExprResult *val_rtrn, 71134345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 712f46a6179Smrg{ 71334345a63Smrg int ok = 0; 71434345a63Smrg ExprResult leftRtrn, rightRtrn; 71534345a63Smrg ExprDef *left; 71634345a63Smrg ExprDef *right; 717c82dfdfbSmrg const char *bogus = NULL; 71834345a63Smrg 71934345a63Smrg switch (expr->op) 72034345a63Smrg { 72134345a63Smrg case ExprValue: 72234345a63Smrg if (expr->type != TypeString) 72334345a63Smrg { 724370d0a5eSmrg ERROR("Found constant of type %s, expected a string\n", 72534345a63Smrg exprTypeText(expr->type)); 72634345a63Smrg return False; 72734345a63Smrg } 72834345a63Smrg val_rtrn->str = XkbAtomGetString(NULL, expr->value.str); 72934345a63Smrg if (val_rtrn->str == NULL) 73034345a63Smrg { 731319fa471Smrg static char empty_char = '\0'; 732319fa471Smrg val_rtrn->str = &empty_char; 73334345a63Smrg } 73434345a63Smrg return True; 73534345a63Smrg case ExprIdent: 73634345a63Smrg if (lookup) 73734345a63Smrg { 73834345a63Smrg ok = (*lookup) (lookupPriv, 73934345a63Smrg None, expr->value.str, TypeString, val_rtrn); 74034345a63Smrg } 74134345a63Smrg if (!ok) 742370d0a5eSmrg ERROR("Identifier \"%s\" of type string not found\n", 74334345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 74434345a63Smrg return ok; 74534345a63Smrg case ExprFieldRef: 74634345a63Smrg if (lookup) 74734345a63Smrg { 74834345a63Smrg ok = (*lookup) (lookupPriv, 74934345a63Smrg expr->value.field.element, 75034345a63Smrg expr->value.field.field, TypeString, val_rtrn); 75134345a63Smrg } 75234345a63Smrg if (!ok) 753370d0a5eSmrg ERROR("Default \"%s.%s\" of type string not found\n", 75434345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 75534345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 75634345a63Smrg return ok; 75734345a63Smrg case OpAdd: 75834345a63Smrg left = expr->value.binary.left; 75934345a63Smrg right = expr->value.binary.right; 76034345a63Smrg if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) && 76134345a63Smrg ExprResolveString(right, &rightRtrn, lookup, lookupPriv)) 76234345a63Smrg { 76334345a63Smrg char *new; 7646ae2c069Smrg 7656ae2c069Smrg#ifdef HAVE_ASPRINTF 7666ae2c069Smrg if (asprintf(&new, "%s%s", leftRtrn.str, rightRtrn.str) < 0) 7676ae2c069Smrg new = NULL; 7686ae2c069Smrg#else 7696ae2c069Smrg size_t len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1; 7706ae2c069Smrg new = malloc(len); 7716ae2c069Smrg#endif 77234345a63Smrg if (new) 77334345a63Smrg { 7746ae2c069Smrg#ifndef HAVE_ASPRINTF 775c82dfdfbSmrg snprintf(new, len, "%s%s", leftRtrn.str, rightRtrn.str); 7766ae2c069Smrg#endif 77734345a63Smrg val_rtrn->str = new; 77834345a63Smrg return True; 77934345a63Smrg } 78034345a63Smrg } 78134345a63Smrg return False; 78234345a63Smrg case OpSubtract: 7836ae2c069Smrg bogus = "Subtraction"; 7846ae2c069Smrg goto string; 78534345a63Smrg case OpMultiply: 7866ae2c069Smrg bogus = "Multiplication"; 7876ae2c069Smrg goto string; 78834345a63Smrg case OpDivide: 7896ae2c069Smrg bogus = "Division"; 7906ae2c069Smrg goto string; 79134345a63Smrg case OpAssign: 7926ae2c069Smrg bogus = "Assignment"; 7936ae2c069Smrg goto string; 79434345a63Smrg case OpNegate: 7956ae2c069Smrg bogus = "Negation"; 7966ae2c069Smrg goto string; 79734345a63Smrg case OpInvert: 7986ae2c069Smrg bogus = "Bitwise complement"; 7996ae2c069Smrg goto string; 8006ae2c069Smrg string: 801370d0a5eSmrg ERROR("%s of string values not permitted\n", bogus); 80234345a63Smrg return False; 80334345a63Smrg case OpNot: 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 case OpUnaryPlus: 81134345a63Smrg left = expr->value.child; 81234345a63Smrg if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv)) 81334345a63Smrg { 81434345a63Smrg ERROR("The + operator cannot be applied to a string\n"); 81534345a63Smrg } 81634345a63Smrg return False; 81734345a63Smrg default: 818370d0a5eSmrg WSGO("Unknown operator %d in ResolveString\n", expr->op); 81934345a63Smrg break; 820f46a6179Smrg } 821f46a6179Smrg return False; 822f46a6179Smrg} 823f46a6179Smrg 824f46a6179Smrgint 8256ae2c069SmrgExprResolveKeyName(const ExprDef *expr, ExprResult *val_rtrn, 82634345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 827f46a6179Smrg{ 82834345a63Smrg int ok = 0; 82934345a63Smrg ExprDef *left; 83034345a63Smrg ExprResult leftRtrn; 831c82dfdfbSmrg const char *bogus = NULL; 83234345a63Smrg 83334345a63Smrg switch (expr->op) 83434345a63Smrg { 83534345a63Smrg case ExprValue: 83634345a63Smrg if (expr->type != TypeKeyName) 83734345a63Smrg { 838370d0a5eSmrg ERROR("Found constant of type %s, expected a key name\n", 83934345a63Smrg exprTypeText(expr->type)); 84034345a63Smrg return False; 84134345a63Smrg } 84234345a63Smrg memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength); 84334345a63Smrg return True; 84434345a63Smrg case ExprIdent: 84534345a63Smrg if (lookup) 84634345a63Smrg { 84734345a63Smrg ok = (*lookup) (lookupPriv, 84834345a63Smrg None, expr->value.str, TypeString, val_rtrn); 84934345a63Smrg } 85034345a63Smrg if (!ok) 851370d0a5eSmrg ERROR("Identifier \"%s\" of type string not found\n", 85234345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 85334345a63Smrg return ok; 85434345a63Smrg case ExprFieldRef: 85534345a63Smrg if (lookup) 85634345a63Smrg { 85734345a63Smrg ok = (*lookup) (lookupPriv, 85834345a63Smrg expr->value.field.element, 85934345a63Smrg expr->value.field.field, TypeString, val_rtrn); 86034345a63Smrg } 86134345a63Smrg if (!ok) 862370d0a5eSmrg ERROR("Default \"%s.%s\" of type key name not found\n", 86334345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 86434345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 86534345a63Smrg return ok; 86634345a63Smrg case OpAdd: 8676ae2c069Smrg bogus = "Addition"; 8686ae2c069Smrg goto keyname; 86934345a63Smrg case OpSubtract: 8706ae2c069Smrg bogus = "Subtraction"; 8716ae2c069Smrg goto keyname; 87234345a63Smrg case OpMultiply: 8736ae2c069Smrg bogus = "Multiplication"; 8746ae2c069Smrg goto keyname; 87534345a63Smrg case OpDivide: 8766ae2c069Smrg bogus = "Division"; 8776ae2c069Smrg goto keyname; 87834345a63Smrg case OpAssign: 8796ae2c069Smrg bogus = "Assignment"; 8806ae2c069Smrg goto keyname; 88134345a63Smrg case OpNegate: 8826ae2c069Smrg bogus = "Negation"; 8836ae2c069Smrg goto keyname; 88434345a63Smrg case OpInvert: 8856ae2c069Smrg bogus = "Bitwise complement"; 8866ae2c069Smrg goto keyname; 8876ae2c069Smrg keyname: 888370d0a5eSmrg ERROR("%s of key name values not permitted\n", bogus); 88934345a63Smrg return False; 89034345a63Smrg case OpNot: 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 case OpUnaryPlus: 89834345a63Smrg left = expr->value.binary.left; 89934345a63Smrg if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv)) 90034345a63Smrg { 90134345a63Smrg ERROR("The + operator cannot be applied to a key name\n"); 90234345a63Smrg } 90334345a63Smrg return False; 90434345a63Smrg default: 905370d0a5eSmrg WSGO("Unknown operator %d in ResolveKeyName\n", expr->op); 90634345a63Smrg break; 907f46a6179Smrg } 908f46a6179Smrg return False; 909f46a6179Smrg} 910f46a6179Smrg 911f46a6179Smrg/***====================================================================***/ 912f46a6179Smrg 913f46a6179Smrgint 9146ae2c069SmrgExprResolveEnum(const ExprDef *expr, ExprResult *val_rtrn, 9156ae2c069Smrg const LookupEntry *values) 916f46a6179Smrg{ 91734345a63Smrg if (expr->op != ExprIdent) 91834345a63Smrg { 919370d0a5eSmrg ERROR("Found a %s where an enumerated value was expected\n", 92034345a63Smrg exprOpText(expr->op)); 92134345a63Smrg return False; 922f46a6179Smrg } 92334345a63Smrg if (!SimpleLookup((XPointer) values, (Atom) None, expr->value.str, 92434345a63Smrg (unsigned) TypeInt, val_rtrn)) 92534345a63Smrg { 92634345a63Smrg int nOut = 0; 927370d0a5eSmrg ERROR("Illegal identifier %s (expected one of: ", 92834345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 92934345a63Smrg while (values && values->name) 93034345a63Smrg { 93134345a63Smrg if (nOut != 0) 932370d0a5eSmrg INFO(", %s", values->name); 93334345a63Smrg else 934370d0a5eSmrg INFO("%s", values->name); 93534345a63Smrg values++; 93634345a63Smrg nOut++; 93734345a63Smrg } 93834345a63Smrg INFO(")\n"); 93934345a63Smrg return False; 940f46a6179Smrg } 941f46a6179Smrg return True; 942f46a6179Smrg} 943f46a6179Smrg 944f46a6179Smrgint 9456ae2c069SmrgExprResolveMask(const ExprDef *expr, ExprResult *val_rtrn, 94634345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 947f46a6179Smrg{ 94834345a63Smrg int ok = 0; 94934345a63Smrg ExprResult leftRtrn, rightRtrn; 9506ae2c069Smrg const ExprDef *left, *right; 951c82dfdfbSmrg const char *bogus = NULL; 95234345a63Smrg 95334345a63Smrg switch (expr->op) 95434345a63Smrg { 95534345a63Smrg case ExprValue: 95634345a63Smrg if (expr->type != TypeInt) 95734345a63Smrg { 958370d0a5eSmrg ERROR 95934345a63Smrg ("Found constant of type %s where a mask was expected\n", 96034345a63Smrg exprTypeText(expr->type)); 96134345a63Smrg return False; 96234345a63Smrg } 96334345a63Smrg val_rtrn->ival = expr->value.ival; 96434345a63Smrg return True; 96534345a63Smrg case ExprIdent: 96634345a63Smrg if (lookup) 96734345a63Smrg { 96834345a63Smrg ok = (*lookup) (lookupPriv, 96934345a63Smrg None, expr->value.str, TypeInt, val_rtrn); 97034345a63Smrg } 97134345a63Smrg if (!ok) 972370d0a5eSmrg ERROR("Identifier \"%s\" of type int is unknown\n", 97334345a63Smrg XkbAtomText(NULL, expr->value.str, XkbMessage)); 97434345a63Smrg return ok; 97534345a63Smrg case ExprFieldRef: 97634345a63Smrg if (lookup) 97734345a63Smrg { 97834345a63Smrg ok = (*lookup) (lookupPriv, 97934345a63Smrg expr->value.field.element, 98034345a63Smrg expr->value.field.field, TypeInt, val_rtrn); 98134345a63Smrg } 98234345a63Smrg if (!ok) 983370d0a5eSmrg ERROR("Default \"%s.%s\" of type int is unknown\n", 98434345a63Smrg XkbAtomText(NULL, expr->value.field.element, XkbMessage), 98534345a63Smrg XkbAtomText(NULL, expr->value.field.field, XkbMessage)); 98634345a63Smrg return ok; 98734345a63Smrg case ExprArrayRef: 98834345a63Smrg bogus = "array reference"; 9896ae2c069Smrg goto unexpected_mask; 99034345a63Smrg case ExprActionDecl: 9916ae2c069Smrg bogus = "function use"; 9926ae2c069Smrg goto unexpected_mask; 9936ae2c069Smrg unexpected_mask: 994370d0a5eSmrg ERROR("Unexpected %s in mask expression\n", bogus); 99534345a63Smrg ACTION("Expression ignored\n"); 99634345a63Smrg return False; 99734345a63Smrg case OpAdd: 99834345a63Smrg case OpSubtract: 99934345a63Smrg case OpMultiply: 100034345a63Smrg case OpDivide: 100134345a63Smrg left = expr->value.binary.left; 100234345a63Smrg right = expr->value.binary.right; 100334345a63Smrg if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) && 100434345a63Smrg ExprResolveMask(right, &rightRtrn, lookup, lookupPriv)) 100534345a63Smrg { 100634345a63Smrg switch (expr->op) 100734345a63Smrg { 100834345a63Smrg case OpAdd: 100934345a63Smrg val_rtrn->ival = leftRtrn.ival | rightRtrn.ival; 101034345a63Smrg break; 101134345a63Smrg case OpSubtract: 101234345a63Smrg val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival); 101334345a63Smrg break; 101434345a63Smrg case OpMultiply: 101534345a63Smrg case OpDivide: 1016370d0a5eSmrg ERROR("Cannot %s masks\n", 101734345a63Smrg expr->op == OpDivide ? "divide" : "multiply"); 101834345a63Smrg ACTION("Illegal operation ignored\n"); 101934345a63Smrg return False; 102034345a63Smrg } 102134345a63Smrg return True; 102234345a63Smrg } 102334345a63Smrg return False; 102434345a63Smrg case OpAssign: 102534345a63Smrg WSGO("Assignment operator not implemented yet\n"); 102634345a63Smrg break; 102734345a63Smrg case OpInvert: 102834345a63Smrg left = expr->value.child; 102934345a63Smrg if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv)) 103034345a63Smrg { 103134345a63Smrg val_rtrn->ival = ~leftRtrn.ival; 103234345a63Smrg return True; 103334345a63Smrg } 103434345a63Smrg return False; 103534345a63Smrg case OpUnaryPlus: 103634345a63Smrg case OpNegate: 103734345a63Smrg case OpNot: 103834345a63Smrg left = expr->value.child; 103934345a63Smrg if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv)) 104034345a63Smrg { 1041370d0a5eSmrg ERROR("The %s operator cannot be used with a mask\n", 104234345a63Smrg (expr->op == OpNegate ? "-" : "!")); 104334345a63Smrg } 104434345a63Smrg return False; 104534345a63Smrg default: 1046370d0a5eSmrg WSGO("Unknown operator %d in ResolveMask\n", expr->op); 104734345a63Smrg break; 1048f46a6179Smrg } 1049f46a6179Smrg return False; 1050f46a6179Smrg} 1051f46a6179Smrg 1052f46a6179Smrgint 10536ae2c069SmrgExprResolveKeySym(const ExprDef *expr, ExprResult *val_rtrn, 105434345a63Smrg IdentLookupFunc lookup, XPointer lookupPriv) 1055f46a6179Smrg{ 105634345a63Smrg int ok = 0; 105734345a63Smrg 105834345a63Smrg if (expr->op == ExprIdent) 105934345a63Smrg { 10606ae2c069Smrg const char *str; 10616ae2c069Smrg KeySym sym; 10626ae2c069Smrg 106334345a63Smrg str = XkbAtomGetString(NULL, expr->value.str); 106434345a63Smrg if ((str != NULL) && ((sym = XStringToKeysym(str)) != NoSymbol)) 106534345a63Smrg { 106634345a63Smrg val_rtrn->uval = sym; 106734345a63Smrg return True; 106834345a63Smrg } 1069f46a6179Smrg } 107034345a63Smrg ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv); 107134345a63Smrg if ((ok) && (val_rtrn->uval < 10)) 107234345a63Smrg val_rtrn->uval += '0'; 1073f46a6179Smrg return ok; 1074f46a6179Smrg} 1075