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