Use xkb_group_index_t for group variables throughout
[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 "expr.h"
28
29 /***====================================================================***/
30
31 typedef bool (*IdentLookupFunc)(struct xkb_context *ctx, const void *priv,
32                                 xkb_atom_t field, unsigned type,
33                                 ExprResult *val_rtrn);
34
35 /***====================================================================***/
36
37 const char *
38 exprOpText(unsigned type)
39 {
40     static char buf[32];
41
42     switch (type) {
43     case ExprValue:
44         strcpy(buf, "literal");
45         break;
46     case ExprIdent:
47         strcpy(buf, "identifier");
48         break;
49     case ExprActionDecl:
50         strcpy(buf, "action declaration");
51         break;
52     case ExprFieldRef:
53         strcpy(buf, "field reference");
54         break;
55     case ExprArrayRef:
56         strcpy(buf, "array reference");
57         break;
58     case ExprKeysymList:
59         strcpy(buf, "list of keysyms");
60         break;
61     case ExprActionList:
62         strcpy(buf, "list of actions");
63         break;
64     case OpAdd:
65         strcpy(buf, "addition");
66         break;
67     case OpSubtract:
68         strcpy(buf, "subtraction");
69         break;
70     case OpMultiply:
71         strcpy(buf, "multiplication");
72         break;
73     case OpDivide:
74         strcpy(buf, "division");
75         break;
76     case OpAssign:
77         strcpy(buf, "assignment");
78         break;
79     case OpNot:
80         strcpy(buf, "logical not");
81         break;
82     case OpNegate:
83         strcpy(buf, "arithmetic negation");
84         break;
85     case OpInvert:
86         strcpy(buf, "bitwise inversion");
87         break;
88     case OpUnaryPlus:
89         strcpy(buf, "plus sign");
90         break;
91     default:
92         snprintf(buf, sizeof(buf), "illegal(%d)", type);
93         break;
94     }
95     return buf;
96 }
97
98 static const char *
99 exprTypeText(unsigned type)
100 {
101     static char buf[20];
102
103     switch (type) {
104     case TypeUnknown:
105         strcpy(buf, "unknown");
106         break;
107     case TypeBoolean:
108         strcpy(buf, "boolean");
109         break;
110     case TypeInt:
111         strcpy(buf, "int");
112         break;
113     case TypeString:
114         strcpy(buf, "string");
115         break;
116     case TypeAction:
117         strcpy(buf, "action");
118         break;
119     case TypeKeyName:
120         strcpy(buf, "keyname");
121         break;
122     default:
123         snprintf(buf, sizeof(buf), "illegal(%d)", type);
124         break;
125     }
126     return buf;
127 }
128
129 int
130 ExprResolveLhs(struct xkb_keymap *keymap, ExprDef *expr,
131                ExprResult *elem_rtrn, ExprResult *field_rtrn,
132                ExprDef **index_rtrn)
133 {
134     switch (expr->op) {
135     case ExprIdent:
136         elem_rtrn->str = NULL;
137         field_rtrn->str = xkb_atom_strdup(keymap->ctx,
138                                           expr->value.str);
139         *index_rtrn = NULL;
140         return true;
141     case ExprFieldRef:
142         elem_rtrn->str = xkb_atom_strdup(keymap->ctx,
143                                          expr->value.field.element);
144         field_rtrn->str = xkb_atom_strdup(keymap->ctx,
145                                           expr->value.field.field);
146         *index_rtrn = NULL;
147         return true;
148     case ExprArrayRef:
149         elem_rtrn->str = xkb_atom_strdup(keymap->ctx,
150                                          expr->value.array.element);
151         field_rtrn->str = xkb_atom_strdup(keymap->ctx,
152                                           expr->value.array.field);
153         *index_rtrn = expr->value.array.entry;
154         return true;
155     }
156     WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
157     return false;
158 }
159
160 static bool
161 SimpleLookup(struct xkb_context *ctx, const void *priv,
162              xkb_atom_t field, unsigned type, ExprResult *val_rtrn)
163 {
164     const LookupEntry *entry;
165     const char *str;
166
167     if ((priv == NULL) || (field == XKB_ATOM_NONE) || (type != TypeInt))
168         return false;
169
170     str = xkb_atom_text(ctx, field);
171     for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++) {
172         if (strcasecmp(str, entry->name) == 0) {
173             val_rtrn->uval = entry->result;
174             return true;
175         }
176     }
177
178     return false;
179 }
180
181 static const LookupEntry modIndexNames[] = {
182     { "shift", ShiftMapIndex },
183     { "control", ControlMapIndex },
184     { "lock", LockMapIndex },
185     { "mod1", Mod1MapIndex },
186     { "mod2", Mod2MapIndex },
187     { "mod3", Mod3MapIndex },
188     { "mod4", Mod4MapIndex },
189     { "mod5", Mod5MapIndex },
190     { "none", XkbNoModifier },
191     { NULL, 0 }
192 };
193
194 bool
195 LookupModIndex(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
196                unsigned type, ExprResult *val_rtrn)
197 {
198     return SimpleLookup(ctx, modIndexNames, field, type, val_rtrn);
199 }
200
201 bool
202 LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
203               unsigned type, ExprResult *val_rtrn)
204 {
205     const char *str;
206     bool ret = true;
207
208     if (type != TypeInt)
209         return false;
210     str = xkb_atom_text(ctx, field);
211     if (str == NULL)
212         return false;
213     if (strcasecmp(str, "all") == 0)
214         val_rtrn->uval = 0xff;
215     else if (strcasecmp(str, "none") == 0)
216         val_rtrn->uval = 0;
217     else if (LookupModIndex(ctx, priv, field, type, val_rtrn))
218         val_rtrn->uval = (1 << val_rtrn->uval);
219     else
220         ret = false;
221     return ret;
222 }
223
224 int
225 ExprResolveBoolean(struct xkb_context *ctx, ExprDef *expr,
226                    ExprResult *val_rtrn)
227 {
228     int ok = 0;
229     const char *bogus = NULL;
230
231     switch (expr->op) {
232     case ExprValue:
233         if (expr->type != TypeBoolean) {
234             ERROR
235                 ("Found constant of type %s where boolean was expected\n",
236                 exprTypeText(expr->type));
237             return false;
238         }
239         val_rtrn->ival = expr->value.ival;
240         return true;
241
242     case ExprIdent:
243         bogus = xkb_atom_text(ctx, expr->value.str);
244         if (bogus) {
245             if ((strcasecmp(bogus, "true") == 0) ||
246                 (strcasecmp(bogus, "yes") == 0) ||
247                 (strcasecmp(bogus, "on") == 0)) {
248                 val_rtrn->uval = 1;
249                 return true;
250             }
251             else if ((strcasecmp(bogus, "false") == 0) ||
252                      (strcasecmp(bogus, "no") == 0) ||
253                      (strcasecmp(bogus, "off") == 0)) {
254                 val_rtrn->uval = 0;
255                 return true;
256             }
257         }
258         ERROR("Identifier \"%s\" of type int is unknown\n",
259               xkb_atom_text(ctx, expr->value.str));
260         return false;
261
262     case ExprFieldRef:
263         ERROR("Default \"%s.%s\" of type boolean is unknown\n",
264               xkb_atom_text(ctx, expr->value.field.element),
265               xkb_atom_text(ctx, expr->value.field.field));
266         return false;
267
268     case OpInvert:
269     case OpNot:
270         ok = ExprResolveBoolean(ctx, expr, val_rtrn);
271         if (ok)
272             val_rtrn->uval = !val_rtrn->uval;
273         return ok;
274     case OpAdd:
275         if (bogus == NULL)
276             bogus = "Addition";
277     case OpSubtract:
278         if (bogus == NULL)
279             bogus = "Subtraction";
280     case OpMultiply:
281         if (bogus == NULL)
282             bogus = "Multiplication";
283     case OpDivide:
284         if (bogus == NULL)
285             bogus = "Division";
286     case OpAssign:
287         if (bogus == NULL)
288             bogus = "Assignment";
289     case OpNegate:
290         if (bogus == NULL)
291             bogus = "Negation";
292         ERROR("%s of boolean values not permitted\n", bogus);
293         break;
294
295     case OpUnaryPlus:
296         ERROR("Unary \"+\" operator not permitted for boolean values\n");
297         break;
298
299     default:
300         WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
301         break;
302     }
303     return false;
304 }
305
306 int
307 ExprResolveFloat(struct xkb_context *ctx, ExprDef *expr,
308                  ExprResult *val_rtrn)
309 {
310     int ok = 0;
311     ExprResult leftRtrn, rightRtrn;
312     ExprDef *left, *right;
313
314     switch (expr->op) {
315     case ExprValue:
316         if (expr->type == TypeString) {
317             const char *str;
318             str = xkb_atom_text(ctx, expr->value.str);
319             if ((str != NULL) && (strlen(str) == 1)) {
320                 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
321                 return true;
322             }
323         }
324         if (expr->type != TypeInt) {
325             ERROR("Found constant of type %s, expected a number\n",
326                   exprTypeText(expr->type));
327             return false;
328         }
329         val_rtrn->ival = expr->value.ival;
330         if (expr->type == TypeInt)
331             val_rtrn->ival *= XkbGeomPtsPerMM;
332         return true;
333
334     case ExprIdent:
335         ERROR("Numeric identifier \"%s\" unknown\n",
336               xkb_atom_text(ctx, expr->value.str));
337         return ok;
338
339     case ExprFieldRef:
340         ERROR("Numeric default \"%s.%s\" unknown\n",
341               xkb_atom_text(ctx, expr->value.field.element),
342               xkb_atom_text(ctx, expr->value.field.field));
343         return false;
344
345     case OpAdd:
346     case OpSubtract:
347     case OpMultiply:
348     case OpDivide:
349         left = expr->value.binary.left;
350         right = expr->value.binary.right;
351         if (ExprResolveFloat(ctx, left, &leftRtrn) &&
352             ExprResolveFloat(ctx, right, &rightRtrn)) {
353             switch (expr->op) {
354             case OpAdd:
355                 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
356                 break;
357
358             case OpSubtract:
359                 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
360                 break;
361
362             case OpMultiply:
363                 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
364                 break;
365
366             case OpDivide:
367                 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
368                 break;
369             }
370             return true;
371         }
372         return false;
373
374     case OpAssign:
375         WSGO("Assignment operator not implemented yet\n");
376         break;
377
378     case OpNot:
379         ERROR("The ! operator cannot be applied to a number\n");
380         return false;
381
382     case OpInvert:
383     case OpNegate:
384         left = expr->value.child;
385         if (ExprResolveFloat(ctx, left, &leftRtrn)) {
386             if (expr->op == OpNegate)
387                 val_rtrn->ival = -leftRtrn.ival;
388             else
389                 val_rtrn->ival = ~leftRtrn.ival;
390             return true;
391         }
392         return false;
393
394     case OpUnaryPlus:
395         left = expr->value.child;
396         return ExprResolveFloat(ctx, left, val_rtrn);
397
398     default:
399         WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
400         break;
401     }
402     return false;
403 }
404
405 int
406 ExprResolveKeyCode(struct xkb_context *ctx, ExprDef *expr,
407                    ExprResult *val_rtrn)
408 {
409     ExprResult leftRtrn, rightRtrn;
410     ExprDef *left, *right;
411
412     switch (expr->op) {
413     case ExprValue:
414         if (expr->type != TypeInt) {
415             ERROR
416                 ("Found constant of type %s where an int was expected\n",
417                 exprTypeText(expr->type));
418             return false;
419         }
420         val_rtrn->uval = expr->value.uval;
421         return true;
422
423     case OpAdd:
424     case OpSubtract:
425     case OpMultiply:
426     case OpDivide:
427         left = expr->value.binary.left;
428         right = expr->value.binary.right;
429         if (ExprResolveKeyCode(ctx, left, &leftRtrn) &&
430             ExprResolveKeyCode(ctx, right, &rightRtrn)) {
431             switch (expr->op) {
432             case OpAdd:
433                 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
434                 break;
435             case OpSubtract:
436                 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
437                 break;
438             case OpMultiply:
439                 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
440                 break;
441             case OpDivide:
442                 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
443                 break;
444             }
445             return true;
446         }
447         return false;
448
449     case OpNegate:
450         left = expr->value.child;
451         if (ExprResolveKeyCode(ctx, left, &leftRtrn)) {
452             val_rtrn->uval = ~leftRtrn.uval;
453             return true;
454         }
455         return false;
456
457     case OpUnaryPlus:
458         left = expr->value.child;
459         return ExprResolveKeyCode(ctx, left, val_rtrn);
460
461     default:
462         WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
463         break;
464     }
465     return false;
466 }
467
468 /**
469  * This function returns ... something.  It's a bit of a guess, really.
470  *
471  * If a string is given in value ctx, its first character will be
472  * returned in uval.  If an integer is given in value ctx, it will be
473  * returned in ival.  If a float is given in value ctx, it will be
474  * returned as millimetres (rather than points) in ival.
475  *
476  * If an ident or field reference is given, the lookup function (if given)
477  * will be called.  At the moment, only SimpleLookup use this, and they both
478  * return the results in uval.  And don't support field references.
479  *
480  * Cool.
481  */
482 static int
483 ExprResolveIntegerLookup(struct xkb_context *ctx, ExprDef *expr,
484                          ExprResult *val_rtrn, IdentLookupFunc lookup,
485                          const void *lookupPriv)
486 {
487     int ok = 0;
488     ExprResult leftRtrn, rightRtrn;
489     ExprDef *left, *right;
490
491     switch (expr->op) {
492     case ExprValue:
493         if (expr->type == TypeString) {
494             const char *str;
495             str = xkb_atom_text(ctx, expr->value.str);
496             if (str != NULL)
497                 switch (strlen(str)) {
498                 case 0:
499                     val_rtrn->uval = 0;
500                     return true;
501                 case 1:
502                     val_rtrn->uval = str[0];
503                     return true;
504                 default:
505                     break;
506                 }
507         }
508         if (expr->type != TypeInt) {
509             ERROR
510                 ("Found constant of type %s where an int was expected\n",
511                 exprTypeText(expr->type));
512             return false;
513         }
514         val_rtrn->ival = expr->value.ival;
515         return true;
516
517     case ExprIdent:
518         if (lookup)
519             ok = lookup(ctx, lookupPriv, expr->value.str,
520                         TypeInt, val_rtrn);
521         if (!ok)
522             ERROR("Identifier \"%s\" of type int is unknown\n",
523                   xkb_atom_text(ctx, expr->value.str));
524         return ok;
525
526     case ExprFieldRef:
527         ERROR("Default \"%s.%s\" of type int is unknown\n",
528               xkb_atom_text(ctx, expr->value.field.element),
529               xkb_atom_text(ctx, expr->value.field.field));
530         return false;
531
532     case OpAdd:
533     case OpSubtract:
534     case OpMultiply:
535     case OpDivide:
536         left = expr->value.binary.left;
537         right = expr->value.binary.right;
538         if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
539                                      lookupPriv) &&
540             ExprResolveIntegerLookup(ctx, right, &rightRtrn, lookup,
541                                      lookupPriv)) {
542             switch (expr->op) {
543             case OpAdd:
544                 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
545                 break;
546             case OpSubtract:
547                 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
548                 break;
549             case OpMultiply:
550                 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
551                 break;
552             case OpDivide:
553                 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
554                 break;
555             }
556             return true;
557         }
558         return false;
559
560     case OpAssign:
561         WSGO("Assignment operator not implemented yet\n");
562         break;
563
564     case OpNot:
565         ERROR("The ! operator cannot be applied to an integer\n");
566         return false;
567
568     case OpInvert:
569     case OpNegate:
570         left = expr->value.child;
571         if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
572                                      lookupPriv)) {
573             if (expr->op == OpNegate)
574                 val_rtrn->ival = -leftRtrn.ival;
575             else
576                 val_rtrn->ival = ~leftRtrn.ival;
577             return true;
578         }
579         return false;
580
581     case OpUnaryPlus:
582         left = expr->value.child;
583         return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup,
584                                         lookupPriv);
585
586     default:
587         WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
588         break;
589     }
590     return false;
591 }
592
593 int
594 ExprResolveInteger(struct xkb_context *ctx, ExprDef *expr,
595                    ExprResult *val_rtrn)
596 {
597     return ExprResolveIntegerLookup(ctx, expr, val_rtrn, NULL, NULL);
598 }
599
600 int
601 ExprResolveGroup(struct xkb_context *ctx, ExprDef *expr,
602                  ExprResult *val_rtrn)
603 {
604     int ret;
605     static const LookupEntry group_names[] = {
606         { "group1", 1 },
607         { "group2", 2 },
608         { "group3", 3 },
609         { "group4", 4 },
610         { "group5", 5 },
611         { "group6", 6 },
612         { "group7", 7 },
613         { "group8", 8 },
614         { NULL, 0 }
615     };
616
617     ret = ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup,
618                                    group_names);
619     if (ret == false)
620         return ret;
621
622     if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
623         ERROR("Group index %u is out of range (1..%d)\n",
624               val_rtrn->uval, XkbNumKbdGroups);
625         return false;
626     }
627
628     return true;
629 }
630
631 int
632 ExprResolveLevel(struct xkb_context *ctx, ExprDef *expr,
633                  ExprResult *val_rtrn)
634 {
635     int ret;
636     static const LookupEntry level_names[] = {
637         { "level1", 1 },
638         { "level2", 2 },
639         { "level3", 3 },
640         { "level4", 4 },
641         { "level5", 5 },
642         { "level6", 6 },
643         { "level7", 7 },
644         { "level8", 8 },
645         { NULL, 0 }
646     };
647
648     ret = ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup,
649                                    level_names);
650     if (ret == false)
651         return ret;
652
653     if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) {
654         ERROR("Shift level %d is out of range (1..%d)\n", val_rtrn->ival,
655               XkbMaxShiftLevel);
656         return false;
657     }
658
659     return true;
660 }
661
662 int
663 ExprResolveButton(struct xkb_context *ctx, ExprDef *expr,
664                   ExprResult *val_rtrn)
665 {
666     static const LookupEntry button_names[] = {
667         { "button1", 1 },
668         { "button2", 2 },
669         { "button3", 3 },
670         { "button4", 4 },
671         { "button5", 5 },
672         { "default", 0 },
673         { NULL, 0 }
674     };
675
676     return ExprResolveIntegerLookup(ctx, expr, val_rtrn, SimpleLookup,
677                                     button_names);
678 }
679
680 int
681 ExprResolveString(struct xkb_context *ctx, ExprDef *expr,
682                   ExprResult *val_rtrn)
683 {
684     ExprResult leftRtrn, rightRtrn;
685     ExprDef *left;
686     ExprDef *right;
687     const char *bogus = NULL;
688
689     switch (expr->op) {
690     case ExprValue:
691         if (expr->type != TypeString) {
692             ERROR("Found constant of type %s, expected a string\n",
693                   exprTypeText(expr->type));
694             return false;
695         }
696         val_rtrn->str = xkb_atom_strdup(ctx, expr->value.str);
697         if (val_rtrn->str == NULL)
698             val_rtrn->str = strdup("");
699         return true;
700
701     case ExprIdent:
702         ERROR("Identifier \"%s\" of type string not found\n",
703               xkb_atom_text(ctx, expr->value.str));
704         return false;
705
706     case ExprFieldRef:
707         ERROR("Default \"%s.%s\" of type string not found\n",
708               xkb_atom_text(ctx, expr->value.field.element),
709               xkb_atom_text(ctx, expr->value.field.field));
710         return false;
711
712     case OpAdd:
713         left = expr->value.binary.left;
714         right = expr->value.binary.right;
715         if (ExprResolveString(ctx, left, &leftRtrn) &&
716             ExprResolveString(ctx, right, &rightRtrn)) {
717             int len;
718             char *new;
719             len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
720             new = malloc(len);
721             if (new) {
722                 sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
723                 free(leftRtrn.str);
724                 free(rightRtrn.str);
725                 val_rtrn->str = new;
726                 return true;
727             }
728             free(leftRtrn.str);
729             free(rightRtrn.str);
730         }
731         return false;
732
733     case OpSubtract:
734         if (bogus == NULL)
735             bogus = "Subtraction";
736     case OpMultiply:
737         if (bogus == NULL)
738             bogus = "Multiplication";
739     case OpDivide:
740         if (bogus == NULL)
741             bogus = "Division";
742     case OpAssign:
743         if (bogus == NULL)
744             bogus = "Assignment";
745     case OpNegate:
746         if (bogus == NULL)
747             bogus = "Negation";
748     case OpInvert:
749         if (bogus == NULL)
750             bogus = "Bitwise complement";
751         ERROR("%s of string values not permitted\n", bogus);
752         return false;
753
754     case OpNot:
755         ERROR("The ! operator cannot be applied to a string\n");
756         return false;
757
758     case OpUnaryPlus:
759         ERROR("The + operator cannot be applied to a string\n");
760         return false;
761
762     default:
763         WSGO("Unknown operator %d in ResolveString\n", expr->op);
764         break;
765     }
766     return false;
767 }
768
769 int
770 ExprResolveKeyName(struct xkb_context *ctx, ExprDef *expr,
771                    ExprResult *val_rtrn)
772 {
773     const char *bogus = NULL;
774
775     switch (expr->op) {
776     case ExprValue:
777         if (expr->type != TypeKeyName) {
778             ERROR("Found constant of type %s, expected a key name\n",
779                   exprTypeText(expr->type));
780             return false;
781         }
782         memcpy(val_rtrn->name, expr->value.keyName, XkbKeyNameLength);
783         return true;
784
785     case ExprIdent:
786         ERROR("Identifier \"%s\" of type string not found\n",
787               xkb_atom_text(ctx, expr->value.str));
788         return false;
789
790     case ExprFieldRef:
791         ERROR("Default \"%s.%s\" of type key name not found\n",
792               xkb_atom_text(ctx, expr->value.field.element),
793               xkb_atom_text(ctx, expr->value.field.field));
794         return false;
795
796     case OpAdd:
797         if (bogus == NULL)
798             bogus = "Addition";
799     case OpSubtract:
800         if (bogus == NULL)
801             bogus = "Subtraction";
802     case OpMultiply:
803         if (bogus == NULL)
804             bogus = "Multiplication";
805     case OpDivide:
806         if (bogus == NULL)
807             bogus = "Division";
808     case OpAssign:
809         if (bogus == NULL)
810             bogus = "Assignment";
811     case OpNegate:
812         if (bogus == NULL)
813             bogus = "Negation";
814     case OpInvert:
815         if (bogus == NULL)
816             bogus = "Bitwise complement";
817         ERROR("%s of key name values not permitted\n", bogus);
818         return false;
819
820     case OpNot:
821         ERROR("The ! operator cannot be applied to a key name\n");
822         return false;
823
824     case OpUnaryPlus:
825         ERROR("The + operator cannot be applied to a key name\n");
826         return false;
827
828     default:
829         WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
830         break;
831     }
832     return false;
833 }
834
835 /***====================================================================***/
836
837 int
838 ExprResolveEnum(struct xkb_context *ctx, ExprDef *expr,
839                 ExprResult *val_rtrn, const LookupEntry *values)
840 {
841     if (expr->op != ExprIdent) {
842         ERROR("Found a %s where an enumerated value was expected\n",
843               exprOpText(expr->op));
844         return false;
845     }
846     if (!SimpleLookup(ctx, values, expr->value.str, TypeInt, val_rtrn)) {
847         int nOut = 0;
848         ERROR("Illegal identifier %s (expected one of: ",
849               xkb_atom_text(ctx, expr->value.str));
850         while (values && values->name)
851         {
852             if (nOut != 0)
853                 INFO(", %s", values->name);
854             else
855                 INFO("%s", values->name);
856             values++;
857             nOut++;
858         }
859         INFO(")\n");
860         return false;
861     }
862     return true;
863 }
864
865 static int
866 ExprResolveMaskLookup(struct xkb_context *ctx, ExprDef *expr,
867                       ExprResult *val_rtrn, IdentLookupFunc lookup,
868                       const void *lookupPriv)
869 {
870     int ok = 0;
871     ExprResult leftRtrn, rightRtrn;
872     ExprDef *left, *right;
873     const char *bogus = NULL;
874
875     switch (expr->op) {
876     case ExprValue:
877         if (expr->type != TypeInt) {
878             ERROR
879                 ("Found constant of type %s where a mask was expected\n",
880                 exprTypeText(expr->type));
881             return false;
882         }
883         val_rtrn->ival = expr->value.ival;
884         return true;
885
886     case ExprIdent:
887         ok = lookup(ctx, lookupPriv, expr->value.str, TypeInt, val_rtrn);
888         if (!ok)
889             ERROR("Identifier \"%s\" of type int is unknown\n",
890                   xkb_atom_text(ctx, expr->value.str));
891         return ok;
892
893     case ExprFieldRef:
894         ERROR("Default \"%s.%s\" of type int is unknown\n",
895               xkb_atom_text(ctx, expr->value.field.element),
896               xkb_atom_text(ctx, expr->value.field.field));
897         return false;
898
899     case ExprArrayRef:
900         bogus = "array reference";
901
902     case ExprActionDecl:
903         if (bogus == NULL)
904             bogus = "function use";
905         ERROR("Unexpected %s in mask expression\n", bogus);
906         ACTION("Expression ignored\n");
907         return false;
908
909     case OpAdd:
910     case OpSubtract:
911     case OpMultiply:
912     case OpDivide:
913         left = expr->value.binary.left;
914         right = expr->value.binary.right;
915         if (ExprResolveMaskLookup(ctx, left, &leftRtrn, lookup,
916                                   lookupPriv) &&
917             ExprResolveMaskLookup(ctx, right, &rightRtrn, lookup,
918                                   lookupPriv)) {
919             switch (expr->op) {
920             case OpAdd:
921                 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
922                 break;
923             case OpSubtract:
924                 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
925                 break;
926             case OpMultiply:
927             case OpDivide:
928                 ERROR("Cannot %s masks\n",
929                       expr->op == OpDivide ? "divide" : "multiply");
930                 ACTION("Illegal operation ignored\n");
931                 return false;
932             }
933             return true;
934         }
935         return false;
936
937     case OpAssign:
938         WSGO("Assignment operator not implemented yet\n");
939         break;
940
941     case OpInvert:
942         left = expr->value.child;
943         if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
944                                      lookupPriv)) {
945             val_rtrn->ival = ~leftRtrn.ival;
946             return true;
947         }
948         return false;
949
950     case OpUnaryPlus:
951     case OpNegate:
952     case OpNot:
953         left = expr->value.child;
954         if (ExprResolveIntegerLookup(ctx, left, &leftRtrn, lookup,
955                                      lookupPriv)) {
956             ERROR("The %s operator cannot be used with a mask\n",
957                   (expr->op == OpNegate ? "-" : "!"));
958         }
959         return false;
960
961     default:
962         WSGO("Unknown operator %d in ResolveMask\n", expr->op);
963         break;
964     }
965     return false;
966 }
967
968 int
969 ExprResolveMask(struct xkb_context *ctx, ExprDef *expr,
970                 ExprResult *val_rtrn, const LookupEntry *values)
971 {
972     return ExprResolveMaskLookup(ctx, expr, val_rtrn, SimpleLookup, values);
973 }
974
975 int
976 ExprResolveModMask(struct xkb_context *ctx, ExprDef *expr,
977                    ExprResult *val_rtrn)
978 {
979     return ExprResolveMaskLookup(ctx, expr, val_rtrn, LookupModMask, NULL);
980 }
981
982 int
983 ExprResolveVModMask(ExprDef *expr, ExprResult *val_rtrn,
984                     struct xkb_keymap *keymap)
985 {
986     return ExprResolveMaskLookup(keymap->ctx, expr, val_rtrn, LookupVModMask,
987                                  keymap);
988 }
989
990 int
991 ExprResolveKeySym(struct xkb_context *ctx, ExprDef *expr,
992                   ExprResult *val_rtrn)
993 {
994     int ok = 0;
995     xkb_keysym_t sym;
996
997     if (expr->op == ExprIdent) {
998         const char *str;
999         str = xkb_atom_text(ctx, expr->value.str);
1000         if (str) {
1001             sym = xkb_keysym_from_name(str);
1002             if (sym != XKB_KEY_NoSymbol) {
1003                 val_rtrn->uval = sym;
1004                 return true;
1005             }
1006         }
1007     }
1008     ok = ExprResolveInteger(ctx, expr, val_rtrn);
1009     if ((ok) && (val_rtrn->uval < 10))
1010         val_rtrn->uval += '0';
1011     return ok;
1012 }