Add a new warning for numeric keysyms
[platform/upstream/libxkbcommon.git] / src / xkbcomp / expr.c
index ba71208..558fef3 100644 (file)
  *
  ********************************************************/
 
+#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,
@@ -42,16 +45,20 @@ ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
         *elem_rtrn = NULL;
         *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->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->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;
@@ -83,7 +90,7 @@ SimpleLookup(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
 
 /* Data passed in the *priv argument for LookupModMask. */
 typedef struct {
-    const struct xkb_keymap *keymap;
+    const struct xkb_mod_set *mods;
     enum mod_type mod_type;
 } LookupModMaskPriv;
 
@@ -94,13 +101,15 @@ LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
     const char *str;
     xkb_mod_index_t ndx;
     const LookupModMaskPriv *arg = priv;
-    const struct xkb_keymap *keymap = arg->keymap;
+    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;
@@ -112,11 +121,11 @@ LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
         return true;
     }
 
-    ndx = ModNameToIndex(keymap, field, mod_type);
+    ndx = XkbModNameToIndex(mods, field, mod_type);
     if (ndx == XKB_MOD_INVALID)
         return false;
 
-    *val_rtrn = (1 << ndx);
+    *val_rtrn = (1u << ndx);
     return true;
 }
 
@@ -165,7 +174,7 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
 
     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;
@@ -176,6 +185,9 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
     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;
@@ -337,7 +349,9 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
             *val_rtrn = l / r;
             break;
         default:
-            break;
+            log_err(ctx, "%s of integers not permitted\n",
+                    expr_op_type_to_string(expr->expr.op));
+            return false;
         }
 
         return true;
@@ -393,8 +407,9 @@ ExprResolveGroup(struct xkb_context *ctx, const ExprDef *expr,
         return false;
 
     if (result <= 0 || result > XKB_MAX_GROUPS) {
-        log_err(ctx, "Group index %u is out of range (1..%d)\n",
-                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;
     }
 
@@ -415,7 +430,8 @@ ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr,
         return false;
 
     if (result < 1) {
-        log_err(ctx, "Shift level %d is out of range\n", result);
+        log_err_with_code(ctx, XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL,
+                          "Shift level %d is out of range\n", result);
         return false;
     }
 
@@ -427,14 +443,8 @@ ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr,
 bool
 ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, int *btn_rtrn)
 {
-    int result;
-
-    if (!ExprResolveIntegerLookup(ctx, expr, &result, SimpleLookup,
-                                  buttonNames))
-        return false;
-
-    *btn_rtrn = result;
-    return true;
+    return ExprResolveIntegerLookup(ctx, expr, btn_rtrn, SimpleLookup,
+                                    buttonNames);
 }
 
 bool
@@ -472,6 +482,9 @@ ExprResolveString(struct xkb_context *ctx, const ExprDef *expr,
     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;
@@ -514,8 +527,8 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
                       unsigned int *val_rtrn, IdentLookupFunc lookup,
                       const void *lookupPriv)
 {
-    bool ok = 0;
-    unsigned int l, r;
+    bool ok = false;
+    unsigned int l = 0, r = 0;
     int v;
     ExprDef *left, *right;
     const char *bogus = NULL;
@@ -547,7 +560,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
 
     case EXPR_ARRAY_REF:
         bogus = "array reference";
-
+        /* fallthrough */
     case EXPR_ACTION_DECL:
         if (bogus == NULL)
             bogus = "function use";
@@ -622,12 +635,12 @@ ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr,
 }
 
 bool
-ExprResolveModMask(struct xkb_keymap *keymap, const ExprDef *expr,
-                   enum mod_type mod_type, xkb_mod_mask_t *mask_rtrn)
+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 = { .keymap = keymap, .mod_type = mod_type };
-    return ExprResolveMaskLookup(keymap->ctx, expr, mask_rtrn, LookupModMask,
-                                 &priv);
+    LookupModMaskPriv priv = { .mods = mods, .mod_type = mod_type };
+    return ExprResolveMaskLookup(ctx, expr, mask_rtrn, LookupModMask, &priv);
 }
 
 bool
@@ -646,22 +659,44 @@ ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr,
     if (!ExprResolveInteger(ctx, expr, &val))
         return false;
 
-    if (val < 0 || val >= 10)
+    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;
+    }
+
+    log_warn_with_code(ctx, XKB_WARNING_UNRECOGNIZED_KEYSYM,
+                       "unrecognized keysym \"0x%x\" (%d)\n",
+                       (unsigned int) val, val);
+    return false;
 
-    *sym_rtrn = XKB_KEY_0 + (xkb_keysym_t) val;
-    return true;
 }
 
 bool
-ExprResolveMod(struct xkb_keymap *keymap, const ExprDef *def,
-               enum mod_type mod_type, xkb_mod_index_t *ndx_rtrn)
+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(keymap->ctx,
+        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));
@@ -669,12 +704,12 @@ ExprResolveMod(struct xkb_keymap *keymap, const ExprDef *def,
     }
 
     name = def->ident.ident;
-    ndx = ModNameToIndex(keymap, name, mod_type);
+    ndx = XkbModNameToIndex(mods, name, mod_type);
     if (ndx == XKB_MOD_INVALID) {
-        log_err(keymap->ctx,
+        log_err(ctx,
                 "Cannot resolve virtual modifier: "
                 "\"%s\" was not previously declared\n",
-                xkb_atom_text(keymap->ctx, name));
+                xkb_atom_text(ctx, name));
         return false;
     }