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