X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fxkbcomp%2Fexpr.c;h=dcf6eadd3297f4f928d5ebd355e89e5831745bbd;hb=eafd3aceca97d4984070115ec67f639b045b0d65;hp=96fd95675aed36e551fb97ef6760b240d35f0632;hpb=0c1bbb05d975cf7b3411259900500cc122fc136b;p=platform%2Fupstream%2Flibxkbcommon.git diff --git a/src/xkbcomp/expr.c b/src/xkbcomp/expr.c index 96fd956..558fef3 100644 --- a/src/xkbcomp/expr.c +++ b/src/xkbcomp/expr.c @@ -1,1065 +1,718 @@ /************************************************************ - Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. - - Permission to use, copy, modify, and distribute this - software and its documentation for any purpose and without - fee is hereby granted, provided that the above copyright - notice appear in all copies and that both that copyright - notice and this permission notice appear in supporting - documentation, and that the name of Silicon Graphics not be - used in advertising or publicity pertaining to distribution - of the software without specific prior written permission. - Silicon Graphics makes no representation about the suitability - of this software for any purpose. It is provided "as is" - without any express or implied warranty. - - SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON - GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH - THE USE OR PERFORMANCE OF THIS SOFTWARE. - + * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of Silicon Graphics not be + * used in advertising or publicity pertaining to distribution + * of the software without specific prior written permission. + * Silicon Graphics makes no representation about the suitability + * of this software for any purpose. It is provided "as is" + * without any express or implied warranty. + * + * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH + * THE USE OR PERFORMANCE OF THIS SOFTWARE. + * ********************************************************/ -#include "xkbcomp.h" -#include "tokens.h" -#include "expr.h" +#include "config.h" -#include +#include "xkbcomp-priv.h" +#include "text.h" +#include "expr.h" +#include "keysym.h" -/***====================================================================***/ +typedef bool (*IdentLookupFunc)(struct xkb_context *ctx, const void *priv, + xkb_atom_t field, enum expr_value_type type, + unsigned int *val_rtrn); -char * -exprOpText(unsigned type) +bool +ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr, + const char **elem_rtrn, const char **field_rtrn, + ExprDef **index_rtrn) { - 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; + switch (expr->expr.op) { + case EXPR_IDENT: + *elem_rtrn = NULL; + *field_rtrn = xkb_atom_text(ctx, expr->ident.ident); + *index_rtrn = NULL; + return (*field_rtrn != NULL); + case EXPR_FIELD_REF: + *elem_rtrn = xkb_atom_text(ctx, expr->field_ref.element); + *field_rtrn = xkb_atom_text(ctx, expr->field_ref.field); + *index_rtrn = NULL; + return (*elem_rtrn != NULL && *field_rtrn != NULL); + case EXPR_ARRAY_REF: + *elem_rtrn = xkb_atom_text(ctx, expr->array_ref.element); + *field_rtrn = xkb_atom_text(ctx, expr->array_ref.field); + *index_rtrn = expr->array_ref.entry; + if (expr->array_ref.element != XKB_ATOM_NONE && *elem_rtrn == NULL) + return false; + if (*field_rtrn == NULL) + return false; + return true; default: - snprintf(buf, sizeof(buf), "illegal(%d)", type); break; } - return buf; + log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->expr.op); + return false; } -char * -exprTypeText(unsigned type) +static bool +SimpleLookup(struct xkb_context *ctx, const void *priv, xkb_atom_t field, + enum expr_value_type type, unsigned int *val_rtrn) { - static char buf[20]; + const LookupEntry *entry; + const char *str; - switch (type) - { - case TypeUnknown: - strcpy(buf, "unknown"); - break; - case TypeBoolean: - strcpy(buf, "boolean"); - break; - case TypeInt: - strcpy(buf, "int"); - break; - case TypeString: - strcpy(buf, "string"); - break; - case TypeAction: - strcpy(buf, "action"); - break; - case TypeKeyName: - strcpy(buf, "keyname"); - break; - default: - snprintf(buf, sizeof(buf), "illegal(%d)", type); - break; - } - return buf; -} + if (!priv || field == XKB_ATOM_NONE || type != EXPR_TYPE_INT) + return false; -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; + str = xkb_atom_text(ctx, field); + for (entry = priv; entry && entry->name; entry++) { + if (istreq(str, entry->name)) { + *val_rtrn = entry->value; + return true; } } - return False; -} - -Bool -RadioLookup(XPointer priv, - Atom elem, Atom field, unsigned type, ExprResult * val_rtrn) -{ - register char *str; - int rg; - - if ((field == None) || (elem != None) || (type != TypeInt)) - return False; - str = XkbAtomGetString(NULL, field); - if (str) - { - if (uStrCasePrefix("group", str)) - str += strlen("group"); - else if (uStrCasePrefix("radiogroup", str)) - str += strlen("radiogroup"); - else if (uStrCasePrefix("rg", str)) - str += strlen("rg"); - else if (!isdigit(str[0])) - str = NULL; - } - if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1) - || (rg > XkbMaxRadioGroups)) - return False; - val_rtrn->uval = rg; - return True; -} -int -TableLookup(XPointer priv, - Atom elem, Atom field, unsigned type, ExprResult * val_rtrn) -{ - LookupTable *tbl = (LookupTable *) priv; - register char *str; - - if ((priv == NULL) || (field == None) || (type != TypeInt)) - return False; - str = XkbAtomGetString(NULL, elem); - while (tbl) - { - if (((str == NULL) && (tbl->element == NULL)) || - ((str != NULL) && (tbl->element != NULL) && - (uStrCaseCmp(str, tbl->element) == 0))) - { - break; - } - tbl = tbl->nextElement; - } - if (tbl == NULL) /* didn't find a matching element */ - return False; - priv = (XPointer) tbl->entries; - return SimpleLookup(priv, (Atom) None, field, type, val_rtrn); + return false; } -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); -} +/* Data passed in the *priv argument for LookupModMask. */ +typedef struct { + const struct xkb_mod_set *mods; + enum mod_type mod_type; +} LookupModMaskPriv; -int -LookupModMask(XPointer priv, - Atom elem, Atom field, unsigned type, ExprResult * val_rtrn) +static bool +LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field, + enum expr_value_type type, xkb_mod_mask_t *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; + const char *str; + xkb_mod_index_t ndx; + const LookupModMaskPriv *arg = priv; + const struct xkb_mod_set *mods = arg->mods; + enum mod_type mod_type = arg->mod_type; + + if (type != EXPR_TYPE_INT) + return false; + + str = xkb_atom_text(ctx, field); + if (!str) + return false; + + if (istreq(str, "all")) { + *val_rtrn = MOD_REAL_MASK_ALL; + return true; } - 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; + if (istreq(str, "none")) { + *val_rtrn = 0; + return true; } - return ok; -} -int -ExprResolveModMask(ExprDef * expr, - ExprResult * val_rtrn, - IdentLookupFunc lookup, XPointer lookupPriv) -{ - LookupPriv priv; + ndx = XkbModNameToIndex(mods, field, mod_type); + if (ndx == XKB_MOD_INVALID) + return false; - priv.priv = NULL; - priv.chain = lookup; - priv.chainPriv = lookupPriv; - return ExprResolveMask(expr, val_rtrn, LookupModMask, (XPointer) & priv); + *val_rtrn = (1u << ndx); + return true; } -int -ExprResolveBoolean(ExprDef * expr, - ExprResult * val_rtrn, - IdentLookupFunc lookup, XPointer lookupPriv) +bool +ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr, + bool *set_rtrn) { - 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; + bool ok = false; + const char *ident; + + switch (expr->expr.op) { + case EXPR_VALUE: + if (expr->expr.value_type != EXPR_TYPE_BOOLEAN) { + log_err(ctx, + "Found constant of type %s where boolean was expected\n", + expr_value_type_to_string(expr->expr.value_type)); + return false; + } + *set_rtrn = expr->boolean.set; + return true; + + case EXPR_IDENT: + ident = xkb_atom_text(ctx, expr->ident.ident); + if (ident) { + if (istreq(ident, "true") || + istreq(ident, "yes") || + istreq(ident, "on")) { + *set_rtrn = true; + return true; } - else if ((uStrCaseCmp(bogus, "false") == 0) || - (uStrCaseCmp(bogus, "no") == 0) || - (uStrCaseCmp(bogus, "off") == 0)) - { - val_rtrn->uval = 0; - return True; + else if (istreq(ident, "false") || + istreq(ident, "no") || + istreq(ident, "off")) { + *set_rtrn = false; + 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); + log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n", ident); + return false; + + case EXPR_FIELD_REF: + log_err(ctx, "Default \"%s.%s\" of type boolean is unknown\n", + xkb_atom_text(ctx, expr->field_ref.element), + xkb_atom_text(ctx, expr->field_ref.field)); + return false; + + case EXPR_INVERT: + case EXPR_NOT: + ok = ExprResolveBoolean(ctx, expr->unary.child, set_rtrn); if (ok) - val_rtrn->uval = !val_rtrn->uval; + *set_rtrn = !*set_rtrn; 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"); + case EXPR_ADD: + case EXPR_SUBTRACT: + case EXPR_MULTIPLY: + case EXPR_DIVIDE: + case EXPR_ASSIGN: + case EXPR_NEGATE: + case EXPR_UNARY_PLUS: + case EXPR_ACTION_DECL: + case EXPR_ACTION_LIST: + case EXPR_KEYSYM_LIST: + log_err(ctx, "%s of boolean values not permitted\n", + expr_op_type_to_string(expr->expr.op)); break; + default: - WSGO1("Unknown operator %d in ResolveBoolean\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n", + expr->expr.op); break; } - return False; + + return false; } -int -ExprResolveFloat(ExprDef * expr, - ExprResult * val_rtrn, - IdentLookupFunc lookup, XPointer lookupPriv) +bool +ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr, + xkb_keycode_t *kc) { - int ok = 0; - ExprResult leftRtrn, rightRtrn; - ExprDef *left, *right; - - switch (expr->op) - { - case ExprValue: - if (expr->type == TypeString) - { - register char *str; - str = XkbAtomGetString(NULL, expr->value.str); - if ((str != NULL) && (strlen(str) == 1)) - { - val_rtrn->uval = str[0] * XkbGeomPtsPerMM; - return True; - } - } - if ((expr->type != TypeInt) && (expr->type != TypeFloat)) - { - ERROR1("Found constant of type %s, expected a number\n", - exprTypeText(expr->type)); - return False; - } - val_rtrn->ival = expr->value.ival; - if (expr->type == TypeInt) - val_rtrn->ival *= XkbGeomPtsPerMM; - return True; - case ExprIdent: - if (lookup) - { - ok = (*lookup) (lookupPriv, - None, expr->value.str, TypeFloat, val_rtrn); - } - if (!ok) - ERROR1("Numeric identifier \"%s\" unknown\n", - XkbAtomText(NULL, expr->value.str, XkbMessage)); - return ok; - case ExprFieldRef: - if (lookup) - { - ok = (*lookup) (lookupPriv, - expr->value.field.element, - expr->value.field.field, TypeFloat, val_rtrn); - } - if (!ok) - ERROR2("Numeric default \"%s.%s\" unknown\n", - XkbAtomText(NULL, expr->value.field.element, XkbMessage), - XkbAtomText(NULL, expr->value.field.field, XkbMessage)); - return ok; - case OpAdd: - case OpSubtract: - case OpMultiply: - case OpDivide: - left = expr->value.binary.left; - right = expr->value.binary.right; - if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) && - ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv)) - { - switch (expr->op) - { - case OpAdd: - val_rtrn->ival = leftRtrn.ival + rightRtrn.ival; - break; - case OpSubtract: - val_rtrn->ival = leftRtrn.ival - rightRtrn.ival; - break; - case OpMultiply: - val_rtrn->ival = leftRtrn.ival * rightRtrn.ival; - break; - case OpDivide: - val_rtrn->ival = leftRtrn.ival / rightRtrn.ival; - break; + xkb_keycode_t leftRtrn, rightRtrn; + + switch (expr->expr.op) { + case EXPR_VALUE: + if (expr->expr.value_type != EXPR_TYPE_INT) { + log_err(ctx, + "Found constant of type %s where an int was expected\n", + expr_value_type_to_string(expr->expr.value_type)); + return false; + } + + *kc = (xkb_keycode_t) expr->integer.ival; + return true; + + case EXPR_ADD: + case EXPR_SUBTRACT: + case EXPR_MULTIPLY: + case EXPR_DIVIDE: + if (!ExprResolveKeyCode(ctx, expr->binary.left, &leftRtrn) || + !ExprResolveKeyCode(ctx, expr->binary.right, &rightRtrn)) + return false; + + switch (expr->expr.op) { + case EXPR_ADD: + *kc = leftRtrn + rightRtrn; + break; + case EXPR_SUBTRACT: + *kc = leftRtrn - rightRtrn; + break; + case EXPR_MULTIPLY: + *kc = leftRtrn * rightRtrn; + break; + case EXPR_DIVIDE: + if (rightRtrn == 0) { + log_err(ctx, "Cannot divide by zero: %d / %d\n", + leftRtrn, rightRtrn); + return false; } - 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; + + *kc = leftRtrn / rightRtrn; + break; + default: + break; } - return False; - case OpUnaryPlus: - left = expr->value.child; - return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv); + + return true; + + case EXPR_NEGATE: + if (!ExprResolveKeyCode(ctx, expr->unary.child, &leftRtrn)) + return false; + + *kc = ~leftRtrn; + return true; + + case EXPR_UNARY_PLUS: + return ExprResolveKeyCode(ctx, expr->unary.child, kc); + default: - WSGO1("Unknown operator %d in ResolveFloat\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n", + expr->expr.op); break; } - return False; + + return false; } -int -ExprResolveInteger(ExprDef * expr, - ExprResult * val_rtrn, - IdentLookupFunc lookup, XPointer lookupPriv) +/** + * This function returns ... something. It's a bit of a guess, really. + * + * If an integer is given in value ctx, it will be returned in ival. + * If an ident or field reference is given, the lookup function (if given) + * will be called. At the moment, only SimpleLookup use this, and they both + * return the results in uval. And don't support field references. + * + * Cool. + */ +static bool +ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr, + int *val_rtrn, IdentLookupFunc lookup, + const void *lookupPriv) { - int ok = 0; - ExprResult leftRtrn, rightRtrn; + bool ok = false; + int l, r; + unsigned u; ExprDef *left, *right; - switch (expr->op) - { - case ExprValue: - if (expr->type == TypeString) - { - register char *str; - str = XkbAtomGetString(NULL, expr->value.str); - if (str != NULL) - switch (strlen(str)) - { - case 0: - val_rtrn->uval = 0; - return True; - case 1: - val_rtrn->uval = str[0]; - return True; - default: - break; - } - } - if ((expr->type != TypeInt) && (expr->type != TypeFloat)) - { - ERROR1 - ("Found constant of type %s where an int was expected\n", - exprTypeText(expr->type)); - return False; + switch (expr->expr.op) { + case EXPR_VALUE: + if (expr->expr.value_type != EXPR_TYPE_INT) { + log_err(ctx, + "Found constant of type %s where an int was expected\n", + expr_value_type_to_string(expr->expr.value_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: + + *val_rtrn = expr->integer.ival; + return true; + + case EXPR_IDENT: if (lookup) - { - ok = (*lookup) (lookupPriv, - expr->value.field.element, - expr->value.field.field, TypeInt, val_rtrn); - } + ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, &u); + 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)); + log_err(ctx, "Identifier \"%s\" of type int is unknown\n", + xkb_atom_text(ctx, expr->ident.ident)); + else + *val_rtrn = (int) u; + 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; + + case EXPR_FIELD_REF: + log_err(ctx, "Default \"%s.%s\" of type int is unknown\n", + xkb_atom_text(ctx, expr->field_ref.element), + xkb_atom_text(ctx, expr->field_ref.field)); + return false; + + case EXPR_ADD: + case EXPR_SUBTRACT: + case EXPR_MULTIPLY: + case EXPR_DIVIDE: + left = expr->binary.left; + right = expr->binary.right; + if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv) || + !ExprResolveIntegerLookup(ctx, right, &r, lookup, lookupPriv)) + return false; + + switch (expr->expr.op) { + case EXPR_ADD: + *val_rtrn = l + r; + break; + case EXPR_SUBTRACT: + *val_rtrn = l - r; + break; + case EXPR_MULTIPLY: + *val_rtrn = l * r; + break; + case EXPR_DIVIDE: + if (r == 0) { + log_err(ctx, "Cannot divide by zero: %d / %d\n", l, r); + return false; } - return True; + *val_rtrn = l / r; + break; + default: + log_err(ctx, "%s of integers not permitted\n", + expr_op_type_to_string(expr->expr.op)); + return false; } - return False; - case OpAssign: - WSGO("Assignment operator not implemented yet\n"); + + return true; + + case EXPR_ASSIGN: + log_wsgo(ctx, "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); + + case EXPR_NOT: + log_err(ctx, "The ! operator cannot be applied to an integer\n"); + return false; + + case EXPR_INVERT: + case EXPR_NEGATE: + left = expr->unary.child; + if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv)) + return false; + + *val_rtrn = (expr->expr.op == EXPR_NEGATE ? -l : ~l); + return true; + + case EXPR_UNARY_PLUS: + left = expr->unary.child; + return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup, + lookupPriv); + default: - WSGO1("Unknown operator %d in ResolveInteger\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n", + expr->expr.op); break; } - return False; + + return false; } -int -ExprResolveString(ExprDef * expr, - ExprResult * val_rtrn, - IdentLookupFunc lookup, XPointer lookupPriv) +bool +ExprResolveInteger(struct xkb_context *ctx, const ExprDef *expr, + int *val_rtrn) { - 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 ExprResolveIntegerLookup(ctx, expr, val_rtrn, NULL, NULL); +} + +bool +ExprResolveGroup(struct xkb_context *ctx, const ExprDef *expr, + xkb_layout_index_t *group_rtrn) +{ + bool ok; + int result; + + ok = ExprResolveIntegerLookup(ctx, expr, &result, SimpleLookup, + groupNames); + if (!ok) + return false; + + if (result <= 0 || result > XKB_MAX_GROUPS) { + log_err_with_code(ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, + "Group index %u is out of range (1..%d)\n", + result, XKB_MAX_GROUPS); + return false; } - return False; + + *group_rtrn = (xkb_layout_index_t) result; + return true; } -int -ExprResolveKeyName(ExprDef * expr, - ExprResult * val_rtrn, - IdentLookupFunc lookup, XPointer lookupPriv) +bool +ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr, + xkb_level_index_t *level_rtrn) { - 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; + bool ok; + int result; + + ok = ExprResolveIntegerLookup(ctx, expr, &result, SimpleLookup, + levelNames); + if (!ok) + return false; + + if (result < 1) { + log_err_with_code(ctx, XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL, + "Shift level %d is out of range\n", result); + return false; + } + + /* Level is zero-indexed from now on. */ + *level_rtrn = (unsigned int) (result - 1); + return true; +} + +bool +ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, int *btn_rtrn) +{ + return ExprResolveIntegerLookup(ctx, expr, btn_rtrn, SimpleLookup, + buttonNames); +} + +bool +ExprResolveString(struct xkb_context *ctx, const ExprDef *expr, + xkb_atom_t *val_rtrn) +{ + switch (expr->expr.op) { + case EXPR_VALUE: + if (expr->expr.value_type != EXPR_TYPE_STRING) { + log_err(ctx, "Found constant of type %s, expected a string\n", + expr_value_type_to_string(expr->expr.value_type)); + return false; + } + + *val_rtrn = expr->string.str; + return true; + + case EXPR_IDENT: + log_err(ctx, "Identifier \"%s\" of type string not found\n", + xkb_atom_text(ctx, expr->ident.ident)); + return false; + + case EXPR_FIELD_REF: + log_err(ctx, "Default \"%s.%s\" of type string not found\n", + xkb_atom_text(ctx, expr->field_ref.element), + xkb_atom_text(ctx, expr->field_ref.field)); + return false; + + case EXPR_ADD: + case EXPR_SUBTRACT: + case EXPR_MULTIPLY: + case EXPR_DIVIDE: + case EXPR_ASSIGN: + case EXPR_NEGATE: + case EXPR_INVERT: + case EXPR_NOT: + case EXPR_UNARY_PLUS: + case EXPR_ACTION_DECL: + case EXPR_ACTION_LIST: + case EXPR_KEYSYM_LIST: + log_err(ctx, "%s of strings not permitted\n", + expr_op_type_to_string(expr->expr.op)); + return false; + default: - WSGO1("Unknown operator %d in ResolveKeyName\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveString\n", + expr->expr.op); break; } - return False; + return false; } -/***====================================================================***/ - -int -ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values) +bool +ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr, + unsigned int *val_rtrn, const LookupEntry *values) { - if (expr->op != ExprIdent) - { - ERROR1("Found a %s where an enumerated value was expected\n", - exprOpText(expr->op)); - return False; + if (expr->expr.op != EXPR_IDENT) { + log_err(ctx, "Found a %s where an enumerated value was expected\n", + expr_op_type_to_string(expr->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)); + + if (!SimpleLookup(ctx, values, expr->ident.ident, EXPR_TYPE_INT, + val_rtrn)) { + log_err(ctx, "Illegal identifier %s; expected one of:\n", + xkb_atom_text(ctx, expr->ident.ident)); while (values && values->name) { - if (nOut != 0) - INFO1(", %s", values->name); - else - INFO1("%s", values->name); + log_err(ctx, "\t%s\n", values->name); values++; - nOut++; } - INFO(")\n"); - return False; + return false; } - return True; + + return true; } -int -ExprResolveMask(ExprDef * expr, - ExprResult * val_rtrn, - IdentLookupFunc lookup, XPointer lookupPriv) +static bool +ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr, + unsigned int *val_rtrn, IdentLookupFunc lookup, + const void *lookupPriv) { - int ok = 0; - ExprResult leftRtrn, rightRtrn; + bool ok = false; + unsigned int l = 0, r = 0; + int v; 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); - } + const char *bogus = NULL; + + switch (expr->expr.op) { + case EXPR_VALUE: + if (expr->expr.value_type != EXPR_TYPE_INT) { + log_err(ctx, + "Found constant of type %s where a mask was expected\n", + expr_value_type_to_string(expr->expr.value_type)); + return false; + } + *val_rtrn = (unsigned int) expr->integer.ival; + return true; + + case EXPR_IDENT: + ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, + 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)); + log_err(ctx, "Identifier \"%s\" of type int is unknown\n", + xkb_atom_text(ctx, expr->ident.ident)); return ok; - case ExprArrayRef: + + case EXPR_FIELD_REF: + log_err(ctx, "Default \"%s.%s\" of type int is unknown\n", + xkb_atom_text(ctx, expr->field_ref.element), + xkb_atom_text(ctx, expr->field_ref.field)); + return false; + + case EXPR_ARRAY_REF: bogus = "array reference"; - case ExprActionDecl: + /* fallthrough */ + case EXPR_ACTION_DECL: 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; + log_err(ctx, + "Unexpected %s in mask expression; Expression Ignored\n", + bogus); + return false; + + case EXPR_ADD: + case EXPR_SUBTRACT: + case EXPR_MULTIPLY: + case EXPR_DIVIDE: + left = expr->binary.left; + right = expr->binary.right; + if (!ExprResolveMaskLookup(ctx, left, &l, lookup, lookupPriv) || + !ExprResolveMaskLookup(ctx, right, &r, lookup, lookupPriv)) + return false; + + switch (expr->expr.op) { + case EXPR_ADD: + *val_rtrn = l | r; + break; + case EXPR_SUBTRACT: + *val_rtrn = l & (~r); + break; + case EXPR_MULTIPLY: + case EXPR_DIVIDE: + log_err(ctx, "Cannot %s masks; Illegal operation ignored\n", + (expr->expr.op == EXPR_DIVIDE ? "divide" : "multiply")); + return false; + default: + break; } - return False; - case OpAssign: - WSGO("Assignment operator not implemented yet\n"); + + return true; + + case EXPR_ASSIGN: + log_wsgo(ctx, "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; + + case EXPR_INVERT: + left = expr->unary.child; + if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv)) + return false; + + *val_rtrn = ~v; + return true; + + case EXPR_UNARY_PLUS: + case EXPR_NEGATE: + case EXPR_NOT: + left = expr->unary.child; + if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv)) + log_err(ctx, "The %s operator cannot be used with a mask\n", + (expr->expr.op == EXPR_NEGATE ? "-" : "!")); + return false; + default: - WSGO1("Unknown operator %d in ResolveMask\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveMask\n", + expr->expr.op); break; } - return False; + + return false; } -int -ExprResolveKeySym(ExprDef * expr, - ExprResult * val_rtrn, - IdentLookupFunc lookup, XPointer lookupPriv) +bool +ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr, + unsigned int *mask_rtrn, const LookupEntry *values) { - 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; - } + return ExprResolveMaskLookup(ctx, expr, mask_rtrn, SimpleLookup, values); +} + +bool +ExprResolveModMask(struct xkb_context *ctx, const ExprDef *expr, + enum mod_type mod_type, const struct xkb_mod_set *mods, + xkb_mod_mask_t *mask_rtrn) +{ + LookupModMaskPriv priv = { .mods = mods, .mod_type = mod_type }; + return ExprResolveMaskLookup(ctx, expr, mask_rtrn, LookupModMask, &priv); +} + +bool +ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr, + xkb_keysym_t *sym_rtrn) +{ + int val; + + if (expr->expr.op == EXPR_IDENT) { + const char *str = xkb_atom_text(ctx, expr->ident.ident); + *sym_rtrn = xkb_keysym_from_name(str, 0); + if (*sym_rtrn != XKB_KEY_NoSymbol) + return true; + } + + if (!ExprResolveInteger(ctx, expr, &val)) + return false; + + if (val < XKB_KEYSYM_MIN) { + log_warn_with_code(ctx, XKB_WARNING_UNRECOGNIZED_KEYSYM, + "unrecognized keysym \"-0x%x\" (%d)\n", + (unsigned int) -val, val); + return false; + } + + /* Special case for digits 0..9 */ + if (val < 10) { + *sym_rtrn = XKB_KEY_0 + (xkb_keysym_t) val; + return true; + } + + if (val <= XKB_KEYSYM_MAX) { + log_warn_with_code(ctx, XKB_WARNING_NUMERIC_KEYSYM, + "numeric keysym \"0x%x\" (%d)", + (unsigned int) val, val); + *sym_rtrn = (xkb_keysym_t) val; + return true; } - ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv); - if ((ok) && (val_rtrn->uval < 10)) - val_rtrn->uval += '0'; - return ok; + + log_warn_with_code(ctx, XKB_WARNING_UNRECOGNIZED_KEYSYM, + "unrecognized keysym \"0x%x\" (%d)\n", + (unsigned int) val, val); + return false; + +} + +bool +ExprResolveMod(struct xkb_context *ctx, const ExprDef *def, + enum mod_type mod_type, const struct xkb_mod_set *mods, + xkb_mod_index_t *ndx_rtrn) +{ + xkb_mod_index_t ndx; + xkb_atom_t name; + + if (def->expr.op != EXPR_IDENT) { + log_err(ctx, + "Cannot resolve virtual modifier: " + "found %s where a virtual modifier name was expected\n", + expr_op_type_to_string(def->expr.op)); + return false; + } + + name = def->ident.ident; + ndx = XkbModNameToIndex(mods, name, mod_type); + if (ndx == XKB_MOD_INVALID) { + log_err(ctx, + "Cannot resolve virtual modifier: " + "\"%s\" was not previously declared\n", + xkb_atom_text(ctx, name)); + return false; + } + + *ndx_rtrn = ndx; + return true; }