Add a new warning for numeric keysyms
[platform/upstream/libxkbcommon.git] / src / xkbcomp / expr.c
index 3ff3c18..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;
@@ -101,6 +108,8 @@ LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
         return false;
 
     str = xkb_atom_text(ctx, field);
+    if (!str)
+        return false;
 
     if (istreq(str, "all")) {
         *val_rtrn  = MOD_REAL_MASK_ALL;
@@ -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;
@@ -395,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;
     }
 
@@ -417,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;
     }
 
@@ -468,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;
@@ -543,7 +560,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
 
     case EXPR_ARRAY_REF:
         bogus = "array reference";
-       /* fallthrough */
+        /* fallthrough */
     case EXPR_ACTION_DECL:
         if (bogus == NULL)
             bogus = "function use";
@@ -642,11 +659,32 @@ 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