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