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