xref: /aosp_15_r20/external/libxkbcommon/src/xkbcomp/expr.c (revision 2b949d0487e80d67f1fda82db69e101e761f8064)
1*2b949d04SAndroid Build Coastguard Worker /************************************************************
2*2b949d04SAndroid Build Coastguard Worker  * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3*2b949d04SAndroid Build Coastguard Worker  *
4*2b949d04SAndroid Build Coastguard Worker  * Permission to use, copy, modify, and distribute this
5*2b949d04SAndroid Build Coastguard Worker  * software and its documentation for any purpose and without
6*2b949d04SAndroid Build Coastguard Worker  * fee is hereby granted, provided that the above copyright
7*2b949d04SAndroid Build Coastguard Worker  * notice appear in all copies and that both that copyright
8*2b949d04SAndroid Build Coastguard Worker  * notice and this permission notice appear in supporting
9*2b949d04SAndroid Build Coastguard Worker  * documentation, and that the name of Silicon Graphics not be
10*2b949d04SAndroid Build Coastguard Worker  * used in advertising or publicity pertaining to distribution
11*2b949d04SAndroid Build Coastguard Worker  * of the software without specific prior written permission.
12*2b949d04SAndroid Build Coastguard Worker  * Silicon Graphics makes no representation about the suitability
13*2b949d04SAndroid Build Coastguard Worker  * of this software for any purpose. It is provided "as is"
14*2b949d04SAndroid Build Coastguard Worker  * without any express or implied warranty.
15*2b949d04SAndroid Build Coastguard Worker  *
16*2b949d04SAndroid Build Coastguard Worker  * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17*2b949d04SAndroid Build Coastguard Worker  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18*2b949d04SAndroid Build Coastguard Worker  * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19*2b949d04SAndroid Build Coastguard Worker  * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20*2b949d04SAndroid Build Coastguard Worker  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21*2b949d04SAndroid Build Coastguard Worker  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22*2b949d04SAndroid Build Coastguard Worker  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23*2b949d04SAndroid Build Coastguard Worker  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
24*2b949d04SAndroid Build Coastguard Worker  *
25*2b949d04SAndroid Build Coastguard Worker  ********************************************************/
26*2b949d04SAndroid Build Coastguard Worker 
27*2b949d04SAndroid Build Coastguard Worker #include "config.h"
28*2b949d04SAndroid Build Coastguard Worker 
29*2b949d04SAndroid Build Coastguard Worker #include "xkbcomp-priv.h"
30*2b949d04SAndroid Build Coastguard Worker #include "text.h"
31*2b949d04SAndroid Build Coastguard Worker #include "expr.h"
32*2b949d04SAndroid Build Coastguard Worker 
33*2b949d04SAndroid Build Coastguard Worker typedef bool (*IdentLookupFunc)(struct xkb_context *ctx, const void *priv,
34*2b949d04SAndroid Build Coastguard Worker                                 xkb_atom_t field, enum expr_value_type type,
35*2b949d04SAndroid Build Coastguard Worker                                 unsigned int *val_rtrn);
36*2b949d04SAndroid Build Coastguard Worker 
37*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveLhs(struct xkb_context * ctx,const ExprDef * expr,const char ** elem_rtrn,const char ** field_rtrn,ExprDef ** index_rtrn)38*2b949d04SAndroid Build Coastguard Worker ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
39*2b949d04SAndroid Build Coastguard Worker                const char **elem_rtrn, const char **field_rtrn,
40*2b949d04SAndroid Build Coastguard Worker                ExprDef **index_rtrn)
41*2b949d04SAndroid Build Coastguard Worker {
42*2b949d04SAndroid Build Coastguard Worker     switch (expr->expr.op) {
43*2b949d04SAndroid Build Coastguard Worker     case EXPR_IDENT:
44*2b949d04SAndroid Build Coastguard Worker         *elem_rtrn = NULL;
45*2b949d04SAndroid Build Coastguard Worker         *field_rtrn = xkb_atom_text(ctx, expr->ident.ident);
46*2b949d04SAndroid Build Coastguard Worker         *index_rtrn = NULL;
47*2b949d04SAndroid Build Coastguard Worker         return (*field_rtrn != NULL);
48*2b949d04SAndroid Build Coastguard Worker     case EXPR_FIELD_REF:
49*2b949d04SAndroid Build Coastguard Worker         *elem_rtrn = xkb_atom_text(ctx, expr->field_ref.element);
50*2b949d04SAndroid Build Coastguard Worker         *field_rtrn = xkb_atom_text(ctx, expr->field_ref.field);
51*2b949d04SAndroid Build Coastguard Worker         *index_rtrn = NULL;
52*2b949d04SAndroid Build Coastguard Worker         return (*elem_rtrn != NULL && *field_rtrn != NULL);
53*2b949d04SAndroid Build Coastguard Worker     case EXPR_ARRAY_REF:
54*2b949d04SAndroid Build Coastguard Worker         *elem_rtrn = xkb_atom_text(ctx, expr->array_ref.element);
55*2b949d04SAndroid Build Coastguard Worker         *field_rtrn = xkb_atom_text(ctx, expr->array_ref.field);
56*2b949d04SAndroid Build Coastguard Worker         *index_rtrn = expr->array_ref.entry;
57*2b949d04SAndroid Build Coastguard Worker         if (expr->array_ref.element != XKB_ATOM_NONE && *elem_rtrn == NULL)
58*2b949d04SAndroid Build Coastguard Worker             return false;
59*2b949d04SAndroid Build Coastguard Worker         if (*field_rtrn == NULL)
60*2b949d04SAndroid Build Coastguard Worker             return false;
61*2b949d04SAndroid Build Coastguard Worker         return true;
62*2b949d04SAndroid Build Coastguard Worker     default:
63*2b949d04SAndroid Build Coastguard Worker         break;
64*2b949d04SAndroid Build Coastguard Worker     }
65*2b949d04SAndroid Build Coastguard Worker     log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->expr.op);
66*2b949d04SAndroid Build Coastguard Worker     return false;
67*2b949d04SAndroid Build Coastguard Worker }
68*2b949d04SAndroid Build Coastguard Worker 
69*2b949d04SAndroid Build Coastguard Worker static bool
SimpleLookup(struct xkb_context * ctx,const void * priv,xkb_atom_t field,enum expr_value_type type,unsigned int * val_rtrn)70*2b949d04SAndroid Build Coastguard Worker SimpleLookup(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
71*2b949d04SAndroid Build Coastguard Worker              enum expr_value_type type, unsigned int *val_rtrn)
72*2b949d04SAndroid Build Coastguard Worker {
73*2b949d04SAndroid Build Coastguard Worker     const LookupEntry *entry;
74*2b949d04SAndroid Build Coastguard Worker     const char *str;
75*2b949d04SAndroid Build Coastguard Worker 
76*2b949d04SAndroid Build Coastguard Worker     if (!priv || field == XKB_ATOM_NONE || type != EXPR_TYPE_INT)
77*2b949d04SAndroid Build Coastguard Worker         return false;
78*2b949d04SAndroid Build Coastguard Worker 
79*2b949d04SAndroid Build Coastguard Worker     str = xkb_atom_text(ctx, field);
80*2b949d04SAndroid Build Coastguard Worker     for (entry = priv; entry && entry->name; entry++) {
81*2b949d04SAndroid Build Coastguard Worker         if (istreq(str, entry->name)) {
82*2b949d04SAndroid Build Coastguard Worker             *val_rtrn = entry->value;
83*2b949d04SAndroid Build Coastguard Worker             return true;
84*2b949d04SAndroid Build Coastguard Worker         }
85*2b949d04SAndroid Build Coastguard Worker     }
86*2b949d04SAndroid Build Coastguard Worker 
87*2b949d04SAndroid Build Coastguard Worker     return false;
88*2b949d04SAndroid Build Coastguard Worker }
89*2b949d04SAndroid Build Coastguard Worker 
90*2b949d04SAndroid Build Coastguard Worker /* Data passed in the *priv argument for LookupModMask. */
91*2b949d04SAndroid Build Coastguard Worker typedef struct {
92*2b949d04SAndroid Build Coastguard Worker     const struct xkb_mod_set *mods;
93*2b949d04SAndroid Build Coastguard Worker     enum mod_type mod_type;
94*2b949d04SAndroid Build Coastguard Worker } LookupModMaskPriv;
95*2b949d04SAndroid Build Coastguard Worker 
96*2b949d04SAndroid Build Coastguard Worker 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)97*2b949d04SAndroid Build Coastguard Worker LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
98*2b949d04SAndroid Build Coastguard Worker               enum expr_value_type type, xkb_mod_mask_t *val_rtrn)
99*2b949d04SAndroid Build Coastguard Worker {
100*2b949d04SAndroid Build Coastguard Worker     const char *str;
101*2b949d04SAndroid Build Coastguard Worker     xkb_mod_index_t ndx;
102*2b949d04SAndroid Build Coastguard Worker     const LookupModMaskPriv *arg = priv;
103*2b949d04SAndroid Build Coastguard Worker     const struct xkb_mod_set *mods = arg->mods;
104*2b949d04SAndroid Build Coastguard Worker     enum mod_type mod_type = arg->mod_type;
105*2b949d04SAndroid Build Coastguard Worker 
106*2b949d04SAndroid Build Coastguard Worker     if (type != EXPR_TYPE_INT)
107*2b949d04SAndroid Build Coastguard Worker         return false;
108*2b949d04SAndroid Build Coastguard Worker 
109*2b949d04SAndroid Build Coastguard Worker     str = xkb_atom_text(ctx, field);
110*2b949d04SAndroid Build Coastguard Worker     if (!str)
111*2b949d04SAndroid Build Coastguard Worker         return false;
112*2b949d04SAndroid Build Coastguard Worker 
113*2b949d04SAndroid Build Coastguard Worker     if (istreq(str, "all")) {
114*2b949d04SAndroid Build Coastguard Worker         *val_rtrn  = MOD_REAL_MASK_ALL;
115*2b949d04SAndroid Build Coastguard Worker         return true;
116*2b949d04SAndroid Build Coastguard Worker     }
117*2b949d04SAndroid Build Coastguard Worker 
118*2b949d04SAndroid Build Coastguard Worker     if (istreq(str, "none")) {
119*2b949d04SAndroid Build Coastguard Worker         *val_rtrn = 0;
120*2b949d04SAndroid Build Coastguard Worker         return true;
121*2b949d04SAndroid Build Coastguard Worker     }
122*2b949d04SAndroid Build Coastguard Worker 
123*2b949d04SAndroid Build Coastguard Worker     ndx = XkbModNameToIndex(mods, field, mod_type);
124*2b949d04SAndroid Build Coastguard Worker     if (ndx == XKB_MOD_INVALID)
125*2b949d04SAndroid Build Coastguard Worker         return false;
126*2b949d04SAndroid Build Coastguard Worker 
127*2b949d04SAndroid Build Coastguard Worker     *val_rtrn = (1u << ndx);
128*2b949d04SAndroid Build Coastguard Worker     return true;
129*2b949d04SAndroid Build Coastguard Worker }
130*2b949d04SAndroid Build Coastguard Worker 
131*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveBoolean(struct xkb_context * ctx,const ExprDef * expr,bool * set_rtrn)132*2b949d04SAndroid Build Coastguard Worker ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
133*2b949d04SAndroid Build Coastguard Worker                    bool *set_rtrn)
134*2b949d04SAndroid Build Coastguard Worker {
135*2b949d04SAndroid Build Coastguard Worker     bool ok = false;
136*2b949d04SAndroid Build Coastguard Worker     const char *ident;
137*2b949d04SAndroid Build Coastguard Worker 
138*2b949d04SAndroid Build Coastguard Worker     switch (expr->expr.op) {
139*2b949d04SAndroid Build Coastguard Worker     case EXPR_VALUE:
140*2b949d04SAndroid Build Coastguard Worker         if (expr->expr.value_type != EXPR_TYPE_BOOLEAN) {
141*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
142*2b949d04SAndroid Build Coastguard Worker                     "Found constant of type %s where boolean was expected\n",
143*2b949d04SAndroid Build Coastguard Worker                     expr_value_type_to_string(expr->expr.value_type));
144*2b949d04SAndroid Build Coastguard Worker             return false;
145*2b949d04SAndroid Build Coastguard Worker         }
146*2b949d04SAndroid Build Coastguard Worker         *set_rtrn = expr->boolean.set;
147*2b949d04SAndroid Build Coastguard Worker         return true;
148*2b949d04SAndroid Build Coastguard Worker 
149*2b949d04SAndroid Build Coastguard Worker     case EXPR_IDENT:
150*2b949d04SAndroid Build Coastguard Worker         ident = xkb_atom_text(ctx, expr->ident.ident);
151*2b949d04SAndroid Build Coastguard Worker         if (ident) {
152*2b949d04SAndroid Build Coastguard Worker             if (istreq(ident, "true") ||
153*2b949d04SAndroid Build Coastguard Worker                 istreq(ident, "yes") ||
154*2b949d04SAndroid Build Coastguard Worker                 istreq(ident, "on")) {
155*2b949d04SAndroid Build Coastguard Worker                 *set_rtrn = true;
156*2b949d04SAndroid Build Coastguard Worker                 return true;
157*2b949d04SAndroid Build Coastguard Worker             }
158*2b949d04SAndroid Build Coastguard Worker             else if (istreq(ident, "false") ||
159*2b949d04SAndroid Build Coastguard Worker                      istreq(ident, "no") ||
160*2b949d04SAndroid Build Coastguard Worker                      istreq(ident, "off")) {
161*2b949d04SAndroid Build Coastguard Worker                 *set_rtrn = false;
162*2b949d04SAndroid Build Coastguard Worker                 return true;
163*2b949d04SAndroid Build Coastguard Worker             }
164*2b949d04SAndroid Build Coastguard Worker         }
165*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n", ident);
166*2b949d04SAndroid Build Coastguard Worker         return false;
167*2b949d04SAndroid Build Coastguard Worker 
168*2b949d04SAndroid Build Coastguard Worker     case EXPR_FIELD_REF:
169*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Default \"%s.%s\" of type boolean is unknown\n",
170*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->field_ref.element),
171*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->field_ref.field));
172*2b949d04SAndroid Build Coastguard Worker         return false;
173*2b949d04SAndroid Build Coastguard Worker 
174*2b949d04SAndroid Build Coastguard Worker     case EXPR_INVERT:
175*2b949d04SAndroid Build Coastguard Worker     case EXPR_NOT:
176*2b949d04SAndroid Build Coastguard Worker         ok = ExprResolveBoolean(ctx, expr->unary.child, set_rtrn);
177*2b949d04SAndroid Build Coastguard Worker         if (ok)
178*2b949d04SAndroid Build Coastguard Worker             *set_rtrn = !*set_rtrn;
179*2b949d04SAndroid Build Coastguard Worker         return ok;
180*2b949d04SAndroid Build Coastguard Worker     case EXPR_ADD:
181*2b949d04SAndroid Build Coastguard Worker     case EXPR_SUBTRACT:
182*2b949d04SAndroid Build Coastguard Worker     case EXPR_MULTIPLY:
183*2b949d04SAndroid Build Coastguard Worker     case EXPR_DIVIDE:
184*2b949d04SAndroid Build Coastguard Worker     case EXPR_ASSIGN:
185*2b949d04SAndroid Build Coastguard Worker     case EXPR_NEGATE:
186*2b949d04SAndroid Build Coastguard Worker     case EXPR_UNARY_PLUS:
187*2b949d04SAndroid Build Coastguard Worker     case EXPR_ACTION_DECL:
188*2b949d04SAndroid Build Coastguard Worker     case EXPR_ACTION_LIST:
189*2b949d04SAndroid Build Coastguard Worker     case EXPR_KEYSYM_LIST:
190*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "%s of boolean values not permitted\n",
191*2b949d04SAndroid Build Coastguard Worker                 expr_op_type_to_string(expr->expr.op));
192*2b949d04SAndroid Build Coastguard Worker         break;
193*2b949d04SAndroid Build Coastguard Worker 
194*2b949d04SAndroid Build Coastguard Worker     default:
195*2b949d04SAndroid Build Coastguard Worker         log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n",
196*2b949d04SAndroid Build Coastguard Worker                  expr->expr.op);
197*2b949d04SAndroid Build Coastguard Worker         break;
198*2b949d04SAndroid Build Coastguard Worker     }
199*2b949d04SAndroid Build Coastguard Worker 
200*2b949d04SAndroid Build Coastguard Worker     return false;
201*2b949d04SAndroid Build Coastguard Worker }
202*2b949d04SAndroid Build Coastguard Worker 
203*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveKeyCode(struct xkb_context * ctx,const ExprDef * expr,xkb_keycode_t * kc)204*2b949d04SAndroid Build Coastguard Worker ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr,
205*2b949d04SAndroid Build Coastguard Worker                    xkb_keycode_t *kc)
206*2b949d04SAndroid Build Coastguard Worker {
207*2b949d04SAndroid Build Coastguard Worker     xkb_keycode_t leftRtrn, rightRtrn;
208*2b949d04SAndroid Build Coastguard Worker 
209*2b949d04SAndroid Build Coastguard Worker     switch (expr->expr.op) {
210*2b949d04SAndroid Build Coastguard Worker     case EXPR_VALUE:
211*2b949d04SAndroid Build Coastguard Worker         if (expr->expr.value_type != EXPR_TYPE_INT) {
212*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
213*2b949d04SAndroid Build Coastguard Worker                     "Found constant of type %s where an int was expected\n",
214*2b949d04SAndroid Build Coastguard Worker                     expr_value_type_to_string(expr->expr.value_type));
215*2b949d04SAndroid Build Coastguard Worker             return false;
216*2b949d04SAndroid Build Coastguard Worker         }
217*2b949d04SAndroid Build Coastguard Worker 
218*2b949d04SAndroid Build Coastguard Worker         *kc = (xkb_keycode_t) expr->integer.ival;
219*2b949d04SAndroid Build Coastguard Worker         return true;
220*2b949d04SAndroid Build Coastguard Worker 
221*2b949d04SAndroid Build Coastguard Worker     case EXPR_ADD:
222*2b949d04SAndroid Build Coastguard Worker     case EXPR_SUBTRACT:
223*2b949d04SAndroid Build Coastguard Worker     case EXPR_MULTIPLY:
224*2b949d04SAndroid Build Coastguard Worker     case EXPR_DIVIDE:
225*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveKeyCode(ctx, expr->binary.left, &leftRtrn) ||
226*2b949d04SAndroid Build Coastguard Worker             !ExprResolveKeyCode(ctx, expr->binary.right, &rightRtrn))
227*2b949d04SAndroid Build Coastguard Worker             return false;
228*2b949d04SAndroid Build Coastguard Worker 
229*2b949d04SAndroid Build Coastguard Worker         switch (expr->expr.op) {
230*2b949d04SAndroid Build Coastguard Worker         case EXPR_ADD:
231*2b949d04SAndroid Build Coastguard Worker             *kc = leftRtrn + rightRtrn;
232*2b949d04SAndroid Build Coastguard Worker             break;
233*2b949d04SAndroid Build Coastguard Worker         case EXPR_SUBTRACT:
234*2b949d04SAndroid Build Coastguard Worker             *kc = leftRtrn - rightRtrn;
235*2b949d04SAndroid Build Coastguard Worker             break;
236*2b949d04SAndroid Build Coastguard Worker         case EXPR_MULTIPLY:
237*2b949d04SAndroid Build Coastguard Worker             *kc = leftRtrn * rightRtrn;
238*2b949d04SAndroid Build Coastguard Worker             break;
239*2b949d04SAndroid Build Coastguard Worker         case EXPR_DIVIDE:
240*2b949d04SAndroid Build Coastguard Worker             if (rightRtrn == 0) {
241*2b949d04SAndroid Build Coastguard Worker                 log_err(ctx, "Cannot divide by zero: %d / %d\n",
242*2b949d04SAndroid Build Coastguard Worker                         leftRtrn, rightRtrn);
243*2b949d04SAndroid Build Coastguard Worker                 return false;
244*2b949d04SAndroid Build Coastguard Worker             }
245*2b949d04SAndroid Build Coastguard Worker 
246*2b949d04SAndroid Build Coastguard Worker             *kc = leftRtrn / rightRtrn;
247*2b949d04SAndroid Build Coastguard Worker             break;
248*2b949d04SAndroid Build Coastguard Worker         default:
249*2b949d04SAndroid Build Coastguard Worker             break;
250*2b949d04SAndroid Build Coastguard Worker         }
251*2b949d04SAndroid Build Coastguard Worker 
252*2b949d04SAndroid Build Coastguard Worker         return true;
253*2b949d04SAndroid Build Coastguard Worker 
254*2b949d04SAndroid Build Coastguard Worker     case EXPR_NEGATE:
255*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveKeyCode(ctx, expr->unary.child, &leftRtrn))
256*2b949d04SAndroid Build Coastguard Worker             return false;
257*2b949d04SAndroid Build Coastguard Worker 
258*2b949d04SAndroid Build Coastguard Worker         *kc = ~leftRtrn;
259*2b949d04SAndroid Build Coastguard Worker         return true;
260*2b949d04SAndroid Build Coastguard Worker 
261*2b949d04SAndroid Build Coastguard Worker     case EXPR_UNARY_PLUS:
262*2b949d04SAndroid Build Coastguard Worker         return ExprResolveKeyCode(ctx, expr->unary.child, kc);
263*2b949d04SAndroid Build Coastguard Worker 
264*2b949d04SAndroid Build Coastguard Worker     default:
265*2b949d04SAndroid Build Coastguard Worker         log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n",
266*2b949d04SAndroid Build Coastguard Worker                  expr->expr.op);
267*2b949d04SAndroid Build Coastguard Worker         break;
268*2b949d04SAndroid Build Coastguard Worker     }
269*2b949d04SAndroid Build Coastguard Worker 
270*2b949d04SAndroid Build Coastguard Worker     return false;
271*2b949d04SAndroid Build Coastguard Worker }
272*2b949d04SAndroid Build Coastguard Worker 
273*2b949d04SAndroid Build Coastguard Worker /**
274*2b949d04SAndroid Build Coastguard Worker  * This function returns ... something.  It's a bit of a guess, really.
275*2b949d04SAndroid Build Coastguard Worker  *
276*2b949d04SAndroid Build Coastguard Worker  * If an integer is given in value ctx, it will be returned in ival.
277*2b949d04SAndroid Build Coastguard Worker  * If an ident or field reference is given, the lookup function (if given)
278*2b949d04SAndroid Build Coastguard Worker  * will be called.  At the moment, only SimpleLookup use this, and they both
279*2b949d04SAndroid Build Coastguard Worker  * return the results in uval.  And don't support field references.
280*2b949d04SAndroid Build Coastguard Worker  *
281*2b949d04SAndroid Build Coastguard Worker  * Cool.
282*2b949d04SAndroid Build Coastguard Worker  */
283*2b949d04SAndroid Build Coastguard Worker static bool
ExprResolveIntegerLookup(struct xkb_context * ctx,const ExprDef * expr,int * val_rtrn,IdentLookupFunc lookup,const void * lookupPriv)284*2b949d04SAndroid Build Coastguard Worker ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
285*2b949d04SAndroid Build Coastguard Worker                          int *val_rtrn, IdentLookupFunc lookup,
286*2b949d04SAndroid Build Coastguard Worker                          const void *lookupPriv)
287*2b949d04SAndroid Build Coastguard Worker {
288*2b949d04SAndroid Build Coastguard Worker     bool ok = false;
289*2b949d04SAndroid Build Coastguard Worker     int l, r;
290*2b949d04SAndroid Build Coastguard Worker     unsigned u;
291*2b949d04SAndroid Build Coastguard Worker     ExprDef *left, *right;
292*2b949d04SAndroid Build Coastguard Worker 
293*2b949d04SAndroid Build Coastguard Worker     switch (expr->expr.op) {
294*2b949d04SAndroid Build Coastguard Worker     case EXPR_VALUE:
295*2b949d04SAndroid Build Coastguard Worker         if (expr->expr.value_type != EXPR_TYPE_INT) {
296*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
297*2b949d04SAndroid Build Coastguard Worker                     "Found constant of type %s where an int was expected\n",
298*2b949d04SAndroid Build Coastguard Worker                     expr_value_type_to_string(expr->expr.value_type));
299*2b949d04SAndroid Build Coastguard Worker             return false;
300*2b949d04SAndroid Build Coastguard Worker         }
301*2b949d04SAndroid Build Coastguard Worker 
302*2b949d04SAndroid Build Coastguard Worker         *val_rtrn = expr->integer.ival;
303*2b949d04SAndroid Build Coastguard Worker         return true;
304*2b949d04SAndroid Build Coastguard Worker 
305*2b949d04SAndroid Build Coastguard Worker     case EXPR_IDENT:
306*2b949d04SAndroid Build Coastguard Worker         if (lookup)
307*2b949d04SAndroid Build Coastguard Worker             ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, &u);
308*2b949d04SAndroid Build Coastguard Worker 
309*2b949d04SAndroid Build Coastguard Worker         if (!ok)
310*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "Identifier \"%s\" of type int is unknown\n",
311*2b949d04SAndroid Build Coastguard Worker                     xkb_atom_text(ctx, expr->ident.ident));
312*2b949d04SAndroid Build Coastguard Worker         else
313*2b949d04SAndroid Build Coastguard Worker             *val_rtrn = (int) u;
314*2b949d04SAndroid Build Coastguard Worker 
315*2b949d04SAndroid Build Coastguard Worker         return ok;
316*2b949d04SAndroid Build Coastguard Worker 
317*2b949d04SAndroid Build Coastguard Worker     case EXPR_FIELD_REF:
318*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Default \"%s.%s\" of type int is unknown\n",
319*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->field_ref.element),
320*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->field_ref.field));
321*2b949d04SAndroid Build Coastguard Worker         return false;
322*2b949d04SAndroid Build Coastguard Worker 
323*2b949d04SAndroid Build Coastguard Worker     case EXPR_ADD:
324*2b949d04SAndroid Build Coastguard Worker     case EXPR_SUBTRACT:
325*2b949d04SAndroid Build Coastguard Worker     case EXPR_MULTIPLY:
326*2b949d04SAndroid Build Coastguard Worker     case EXPR_DIVIDE:
327*2b949d04SAndroid Build Coastguard Worker         left = expr->binary.left;
328*2b949d04SAndroid Build Coastguard Worker         right = expr->binary.right;
329*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv) ||
330*2b949d04SAndroid Build Coastguard Worker             !ExprResolveIntegerLookup(ctx, right, &r, lookup, lookupPriv))
331*2b949d04SAndroid Build Coastguard Worker             return false;
332*2b949d04SAndroid Build Coastguard Worker 
333*2b949d04SAndroid Build Coastguard Worker         switch (expr->expr.op) {
334*2b949d04SAndroid Build Coastguard Worker         case EXPR_ADD:
335*2b949d04SAndroid Build Coastguard Worker             *val_rtrn = l + r;
336*2b949d04SAndroid Build Coastguard Worker             break;
337*2b949d04SAndroid Build Coastguard Worker         case EXPR_SUBTRACT:
338*2b949d04SAndroid Build Coastguard Worker             *val_rtrn = l - r;
339*2b949d04SAndroid Build Coastguard Worker             break;
340*2b949d04SAndroid Build Coastguard Worker         case EXPR_MULTIPLY:
341*2b949d04SAndroid Build Coastguard Worker             *val_rtrn = l * r;
342*2b949d04SAndroid Build Coastguard Worker             break;
343*2b949d04SAndroid Build Coastguard Worker         case EXPR_DIVIDE:
344*2b949d04SAndroid Build Coastguard Worker             if (r == 0) {
345*2b949d04SAndroid Build Coastguard Worker                 log_err(ctx, "Cannot divide by zero: %d / %d\n", l, r);
346*2b949d04SAndroid Build Coastguard Worker                 return false;
347*2b949d04SAndroid Build Coastguard Worker             }
348*2b949d04SAndroid Build Coastguard Worker             *val_rtrn = l / r;
349*2b949d04SAndroid Build Coastguard Worker             break;
350*2b949d04SAndroid Build Coastguard Worker         default:
351*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "%s of integers not permitted\n",
352*2b949d04SAndroid Build Coastguard Worker                     expr_op_type_to_string(expr->expr.op));
353*2b949d04SAndroid Build Coastguard Worker             return false;
354*2b949d04SAndroid Build Coastguard Worker         }
355*2b949d04SAndroid Build Coastguard Worker 
356*2b949d04SAndroid Build Coastguard Worker         return true;
357*2b949d04SAndroid Build Coastguard Worker 
358*2b949d04SAndroid Build Coastguard Worker     case EXPR_ASSIGN:
359*2b949d04SAndroid Build Coastguard Worker         log_wsgo(ctx, "Assignment operator not implemented yet\n");
360*2b949d04SAndroid Build Coastguard Worker         break;
361*2b949d04SAndroid Build Coastguard Worker 
362*2b949d04SAndroid Build Coastguard Worker     case EXPR_NOT:
363*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "The ! operator cannot be applied to an integer\n");
364*2b949d04SAndroid Build Coastguard Worker         return false;
365*2b949d04SAndroid Build Coastguard Worker 
366*2b949d04SAndroid Build Coastguard Worker     case EXPR_INVERT:
367*2b949d04SAndroid Build Coastguard Worker     case EXPR_NEGATE:
368*2b949d04SAndroid Build Coastguard Worker         left = expr->unary.child;
369*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv))
370*2b949d04SAndroid Build Coastguard Worker             return false;
371*2b949d04SAndroid Build Coastguard Worker 
372*2b949d04SAndroid Build Coastguard Worker         *val_rtrn = (expr->expr.op == EXPR_NEGATE ? -l : ~l);
373*2b949d04SAndroid Build Coastguard Worker         return true;
374*2b949d04SAndroid Build Coastguard Worker 
375*2b949d04SAndroid Build Coastguard Worker     case EXPR_UNARY_PLUS:
376*2b949d04SAndroid Build Coastguard Worker         left = expr->unary.child;
377*2b949d04SAndroid Build Coastguard Worker         return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup,
378*2b949d04SAndroid Build Coastguard Worker                                         lookupPriv);
379*2b949d04SAndroid Build Coastguard Worker 
380*2b949d04SAndroid Build Coastguard Worker     default:
381*2b949d04SAndroid Build Coastguard Worker         log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n",
382*2b949d04SAndroid Build Coastguard Worker                  expr->expr.op);
383*2b949d04SAndroid Build Coastguard Worker         break;
384*2b949d04SAndroid Build Coastguard Worker     }
385*2b949d04SAndroid Build Coastguard Worker 
386*2b949d04SAndroid Build Coastguard Worker     return false;
387*2b949d04SAndroid Build Coastguard Worker }
388*2b949d04SAndroid Build Coastguard Worker 
389*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveInteger(struct xkb_context * ctx,const ExprDef * expr,int * val_rtrn)390*2b949d04SAndroid Build Coastguard Worker ExprResolveInteger(struct xkb_context *ctx, const ExprDef *expr,
391*2b949d04SAndroid Build Coastguard Worker                    int *val_rtrn)
392*2b949d04SAndroid Build Coastguard Worker {
393*2b949d04SAndroid Build Coastguard Worker     return ExprResolveIntegerLookup(ctx, expr, val_rtrn, NULL, NULL);
394*2b949d04SAndroid Build Coastguard Worker }
395*2b949d04SAndroid Build Coastguard Worker 
396*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveGroup(struct xkb_context * ctx,const ExprDef * expr,xkb_layout_index_t * group_rtrn)397*2b949d04SAndroid Build Coastguard Worker ExprResolveGroup(struct xkb_context *ctx, const ExprDef *expr,
398*2b949d04SAndroid Build Coastguard Worker                  xkb_layout_index_t *group_rtrn)
399*2b949d04SAndroid Build Coastguard Worker {
400*2b949d04SAndroid Build Coastguard Worker     bool ok;
401*2b949d04SAndroid Build Coastguard Worker     int result;
402*2b949d04SAndroid Build Coastguard Worker 
403*2b949d04SAndroid Build Coastguard Worker     ok = ExprResolveIntegerLookup(ctx, expr, &result, SimpleLookup,
404*2b949d04SAndroid Build Coastguard Worker                                   groupNames);
405*2b949d04SAndroid Build Coastguard Worker     if (!ok)
406*2b949d04SAndroid Build Coastguard Worker         return false;
407*2b949d04SAndroid Build Coastguard Worker 
408*2b949d04SAndroid Build Coastguard Worker     if (result <= 0 || result > XKB_MAX_GROUPS) {
409*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Group index %u is out of range (1..%d)\n",
410*2b949d04SAndroid Build Coastguard Worker                 result, XKB_MAX_GROUPS);
411*2b949d04SAndroid Build Coastguard Worker         return false;
412*2b949d04SAndroid Build Coastguard Worker     }
413*2b949d04SAndroid Build Coastguard Worker 
414*2b949d04SAndroid Build Coastguard Worker     *group_rtrn = (xkb_layout_index_t) result;
415*2b949d04SAndroid Build Coastguard Worker     return true;
416*2b949d04SAndroid Build Coastguard Worker }
417*2b949d04SAndroid Build Coastguard Worker 
418*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveLevel(struct xkb_context * ctx,const ExprDef * expr,xkb_level_index_t * level_rtrn)419*2b949d04SAndroid Build Coastguard Worker ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr,
420*2b949d04SAndroid Build Coastguard Worker                  xkb_level_index_t *level_rtrn)
421*2b949d04SAndroid Build Coastguard Worker {
422*2b949d04SAndroid Build Coastguard Worker     bool ok;
423*2b949d04SAndroid Build Coastguard Worker     int result;
424*2b949d04SAndroid Build Coastguard Worker 
425*2b949d04SAndroid Build Coastguard Worker     ok = ExprResolveIntegerLookup(ctx, expr, &result, SimpleLookup,
426*2b949d04SAndroid Build Coastguard Worker                                   levelNames);
427*2b949d04SAndroid Build Coastguard Worker     if (!ok)
428*2b949d04SAndroid Build Coastguard Worker         return false;
429*2b949d04SAndroid Build Coastguard Worker 
430*2b949d04SAndroid Build Coastguard Worker     if (result < 1) {
431*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Shift level %d is out of range\n", result);
432*2b949d04SAndroid Build Coastguard Worker         return false;
433*2b949d04SAndroid Build Coastguard Worker     }
434*2b949d04SAndroid Build Coastguard Worker 
435*2b949d04SAndroid Build Coastguard Worker     /* Level is zero-indexed from now on. */
436*2b949d04SAndroid Build Coastguard Worker     *level_rtrn = (unsigned int) (result - 1);
437*2b949d04SAndroid Build Coastguard Worker     return true;
438*2b949d04SAndroid Build Coastguard Worker }
439*2b949d04SAndroid Build Coastguard Worker 
440*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveButton(struct xkb_context * ctx,const ExprDef * expr,int * btn_rtrn)441*2b949d04SAndroid Build Coastguard Worker ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, int *btn_rtrn)
442*2b949d04SAndroid Build Coastguard Worker {
443*2b949d04SAndroid Build Coastguard Worker     return ExprResolveIntegerLookup(ctx, expr, btn_rtrn, SimpleLookup,
444*2b949d04SAndroid Build Coastguard Worker                                     buttonNames);
445*2b949d04SAndroid Build Coastguard Worker }
446*2b949d04SAndroid Build Coastguard Worker 
447*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveString(struct xkb_context * ctx,const ExprDef * expr,xkb_atom_t * val_rtrn)448*2b949d04SAndroid Build Coastguard Worker ExprResolveString(struct xkb_context *ctx, const ExprDef *expr,
449*2b949d04SAndroid Build Coastguard Worker                   xkb_atom_t *val_rtrn)
450*2b949d04SAndroid Build Coastguard Worker {
451*2b949d04SAndroid Build Coastguard Worker     switch (expr->expr.op) {
452*2b949d04SAndroid Build Coastguard Worker     case EXPR_VALUE:
453*2b949d04SAndroid Build Coastguard Worker         if (expr->expr.value_type != EXPR_TYPE_STRING) {
454*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "Found constant of type %s, expected a string\n",
455*2b949d04SAndroid Build Coastguard Worker                     expr_value_type_to_string(expr->expr.value_type));
456*2b949d04SAndroid Build Coastguard Worker             return false;
457*2b949d04SAndroid Build Coastguard Worker         }
458*2b949d04SAndroid Build Coastguard Worker 
459*2b949d04SAndroid Build Coastguard Worker         *val_rtrn = expr->string.str;
460*2b949d04SAndroid Build Coastguard Worker         return true;
461*2b949d04SAndroid Build Coastguard Worker 
462*2b949d04SAndroid Build Coastguard Worker     case EXPR_IDENT:
463*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Identifier \"%s\" of type string not found\n",
464*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->ident.ident));
465*2b949d04SAndroid Build Coastguard Worker         return false;
466*2b949d04SAndroid Build Coastguard Worker 
467*2b949d04SAndroid Build Coastguard Worker     case EXPR_FIELD_REF:
468*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Default \"%s.%s\" of type string not found\n",
469*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->field_ref.element),
470*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->field_ref.field));
471*2b949d04SAndroid Build Coastguard Worker         return false;
472*2b949d04SAndroid Build Coastguard Worker 
473*2b949d04SAndroid Build Coastguard Worker     case EXPR_ADD:
474*2b949d04SAndroid Build Coastguard Worker     case EXPR_SUBTRACT:
475*2b949d04SAndroid Build Coastguard Worker     case EXPR_MULTIPLY:
476*2b949d04SAndroid Build Coastguard Worker     case EXPR_DIVIDE:
477*2b949d04SAndroid Build Coastguard Worker     case EXPR_ASSIGN:
478*2b949d04SAndroid Build Coastguard Worker     case EXPR_NEGATE:
479*2b949d04SAndroid Build Coastguard Worker     case EXPR_INVERT:
480*2b949d04SAndroid Build Coastguard Worker     case EXPR_NOT:
481*2b949d04SAndroid Build Coastguard Worker     case EXPR_UNARY_PLUS:
482*2b949d04SAndroid Build Coastguard Worker     case EXPR_ACTION_DECL:
483*2b949d04SAndroid Build Coastguard Worker     case EXPR_ACTION_LIST:
484*2b949d04SAndroid Build Coastguard Worker     case EXPR_KEYSYM_LIST:
485*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "%s of strings not permitted\n",
486*2b949d04SAndroid Build Coastguard Worker                 expr_op_type_to_string(expr->expr.op));
487*2b949d04SAndroid Build Coastguard Worker         return false;
488*2b949d04SAndroid Build Coastguard Worker 
489*2b949d04SAndroid Build Coastguard Worker     default:
490*2b949d04SAndroid Build Coastguard Worker         log_wsgo(ctx, "Unknown operator %d in ResolveString\n",
491*2b949d04SAndroid Build Coastguard Worker                  expr->expr.op);
492*2b949d04SAndroid Build Coastguard Worker         break;
493*2b949d04SAndroid Build Coastguard Worker     }
494*2b949d04SAndroid Build Coastguard Worker     return false;
495*2b949d04SAndroid Build Coastguard Worker }
496*2b949d04SAndroid Build Coastguard Worker 
497*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveEnum(struct xkb_context * ctx,const ExprDef * expr,unsigned int * val_rtrn,const LookupEntry * values)498*2b949d04SAndroid Build Coastguard Worker ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr,
499*2b949d04SAndroid Build Coastguard Worker                 unsigned int *val_rtrn, const LookupEntry *values)
500*2b949d04SAndroid Build Coastguard Worker {
501*2b949d04SAndroid Build Coastguard Worker     if (expr->expr.op != EXPR_IDENT) {
502*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Found a %s where an enumerated value was expected\n",
503*2b949d04SAndroid Build Coastguard Worker                 expr_op_type_to_string(expr->expr.op));
504*2b949d04SAndroid Build Coastguard Worker         return false;
505*2b949d04SAndroid Build Coastguard Worker     }
506*2b949d04SAndroid Build Coastguard Worker 
507*2b949d04SAndroid Build Coastguard Worker     if (!SimpleLookup(ctx, values, expr->ident.ident, EXPR_TYPE_INT,
508*2b949d04SAndroid Build Coastguard Worker                       val_rtrn)) {
509*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Illegal identifier %s; expected one of:\n",
510*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->ident.ident));
511*2b949d04SAndroid Build Coastguard Worker         while (values && values->name)
512*2b949d04SAndroid Build Coastguard Worker         {
513*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "\t%s\n", values->name);
514*2b949d04SAndroid Build Coastguard Worker             values++;
515*2b949d04SAndroid Build Coastguard Worker         }
516*2b949d04SAndroid Build Coastguard Worker         return false;
517*2b949d04SAndroid Build Coastguard Worker     }
518*2b949d04SAndroid Build Coastguard Worker 
519*2b949d04SAndroid Build Coastguard Worker     return true;
520*2b949d04SAndroid Build Coastguard Worker }
521*2b949d04SAndroid Build Coastguard Worker 
522*2b949d04SAndroid Build Coastguard Worker static bool
ExprResolveMaskLookup(struct xkb_context * ctx,const ExprDef * expr,unsigned int * val_rtrn,IdentLookupFunc lookup,const void * lookupPriv)523*2b949d04SAndroid Build Coastguard Worker ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
524*2b949d04SAndroid Build Coastguard Worker                       unsigned int *val_rtrn, IdentLookupFunc lookup,
525*2b949d04SAndroid Build Coastguard Worker                       const void *lookupPriv)
526*2b949d04SAndroid Build Coastguard Worker {
527*2b949d04SAndroid Build Coastguard Worker     bool ok = false;
528*2b949d04SAndroid Build Coastguard Worker     unsigned int l = 0, r = 0;
529*2b949d04SAndroid Build Coastguard Worker     int v;
530*2b949d04SAndroid Build Coastguard Worker     ExprDef *left, *right;
531*2b949d04SAndroid Build Coastguard Worker     const char *bogus = NULL;
532*2b949d04SAndroid Build Coastguard Worker 
533*2b949d04SAndroid Build Coastguard Worker     switch (expr->expr.op) {
534*2b949d04SAndroid Build Coastguard Worker     case EXPR_VALUE:
535*2b949d04SAndroid Build Coastguard Worker         if (expr->expr.value_type != EXPR_TYPE_INT) {
536*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
537*2b949d04SAndroid Build Coastguard Worker                     "Found constant of type %s where a mask was expected\n",
538*2b949d04SAndroid Build Coastguard Worker                     expr_value_type_to_string(expr->expr.value_type));
539*2b949d04SAndroid Build Coastguard Worker             return false;
540*2b949d04SAndroid Build Coastguard Worker         }
541*2b949d04SAndroid Build Coastguard Worker         *val_rtrn = (unsigned int) expr->integer.ival;
542*2b949d04SAndroid Build Coastguard Worker         return true;
543*2b949d04SAndroid Build Coastguard Worker 
544*2b949d04SAndroid Build Coastguard Worker     case EXPR_IDENT:
545*2b949d04SAndroid Build Coastguard Worker         ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT,
546*2b949d04SAndroid Build Coastguard Worker                     val_rtrn);
547*2b949d04SAndroid Build Coastguard Worker         if (!ok)
548*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "Identifier \"%s\" of type int is unknown\n",
549*2b949d04SAndroid Build Coastguard Worker                     xkb_atom_text(ctx, expr->ident.ident));
550*2b949d04SAndroid Build Coastguard Worker         return ok;
551*2b949d04SAndroid Build Coastguard Worker 
552*2b949d04SAndroid Build Coastguard Worker     case EXPR_FIELD_REF:
553*2b949d04SAndroid Build Coastguard Worker         log_err(ctx, "Default \"%s.%s\" of type int is unknown\n",
554*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->field_ref.element),
555*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, expr->field_ref.field));
556*2b949d04SAndroid Build Coastguard Worker         return false;
557*2b949d04SAndroid Build Coastguard Worker 
558*2b949d04SAndroid Build Coastguard Worker     case EXPR_ARRAY_REF:
559*2b949d04SAndroid Build Coastguard Worker         bogus = "array reference";
560*2b949d04SAndroid Build Coastguard Worker         /* fallthrough */
561*2b949d04SAndroid Build Coastguard Worker     case EXPR_ACTION_DECL:
562*2b949d04SAndroid Build Coastguard Worker         if (bogus == NULL)
563*2b949d04SAndroid Build Coastguard Worker             bogus = "function use";
564*2b949d04SAndroid Build Coastguard Worker         log_err(ctx,
565*2b949d04SAndroid Build Coastguard Worker                 "Unexpected %s in mask expression; Expression Ignored\n",
566*2b949d04SAndroid Build Coastguard Worker                 bogus);
567*2b949d04SAndroid Build Coastguard Worker         return false;
568*2b949d04SAndroid Build Coastguard Worker 
569*2b949d04SAndroid Build Coastguard Worker     case EXPR_ADD:
570*2b949d04SAndroid Build Coastguard Worker     case EXPR_SUBTRACT:
571*2b949d04SAndroid Build Coastguard Worker     case EXPR_MULTIPLY:
572*2b949d04SAndroid Build Coastguard Worker     case EXPR_DIVIDE:
573*2b949d04SAndroid Build Coastguard Worker         left = expr->binary.left;
574*2b949d04SAndroid Build Coastguard Worker         right = expr->binary.right;
575*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveMaskLookup(ctx, left, &l, lookup, lookupPriv) ||
576*2b949d04SAndroid Build Coastguard Worker             !ExprResolveMaskLookup(ctx, right, &r, lookup, lookupPriv))
577*2b949d04SAndroid Build Coastguard Worker             return false;
578*2b949d04SAndroid Build Coastguard Worker 
579*2b949d04SAndroid Build Coastguard Worker         switch (expr->expr.op) {
580*2b949d04SAndroid Build Coastguard Worker         case EXPR_ADD:
581*2b949d04SAndroid Build Coastguard Worker             *val_rtrn = l | r;
582*2b949d04SAndroid Build Coastguard Worker             break;
583*2b949d04SAndroid Build Coastguard Worker         case EXPR_SUBTRACT:
584*2b949d04SAndroid Build Coastguard Worker             *val_rtrn = l & (~r);
585*2b949d04SAndroid Build Coastguard Worker             break;
586*2b949d04SAndroid Build Coastguard Worker         case EXPR_MULTIPLY:
587*2b949d04SAndroid Build Coastguard Worker         case EXPR_DIVIDE:
588*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "Cannot %s masks; Illegal operation ignored\n",
589*2b949d04SAndroid Build Coastguard Worker                     (expr->expr.op == EXPR_DIVIDE ? "divide" : "multiply"));
590*2b949d04SAndroid Build Coastguard Worker             return false;
591*2b949d04SAndroid Build Coastguard Worker         default:
592*2b949d04SAndroid Build Coastguard Worker             break;
593*2b949d04SAndroid Build Coastguard Worker         }
594*2b949d04SAndroid Build Coastguard Worker 
595*2b949d04SAndroid Build Coastguard Worker         return true;
596*2b949d04SAndroid Build Coastguard Worker 
597*2b949d04SAndroid Build Coastguard Worker     case EXPR_ASSIGN:
598*2b949d04SAndroid Build Coastguard Worker         log_wsgo(ctx, "Assignment operator not implemented yet\n");
599*2b949d04SAndroid Build Coastguard Worker         break;
600*2b949d04SAndroid Build Coastguard Worker 
601*2b949d04SAndroid Build Coastguard Worker     case EXPR_INVERT:
602*2b949d04SAndroid Build Coastguard Worker         left = expr->unary.child;
603*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv))
604*2b949d04SAndroid Build Coastguard Worker             return false;
605*2b949d04SAndroid Build Coastguard Worker 
606*2b949d04SAndroid Build Coastguard Worker         *val_rtrn = ~v;
607*2b949d04SAndroid Build Coastguard Worker         return true;
608*2b949d04SAndroid Build Coastguard Worker 
609*2b949d04SAndroid Build Coastguard Worker     case EXPR_UNARY_PLUS:
610*2b949d04SAndroid Build Coastguard Worker     case EXPR_NEGATE:
611*2b949d04SAndroid Build Coastguard Worker     case EXPR_NOT:
612*2b949d04SAndroid Build Coastguard Worker         left = expr->unary.child;
613*2b949d04SAndroid Build Coastguard Worker         if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv))
614*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "The %s operator cannot be used with a mask\n",
615*2b949d04SAndroid Build Coastguard Worker                     (expr->expr.op == EXPR_NEGATE ? "-" : "!"));
616*2b949d04SAndroid Build Coastguard Worker         return false;
617*2b949d04SAndroid Build Coastguard Worker 
618*2b949d04SAndroid Build Coastguard Worker     default:
619*2b949d04SAndroid Build Coastguard Worker         log_wsgo(ctx, "Unknown operator %d in ResolveMask\n",
620*2b949d04SAndroid Build Coastguard Worker                  expr->expr.op);
621*2b949d04SAndroid Build Coastguard Worker         break;
622*2b949d04SAndroid Build Coastguard Worker     }
623*2b949d04SAndroid Build Coastguard Worker 
624*2b949d04SAndroid Build Coastguard Worker     return false;
625*2b949d04SAndroid Build Coastguard Worker }
626*2b949d04SAndroid Build Coastguard Worker 
627*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveMask(struct xkb_context * ctx,const ExprDef * expr,unsigned int * mask_rtrn,const LookupEntry * values)628*2b949d04SAndroid Build Coastguard Worker ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr,
629*2b949d04SAndroid Build Coastguard Worker                 unsigned int *mask_rtrn, const LookupEntry *values)
630*2b949d04SAndroid Build Coastguard Worker {
631*2b949d04SAndroid Build Coastguard Worker     return ExprResolveMaskLookup(ctx, expr, mask_rtrn, SimpleLookup, values);
632*2b949d04SAndroid Build Coastguard Worker }
633*2b949d04SAndroid Build Coastguard Worker 
634*2b949d04SAndroid Build Coastguard Worker 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)635*2b949d04SAndroid Build Coastguard Worker ExprResolveModMask(struct xkb_context *ctx, const ExprDef *expr,
636*2b949d04SAndroid Build Coastguard Worker                    enum mod_type mod_type, const struct xkb_mod_set *mods,
637*2b949d04SAndroid Build Coastguard Worker                    xkb_mod_mask_t *mask_rtrn)
638*2b949d04SAndroid Build Coastguard Worker {
639*2b949d04SAndroid Build Coastguard Worker     LookupModMaskPriv priv = { .mods = mods, .mod_type = mod_type };
640*2b949d04SAndroid Build Coastguard Worker     return ExprResolveMaskLookup(ctx, expr, mask_rtrn, LookupModMask, &priv);
641*2b949d04SAndroid Build Coastguard Worker }
642*2b949d04SAndroid Build Coastguard Worker 
643*2b949d04SAndroid Build Coastguard Worker bool
ExprResolveKeySym(struct xkb_context * ctx,const ExprDef * expr,xkb_keysym_t * sym_rtrn)644*2b949d04SAndroid Build Coastguard Worker ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr,
645*2b949d04SAndroid Build Coastguard Worker                   xkb_keysym_t *sym_rtrn)
646*2b949d04SAndroid Build Coastguard Worker {
647*2b949d04SAndroid Build Coastguard Worker     int val;
648*2b949d04SAndroid Build Coastguard Worker 
649*2b949d04SAndroid Build Coastguard Worker     if (expr->expr.op == EXPR_IDENT) {
650*2b949d04SAndroid Build Coastguard Worker         const char *str = xkb_atom_text(ctx, expr->ident.ident);
651*2b949d04SAndroid Build Coastguard Worker         *sym_rtrn = xkb_keysym_from_name(str, 0);
652*2b949d04SAndroid Build Coastguard Worker         if (*sym_rtrn != XKB_KEY_NoSymbol)
653*2b949d04SAndroid Build Coastguard Worker             return true;
654*2b949d04SAndroid Build Coastguard Worker     }
655*2b949d04SAndroid Build Coastguard Worker 
656*2b949d04SAndroid Build Coastguard Worker     if (!ExprResolveInteger(ctx, expr, &val))
657*2b949d04SAndroid Build Coastguard Worker         return false;
658*2b949d04SAndroid Build Coastguard Worker 
659*2b949d04SAndroid Build Coastguard Worker     if (val < 0 || val >= 10)
660*2b949d04SAndroid Build Coastguard Worker         return false;
661*2b949d04SAndroid Build Coastguard Worker 
662*2b949d04SAndroid Build Coastguard Worker     *sym_rtrn = XKB_KEY_0 + (xkb_keysym_t) val;
663*2b949d04SAndroid Build Coastguard Worker     return true;
664*2b949d04SAndroid Build Coastguard Worker }
665*2b949d04SAndroid Build Coastguard Worker 
666*2b949d04SAndroid Build Coastguard Worker 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)667*2b949d04SAndroid Build Coastguard Worker ExprResolveMod(struct xkb_context *ctx, const ExprDef *def,
668*2b949d04SAndroid Build Coastguard Worker                enum mod_type mod_type, const struct xkb_mod_set *mods,
669*2b949d04SAndroid Build Coastguard Worker                xkb_mod_index_t *ndx_rtrn)
670*2b949d04SAndroid Build Coastguard Worker {
671*2b949d04SAndroid Build Coastguard Worker     xkb_mod_index_t ndx;
672*2b949d04SAndroid Build Coastguard Worker     xkb_atom_t name;
673*2b949d04SAndroid Build Coastguard Worker 
674*2b949d04SAndroid Build Coastguard Worker     if (def->expr.op != EXPR_IDENT) {
675*2b949d04SAndroid Build Coastguard Worker         log_err(ctx,
676*2b949d04SAndroid Build Coastguard Worker                 "Cannot resolve virtual modifier: "
677*2b949d04SAndroid Build Coastguard Worker                 "found %s where a virtual modifier name was expected\n",
678*2b949d04SAndroid Build Coastguard Worker                 expr_op_type_to_string(def->expr.op));
679*2b949d04SAndroid Build Coastguard Worker         return false;
680*2b949d04SAndroid Build Coastguard Worker     }
681*2b949d04SAndroid Build Coastguard Worker 
682*2b949d04SAndroid Build Coastguard Worker     name = def->ident.ident;
683*2b949d04SAndroid Build Coastguard Worker     ndx = XkbModNameToIndex(mods, name, mod_type);
684*2b949d04SAndroid Build Coastguard Worker     if (ndx == XKB_MOD_INVALID) {
685*2b949d04SAndroid Build Coastguard Worker         log_err(ctx,
686*2b949d04SAndroid Build Coastguard Worker                 "Cannot resolve virtual modifier: "
687*2b949d04SAndroid Build Coastguard Worker                 "\"%s\" was not previously declared\n",
688*2b949d04SAndroid Build Coastguard Worker                 xkb_atom_text(ctx, name));
689*2b949d04SAndroid Build Coastguard Worker         return false;
690*2b949d04SAndroid Build Coastguard Worker     }
691*2b949d04SAndroid Build Coastguard Worker 
692*2b949d04SAndroid Build Coastguard Worker     *ndx_rtrn = ndx;
693*2b949d04SAndroid Build Coastguard Worker     return true;
694*2b949d04SAndroid Build Coastguard Worker }
695