X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fxkbcomp%2Fexpr.c;h=f935ce6db10000b6fe243ab74357b47ca50a6155;hb=ef81d04eef4b1a60ff42bd9ccbe2918b0a5420ec;hp=2d71ca7f30db759efb2eaad7fe01e7d4ae63d082;hpb=0d262fa1051cad9d1cf55939753799ab431676f2;p=platform%2Fupstream%2Flibxkbcommon.git diff --git a/src/xkbcomp/expr.c b/src/xkbcomp/expr.c index 2d71ca7..f935ce6 100644 --- a/src/xkbcomp/expr.c +++ b/src/xkbcomp/expr.c @@ -24,135 +24,52 @@ * ********************************************************/ +#include "config.h" + +#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, - ExprResult *val_rtrn); - -const char * -exprOpText(enum expr_op_type op) -{ - static char buf[32]; - - switch (op) { - case EXPR_VALUE: - strcpy(buf, "literal"); - break; - case EXPR_IDENT: - strcpy(buf, "identifier"); - break; - case EXPR_ACTION_DECL: - strcpy(buf, "action declaration"); - break; - case EXPR_FIELD_REF: - strcpy(buf, "field reference"); - break; - case EXPR_ARRAY_REF: - strcpy(buf, "array reference"); - break; - case EXPR_KEYSYM_LIST: - strcpy(buf, "list of keysyms"); - break; - case EXPR_ACTION_LIST: - strcpy(buf, "list of actions"); - break; - case EXPR_ADD: - strcpy(buf, "addition"); - break; - case EXPR_SUBTRACT: - strcpy(buf, "subtraction"); - break; - case EXPR_MULTIPLY: - strcpy(buf, "multiplication"); - break; - case EXPR_DIVIDE: - strcpy(buf, "division"); - break; - case EXPR_ASSIGN: - strcpy(buf, "assignment"); - break; - case EXPR_NOT: - strcpy(buf, "logical not"); - break; - case EXPR_NEGATE: - strcpy(buf, "arithmetic negation"); - break; - case EXPR_INVERT: - strcpy(buf, "bitwise inversion"); - break; - case EXPR_UNARY_PLUS: - strcpy(buf, "unary plus"); - break; - default: - snprintf(buf, sizeof(buf), "illegal(%d)", op); - break; - } - return buf; -} - -static const char * -exprValueTypeText(enum expr_value_type type) -{ - static char buf[20]; - - switch (type) { - case EXPR_TYPE_UNKNOWN: - strcpy(buf, "unknown"); - break; - case EXPR_TYPE_BOOLEAN: - strcpy(buf, "boolean"); - break; - case EXPR_TYPE_INT: - strcpy(buf, "int"); - break; - case EXPR_TYPE_STRING: - strcpy(buf, "string"); - break; - case EXPR_TYPE_ACTION: - strcpy(buf, "action"); - break; - case EXPR_TYPE_KEYNAME: - strcpy(buf, "keyname"); - break; - default: - snprintf(buf, sizeof(buf), "illegal(%d)", type); - break; - } - return buf; -} + unsigned int *val_rtrn); bool -ExprResolveLhs(struct xkb_context *ctx, ExprDef *expr, const char **elem_rtrn, - const char **field_rtrn, ExprDef **index_rtrn) +ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr, + const char **elem_rtrn, const char **field_rtrn, + ExprDef **index_rtrn) { - switch (expr->op) { + switch (expr->expr.op) { case EXPR_IDENT: *elem_rtrn = NULL; - *field_rtrn = xkb_atom_text(ctx, expr->value.str); + *field_rtrn = xkb_atom_text(ctx, expr->ident.ident); *index_rtrn = NULL; - return true; + return (*field_rtrn != NULL); case EXPR_FIELD_REF: - *elem_rtrn = xkb_atom_text(ctx, expr->value.field.element); - *field_rtrn = xkb_atom_text(ctx, expr->value.field.field); + *elem_rtrn = xkb_atom_text(ctx, expr->field_ref.element); + *field_rtrn = xkb_atom_text(ctx, expr->field_ref.field); *index_rtrn = NULL; - return true; + return (*elem_rtrn != NULL && *field_rtrn != NULL); case EXPR_ARRAY_REF: - *elem_rtrn = xkb_atom_text(ctx, expr->value.array.element); - *field_rtrn = xkb_atom_text(ctx, expr->value.array.field); - *index_rtrn = expr->value.array.entry; + *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: break; } - log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->op); + log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->expr.op); return false; } static bool -SimpleLookup(struct xkb_context *ctx, const void *priv, - xkb_atom_t field, enum expr_value_type type, - ExprResult *val_rtrn) +SimpleLookup(struct xkb_context *ctx, const void *priv, xkb_atom_t field, + enum expr_value_type type, unsigned int *val_rtrn) { const LookupEntry *entry; const char *str; @@ -163,7 +80,7 @@ SimpleLookup(struct xkb_context *ctx, const void *priv, str = xkb_atom_text(ctx, field); for (entry = priv; entry && entry->name; entry++) { if (istreq(str, entry->name)) { - val_rtrn->uval = entry->result; + *val_rtrn = entry->value; return true; } } @@ -171,68 +88,67 @@ SimpleLookup(struct xkb_context *ctx, const void *priv, return false; } -static const LookupEntry modIndexNames[] = { - { "shift", ShiftMapIndex }, - { "control", ControlMapIndex }, - { "lock", LockMapIndex }, - { "mod1", Mod1MapIndex }, - { "mod2", Mod2MapIndex }, - { "mod3", Mod3MapIndex }, - { "mod4", Mod4MapIndex }, - { "mod5", Mod5MapIndex }, - { "none", XkbNoModifier }, - { NULL, 0 } -}; +/* Data passed in the *priv argument for LookupModMask. */ +typedef struct { + const struct xkb_mod_set *mods; + enum mod_type mod_type; +} LookupModMaskPriv; -bool -LookupModIndex(struct xkb_context *ctx, const void *priv, xkb_atom_t field, - enum expr_value_type type, ExprResult *val_rtrn) -{ - return SimpleLookup(ctx, modIndexNames, field, type, val_rtrn); -} - -bool +static bool LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field, - enum expr_value_type type, ExprResult *val_rtrn) + enum expr_value_type type, xkb_mod_mask_t *val_rtrn) { const char *str; - bool ret = true; + 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 == NULL) + if (!str) + return false; + + if (istreq(str, "all")) { + *val_rtrn = MOD_REAL_MASK_ALL; + return true; + } + + if (istreq(str, "none")) { + *val_rtrn = 0; + return true; + } + + ndx = XkbModNameToIndex(mods, field, mod_type); + if (ndx == XKB_MOD_INVALID) return false; - if (istreq(str, "all")) - val_rtrn->uval = 0xff; - else if (istreq(str, "none")) - val_rtrn->uval = 0; - else if (LookupModIndex(ctx, priv, field, type, val_rtrn)) - val_rtrn->uval = (1 << val_rtrn->uval); - else - ret = false; - return ret; + + *val_rtrn = (1u << ndx); + return true; } bool -ExprResolveBoolean(struct xkb_context *ctx, ExprDef *expr, bool *set_rtrn) +ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr, + bool *set_rtrn) { bool ok = false; const char *ident; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_BOOLEAN) { + if (expr->expr.value_type != EXPR_TYPE_BOOLEAN) { log_err(ctx, "Found constant of type %s where boolean was expected\n", - exprValueTypeText(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - *set_rtrn = !!expr->value.ival; + *set_rtrn = expr->boolean.set; return true; case EXPR_IDENT: - ident = xkb_atom_text(ctx, expr->value.str); + ident = xkb_atom_text(ctx, expr->ident.ident); if (ident) { if (istreq(ident, "true") || istreq(ident, "yes") || @@ -247,19 +163,18 @@ ExprResolveBoolean(struct xkb_context *ctx, ExprDef *expr, bool *set_rtrn) return true; } } - log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n", - xkb_atom_text(ctx, expr->value.str)); + 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->value.field.element), - xkb_atom_text(ctx, expr->value.field.field)); + 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, set_rtrn); + ok = ExprResolveBoolean(ctx, expr->unary.child, set_rtrn); if (ok) *set_rtrn = !*set_rtrn; return ok; @@ -270,63 +185,66 @@ ExprResolveBoolean(struct xkb_context *ctx, ExprDef *expr, bool *set_rtrn) 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", - exprOpText(expr->op)); + expr_op_type_to_string(expr->expr.op)); break; default: - log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n", + expr->expr.op); break; } return false; } -int -ExprResolveKeyCode(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn) +bool +ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr, + xkb_keycode_t *kc) { - ExprResult leftRtrn, rightRtrn; - ExprDef *left, *right; + xkb_keycode_t leftRtrn, rightRtrn; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_INT) { + if (expr->expr.value_type != EXPR_TYPE_INT) { log_err(ctx, "Found constant of type %s where an int was expected\n", - exprValueTypeText(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - val_rtrn->uval = expr->value.uval; + + *kc = (xkb_keycode_t) expr->integer.ival; return true; case EXPR_ADD: case EXPR_SUBTRACT: case EXPR_MULTIPLY: case EXPR_DIVIDE: - left = expr->value.binary.left; - right = expr->value.binary.right; - if (!ExprResolveKeyCode(ctx, left, &leftRtrn) || - !ExprResolveKeyCode(ctx, right, &rightRtrn)) + if (!ExprResolveKeyCode(ctx, expr->binary.left, &leftRtrn) || + !ExprResolveKeyCode(ctx, expr->binary.right, &rightRtrn)) return false; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_ADD: - val_rtrn->uval = leftRtrn.uval + rightRtrn.uval; + *kc = leftRtrn + rightRtrn; break; case EXPR_SUBTRACT: - val_rtrn->uval = leftRtrn.uval - rightRtrn.uval; + *kc = leftRtrn - rightRtrn; break; case EXPR_MULTIPLY: - val_rtrn->uval = leftRtrn.uval * rightRtrn.uval; + *kc = leftRtrn * rightRtrn; break; case EXPR_DIVIDE: - if (rightRtrn.uval == 0) { + if (rightRtrn == 0) { log_err(ctx, "Cannot divide by zero: %d / %d\n", - leftRtrn.uval, rightRtrn.uval); + leftRtrn, rightRtrn); return false; } - val_rtrn->uval = leftRtrn.uval / rightRtrn.uval; + + *kc = leftRtrn / rightRtrn; break; default: break; @@ -335,122 +253,108 @@ ExprResolveKeyCode(struct xkb_context *ctx, ExprDef *expr, return true; case EXPR_NEGATE: - left = expr->value.child; - if (ExprResolveKeyCode(ctx, left, &leftRtrn)) { - val_rtrn->uval = ~leftRtrn.uval; - return true; - } - return false; + if (!ExprResolveKeyCode(ctx, expr->unary.child, &leftRtrn)) + return false; + + *kc = ~leftRtrn; + return true; case EXPR_UNARY_PLUS: - left = expr->value.child; - return ExprResolveKeyCode(ctx, left, val_rtrn); + return ExprResolveKeyCode(ctx, expr->unary.child, kc); default: - log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n", + expr->expr.op); break; } + return false; } /** * This function returns ... something. It's a bit of a guess, really. * - * If a string is given in value ctx, its first character will be - * returned in uval. If an integer is given in value ctx, it will be - * returned in ival. If a float is given in value ctx, it will be - * returned as millimetres (rather than points) in ival. - * + * 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 int -ExprResolveIntegerLookup(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn, IdentLookupFunc lookup, +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) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type == EXPR_TYPE_STRING) { - const char *str; - str = xkb_atom_text(ctx, 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->value_type != EXPR_TYPE_INT) { + if (expr->expr.value_type != EXPR_TYPE_INT) { log_err(ctx, "Found constant of type %s where an int was expected\n", - exprValueTypeText(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - val_rtrn->ival = expr->value.ival; + + *val_rtrn = expr->integer.ival; return true; case EXPR_IDENT: if (lookup) - ok = lookup(ctx, lookupPriv, expr->value.str, - EXPR_TYPE_INT, val_rtrn); + ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, &u); + if (!ok) log_err(ctx, "Identifier \"%s\" of type int is unknown\n", - xkb_atom_text(ctx, expr->value.str)); + xkb_atom_text(ctx, expr->ident.ident)); + else + *val_rtrn = (int) u; + return ok; case EXPR_FIELD_REF: log_err(ctx, "Default \"%s.%s\" of type int is unknown\n", - xkb_atom_text(ctx, expr->value.field.element), - xkb_atom_text(ctx, expr->value.field.field)); + 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->value.binary.left; - right = expr->value.binary.right; - if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup, - lookupPriv) && - ExprResolveIntegerLookup(ctx, right, &rightRtrn, lookup, - lookupPriv)) { - switch (expr->op) { - case EXPR_ADD: - val_rtrn->ival = leftRtrn.ival + rightRtrn.ival; - break; - case EXPR_SUBTRACT: - val_rtrn->ival = leftRtrn.ival - rightRtrn.ival; - break; - case EXPR_MULTIPLY: - val_rtrn->ival = leftRtrn.ival * rightRtrn.ival; - break; - case EXPR_DIVIDE: - if (rightRtrn.ival == 0) { - log_err(ctx, "Cannot divide by zero: %d / %d\n", - leftRtrn.ival, rightRtrn.ival); - return false; - } - val_rtrn->ival = leftRtrn.ival / rightRtrn.ival; - break; - default: - break; + 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; + + return true; case EXPR_ASSIGN: log_wsgo(ctx, "Assignment operator not implemented yet\n"); @@ -462,140 +366,111 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, ExprDef *expr, case EXPR_INVERT: case EXPR_NEGATE: - left = expr->value.child; - if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup, - lookupPriv)) { - if (expr->op == EXPR_NEGATE) - val_rtrn->ival = -leftRtrn.ival; - else - val_rtrn->ival = ~leftRtrn.ival; - return true; - } - return false; + 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->value.child; + left = expr->unary.child; return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup, lookupPriv); default: - log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n", + expr->expr.op); break; } + return false; } -int -ExprResolveInteger(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn) +bool +ExprResolveInteger(struct xkb_context *ctx, const ExprDef *expr, + int *val_rtrn) { return ExprResolveIntegerLookup(ctx, expr, val_rtrn, NULL, NULL); } -int -ExprResolveGroup(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn) +bool +ExprResolveGroup(struct xkb_context *ctx, const ExprDef *expr, + xkb_layout_index_t *group_rtrn) { - int ret; - static const LookupEntry group_names[] = { - { "group1", 1 }, - { "group2", 2 }, - { "group3", 3 }, - { "group4", 4 }, - { "group5", 5 }, - { "group6", 6 }, - { "group7", 7 }, - { "group8", 8 }, - { NULL, 0 } - }; - - ret = ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup, - group_names); - if (ret == false) - return ret; - - if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) { - log_err(ctx, "Group index %u is out of range (1..%d)\n", - val_rtrn->uval, XkbNumKbdGroups); + 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; } + *group_rtrn = (xkb_layout_index_t) result; return true; } -int -ExprResolveLevel(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn) +bool +ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr, + xkb_level_index_t *level_rtrn) { - int ret; - static const LookupEntry level_names[] = { - { "level1", 1 }, - { "level2", 2 }, - { "level3", 3 }, - { "level4", 4 }, - { "level5", 5 }, - { "level6", 6 }, - { "level7", 7 }, - { "level8", 8 }, - { NULL, 0 } - }; - - ret = ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup, - level_names); - if (ret == false) - return ret; - - if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) { - log_err(ctx, "Shift level %d is out of range (1..%d)\n", - val_rtrn->ival, XkbMaxShiftLevel); + 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; } -int -ExprResolveButton(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn) +bool +ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, int *btn_rtrn) { - static const LookupEntry button_names[] = { - { "button1", 1 }, - { "button2", 2 }, - { "button3", 3 }, - { "button4", 4 }, - { "button5", 5 }, - { "default", 0 }, - { NULL, 0 } - }; - - return ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup, - button_names); + return ExprResolveIntegerLookup(ctx, expr, btn_rtrn, SimpleLookup, + buttonNames); } bool -ExprResolveString(struct xkb_context *ctx, ExprDef *expr, - const char **val_rtrn) +ExprResolveString(struct xkb_context *ctx, const ExprDef *expr, + xkb_atom_t *val_rtrn) { - switch (expr->op) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_STRING) { + if (expr->expr.value_type != EXPR_TYPE_STRING) { log_err(ctx, "Found constant of type %s, expected a string\n", - exprValueTypeText(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - *val_rtrn = xkb_atom_text(ctx, expr->value.str); + *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->value.str)); + 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->value.field.element), - xkb_atom_text(ctx, expr->value.field.field)); + xkb_atom_text(ctx, expr->field_ref.element), + xkb_atom_text(ctx, expr->field_ref.field)); return false; case EXPR_ADD: @@ -607,129 +482,85 @@ ExprResolveString(struct xkb_context *ctx, ExprDef *expr, case EXPR_INVERT: case EXPR_NOT: case EXPR_UNARY_PLUS: - log_err(ctx, "%s of strings not permitted\n", exprOpText(expr->op)); + 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: - log_wsgo(ctx, "Unknown operator %d in ResolveString\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveString\n", + expr->expr.op); break; } return false; } bool -ExprResolveKeyName(struct xkb_context *ctx, ExprDef *expr, - char name[XkbKeyNameLength]) +ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr, + unsigned int *val_rtrn, const LookupEntry *values) { - switch (expr->op) { - case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_KEYNAME) { - log_err(ctx, "Found constant of type %s, expected a key name\n", - exprValueTypeText(expr->value_type)); - return false; - } - memcpy(name, expr->value.keyName, XkbKeyNameLength); - return true; - - case EXPR_IDENT: - log_err(ctx, "Identifier \"%s\" of type string not found\n", - xkb_atom_text(ctx, expr->value.str)); - return false; - - case EXPR_FIELD_REF: - log_err(ctx, "Default \"%s.%s\" of type key name not found\n", - xkb_atom_text(ctx, expr->value.field.element), - xkb_atom_text(ctx, expr->value.field.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: - log_err(ctx, "%s of key name values not permitted\n", - exprOpText(expr->op)); - return false; - - default: - log_wsgo(ctx, "Unknown operator %d in ResolveKeyName\n", expr->op); - break; - } - return false; -} - -/***====================================================================***/ - -int -ExprResolveEnum(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn, const LookupEntry *values) -{ - if (expr->op != EXPR_IDENT) { + if (expr->expr.op != EXPR_IDENT) { log_err(ctx, "Found a %s where an enumerated value was expected\n", - exprOpText(expr->op)); + expr_op_type_to_string(expr->expr.op)); return false; } - if (!SimpleLookup(ctx, values, expr->value.str, EXPR_TYPE_INT, + + if (!SimpleLookup(ctx, values, expr->ident.ident, EXPR_TYPE_INT, val_rtrn)) { - int nOut = 0; - log_err(ctx, "Illegal identifier %s (expected one of: ", - xkb_atom_text(ctx, expr->value.str)); + log_err(ctx, "Illegal identifier %s; expected one of:\n", + xkb_atom_text(ctx, expr->ident.ident)); while (values && values->name) { - if (nOut != 0) - log_info(ctx, ", %s", values->name); - else - log_info(ctx, "%s", values->name); + log_err(ctx, "\t%s\n", values->name); values++; - nOut++; } - log_info(ctx, ")\n"); return false; } + return true; } -static int -ExprResolveMaskLookup(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn, IdentLookupFunc lookup, +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; const char *bogus = NULL; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_INT) { + if (expr->expr.value_type != EXPR_TYPE_INT) { log_err(ctx, "Found constant of type %s where a mask was expected\n", - exprValueTypeText(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - val_rtrn->ival = expr->value.ival; + *val_rtrn = (unsigned int) expr->integer.ival; return true; case EXPR_IDENT: - ok = lookup(ctx, lookupPriv, expr->value.str, EXPR_TYPE_INT, val_rtrn); + ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, + val_rtrn); if (!ok) log_err(ctx, "Identifier \"%s\" of type int is unknown\n", - xkb_atom_text(ctx, expr->value.str)); + xkb_atom_text(ctx, expr->ident.ident)); return ok; case EXPR_FIELD_REF: log_err(ctx, "Default \"%s.%s\" of type int is unknown\n", - xkb_atom_text(ctx, expr->value.field.element), - xkb_atom_text(ctx, expr->value.field.field)); + 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"; - + /* fallthrough */ case EXPR_ACTION_DECL: if (bogus == NULL) bogus = "function use"; @@ -742,104 +573,143 @@ ExprResolveMaskLookup(struct xkb_context *ctx, ExprDef *expr, case EXPR_SUBTRACT: case EXPR_MULTIPLY: case EXPR_DIVIDE: - left = expr->value.binary.left; - right = expr->value.binary.right; - if (ExprResolveMaskLookup(ctx, left, &leftRtrn, lookup, - lookupPriv) && - ExprResolveMaskLookup(ctx, right, &rightRtrn, lookup, - lookupPriv)) { - switch (expr->op) { - case EXPR_ADD: - val_rtrn->ival = leftRtrn.ival | rightRtrn.ival; - break; - case EXPR_SUBTRACT: - val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival); - break; - case EXPR_MULTIPLY: - case EXPR_DIVIDE: - log_err(ctx, "Cannot %s masks; Illegal operation ignored\n", - (expr->op == EXPR_DIVIDE ? "divide" : "multiply")); - return false; - default: - break; - } - return true; + 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; + + return true; case EXPR_ASSIGN: log_wsgo(ctx, "Assignment operator not implemented yet\n"); break; case EXPR_INVERT: - left = expr->value.child; - if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup, - lookupPriv)) { - val_rtrn->ival = ~leftRtrn.ival; - return true; - } - return false; + 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->value.child; - if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup, - lookupPriv)) { + 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->op == EXPR_NEGATE ? "-" : "!")); - } + (expr->expr.op == EXPR_NEGATE ? "-" : "!")); return false; default: - log_wsgo(ctx, "Unknown operator %d in ResolveMask\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveMask\n", + expr->expr.op); break; } + return false; } -int -ExprResolveMask(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn, const LookupEntry *values) +bool +ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr, + unsigned int *mask_rtrn, const LookupEntry *values) { - return ExprResolveMaskLookup(ctx, expr, val_rtrn, SimpleLookup, values); + return ExprResolveMaskLookup(ctx, expr, mask_rtrn, SimpleLookup, values); } -int -ExprResolveModMask(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn) +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) { - return ExprResolveMaskLookup(ctx, expr, val_rtrn, LookupModMask, NULL); + LookupModMaskPriv priv = { .mods = mods, .mod_type = mod_type }; + return ExprResolveMaskLookup(ctx, expr, mask_rtrn, LookupModMask, &priv); } -int -ExprResolveVModMask(struct xkb_keymap *keymap, ExprDef *expr, - ExprResult *val_rtrn) +bool +ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr, + xkb_keysym_t *sym_rtrn) { - return ExprResolveMaskLookup(keymap->ctx, expr, val_rtrn, LookupVModMask, - keymap); + 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) { + *sym_rtrn = (xkb_keysym_t) val; + return true; + } + + log_warn_with_code(ctx, XKB_WARNING_UNRECOGNIZED_KEYSYM, + "unrecognized keysym \"0x%x\" (%d)\n", + (unsigned int) val, val); + return false; + } -int -ExprResolveKeySym(struct xkb_context *ctx, ExprDef *expr, - ExprResult *val_rtrn) +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) { - int ok = 0; - xkb_keysym_t sym; - - if (expr->op == EXPR_IDENT) { - const char *str; - str = xkb_atom_text(ctx, expr->value.str); - if (str) { - sym = xkb_keysym_from_name(str); - if (sym != XKB_KEY_NoSymbol) { - val_rtrn->uval = sym; - return true; - } - } + 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; } - ok = ExprResolveInteger(ctx, expr, val_rtrn); - if ((ok) && (val_rtrn->uval < 10)) - val_rtrn->uval += '0'; - return ok; + + 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; }