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