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