expr: constify function arguments
[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                  unsigned int *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_rtrn = (unsigned int) result;
540     return true;
541 }
542
543 bool
544 ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, int *btn_rtrn)
545 {
546     int result;
547     static const LookupEntry button_names[] = {
548         { "button1", 1 },
549         { "button2", 2 },
550         { "button3", 3 },
551         { "button4", 4 },
552         { "button5", 5 },
553         { "default", 0 },
554         { NULL, 0 }
555     };
556
557     if (!ExprResolveIntegerLookup(ctx, expr, &result, SimpleLookup,
558                                   button_names))
559         return false;
560
561     *btn_rtrn = result;
562     return true;
563 }
564
565 bool
566 ExprResolveString(struct xkb_context *ctx, const ExprDef *expr,
567                   const char **val_rtrn)
568 {
569     switch (expr->op) {
570     case EXPR_VALUE:
571         if (expr->value_type != EXPR_TYPE_STRING) {
572             log_err(ctx, "Found constant of type %s, expected a string\n",
573                     exprValueTypeText(expr->value_type));
574             return false;
575         }
576
577         *val_rtrn = xkb_atom_text(ctx, expr->value.str);
578         return true;
579
580     case EXPR_IDENT:
581         log_err(ctx, "Identifier \"%s\" of type string not found\n",
582                 xkb_atom_text(ctx, expr->value.str));
583         return false;
584
585     case EXPR_FIELD_REF:
586         log_err(ctx, "Default \"%s.%s\" of type string not found\n",
587                 xkb_atom_text(ctx, expr->value.field.element),
588                 xkb_atom_text(ctx, expr->value.field.field));
589         return false;
590
591     case EXPR_ADD:
592     case EXPR_SUBTRACT:
593     case EXPR_MULTIPLY:
594     case EXPR_DIVIDE:
595     case EXPR_ASSIGN:
596     case EXPR_NEGATE:
597     case EXPR_INVERT:
598     case EXPR_NOT:
599     case EXPR_UNARY_PLUS:
600         log_err(ctx, "%s of strings not permitted\n", exprOpText(expr->op));
601         return false;
602
603     default:
604         log_wsgo(ctx, "Unknown operator %d in ResolveString\n", expr->op);
605         break;
606     }
607     return false;
608 }
609
610 bool
611 ExprResolveKeyName(struct xkb_context *ctx, const ExprDef *expr,
612                    char name[XkbKeyNameLength])
613 {
614     switch (expr->op) {
615     case EXPR_VALUE:
616         if (expr->value_type != EXPR_TYPE_KEYNAME) {
617             log_err(ctx, "Found constant of type %s, expected a key name\n",
618                     exprValueTypeText(expr->value_type));
619             return false;
620         }
621         memcpy(name, expr->value.keyName, XkbKeyNameLength);
622         return true;
623
624     case EXPR_IDENT:
625         log_err(ctx, "Identifier \"%s\" of type string not found\n",
626                 xkb_atom_text(ctx, expr->value.str));
627         return false;
628
629     case EXPR_FIELD_REF:
630         log_err(ctx, "Default \"%s.%s\" of type key name not found\n",
631                 xkb_atom_text(ctx, expr->value.field.element),
632                 xkb_atom_text(ctx, expr->value.field.field));
633         return false;
634
635     case EXPR_ADD:
636     case EXPR_SUBTRACT:
637     case EXPR_MULTIPLY:
638     case EXPR_DIVIDE:
639     case EXPR_ASSIGN:
640     case EXPR_NEGATE:
641     case EXPR_INVERT:
642     case EXPR_NOT:
643     case EXPR_UNARY_PLUS:
644         log_err(ctx, "%s of key name values not permitted\n",
645                 exprOpText(expr->op));
646         return false;
647
648     default:
649         log_wsgo(ctx, "Unknown operator %d in ResolveKeyName\n", expr->op);
650         break;
651     }
652     return false;
653 }
654
655 bool
656 ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr,
657                 unsigned int *val_rtrn, const LookupEntry *values)
658 {
659     if (expr->op != EXPR_IDENT) {
660         log_err(ctx, "Found a %s where an enumerated value was expected\n",
661                 exprOpText(expr->op));
662         return false;
663     }
664
665     if (!SimpleLookup(ctx, values, expr->value.str, EXPR_TYPE_INT,
666                       val_rtrn)) {
667         log_err(ctx, "Illegal identifier %s; expected one of:\n",
668                 xkb_atom_text(ctx, expr->value.str));
669         while (values && values->name)
670         {
671             log_err(ctx, "\t%s\n", values->name);
672             values++;
673         }
674         return false;
675     }
676
677     return true;
678 }
679
680 static bool
681 ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
682                       unsigned int *val_rtrn, IdentLookupFunc lookup,
683                       const void *lookupPriv)
684 {
685     bool ok = 0;
686     unsigned int l, r;
687     int v;
688     ExprDef *left, *right;
689     const char *bogus = NULL;
690
691     switch (expr->op) {
692     case EXPR_VALUE:
693         if (expr->value_type != EXPR_TYPE_INT) {
694             log_err(ctx,
695                     "Found constant of type %s where a mask was expected\n",
696                     exprValueTypeText(expr->value_type));
697             return false;
698         }
699         *val_rtrn = (unsigned int) expr->value.ival;
700         return true;
701
702     case EXPR_IDENT:
703         ok = lookup(ctx, lookupPriv, expr->value.str, EXPR_TYPE_INT,
704                     val_rtrn);
705         if (!ok)
706             log_err(ctx, "Identifier \"%s\" of type int is unknown\n",
707                     xkb_atom_text(ctx, expr->value.str));
708         return ok;
709
710     case EXPR_FIELD_REF:
711         log_err(ctx, "Default \"%s.%s\" of type int is unknown\n",
712                 xkb_atom_text(ctx, expr->value.field.element),
713                 xkb_atom_text(ctx, expr->value.field.field));
714         return false;
715
716     case EXPR_ARRAY_REF:
717         bogus = "array reference";
718
719     case EXPR_ACTION_DECL:
720         if (bogus == NULL)
721             bogus = "function use";
722         log_err(ctx,
723                 "Unexpected %s in mask expression; Expression Ignored\n",
724                 bogus);
725         return false;
726
727     case EXPR_ADD:
728     case EXPR_SUBTRACT:
729     case EXPR_MULTIPLY:
730     case EXPR_DIVIDE:
731         left = expr->value.binary.left;
732         right = expr->value.binary.right;
733         if (!ExprResolveMaskLookup(ctx, left, &l, lookup, lookupPriv) ||
734             !ExprResolveMaskLookup(ctx, right, &r, lookup, lookupPriv))
735             return false;
736
737         switch (expr->op) {
738         case EXPR_ADD:
739             *val_rtrn = l | r;
740             break;
741         case EXPR_SUBTRACT:
742             *val_rtrn = l & (~r);
743             break;
744         case EXPR_MULTIPLY:
745         case EXPR_DIVIDE:
746             log_err(ctx, "Cannot %s masks; Illegal operation ignored\n",
747                     (expr->op == EXPR_DIVIDE ? "divide" : "multiply"));
748             return false;
749         default:
750             break;
751         }
752
753         return true;
754
755     case EXPR_ASSIGN:
756         log_wsgo(ctx, "Assignment operator not implemented yet\n");
757         break;
758
759     case EXPR_INVERT:
760         left = expr->value.child;
761         if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv))
762             return false;
763
764         *val_rtrn = ~v;
765         return true;
766
767     case EXPR_UNARY_PLUS:
768     case EXPR_NEGATE:
769     case EXPR_NOT:
770         left = expr->value.child;
771         if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv))
772             log_err(ctx, "The %s operator cannot be used with a mask\n",
773                     (expr->op == EXPR_NEGATE ? "-" : "!"));
774         return false;
775
776     default:
777         log_wsgo(ctx, "Unknown operator %d in ResolveMask\n", expr->op);
778         break;
779     }
780
781     return false;
782 }
783
784 bool
785 ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr,
786                 unsigned int *mask_rtrn, const LookupEntry *values)
787 {
788     return ExprResolveMaskLookup(ctx, expr, mask_rtrn, SimpleLookup, values);
789 }
790
791 bool
792 ExprResolveModMask(struct xkb_context *ctx, const ExprDef *expr,
793                    xkb_mod_mask_t *mask_rtrn)
794 {
795     return ExprResolveMaskLookup(ctx, expr, mask_rtrn, LookupModMask, NULL);
796 }
797
798 bool
799 ExprResolveVModMask(struct xkb_keymap *keymap, const ExprDef *expr,
800                     xkb_mod_mask_t *mask_rtrn)
801 {
802     return ExprResolveMaskLookup(keymap->ctx, expr, mask_rtrn, LookupVModMask,
803                                  keymap);
804 }
805
806 bool
807 ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr,
808                   xkb_keysym_t *sym_rtrn)
809 {
810     int val;
811
812     if (expr->op == EXPR_IDENT) {
813         const char *str;
814         str = xkb_atom_text(ctx, expr->value.str);
815         *sym_rtrn = xkb_keysym_from_name(str);
816         if (*sym_rtrn != XKB_KEY_NoSymbol)
817             return true;
818     }
819
820     if (!ExprResolveInteger(ctx, expr, &val))
821         return false;
822
823     if (val < 0 || val >= 10)
824         return false;
825
826     *sym_rtrn = ((xkb_keysym_t) val) + '0';
827     return true;
828 }