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