Remove priv arguments from ExprResolveModMask
[platform/upstream/libxkbcommon.git] / src / xkbcomp / expr.c
1 /************************************************************
2  Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
4  Permission to use, copy, modify, and distribute this
5  software and its documentation for any purpose and without
6  fee is hereby granted, provided that the above copyright
7  notice appear in all copies and that both that copyright
8  notice and this permission notice appear in supporting
9  documentation, and that the name of Silicon Graphics not be
10  used in advertising or publicity pertaining to distribution
11  of the software without specific prior written permission.
12  Silicon Graphics makes no representation about the suitability
13  of this software for any purpose. It is provided "as is"
14  without any express or implied warranty.
15
16  SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18  AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19  GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23  THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25  ********************************************************/
26
27 #include "xkbcomp.h"
28 #include "xkbmisc.h"
29 #include "tokens.h"
30 #include "expr.h"
31 #include "vmod.h"
32
33 #include <ctype.h>
34
35 /***====================================================================***/
36
37 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 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(ExprDef * expr,
133                ExprResult * elem_rtrn,
134                ExprResult * field_rtrn, ExprDef ** index_rtrn)
135 {
136     switch (expr->op)
137     {
138     case ExprIdent:
139         elem_rtrn->str = NULL;
140         field_rtrn->str = XkbcAtomGetString(expr->value.str);
141         *index_rtrn = NULL;
142         return True;
143     case ExprFieldRef:
144         elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
145         field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
146         *index_rtrn = NULL;
147         return True;
148     case ExprArrayRef:
149         elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
150         field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
151         *index_rtrn = expr->value.array.entry;
152         return True;
153     }
154     WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
155     return False;
156 }
157
158 Bool
159 SimpleLookup(char * priv,
160              uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
161 {
162     LookupEntry *entry;
163     const char *str;
164
165     if ((priv == NULL) ||
166         (field == None) || (elem != None) ||
167         ((type != TypeInt) && (type != TypeFloat)))
168     {
169         return False;
170     }
171     str = XkbcAtomText(field);
172     for (entry = (LookupEntry *) priv;
173          (entry != NULL) && (entry->name != NULL); entry++)
174     {
175         if (uStrCaseCmp(str, entry->name) == 0)
176         {
177             val_rtrn->uval = entry->result;
178             if (type == TypeFloat)
179                 val_rtrn->uval *= XkbGeomPtsPerMM;
180             return True;
181         }
182     }
183     return False;
184 }
185
186 Bool
187 RadioLookup(char * priv,
188             uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
189 {
190     const char *str;
191     int rg;
192
193     if ((field == None) || (elem != None) || (type != TypeInt))
194         return False;
195     str = XkbcAtomText(field);
196     if (str)
197     {
198         if (uStrCasePrefix("group", str))
199             str += strlen("group");
200         else if (uStrCasePrefix("radiogroup", str))
201             str += strlen("radiogroup");
202         else if (uStrCasePrefix("rg", str))
203             str += strlen("rg");
204         else if (!isdigit(str[0]))
205             str = NULL;
206     }
207     if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
208         || (rg > XkbMaxRadioGroups))
209         return False;
210     val_rtrn->uval = rg;
211     return True;
212 }
213
214 static LookupEntry modIndexNames[] = {
215     {"shift", ShiftMapIndex},
216     {"control", ControlMapIndex},
217     {"lock", LockMapIndex},
218     {"mod1", Mod1MapIndex},
219     {"mod2", Mod2MapIndex},
220     {"mod3", Mod3MapIndex},
221     {"mod4", Mod4MapIndex},
222     {"mod5", Mod5MapIndex},
223     {"none", XkbNoModifier},
224     {NULL, 0}
225 };
226
227 int
228 LookupModIndex(char * priv,
229                uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
230 {
231     return SimpleLookup((char *) modIndexNames, elem, field, type,
232                         val_rtrn);
233 }
234
235 static int
236 LookupModMask(char * priv,
237               uint32_t elem, uint32_t field, unsigned type, ExprResult * val_rtrn)
238 {
239     char *str;
240     Bool ret = True;
241
242     if ((elem != None) || (type != TypeInt))
243         return False;
244     str = XkbcAtomGetString(field);
245     if (str == NULL)
246         return False;
247     if (uStrCaseCmp(str, "all") == 0)
248         val_rtrn->uval = 0xff;
249     else if (uStrCaseCmp(str, "none") == 0)
250         val_rtrn->uval = 0;
251     else if (LookupModIndex(priv, elem, field, type, val_rtrn))
252         val_rtrn->uval = (1 << val_rtrn->uval);
253     else if (priv != NULL)
254     {
255         LookupPriv *lpriv = (LookupPriv *) priv;
256         if ((lpriv->chain == NULL) ||
257             (!(*lpriv->chain) (lpriv->chainPriv, elem, field, type,
258                                val_rtrn)))
259             ret = False;
260     }
261     else
262         ret = False;
263     free(str);
264     return ret;
265 }
266
267 int
268 ExprResolveModMask(ExprDef * expr,
269                    ExprResult * val_rtrn)
270 {
271     LookupPriv priv;
272
273     priv.priv = NULL;
274     priv.chain = NULL;
275     priv.chainPriv = NULL;
276     return ExprResolveMask(expr, val_rtrn, LookupModMask, (char *) & priv);
277 }
278
279 int
280 ExprResolveVModMask(ExprDef * expr,
281                     ExprResult * val_rtrn,
282                     struct xkb_desc *xkb)
283 {
284     LookupPriv priv;
285
286     priv.priv = NULL;
287     priv.chain = LookupVModMask;
288     priv.chainPriv = (char *) xkb;
289     return ExprResolveMask(expr, val_rtrn, LookupModMask, (char *) & priv);
290 }
291
292 int
293 ExprResolveBoolean(ExprDef * expr,
294                    ExprResult * val_rtrn,
295                    IdentLookupFunc lookup, char * lookupPriv)
296 {
297     int ok = 0;
298     const char *bogus = NULL;
299
300     switch (expr->op)
301     {
302     case ExprValue:
303         if (expr->type != TypeBoolean)
304         {
305             ERROR
306                 ("Found constant of type %s where boolean was expected\n",
307                  exprTypeText(expr->type));
308             return False;
309         }
310         val_rtrn->ival = expr->value.ival;
311         return True;
312     case ExprIdent:
313         bogus = XkbcAtomText(expr->value.str);
314         if (bogus)
315         {
316             if ((uStrCaseCmp(bogus, "true") == 0) ||
317                 (uStrCaseCmp(bogus, "yes") == 0) ||
318                 (uStrCaseCmp(bogus, "on") == 0))
319             {
320                 val_rtrn->uval = 1;
321                 return True;
322             }
323             else if ((uStrCaseCmp(bogus, "false") == 0) ||
324                      (uStrCaseCmp(bogus, "no") == 0) ||
325                      (uStrCaseCmp(bogus, "off") == 0))
326             {
327                 val_rtrn->uval = 0;
328                 return True;
329             }
330         }
331         if (lookup)
332         {
333             ok = (*lookup) (lookupPriv,
334                             None, expr->value.str, TypeBoolean, val_rtrn);
335         }
336         if (!ok)
337             ERROR("Identifier \"%s\" of type int is unknown\n",
338                    XkbcAtomText(expr->value.str));
339         return ok;
340     case ExprFieldRef:
341         if (lookup)
342         {
343             ok = (*lookup) (lookupPriv,
344                             expr->value.field.element,
345                             expr->value.field.field, TypeBoolean, val_rtrn);
346         }
347         if (!ok)
348             ERROR("Default \"%s.%s\" of type boolean is unknown\n",
349                    XkbcAtomText(expr->value.field.element),
350                    XkbcAtomText(expr->value.field.field));
351         return ok;
352     case OpInvert:
353     case OpNot:
354         ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv);
355         if (ok)
356             val_rtrn->uval = !val_rtrn->uval;
357         return ok;
358     case OpAdd:
359         if (bogus == NULL)
360             bogus = "Addition";
361     case OpSubtract:
362         if (bogus == NULL)
363             bogus = "Subtraction";
364     case OpMultiply:
365         if (bogus == NULL)
366             bogus = "Multiplication";
367     case OpDivide:
368         if (bogus == NULL)
369             bogus = "Division";
370     case OpAssign:
371         if (bogus == NULL)
372             bogus = "Assignment";
373     case OpNegate:
374         if (bogus == NULL)
375             bogus = "Negation";
376         ERROR("%s of boolean values not permitted\n", bogus);
377         break;
378     case OpUnaryPlus:
379         ERROR("Unary \"+\" operator not permitted for boolean values\n");
380         break;
381     default:
382         WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
383         break;
384     }
385     return False;
386 }
387
388 int
389 ExprResolveFloat(ExprDef * expr,
390                  ExprResult * val_rtrn,
391                  IdentLookupFunc lookup, char * lookupPriv)
392 {
393     int ok = 0;
394     ExprResult leftRtrn, rightRtrn;
395     ExprDef *left, *right;
396
397     switch (expr->op)
398     {
399     case ExprValue:
400         if (expr->type == TypeString)
401         {
402             const char *str;
403             str = XkbcAtomText(expr->value.str);
404             if ((str != NULL) && (strlen(str) == 1))
405             {
406                 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
407                 return True;
408             }
409         }
410         if ((expr->type != TypeInt) && (expr->type != TypeFloat))
411         {
412             ERROR("Found constant of type %s, expected a number\n",
413                    exprTypeText(expr->type));
414             return False;
415         }
416         val_rtrn->ival = expr->value.ival;
417         if (expr->type == TypeInt)
418             val_rtrn->ival *= XkbGeomPtsPerMM;
419         return True;
420     case ExprIdent:
421         if (lookup)
422         {
423             ok = (*lookup) (lookupPriv,
424                             None, expr->value.str, TypeFloat, val_rtrn);
425         }
426         if (!ok)
427             ERROR("Numeric identifier \"%s\" unknown\n",
428                    XkbcAtomText(expr->value.str));
429         return ok;
430     case ExprFieldRef:
431         if (lookup)
432         {
433             ok = (*lookup) (lookupPriv,
434                             expr->value.field.element,
435                             expr->value.field.field, TypeFloat, val_rtrn);
436         }
437         if (!ok)
438             ERROR("Numeric default \"%s.%s\" unknown\n",
439                    XkbcAtomText(expr->value.field.element),
440                    XkbcAtomText(expr->value.field.field));
441         return ok;
442     case OpAdd:
443     case OpSubtract:
444     case OpMultiply:
445     case OpDivide:
446         left = expr->value.binary.left;
447         right = expr->value.binary.right;
448         if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) &&
449             ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv))
450         {
451             switch (expr->op)
452             {
453             case OpAdd:
454                 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
455                 break;
456             case OpSubtract:
457                 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
458                 break;
459             case OpMultiply:
460                 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
461                 break;
462             case OpDivide:
463                 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
464                 break;
465             }
466             return True;
467         }
468         return False;
469     case OpAssign:
470         WSGO("Assignment operator not implemented yet\n");
471         break;
472     case OpNot:
473         left = expr->value.child;
474         if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
475         {
476             ERROR("The ! operator cannot be applied to a number\n");
477         }
478         return False;
479     case OpInvert:
480     case OpNegate:
481         left = expr->value.child;
482         if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
483         {
484             if (expr->op == OpNegate)
485                 val_rtrn->ival = -leftRtrn.ival;
486             else
487                 val_rtrn->ival = ~leftRtrn.ival;
488             return True;
489         }
490         return False;
491     case OpUnaryPlus:
492         left = expr->value.child;
493         return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv);
494     default:
495         WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
496         break;
497     }
498     return False;
499 }
500
501 int
502 ExprResolveKeyCode(ExprDef * expr,
503                    ExprResult * val_rtrn)
504 {
505     ExprResult leftRtrn, rightRtrn;
506     ExprDef *left, *right;
507
508     switch (expr->op)
509     {
510     case ExprValue:
511         if (expr->type != TypeInt)
512         {
513             ERROR
514                 ("Found constant of type %s where an int was expected\n",
515                  exprTypeText(expr->type));
516             return False;
517         }
518         val_rtrn->uval = expr->value.uval;
519         return True;
520     case OpAdd:
521     case OpSubtract:
522     case OpMultiply:
523     case OpDivide:
524         left = expr->value.binary.left;
525         right = expr->value.binary.right;
526         if (ExprResolveKeyCode(left, &leftRtrn) &&
527             ExprResolveKeyCode(right, &rightRtrn))
528         {
529             switch (expr->op)
530             {
531             case OpAdd:
532                 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
533                 break;
534             case OpSubtract:
535                 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
536                 break;
537             case OpMultiply:
538                 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
539                 break;
540             case OpDivide:
541                 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
542                 break;
543             }
544             return True;
545         }
546         return False;
547     case OpNegate:
548         left = expr->value.child;
549         if (ExprResolveKeyCode(left, &leftRtrn))
550         {
551             val_rtrn->uval = ~leftRtrn.uval;
552             return True;
553         }
554         return False;
555     case OpUnaryPlus:
556         left = expr->value.child;
557         return ExprResolveKeyCode(left, val_rtrn);
558     default:
559         WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
560         break;
561     }
562     return False;
563 }
564 int
565 ExprResolveInteger(ExprDef * expr,
566                    ExprResult * val_rtrn,
567                    IdentLookupFunc lookup, char * lookupPriv)
568 {
569     int ok = 0;
570     ExprResult leftRtrn, rightRtrn;
571     ExprDef *left, *right;
572
573     switch (expr->op)
574     {
575     case ExprValue:
576         if (expr->type == TypeString)
577         {
578             const char *str;
579             str = XkbcAtomText(expr->value.str);
580             if (str != NULL)
581                 switch (strlen(str))
582                 {
583                 case 0:
584                     val_rtrn->uval = 0;
585                     return True;
586                 case 1:
587                     val_rtrn->uval = str[0];
588                     return True;
589                 default:
590                     break;
591                 }
592         }
593         if ((expr->type != TypeInt) && (expr->type != TypeFloat))
594         {
595             ERROR
596                 ("Found constant of type %s where an int was expected\n",
597                  exprTypeText(expr->type));
598             return False;
599         }
600         val_rtrn->ival = expr->value.ival;
601         if (expr->type == TypeFloat)
602             val_rtrn->ival /= XkbGeomPtsPerMM;
603         return True;
604     case ExprIdent:
605         if (lookup)
606         {
607             ok = (*lookup) (lookupPriv,
608                             None, expr->value.str, TypeInt, val_rtrn);
609         }
610         if (!ok)
611             ERROR("Identifier \"%s\" of type int is unknown\n",
612                    XkbcAtomText(expr->value.str));
613         return ok;
614     case ExprFieldRef:
615         if (lookup)
616         {
617             ok = (*lookup) (lookupPriv,
618                             expr->value.field.element,
619                             expr->value.field.field, TypeInt, val_rtrn);
620         }
621         if (!ok)
622             ERROR("Default \"%s.%s\" of type int is unknown\n",
623                    XkbcAtomText(expr->value.field.element),
624                    XkbcAtomText(expr->value.field.field));
625         return ok;
626     case OpAdd:
627     case OpSubtract:
628     case OpMultiply:
629     case OpDivide:
630         left = expr->value.binary.left;
631         right = expr->value.binary.right;
632         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv) &&
633             ExprResolveInteger(right, &rightRtrn, lookup, lookupPriv))
634         {
635             switch (expr->op)
636             {
637             case OpAdd:
638                 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
639                 break;
640             case OpSubtract:
641                 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
642                 break;
643             case OpMultiply:
644                 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
645                 break;
646             case OpDivide:
647                 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
648                 break;
649             }
650             return True;
651         }
652         return False;
653     case OpAssign:
654         WSGO("Assignment operator not implemented yet\n");
655         break;
656     case OpNot:
657         left = expr->value.child;
658         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
659         {
660             ERROR("The ! operator cannot be applied to an integer\n");
661         }
662         return False;
663     case OpInvert:
664     case OpNegate:
665         left = expr->value.child;
666         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
667         {
668             if (expr->op == OpNegate)
669                 val_rtrn->ival = -leftRtrn.ival;
670             else
671                 val_rtrn->ival = ~leftRtrn.ival;
672             return True;
673         }
674         return False;
675     case OpUnaryPlus:
676         left = expr->value.child;
677         return ExprResolveInteger(left, val_rtrn, lookup, lookupPriv);
678     default:
679         WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
680         break;
681     }
682     return False;
683 }
684
685 int
686 ExprResolveString(ExprDef * expr,
687                   ExprResult * val_rtrn,
688                   IdentLookupFunc lookup, char * lookupPriv)
689 {
690     int ok = 0;
691     ExprResult leftRtrn, rightRtrn;
692     ExprDef *left;
693     ExprDef *right;
694     char *bogus = NULL;
695
696     switch (expr->op)
697     {
698     case ExprValue:
699         if (expr->type != TypeString)
700         {
701             ERROR("Found constant of type %s, expected a string\n",
702                    exprTypeText(expr->type));
703             return False;
704         }
705         val_rtrn->str = XkbcAtomGetString(expr->value.str);
706         if (val_rtrn->str == NULL)
707             val_rtrn->str = strdup("");
708         return True;
709     case ExprIdent:
710         if (lookup)
711         {
712             ok = (*lookup) (lookupPriv,
713                             None, expr->value.str, TypeString, val_rtrn);
714         }
715         if (!ok)
716             ERROR("Identifier \"%s\" of type string not found\n",
717                    XkbcAtomText(expr->value.str));
718         return ok;
719     case ExprFieldRef:
720         if (lookup)
721         {
722             ok = (*lookup) (lookupPriv,
723                             expr->value.field.element,
724                             expr->value.field.field, TypeString, val_rtrn);
725         }
726         if (!ok)
727             ERROR("Default \"%s.%s\" of type string not found\n",
728                    XkbcAtomText(expr->value.field.element),
729                    XkbcAtomText(expr->value.field.field));
730         return ok;
731     case OpAdd:
732         left = expr->value.binary.left;
733         right = expr->value.binary.right;
734         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) &&
735             ExprResolveString(right, &rightRtrn, lookup, lookupPriv))
736         {
737             int len;
738             char *new;
739             len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
740             new = (char *) malloc(len);
741             if (new)
742             {
743                 sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
744                 free(leftRtrn.str);
745                 free(rightRtrn.str);
746                 val_rtrn->str = new;
747                 return True;
748             }
749             free(leftRtrn.str);
750             free(rightRtrn.str);
751         }
752         return False;
753     case OpSubtract:
754         if (bogus == NULL)
755             bogus = "Subtraction";
756     case OpMultiply:
757         if (bogus == NULL)
758             bogus = "Multiplication";
759     case OpDivide:
760         if (bogus == NULL)
761             bogus = "Division";
762     case OpAssign:
763         if (bogus == NULL)
764             bogus = "Assignment";
765     case OpNegate:
766         if (bogus == NULL)
767             bogus = "Negation";
768     case OpInvert:
769         if (bogus == NULL)
770             bogus = "Bitwise complement";
771         ERROR("%s of string values not permitted\n", bogus);
772         return False;
773     case OpNot:
774         left = expr->value.child;
775         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
776         {
777             ERROR("The ! operator cannot be applied to a string\n");
778         }
779         return False;
780     case OpUnaryPlus:
781         left = expr->value.child;
782         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
783         {
784             ERROR("The + operator cannot be applied to a string\n");
785         }
786         return False;
787     default:
788         WSGO("Unknown operator %d in ResolveString\n", expr->op);
789         break;
790     }
791     return False;
792 }
793
794 int
795 ExprResolveKeyName(ExprDef * expr,
796                    ExprResult * val_rtrn,
797                    IdentLookupFunc lookup, char * lookupPriv)
798 {
799     int ok = 0;
800     ExprDef *left;
801     ExprResult leftRtrn;
802     char *bogus = NULL;
803
804     switch (expr->op)
805     {
806     case ExprValue:
807         if (expr->type != TypeKeyName)
808         {
809             ERROR("Found constant of type %s, expected a key name\n",
810                    exprTypeText(expr->type));
811             return False;
812         }
813         memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
814         return True;
815     case ExprIdent:
816         if (lookup)
817         {
818             ok = (*lookup) (lookupPriv,
819                             None, expr->value.str, TypeString, val_rtrn);
820         }
821         if (!ok)
822             ERROR("Identifier \"%s\" of type string not found\n",
823                    XkbcAtomText(expr->value.str));
824         return ok;
825     case ExprFieldRef:
826         if (lookup)
827         {
828             ok = (*lookup) (lookupPriv,
829                             expr->value.field.element,
830                             expr->value.field.field, TypeString, val_rtrn);
831         }
832         if (!ok)
833             ERROR("Default \"%s.%s\" of type key name not found\n",
834                    XkbcAtomText(expr->value.field.element),
835                    XkbcAtomText(expr->value.field.field));
836         return ok;
837     case OpAdd:
838         if (bogus == NULL)
839             bogus = "Addition";
840     case OpSubtract:
841         if (bogus == NULL)
842             bogus = "Subtraction";
843     case OpMultiply:
844         if (bogus == NULL)
845             bogus = "Multiplication";
846     case OpDivide:
847         if (bogus == NULL)
848             bogus = "Division";
849     case OpAssign:
850         if (bogus == NULL)
851             bogus = "Assignment";
852     case OpNegate:
853         if (bogus == NULL)
854             bogus = "Negation";
855     case OpInvert:
856         if (bogus == NULL)
857             bogus = "Bitwise complement";
858         ERROR("%s of key name values not permitted\n", bogus);
859         return False;
860     case OpNot:
861         left = expr->value.binary.left;
862         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
863         {
864             ERROR("The ! operator cannot be applied to a key name\n");
865         }
866         return False;
867     case OpUnaryPlus:
868         left = expr->value.binary.left;
869         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
870         {
871             ERROR("The + operator cannot be applied to a key name\n");
872         }
873         return False;
874     default:
875         WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
876         break;
877     }
878     return False;
879 }
880
881 /***====================================================================***/
882
883 int
884 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
885 {
886     if (expr->op != ExprIdent)
887     {
888         ERROR("Found a %s where an enumerated value was expected\n",
889                exprOpText(expr->op));
890         return False;
891     }
892     if (!SimpleLookup((char *) values, (uint32_t) None, expr->value.str,
893                       (unsigned) TypeInt, val_rtrn))
894     {
895         int nOut = 0;
896         ERROR("Illegal identifier %s (expected one of: ",
897                XkbcAtomText(expr->value.str));
898         while (values && values->name)
899         {
900             if (nOut != 0)
901                 INFO(", %s", values->name);
902             else
903                 INFO("%s", values->name);
904             values++;
905             nOut++;
906         }
907         INFO(")\n");
908         return False;
909     }
910     return True;
911 }
912
913 int
914 ExprResolveMask(ExprDef * expr,
915                 ExprResult * val_rtrn,
916                 IdentLookupFunc lookup, char * lookupPriv)
917 {
918     int ok = 0;
919     ExprResult leftRtrn, rightRtrn;
920     ExprDef *left, *right;
921     char *bogus = NULL;
922
923     switch (expr->op)
924     {
925     case ExprValue:
926         if (expr->type != TypeInt)
927         {
928             ERROR
929                 ("Found constant of type %s where a mask was expected\n",
930                  exprTypeText(expr->type));
931             return False;
932         }
933         val_rtrn->ival = expr->value.ival;
934         return True;
935     case ExprIdent:
936         if (lookup)
937         {
938             ok = (*lookup) (lookupPriv,
939                             None, expr->value.str, TypeInt, val_rtrn);
940         }
941         if (!ok)
942             ERROR("Identifier \"%s\" of type int is unknown\n",
943                    XkbcAtomText(expr->value.str));
944         return ok;
945     case ExprFieldRef:
946         if (lookup)
947         {
948             ok = (*lookup) (lookupPriv,
949                             expr->value.field.element,
950                             expr->value.field.field, TypeInt, val_rtrn);
951         }
952         if (!ok)
953             ERROR("Default \"%s.%s\" of type int is unknown\n",
954                    XkbcAtomText(expr->value.field.element),
955                    XkbcAtomText(expr->value.field.field));
956         return ok;
957     case ExprArrayRef:
958         bogus = "array reference";
959     case ExprActionDecl:
960         if (bogus == NULL)
961             bogus = "function use";
962         ERROR("Unexpected %s in mask expression\n", bogus);
963         ACTION("Expression ignored\n");
964         return False;
965     case OpAdd:
966     case OpSubtract:
967     case OpMultiply:
968     case OpDivide:
969         left = expr->value.binary.left;
970         right = expr->value.binary.right;
971         if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) &&
972             ExprResolveMask(right, &rightRtrn, lookup, lookupPriv))
973         {
974             switch (expr->op)
975             {
976             case OpAdd:
977                 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
978                 break;
979             case OpSubtract:
980                 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
981                 break;
982             case OpMultiply:
983             case OpDivide:
984                 ERROR("Cannot %s masks\n",
985                        expr->op == OpDivide ? "divide" : "multiply");
986                 ACTION("Illegal operation ignored\n");
987                 return False;
988             }
989             return True;
990         }
991         return False;
992     case OpAssign:
993         WSGO("Assignment operator not implemented yet\n");
994         break;
995     case OpInvert:
996         left = expr->value.child;
997         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
998         {
999             val_rtrn->ival = ~leftRtrn.ival;
1000             return True;
1001         }
1002         return False;
1003     case OpUnaryPlus:
1004     case OpNegate:
1005     case OpNot:
1006         left = expr->value.child;
1007         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
1008         {
1009             ERROR("The %s operator cannot be used with a mask\n",
1010                    (expr->op == OpNegate ? "-" : "!"));
1011         }
1012         return False;
1013     default:
1014         WSGO("Unknown operator %d in ResolveMask\n", expr->op);
1015         break;
1016     }
1017     return False;
1018 }
1019
1020 int
1021 ExprResolveKeySym(ExprDef * expr,
1022                   ExprResult * val_rtrn,
1023                   IdentLookupFunc lookup, char * lookupPriv)
1024 {
1025     int ok = 0;
1026     uint32_t sym;
1027
1028     if (expr->op == ExprIdent)
1029     {
1030         const char *str;
1031         str = XkbcAtomText(expr->value.str);
1032         if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
1033         {
1034             val_rtrn->uval = sym;
1035             return True;
1036         }
1037     }
1038     ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv);
1039     if ((ok) && (val_rtrn->uval < 10))
1040         val_rtrn->uval += '0';
1041     return ok;
1042 }