2416bd22d9078d6adb7c5adff6025bb3d3b5663c
[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                    IdentLookupFunc lookup, char * lookupPriv)
271 {
272     LookupPriv priv;
273
274     priv.priv = NULL;
275     priv.chain = lookup;
276     priv.chainPriv = lookupPriv;
277     return ExprResolveMask(expr, val_rtrn, LookupModMask, (char *) & priv);
278 }
279
280 int
281 ExprResolveVModMask(ExprDef * expr,
282                     ExprResult * val_rtrn,
283                     struct xkb_desc *xkb)
284 {
285     LookupPriv priv;
286
287     priv.priv = NULL;
288     priv.chain = LookupVModMask;
289     priv.chainPriv = (char *) xkb;
290     return ExprResolveMask(expr, val_rtrn, LookupModMask, (char *) & priv);
291 }
292
293 int
294 ExprResolveBoolean(ExprDef * expr,
295                    ExprResult * val_rtrn,
296                    IdentLookupFunc lookup, char * lookupPriv)
297 {
298     int ok = 0;
299     const char *bogus = NULL;
300
301     switch (expr->op)
302     {
303     case ExprValue:
304         if (expr->type != TypeBoolean)
305         {
306             ERROR
307                 ("Found constant of type %s where boolean was expected\n",
308                  exprTypeText(expr->type));
309             return False;
310         }
311         val_rtrn->ival = expr->value.ival;
312         return True;
313     case ExprIdent:
314         bogus = XkbcAtomText(expr->value.str);
315         if (bogus)
316         {
317             if ((uStrCaseCmp(bogus, "true") == 0) ||
318                 (uStrCaseCmp(bogus, "yes") == 0) ||
319                 (uStrCaseCmp(bogus, "on") == 0))
320             {
321                 val_rtrn->uval = 1;
322                 return True;
323             }
324             else if ((uStrCaseCmp(bogus, "false") == 0) ||
325                      (uStrCaseCmp(bogus, "no") == 0) ||
326                      (uStrCaseCmp(bogus, "off") == 0))
327             {
328                 val_rtrn->uval = 0;
329                 return True;
330             }
331         }
332         if (lookup)
333         {
334             ok = (*lookup) (lookupPriv,
335                             None, expr->value.str, TypeBoolean, val_rtrn);
336         }
337         if (!ok)
338             ERROR("Identifier \"%s\" of type int is unknown\n",
339                    XkbcAtomText(expr->value.str));
340         return ok;
341     case ExprFieldRef:
342         if (lookup)
343         {
344             ok = (*lookup) (lookupPriv,
345                             expr->value.field.element,
346                             expr->value.field.field, TypeBoolean, val_rtrn);
347         }
348         if (!ok)
349             ERROR("Default \"%s.%s\" of type boolean is unknown\n",
350                    XkbcAtomText(expr->value.field.element),
351                    XkbcAtomText(expr->value.field.field));
352         return ok;
353     case OpInvert:
354     case OpNot:
355         ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv);
356         if (ok)
357             val_rtrn->uval = !val_rtrn->uval;
358         return ok;
359     case OpAdd:
360         if (bogus == NULL)
361             bogus = "Addition";
362     case OpSubtract:
363         if (bogus == NULL)
364             bogus = "Subtraction";
365     case OpMultiply:
366         if (bogus == NULL)
367             bogus = "Multiplication";
368     case OpDivide:
369         if (bogus == NULL)
370             bogus = "Division";
371     case OpAssign:
372         if (bogus == NULL)
373             bogus = "Assignment";
374     case OpNegate:
375         if (bogus == NULL)
376             bogus = "Negation";
377         ERROR("%s of boolean values not permitted\n", bogus);
378         break;
379     case OpUnaryPlus:
380         ERROR("Unary \"+\" operator not permitted for boolean values\n");
381         break;
382     default:
383         WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
384         break;
385     }
386     return False;
387 }
388
389 int
390 ExprResolveFloat(ExprDef * expr,
391                  ExprResult * val_rtrn,
392                  IdentLookupFunc lookup, char * lookupPriv)
393 {
394     int ok = 0;
395     ExprResult leftRtrn, rightRtrn;
396     ExprDef *left, *right;
397
398     switch (expr->op)
399     {
400     case ExprValue:
401         if (expr->type == TypeString)
402         {
403             const char *str;
404             str = XkbcAtomText(expr->value.str);
405             if ((str != NULL) && (strlen(str) == 1))
406             {
407                 val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
408                 return True;
409             }
410         }
411         if ((expr->type != TypeInt) && (expr->type != TypeFloat))
412         {
413             ERROR("Found constant of type %s, expected a number\n",
414                    exprTypeText(expr->type));
415             return False;
416         }
417         val_rtrn->ival = expr->value.ival;
418         if (expr->type == TypeInt)
419             val_rtrn->ival *= XkbGeomPtsPerMM;
420         return True;
421     case ExprIdent:
422         if (lookup)
423         {
424             ok = (*lookup) (lookupPriv,
425                             None, expr->value.str, TypeFloat, val_rtrn);
426         }
427         if (!ok)
428             ERROR("Numeric identifier \"%s\" unknown\n",
429                    XkbcAtomText(expr->value.str));
430         return ok;
431     case ExprFieldRef:
432         if (lookup)
433         {
434             ok = (*lookup) (lookupPriv,
435                             expr->value.field.element,
436                             expr->value.field.field, TypeFloat, val_rtrn);
437         }
438         if (!ok)
439             ERROR("Numeric default \"%s.%s\" unknown\n",
440                    XkbcAtomText(expr->value.field.element),
441                    XkbcAtomText(expr->value.field.field));
442         return ok;
443     case OpAdd:
444     case OpSubtract:
445     case OpMultiply:
446     case OpDivide:
447         left = expr->value.binary.left;
448         right = expr->value.binary.right;
449         if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) &&
450             ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv))
451         {
452             switch (expr->op)
453             {
454             case OpAdd:
455                 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
456                 break;
457             case OpSubtract:
458                 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
459                 break;
460             case OpMultiply:
461                 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
462                 break;
463             case OpDivide:
464                 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
465                 break;
466             }
467             return True;
468         }
469         return False;
470     case OpAssign:
471         WSGO("Assignment operator not implemented yet\n");
472         break;
473     case OpNot:
474         left = expr->value.child;
475         if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
476         {
477             ERROR("The ! operator cannot be applied to a number\n");
478         }
479         return False;
480     case OpInvert:
481     case OpNegate:
482         left = expr->value.child;
483         if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
484         {
485             if (expr->op == OpNegate)
486                 val_rtrn->ival = -leftRtrn.ival;
487             else
488                 val_rtrn->ival = ~leftRtrn.ival;
489             return True;
490         }
491         return False;
492     case OpUnaryPlus:
493         left = expr->value.child;
494         return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv);
495     default:
496         WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
497         break;
498     }
499     return False;
500 }
501
502 int
503 ExprResolveKeyCode(ExprDef * expr,
504                    ExprResult * val_rtrn)
505 {
506     ExprResult leftRtrn, rightRtrn;
507     ExprDef *left, *right;
508
509     switch (expr->op)
510     {
511     case ExprValue:
512         if (expr->type != TypeInt)
513         {
514             ERROR
515                 ("Found constant of type %s where an int was expected\n",
516                  exprTypeText(expr->type));
517             return False;
518         }
519         val_rtrn->uval = expr->value.uval;
520         return True;
521     case OpAdd:
522     case OpSubtract:
523     case OpMultiply:
524     case OpDivide:
525         left = expr->value.binary.left;
526         right = expr->value.binary.right;
527         if (ExprResolveKeyCode(left, &leftRtrn) &&
528             ExprResolveKeyCode(right, &rightRtrn))
529         {
530             switch (expr->op)
531             {
532             case OpAdd:
533                 val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
534                 break;
535             case OpSubtract:
536                 val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
537                 break;
538             case OpMultiply:
539                 val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
540                 break;
541             case OpDivide:
542                 val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
543                 break;
544             }
545             return True;
546         }
547         return False;
548     case OpNegate:
549         left = expr->value.child;
550         if (ExprResolveKeyCode(left, &leftRtrn))
551         {
552             val_rtrn->uval = ~leftRtrn.uval;
553             return True;
554         }
555         return False;
556     case OpUnaryPlus:
557         left = expr->value.child;
558         return ExprResolveKeyCode(left, val_rtrn);
559     default:
560         WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
561         break;
562     }
563     return False;
564 }
565 int
566 ExprResolveInteger(ExprDef * expr,
567                    ExprResult * val_rtrn,
568                    IdentLookupFunc lookup, char * lookupPriv)
569 {
570     int ok = 0;
571     ExprResult leftRtrn, rightRtrn;
572     ExprDef *left, *right;
573
574     switch (expr->op)
575     {
576     case ExprValue:
577         if (expr->type == TypeString)
578         {
579             const char *str;
580             str = XkbcAtomText(expr->value.str);
581             if (str != NULL)
582                 switch (strlen(str))
583                 {
584                 case 0:
585                     val_rtrn->uval = 0;
586                     return True;
587                 case 1:
588                     val_rtrn->uval = str[0];
589                     return True;
590                 default:
591                     break;
592                 }
593         }
594         if ((expr->type != TypeInt) && (expr->type != TypeFloat))
595         {
596             ERROR
597                 ("Found constant of type %s where an int was expected\n",
598                  exprTypeText(expr->type));
599             return False;
600         }
601         val_rtrn->ival = expr->value.ival;
602         if (expr->type == TypeFloat)
603             val_rtrn->ival /= XkbGeomPtsPerMM;
604         return True;
605     case ExprIdent:
606         if (lookup)
607         {
608             ok = (*lookup) (lookupPriv,
609                             None, expr->value.str, TypeInt, val_rtrn);
610         }
611         if (!ok)
612             ERROR("Identifier \"%s\" of type int is unknown\n",
613                    XkbcAtomText(expr->value.str));
614         return ok;
615     case ExprFieldRef:
616         if (lookup)
617         {
618             ok = (*lookup) (lookupPriv,
619                             expr->value.field.element,
620                             expr->value.field.field, TypeInt, val_rtrn);
621         }
622         if (!ok)
623             ERROR("Default \"%s.%s\" of type int is unknown\n",
624                    XkbcAtomText(expr->value.field.element),
625                    XkbcAtomText(expr->value.field.field));
626         return ok;
627     case OpAdd:
628     case OpSubtract:
629     case OpMultiply:
630     case OpDivide:
631         left = expr->value.binary.left;
632         right = expr->value.binary.right;
633         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv) &&
634             ExprResolveInteger(right, &rightRtrn, lookup, lookupPriv))
635         {
636             switch (expr->op)
637             {
638             case OpAdd:
639                 val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
640                 break;
641             case OpSubtract:
642                 val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
643                 break;
644             case OpMultiply:
645                 val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
646                 break;
647             case OpDivide:
648                 val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
649                 break;
650             }
651             return True;
652         }
653         return False;
654     case OpAssign:
655         WSGO("Assignment operator not implemented yet\n");
656         break;
657     case OpNot:
658         left = expr->value.child;
659         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
660         {
661             ERROR("The ! operator cannot be applied to an integer\n");
662         }
663         return False;
664     case OpInvert:
665     case OpNegate:
666         left = expr->value.child;
667         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
668         {
669             if (expr->op == OpNegate)
670                 val_rtrn->ival = -leftRtrn.ival;
671             else
672                 val_rtrn->ival = ~leftRtrn.ival;
673             return True;
674         }
675         return False;
676     case OpUnaryPlus:
677         left = expr->value.child;
678         return ExprResolveInteger(left, val_rtrn, lookup, lookupPriv);
679     default:
680         WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
681         break;
682     }
683     return False;
684 }
685
686 int
687 ExprResolveString(ExprDef * expr,
688                   ExprResult * val_rtrn,
689                   IdentLookupFunc lookup, char * lookupPriv)
690 {
691     int ok = 0;
692     ExprResult leftRtrn, rightRtrn;
693     ExprDef *left;
694     ExprDef *right;
695     char *bogus = NULL;
696
697     switch (expr->op)
698     {
699     case ExprValue:
700         if (expr->type != TypeString)
701         {
702             ERROR("Found constant of type %s, expected a string\n",
703                    exprTypeText(expr->type));
704             return False;
705         }
706         val_rtrn->str = XkbcAtomGetString(expr->value.str);
707         if (val_rtrn->str == NULL)
708             val_rtrn->str = strdup("");
709         return True;
710     case ExprIdent:
711         if (lookup)
712         {
713             ok = (*lookup) (lookupPriv,
714                             None, expr->value.str, TypeString, val_rtrn);
715         }
716         if (!ok)
717             ERROR("Identifier \"%s\" of type string not found\n",
718                    XkbcAtomText(expr->value.str));
719         return ok;
720     case ExprFieldRef:
721         if (lookup)
722         {
723             ok = (*lookup) (lookupPriv,
724                             expr->value.field.element,
725                             expr->value.field.field, TypeString, val_rtrn);
726         }
727         if (!ok)
728             ERROR("Default \"%s.%s\" of type string not found\n",
729                    XkbcAtomText(expr->value.field.element),
730                    XkbcAtomText(expr->value.field.field));
731         return ok;
732     case OpAdd:
733         left = expr->value.binary.left;
734         right = expr->value.binary.right;
735         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) &&
736             ExprResolveString(right, &rightRtrn, lookup, lookupPriv))
737         {
738             int len;
739             char *new;
740             len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
741             new = (char *) malloc(len);
742             if (new)
743             {
744                 sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
745                 free(leftRtrn.str);
746                 free(rightRtrn.str);
747                 val_rtrn->str = new;
748                 return True;
749             }
750             free(leftRtrn.str);
751             free(rightRtrn.str);
752         }
753         return False;
754     case OpSubtract:
755         if (bogus == NULL)
756             bogus = "Subtraction";
757     case OpMultiply:
758         if (bogus == NULL)
759             bogus = "Multiplication";
760     case OpDivide:
761         if (bogus == NULL)
762             bogus = "Division";
763     case OpAssign:
764         if (bogus == NULL)
765             bogus = "Assignment";
766     case OpNegate:
767         if (bogus == NULL)
768             bogus = "Negation";
769     case OpInvert:
770         if (bogus == NULL)
771             bogus = "Bitwise complement";
772         ERROR("%s of string values not permitted\n", bogus);
773         return False;
774     case OpNot:
775         left = expr->value.child;
776         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
777         {
778             ERROR("The ! operator cannot be applied to a string\n");
779         }
780         return False;
781     case OpUnaryPlus:
782         left = expr->value.child;
783         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
784         {
785             ERROR("The + operator cannot be applied to a string\n");
786         }
787         return False;
788     default:
789         WSGO("Unknown operator %d in ResolveString\n", expr->op);
790         break;
791     }
792     return False;
793 }
794
795 int
796 ExprResolveKeyName(ExprDef * expr,
797                    ExprResult * val_rtrn,
798                    IdentLookupFunc lookup, char * lookupPriv)
799 {
800     int ok = 0;
801     ExprDef *left;
802     ExprResult leftRtrn;
803     char *bogus = NULL;
804
805     switch (expr->op)
806     {
807     case ExprValue:
808         if (expr->type != TypeKeyName)
809         {
810             ERROR("Found constant of type %s, expected a key name\n",
811                    exprTypeText(expr->type));
812             return False;
813         }
814         memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
815         return True;
816     case ExprIdent:
817         if (lookup)
818         {
819             ok = (*lookup) (lookupPriv,
820                             None, expr->value.str, TypeString, val_rtrn);
821         }
822         if (!ok)
823             ERROR("Identifier \"%s\" of type string not found\n",
824                    XkbcAtomText(expr->value.str));
825         return ok;
826     case ExprFieldRef:
827         if (lookup)
828         {
829             ok = (*lookup) (lookupPriv,
830                             expr->value.field.element,
831                             expr->value.field.field, TypeString, val_rtrn);
832         }
833         if (!ok)
834             ERROR("Default \"%s.%s\" of type key name not found\n",
835                    XkbcAtomText(expr->value.field.element),
836                    XkbcAtomText(expr->value.field.field));
837         return ok;
838     case OpAdd:
839         if (bogus == NULL)
840             bogus = "Addition";
841     case OpSubtract:
842         if (bogus == NULL)
843             bogus = "Subtraction";
844     case OpMultiply:
845         if (bogus == NULL)
846             bogus = "Multiplication";
847     case OpDivide:
848         if (bogus == NULL)
849             bogus = "Division";
850     case OpAssign:
851         if (bogus == NULL)
852             bogus = "Assignment";
853     case OpNegate:
854         if (bogus == NULL)
855             bogus = "Negation";
856     case OpInvert:
857         if (bogus == NULL)
858             bogus = "Bitwise complement";
859         ERROR("%s of key name values not permitted\n", bogus);
860         return False;
861     case OpNot:
862         left = expr->value.binary.left;
863         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
864         {
865             ERROR("The ! operator cannot be applied to a key name\n");
866         }
867         return False;
868     case OpUnaryPlus:
869         left = expr->value.binary.left;
870         if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
871         {
872             ERROR("The + operator cannot be applied to a key name\n");
873         }
874         return False;
875     default:
876         WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
877         break;
878     }
879     return False;
880 }
881
882 /***====================================================================***/
883
884 int
885 ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
886 {
887     if (expr->op != ExprIdent)
888     {
889         ERROR("Found a %s where an enumerated value was expected\n",
890                exprOpText(expr->op));
891         return False;
892     }
893     if (!SimpleLookup((char *) values, (uint32_t) None, expr->value.str,
894                       (unsigned) TypeInt, val_rtrn))
895     {
896         int nOut = 0;
897         ERROR("Illegal identifier %s (expected one of: ",
898                XkbcAtomText(expr->value.str));
899         while (values && values->name)
900         {
901             if (nOut != 0)
902                 INFO(", %s", values->name);
903             else
904                 INFO("%s", values->name);
905             values++;
906             nOut++;
907         }
908         INFO(")\n");
909         return False;
910     }
911     return True;
912 }
913
914 int
915 ExprResolveMask(ExprDef * expr,
916                 ExprResult * val_rtrn,
917                 IdentLookupFunc lookup, char * lookupPriv)
918 {
919     int ok = 0;
920     ExprResult leftRtrn, rightRtrn;
921     ExprDef *left, *right;
922     char *bogus = NULL;
923
924     switch (expr->op)
925     {
926     case ExprValue:
927         if (expr->type != TypeInt)
928         {
929             ERROR
930                 ("Found constant of type %s where a mask was expected\n",
931                  exprTypeText(expr->type));
932             return False;
933         }
934         val_rtrn->ival = expr->value.ival;
935         return True;
936     case ExprIdent:
937         if (lookup)
938         {
939             ok = (*lookup) (lookupPriv,
940                             None, expr->value.str, TypeInt, val_rtrn);
941         }
942         if (!ok)
943             ERROR("Identifier \"%s\" of type int is unknown\n",
944                    XkbcAtomText(expr->value.str));
945         return ok;
946     case ExprFieldRef:
947         if (lookup)
948         {
949             ok = (*lookup) (lookupPriv,
950                             expr->value.field.element,
951                             expr->value.field.field, TypeInt, val_rtrn);
952         }
953         if (!ok)
954             ERROR("Default \"%s.%s\" of type int is unknown\n",
955                    XkbcAtomText(expr->value.field.element),
956                    XkbcAtomText(expr->value.field.field));
957         return ok;
958     case ExprArrayRef:
959         bogus = "array reference";
960     case ExprActionDecl:
961         if (bogus == NULL)
962             bogus = "function use";
963         ERROR("Unexpected %s in mask expression\n", bogus);
964         ACTION("Expression ignored\n");
965         return False;
966     case OpAdd:
967     case OpSubtract:
968     case OpMultiply:
969     case OpDivide:
970         left = expr->value.binary.left;
971         right = expr->value.binary.right;
972         if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) &&
973             ExprResolveMask(right, &rightRtrn, lookup, lookupPriv))
974         {
975             switch (expr->op)
976             {
977             case OpAdd:
978                 val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
979                 break;
980             case OpSubtract:
981                 val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
982                 break;
983             case OpMultiply:
984             case OpDivide:
985                 ERROR("Cannot %s masks\n",
986                        expr->op == OpDivide ? "divide" : "multiply");
987                 ACTION("Illegal operation ignored\n");
988                 return False;
989             }
990             return True;
991         }
992         return False;
993     case OpAssign:
994         WSGO("Assignment operator not implemented yet\n");
995         break;
996     case OpInvert:
997         left = expr->value.child;
998         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
999         {
1000             val_rtrn->ival = ~leftRtrn.ival;
1001             return True;
1002         }
1003         return False;
1004     case OpUnaryPlus:
1005     case OpNegate:
1006     case OpNot:
1007         left = expr->value.child;
1008         if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
1009         {
1010             ERROR("The %s operator cannot be used with a mask\n",
1011                    (expr->op == OpNegate ? "-" : "!"));
1012         }
1013         return False;
1014     default:
1015         WSGO("Unknown operator %d in ResolveMask\n", expr->op);
1016         break;
1017     }
1018     return False;
1019 }
1020
1021 int
1022 ExprResolveKeySym(ExprDef * expr,
1023                   ExprResult * val_rtrn,
1024                   IdentLookupFunc lookup, char * lookupPriv)
1025 {
1026     int ok = 0;
1027     uint32_t sym;
1028
1029     if (expr->op == ExprIdent)
1030     {
1031         const char *str;
1032         str = XkbcAtomText(expr->value.str);
1033         if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
1034         {
1035             val_rtrn->uval = sym;
1036             return True;
1037         }
1038     }
1039     ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv);
1040     if ((ok) && (val_rtrn->uval < 10))
1041         val_rtrn->uval += '0';
1042     return ok;
1043 }