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