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