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