expr.c revision 319fa471
1f46a6179Smrg/************************************************************
2f46a6179Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3f46a6179Smrg
4f46a6179Smrg Permission to use, copy, modify, and distribute this
5f46a6179Smrg software and its documentation for any purpose and without
6f46a6179Smrg fee is hereby granted, provided that the above copyright
7f46a6179Smrg notice appear in all copies and that both that copyright
8f46a6179Smrg notice and this permission notice appear in supporting
9f46a6179Smrg documentation, and that the name of Silicon Graphics not be
10f46a6179Smrg used in advertising or publicity pertaining to distribution
11f46a6179Smrg of the software without specific prior written permission.
12f46a6179Smrg Silicon Graphics makes no representation about the suitability
13f46a6179Smrg of this software for any purpose. It is provided "as is"
14f46a6179Smrg without any express or implied warranty.
15f46a6179Smrg
16f46a6179Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17f46a6179Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19f46a6179Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20f46a6179Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21f46a6179Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
24f46a6179Smrg
25f46a6179Smrg ********************************************************/
26f46a6179Smrg
27f46a6179Smrg#include "xkbcomp.h"
28f46a6179Smrg#include "tokens.h"
29f46a6179Smrg#include "expr.h"
30f46a6179Smrg
31f46a6179Smrg#include <ctype.h>
32f46a6179Smrg
33f46a6179Smrg/***====================================================================***/
34f46a6179Smrg
35f46a6179Smrgchar *
36f46a6179SmrgexprOpText(unsigned type)
37f46a6179Smrg{
3834345a63Smrg    static char buf[32];
3934345a63Smrg
4034345a63Smrg    switch (type)
4134345a63Smrg    {
4234345a63Smrg    case ExprValue:
4334345a63Smrg        strcpy(buf, "literal");
4434345a63Smrg        break;
4534345a63Smrg    case ExprIdent:
4634345a63Smrg        strcpy(buf, "identifier");
4734345a63Smrg        break;
4834345a63Smrg    case ExprActionDecl:
4934345a63Smrg        strcpy(buf, "action declaration");
5034345a63Smrg        break;
5134345a63Smrg    case ExprFieldRef:
5234345a63Smrg        strcpy(buf, "field reference");
5334345a63Smrg        break;
5434345a63Smrg    case ExprArrayRef:
5534345a63Smrg        strcpy(buf, "array reference");
5634345a63Smrg        break;
5734345a63Smrg    case ExprKeysymList:
5834345a63Smrg        strcpy(buf, "list of keysyms");
5934345a63Smrg        break;
6034345a63Smrg    case ExprActionList:
6134345a63Smrg        strcpy(buf, "list of actions");
6234345a63Smrg        break;
6334345a63Smrg    case OpAdd:
6434345a63Smrg        strcpy(buf, "addition");
6534345a63Smrg        break;
6634345a63Smrg    case OpSubtract:
6734345a63Smrg        strcpy(buf, "subtraction");
6834345a63Smrg        break;
6934345a63Smrg    case OpMultiply:
7034345a63Smrg        strcpy(buf, "multiplication");
7134345a63Smrg        break;
7234345a63Smrg    case OpDivide:
7334345a63Smrg        strcpy(buf, "division");
7434345a63Smrg        break;
7534345a63Smrg    case OpAssign:
7634345a63Smrg        strcpy(buf, "assignment");
7734345a63Smrg        break;
7834345a63Smrg    case OpNot:
7934345a63Smrg        strcpy(buf, "logical not");
8034345a63Smrg        break;
8134345a63Smrg    case OpNegate:
8234345a63Smrg        strcpy(buf, "arithmetic negation");
8334345a63Smrg        break;
8434345a63Smrg    case OpInvert:
8534345a63Smrg        strcpy(buf, "bitwise inversion");
8634345a63Smrg        break;
8734345a63Smrg    case OpUnaryPlus:
8834345a63Smrg        strcpy(buf, "plus sign");
8934345a63Smrg        break;
9034345a63Smrg    default:
9134345a63Smrg        snprintf(buf, sizeof(buf), "illegal(%d)", type);
9234345a63Smrg        break;
9334345a63Smrg    }
9434345a63Smrg    return buf;
95f46a6179Smrg}
96f46a6179Smrg
97f46a6179Smrgchar *
98f46a6179SmrgexprTypeText(unsigned type)
99f46a6179Smrg{
10034345a63Smrg    static char buf[20];
10134345a63Smrg
10234345a63Smrg    switch (type)
10334345a63Smrg    {
10434345a63Smrg    case TypeUnknown:
10534345a63Smrg        strcpy(buf, "unknown");
10634345a63Smrg        break;
10734345a63Smrg    case TypeBoolean:
10834345a63Smrg        strcpy(buf, "boolean");
10934345a63Smrg        break;
11034345a63Smrg    case TypeInt:
11134345a63Smrg        strcpy(buf, "int");
11234345a63Smrg        break;
11334345a63Smrg    case TypeString:
11434345a63Smrg        strcpy(buf, "string");
11534345a63Smrg        break;
11634345a63Smrg    case TypeAction:
11734345a63Smrg        strcpy(buf, "action");
11834345a63Smrg        break;
11934345a63Smrg    case TypeKeyName:
12034345a63Smrg        strcpy(buf, "keyname");
12134345a63Smrg        break;
12234345a63Smrg    default:
12334345a63Smrg        snprintf(buf, sizeof(buf), "illegal(%d)", type);
12434345a63Smrg        break;
12534345a63Smrg    }
12634345a63Smrg    return buf;
127f46a6179Smrg}
128f46a6179Smrg
129f46a6179Smrgint
13034345a63SmrgExprResolveLhs(ExprDef * expr,
13134345a63Smrg               ExprResult * elem_rtrn,
13234345a63Smrg               ExprResult * field_rtrn, ExprDef ** index_rtrn)
133f46a6179Smrg{
13434345a63Smrg    switch (expr->op)
13534345a63Smrg    {
13634345a63Smrg    case ExprIdent:
13734345a63Smrg        elem_rtrn->str = NULL;
13834345a63Smrg        field_rtrn->str = XkbAtomGetString(NULL, expr->value.str);
13934345a63Smrg        *index_rtrn = NULL;
14034345a63Smrg        return True;
14134345a63Smrg    case ExprFieldRef:
14234345a63Smrg        elem_rtrn->str = XkbAtomGetString(NULL, expr->value.field.element);
14334345a63Smrg        field_rtrn->str = XkbAtomGetString(NULL, expr->value.field.field);
14434345a63Smrg        *index_rtrn = NULL;
14534345a63Smrg        return True;
14634345a63Smrg    case ExprArrayRef:
14734345a63Smrg        elem_rtrn->str = XkbAtomGetString(NULL, expr->value.array.element);
14834345a63Smrg        field_rtrn->str = XkbAtomGetString(NULL, expr->value.array.field);
14934345a63Smrg        *index_rtrn = expr->value.array.entry;
15034345a63Smrg        return True;
151f46a6179Smrg    }
15234345a63Smrg    WSGO1("Unexpected operator %d in ResolveLhs\n", expr->op);
153f46a6179Smrg    return False;
154f46a6179Smrg}
155f46a6179Smrg
156f46a6179SmrgBool
15734345a63SmrgSimpleLookup(XPointer priv,
15834345a63Smrg             Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
159f46a6179Smrg{
16034345a63Smrg    LookupEntry *entry;
16134345a63Smrg    register char *str;
162f46a6179Smrg
16334345a63Smrg    if ((priv == NULL) ||
16434345a63Smrg        (field == None) || (elem != None) ||
16534345a63Smrg        ((type != TypeInt) && (type != TypeFloat)))
16634345a63Smrg    {
16734345a63Smrg        return False;
168f46a6179Smrg    }
16934345a63Smrg    str = XkbAtomGetString(NULL, field);
17034345a63Smrg    for (entry = (LookupEntry *) priv;
17134345a63Smrg         (entry != NULL) && (entry->name != NULL); entry++)
17234345a63Smrg    {
17334345a63Smrg        if (uStrCaseCmp(str, entry->name) == 0)
17434345a63Smrg        {
17534345a63Smrg            val_rtrn->uval = entry->result;
17634345a63Smrg            if (type == TypeFloat)
17734345a63Smrg                val_rtrn->uval *= XkbGeomPtsPerMM;
17834345a63Smrg            return True;
17934345a63Smrg        }
180f46a6179Smrg    }
181f46a6179Smrg    return False;
182f46a6179Smrg}
183f46a6179Smrg
184f46a6179SmrgBool
18534345a63SmrgRadioLookup(XPointer priv,
18634345a63Smrg            Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
187f46a6179Smrg{
18834345a63Smrg    register char *str;
18934345a63Smrg    int rg;
19034345a63Smrg
19134345a63Smrg    if ((field == None) || (elem != None) || (type != TypeInt))
19234345a63Smrg        return False;
19334345a63Smrg    str = XkbAtomGetString(NULL, field);
19434345a63Smrg    if (str)
19534345a63Smrg    {
19634345a63Smrg        if (uStrCasePrefix("group", str))
19734345a63Smrg            str += strlen("group");
19834345a63Smrg        else if (uStrCasePrefix("radiogroup", str))
19934345a63Smrg            str += strlen("radiogroup");
20034345a63Smrg        else if (uStrCasePrefix("rg", str))
20134345a63Smrg            str += strlen("rg");
20234345a63Smrg        else if (!isdigit(str[0]))
20334345a63Smrg            str = NULL;
204f46a6179Smrg    }
20534345a63Smrg    if ((!str) || (sscanf(str, "%i", &rg) < 1) || (rg < 1)
20634345a63Smrg        || (rg > XkbMaxRadioGroups))
20734345a63Smrg        return False;
20834345a63Smrg    val_rtrn->uval = rg;
209f46a6179Smrg    return True;
210f46a6179Smrg}
211f46a6179Smrg
212f46a6179Smrgint
21334345a63SmrgTableLookup(XPointer priv,
21434345a63Smrg            Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
215f46a6179Smrg{
21634345a63Smrg    LookupTable *tbl = (LookupTable *) priv;
21734345a63Smrg    register char *str;
21834345a63Smrg
21934345a63Smrg    if ((priv == NULL) || (field == None) || (type != TypeInt))
22034345a63Smrg        return False;
22134345a63Smrg    str = XkbAtomGetString(NULL, elem);
22234345a63Smrg    while (tbl)
22334345a63Smrg    {
22434345a63Smrg        if (((str == NULL) && (tbl->element == NULL)) ||
22534345a63Smrg            ((str != NULL) && (tbl->element != NULL) &&
22634345a63Smrg             (uStrCaseCmp(str, tbl->element) == 0)))
22734345a63Smrg        {
22834345a63Smrg            break;
22934345a63Smrg        }
23034345a63Smrg        tbl = tbl->nextElement;
231f46a6179Smrg    }
23234345a63Smrg    if (tbl == NULL)            /* didn't find a matching element */
23334345a63Smrg        return False;
23434345a63Smrg    priv = (XPointer) tbl->entries;
23534345a63Smrg    return SimpleLookup(priv, (Atom) None, field, type, val_rtrn);
236f46a6179Smrg}
237f46a6179Smrg
238f46a6179Smrgstatic LookupEntry modIndexNames[] = {
23934345a63Smrg    {"shift", ShiftMapIndex},
24034345a63Smrg    {"control", ControlMapIndex},
24134345a63Smrg    {"lock", LockMapIndex},
24234345a63Smrg    {"mod1", Mod1MapIndex},
24334345a63Smrg    {"mod2", Mod2MapIndex},
24434345a63Smrg    {"mod3", Mod3MapIndex},
24534345a63Smrg    {"mod4", Mod4MapIndex},
24634345a63Smrg    {"mod5", Mod5MapIndex},
24734345a63Smrg    {"none", XkbNoModifier},
24834345a63Smrg    {NULL, 0}
249f46a6179Smrg};
250f46a6179Smrg
251f46a6179Smrgint
25234345a63SmrgLookupModIndex(XPointer priv,
25334345a63Smrg               Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
254f46a6179Smrg{
25534345a63Smrg    return SimpleLookup((XPointer) modIndexNames, elem, field, type,
25634345a63Smrg                        val_rtrn);
257f46a6179Smrg}
258f46a6179Smrg
259f46a6179Smrgint
26034345a63SmrgLookupModMask(XPointer priv,
26134345a63Smrg              Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
262f46a6179Smrg{
26334345a63Smrg    char *str;
26434345a63Smrg
26534345a63Smrg    if ((elem != None) || (type != TypeInt))
26634345a63Smrg        return False;
26734345a63Smrg    str = XkbAtomGetString(NULL, field);
26834345a63Smrg    if (str == NULL)
26934345a63Smrg        return False;
27034345a63Smrg    if (uStrCaseCmp(str, "all") == 0)
27134345a63Smrg        val_rtrn->uval = 0xff;
27234345a63Smrg    else if (uStrCaseCmp(str, "none") == 0)
27334345a63Smrg        val_rtrn->uval = 0;
27434345a63Smrg    else if (LookupModIndex(priv, elem, field, type, val_rtrn))
27534345a63Smrg        val_rtrn->uval = (1 << val_rtrn->uval);
27634345a63Smrg    else if (priv != NULL)
27734345a63Smrg    {
27834345a63Smrg        LookupPriv *lpriv = (LookupPriv *) priv;
27934345a63Smrg        if ((lpriv->chain == NULL) ||
28034345a63Smrg            (!(*lpriv->chain) (lpriv->chainPriv, elem, field, type,
28134345a63Smrg                               val_rtrn)))
28234345a63Smrg            return False;
283f46a6179Smrg    }
28434345a63Smrg    else
28534345a63Smrg        return False;
286f46a6179Smrg    return True;
287f46a6179Smrg}
288f46a6179Smrg
289f46a6179Smrgint
29034345a63SmrgExprResolveModIndex(ExprDef * expr,
29134345a63Smrg                    ExprResult * val_rtrn,
29234345a63Smrg                    IdentLookupFunc lookup, XPointer lookupPriv)
293f46a6179Smrg{
29434345a63Smrg    int ok = 0;
295c82dfdfbSmrg    const char *bogus = NULL;
29634345a63Smrg
29734345a63Smrg    switch (expr->op)
29834345a63Smrg    {
29934345a63Smrg    case ExprValue:
30034345a63Smrg        if (expr->type != TypeInt)
30134345a63Smrg        {
30234345a63Smrg            ERROR1
30334345a63Smrg                ("Found constant of type %s where a modifier mask was expected\n",
30434345a63Smrg                 exprTypeText(expr->type));
30534345a63Smrg            return False;
30634345a63Smrg        }
30734345a63Smrg        else if ((expr->value.ival >= XkbNumModifiers)
30834345a63Smrg                 || (expr->value.ival < 0))
30934345a63Smrg        {
31034345a63Smrg            ERROR2("Illegal modifier index (%d, must be 0..%d)\n",
31134345a63Smrg                   expr->value.ival, XkbNumModifiers - 1);
31234345a63Smrg            return False;
31334345a63Smrg        }
31434345a63Smrg        val_rtrn->ival = expr->value.ival;
31534345a63Smrg        return True;
31634345a63Smrg    case ExprIdent:
31734345a63Smrg        if (LookupModIndex(lookupPriv, (Atom) None, expr->value.str,
31834345a63Smrg                           (unsigned) TypeInt, val_rtrn))
31934345a63Smrg        {
32034345a63Smrg            return True;
32134345a63Smrg        }
32234345a63Smrg        if (lookup)
32334345a63Smrg        {
32434345a63Smrg            ok = (*lookup) (lookupPriv,
32534345a63Smrg                            None, expr->value.str, TypeInt, val_rtrn);
32634345a63Smrg        }
32734345a63Smrg        if (!ok)
32834345a63Smrg            ERROR1("Cannot determine modifier index for \"%s\"\n",
32934345a63Smrg                   XkbAtomText(NULL, expr->value.str, XkbMessage));
33034345a63Smrg        break;
33134345a63Smrg    case ExprFieldRef:
33234345a63Smrg        bogus = "field reference";
33334345a63Smrg        break;
33434345a63Smrg    case ExprArrayRef:
33534345a63Smrg        bogus = "array reference";
33634345a63Smrg        break;
33734345a63Smrg    case ExprActionDecl:
33834345a63Smrg        bogus = "function";
33934345a63Smrg        break;
34034345a63Smrg    case OpAdd:
34134345a63Smrg    case OpSubtract:
34234345a63Smrg    case OpMultiply:
34334345a63Smrg    case OpDivide:
34434345a63Smrg    case OpInvert:
34534345a63Smrg    case OpNegate:
34634345a63Smrg    case OpNot:
34734345a63Smrg    case OpUnaryPlus:
34834345a63Smrg        bogus = "arithmetic operations";
34934345a63Smrg        break;
35034345a63Smrg    case OpAssign:
35134345a63Smrg        bogus = "assignment";
35234345a63Smrg        break;
35334345a63Smrg    default:
35434345a63Smrg        WSGO1("Unknown operator %d in ResolveModIndex\n", expr->op);
35534345a63Smrg        return False;
356f46a6179Smrg    }
35734345a63Smrg    if (bogus)
35834345a63Smrg    {
35934345a63Smrg        ERROR1("Modifier index must be a name or number, %s ignored\n",
36034345a63Smrg               bogus);
36134345a63Smrg        return False;
362f46a6179Smrg    }
363f46a6179Smrg    return ok;
364f46a6179Smrg}
365f46a6179Smrg
366f46a6179Smrgint
36734345a63SmrgExprResolveModMask(ExprDef * expr,
36834345a63Smrg                   ExprResult * val_rtrn,
36934345a63Smrg                   IdentLookupFunc lookup, XPointer lookupPriv)
370f46a6179Smrg{
37134345a63Smrg    LookupPriv priv;
372f46a6179Smrg
37334345a63Smrg    priv.priv = NULL;
37434345a63Smrg    priv.chain = lookup;
37534345a63Smrg    priv.chainPriv = lookupPriv;
37634345a63Smrg    return ExprResolveMask(expr, val_rtrn, LookupModMask, (XPointer) & priv);
377f46a6179Smrg}
378f46a6179Smrg
379f46a6179Smrgint
38034345a63SmrgExprResolveBoolean(ExprDef * expr,
38134345a63Smrg                   ExprResult * val_rtrn,
38234345a63Smrg                   IdentLookupFunc lookup, XPointer lookupPriv)
383f46a6179Smrg{
38434345a63Smrg    int ok = 0;
385c82dfdfbSmrg    const char *bogus = NULL;
38634345a63Smrg
38734345a63Smrg    switch (expr->op)
38834345a63Smrg    {
38934345a63Smrg    case ExprValue:
39034345a63Smrg        if (expr->type != TypeBoolean)
39134345a63Smrg        {
39234345a63Smrg            ERROR1
39334345a63Smrg                ("Found constant of type %s where boolean was expected\n",
39434345a63Smrg                 exprTypeText(expr->type));
39534345a63Smrg            return False;
39634345a63Smrg        }
39734345a63Smrg        val_rtrn->ival = expr->value.ival;
39834345a63Smrg        return True;
39934345a63Smrg    case ExprIdent:
40034345a63Smrg        bogus = XkbAtomGetString(NULL, expr->value.str);
40134345a63Smrg        if (bogus)
40234345a63Smrg        {
40334345a63Smrg            if ((uStrCaseCmp(bogus, "true") == 0) ||
40434345a63Smrg                (uStrCaseCmp(bogus, "yes") == 0) ||
40534345a63Smrg                (uStrCaseCmp(bogus, "on") == 0))
40634345a63Smrg            {
40734345a63Smrg                val_rtrn->uval = 1;
40834345a63Smrg                return True;
40934345a63Smrg            }
41034345a63Smrg            else if ((uStrCaseCmp(bogus, "false") == 0) ||
41134345a63Smrg                     (uStrCaseCmp(bogus, "no") == 0) ||
41234345a63Smrg                     (uStrCaseCmp(bogus, "off") == 0))
41334345a63Smrg            {
41434345a63Smrg                val_rtrn->uval = 0;
41534345a63Smrg                return True;
41634345a63Smrg            }
41734345a63Smrg        }
41834345a63Smrg        if (lookup)
41934345a63Smrg        {
42034345a63Smrg            ok = (*lookup) (lookupPriv,
42134345a63Smrg                            None, expr->value.str, TypeBoolean, val_rtrn);
42234345a63Smrg        }
42334345a63Smrg        if (!ok)
42434345a63Smrg            ERROR1("Identifier \"%s\" of type int is unknown\n",
42534345a63Smrg                   XkbAtomText(NULL, expr->value.str, XkbMessage));
42634345a63Smrg        return ok;
42734345a63Smrg    case ExprFieldRef:
42834345a63Smrg        if (lookup)
42934345a63Smrg        {
43034345a63Smrg            ok = (*lookup) (lookupPriv,
43134345a63Smrg                            expr->value.field.element,
43234345a63Smrg                            expr->value.field.field, TypeBoolean, val_rtrn);
43334345a63Smrg        }
43434345a63Smrg        if (!ok)
43534345a63Smrg            ERROR2("Default \"%s.%s\" of type boolean is unknown\n",
43634345a63Smrg                   XkbAtomText(NULL, expr->value.field.element, XkbMessage),
43734345a63Smrg                   XkbAtomText(NULL, expr->value.field.field, XkbMessage));
43834345a63Smrg        return ok;
43934345a63Smrg    case OpInvert:
44034345a63Smrg    case OpNot:
44134345a63Smrg        ok = ExprResolveBoolean(expr, val_rtrn, lookup, lookupPriv);
44234345a63Smrg        if (ok)
44334345a63Smrg            val_rtrn->uval = !val_rtrn->uval;
44434345a63Smrg        return ok;
44534345a63Smrg    case OpAdd:
44634345a63Smrg        if (bogus == NULL)
44734345a63Smrg            bogus = "Addition";
44834345a63Smrg    case OpSubtract:
44934345a63Smrg        if (bogus == NULL)
45034345a63Smrg            bogus = "Subtraction";
45134345a63Smrg    case OpMultiply:
45234345a63Smrg        if (bogus == NULL)
45334345a63Smrg            bogus = "Multiplication";
45434345a63Smrg    case OpDivide:
45534345a63Smrg        if (bogus == NULL)
45634345a63Smrg            bogus = "Division";
45734345a63Smrg    case OpAssign:
45834345a63Smrg        if (bogus == NULL)
45934345a63Smrg            bogus = "Assignment";
46034345a63Smrg    case OpNegate:
46134345a63Smrg        if (bogus == NULL)
46234345a63Smrg            bogus = "Negation";
46334345a63Smrg        ERROR1("%s of boolean values not permitted\n", bogus);
46434345a63Smrg        break;
46534345a63Smrg    case OpUnaryPlus:
46634345a63Smrg        ERROR("Unary \"+\" operator not permitted for boolean values\n");
46734345a63Smrg        break;
46834345a63Smrg    default:
46934345a63Smrg        WSGO1("Unknown operator %d in ResolveBoolean\n", expr->op);
47034345a63Smrg        break;
471f46a6179Smrg    }
472f46a6179Smrg    return False;
473f46a6179Smrg}
474f46a6179Smrg
475f46a6179Smrgint
47634345a63SmrgExprResolveFloat(ExprDef * expr,
47734345a63Smrg                 ExprResult * val_rtrn,
47834345a63Smrg                 IdentLookupFunc lookup, XPointer lookupPriv)
479f46a6179Smrg{
48034345a63Smrg    int ok = 0;
48134345a63Smrg    ExprResult leftRtrn, rightRtrn;
48234345a63Smrg    ExprDef *left, *right;
48334345a63Smrg
48434345a63Smrg    switch (expr->op)
48534345a63Smrg    {
48634345a63Smrg    case ExprValue:
48734345a63Smrg        if (expr->type == TypeString)
48834345a63Smrg        {
48934345a63Smrg            register char *str;
49034345a63Smrg            str = XkbAtomGetString(NULL, expr->value.str);
49134345a63Smrg            if ((str != NULL) && (strlen(str) == 1))
49234345a63Smrg            {
49334345a63Smrg                val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
49434345a63Smrg                return True;
49534345a63Smrg            }
49634345a63Smrg        }
49734345a63Smrg        if ((expr->type != TypeInt) && (expr->type != TypeFloat))
49834345a63Smrg        {
49934345a63Smrg            ERROR1("Found constant of type %s, expected a number\n",
50034345a63Smrg                   exprTypeText(expr->type));
50134345a63Smrg            return False;
50234345a63Smrg        }
50334345a63Smrg        val_rtrn->ival = expr->value.ival;
50434345a63Smrg        if (expr->type == TypeInt)
50534345a63Smrg            val_rtrn->ival *= XkbGeomPtsPerMM;
50634345a63Smrg        return True;
50734345a63Smrg    case ExprIdent:
50834345a63Smrg        if (lookup)
50934345a63Smrg        {
51034345a63Smrg            ok = (*lookup) (lookupPriv,
51134345a63Smrg                            None, expr->value.str, TypeFloat, val_rtrn);
51234345a63Smrg        }
51334345a63Smrg        if (!ok)
51434345a63Smrg            ERROR1("Numeric identifier \"%s\" unknown\n",
51534345a63Smrg                   XkbAtomText(NULL, expr->value.str, XkbMessage));
51634345a63Smrg        return ok;
51734345a63Smrg    case ExprFieldRef:
51834345a63Smrg        if (lookup)
51934345a63Smrg        {
52034345a63Smrg            ok = (*lookup) (lookupPriv,
52134345a63Smrg                            expr->value.field.element,
52234345a63Smrg                            expr->value.field.field, TypeFloat, val_rtrn);
52334345a63Smrg        }
52434345a63Smrg        if (!ok)
52534345a63Smrg            ERROR2("Numeric default \"%s.%s\" unknown\n",
52634345a63Smrg                   XkbAtomText(NULL, expr->value.field.element, XkbMessage),
52734345a63Smrg                   XkbAtomText(NULL, expr->value.field.field, XkbMessage));
52834345a63Smrg        return ok;
52934345a63Smrg    case OpAdd:
53034345a63Smrg    case OpSubtract:
53134345a63Smrg    case OpMultiply:
53234345a63Smrg    case OpDivide:
53334345a63Smrg        left = expr->value.binary.left;
53434345a63Smrg        right = expr->value.binary.right;
53534345a63Smrg        if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv) &&
53634345a63Smrg            ExprResolveFloat(right, &rightRtrn, lookup, lookupPriv))
53734345a63Smrg        {
53834345a63Smrg            switch (expr->op)
53934345a63Smrg            {
54034345a63Smrg            case OpAdd:
54134345a63Smrg                val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
54234345a63Smrg                break;
54334345a63Smrg            case OpSubtract:
54434345a63Smrg                val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
54534345a63Smrg                break;
54634345a63Smrg            case OpMultiply:
54734345a63Smrg                val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
54834345a63Smrg                break;
54934345a63Smrg            case OpDivide:
55034345a63Smrg                val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
55134345a63Smrg                break;
55234345a63Smrg            }
55334345a63Smrg            return True;
55434345a63Smrg        }
55534345a63Smrg        return False;
55634345a63Smrg    case OpAssign:
55734345a63Smrg        WSGO("Assignment operator not implemented yet\n");
55834345a63Smrg        break;
55934345a63Smrg    case OpNot:
56034345a63Smrg        left = expr->value.child;
56134345a63Smrg        if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
56234345a63Smrg        {
56334345a63Smrg            ERROR("The ! operator cannot be applied to a number\n");
56434345a63Smrg        }
56534345a63Smrg        return False;
56634345a63Smrg    case OpInvert:
56734345a63Smrg    case OpNegate:
56834345a63Smrg        left = expr->value.child;
56934345a63Smrg        if (ExprResolveFloat(left, &leftRtrn, lookup, lookupPriv))
57034345a63Smrg        {
57134345a63Smrg            if (expr->op == OpNegate)
57234345a63Smrg                val_rtrn->ival = -leftRtrn.ival;
57334345a63Smrg            else
57434345a63Smrg                val_rtrn->ival = ~leftRtrn.ival;
57534345a63Smrg            return True;
57634345a63Smrg        }
57734345a63Smrg        return False;
57834345a63Smrg    case OpUnaryPlus:
57934345a63Smrg        left = expr->value.child;
58034345a63Smrg        return ExprResolveFloat(left, val_rtrn, lookup, lookupPriv);
58134345a63Smrg    default:
58234345a63Smrg        WSGO1("Unknown operator %d in ResolveFloat\n", expr->op);
58334345a63Smrg        break;
584f46a6179Smrg    }
585f46a6179Smrg    return False;
586f46a6179Smrg}
587f46a6179Smrg
588f46a6179Smrgint
58934345a63SmrgExprResolveInteger(ExprDef * expr,
59034345a63Smrg                   ExprResult * val_rtrn,
59134345a63Smrg                   IdentLookupFunc lookup, XPointer lookupPriv)
592f46a6179Smrg{
59334345a63Smrg    int ok = 0;
59434345a63Smrg    ExprResult leftRtrn, rightRtrn;
59534345a63Smrg    ExprDef *left, *right;
59634345a63Smrg
59734345a63Smrg    switch (expr->op)
59834345a63Smrg    {
59934345a63Smrg    case ExprValue:
60034345a63Smrg        if (expr->type == TypeString)
60134345a63Smrg        {
60234345a63Smrg            register char *str;
60334345a63Smrg            str = XkbAtomGetString(NULL, expr->value.str);
60434345a63Smrg            if (str != NULL)
60534345a63Smrg                switch (strlen(str))
60634345a63Smrg                {
60734345a63Smrg                case 0:
60834345a63Smrg                    val_rtrn->uval = 0;
60934345a63Smrg                    return True;
61034345a63Smrg                case 1:
61134345a63Smrg                    val_rtrn->uval = str[0];
61234345a63Smrg                    return True;
61334345a63Smrg                default:
61434345a63Smrg                    break;
61534345a63Smrg                }
61634345a63Smrg        }
61734345a63Smrg        if ((expr->type != TypeInt) && (expr->type != TypeFloat))
61834345a63Smrg        {
61934345a63Smrg            ERROR1
62034345a63Smrg                ("Found constant of type %s where an int was expected\n",
62134345a63Smrg                 exprTypeText(expr->type));
62234345a63Smrg            return False;
62334345a63Smrg        }
62434345a63Smrg        val_rtrn->ival = expr->value.ival;
62534345a63Smrg        if (expr->type == TypeFloat)
62634345a63Smrg            val_rtrn->ival /= XkbGeomPtsPerMM;
62734345a63Smrg        return True;
62834345a63Smrg    case ExprIdent:
62934345a63Smrg        if (lookup)
63034345a63Smrg        {
63134345a63Smrg            ok = (*lookup) (lookupPriv,
63234345a63Smrg                            None, expr->value.str, TypeInt, val_rtrn);
63334345a63Smrg        }
63434345a63Smrg        if (!ok)
63534345a63Smrg            ERROR1("Identifier \"%s\" of type int is unknown\n",
63634345a63Smrg                   XkbAtomText(NULL, expr->value.str, XkbMessage));
63734345a63Smrg        return ok;
63834345a63Smrg    case ExprFieldRef:
63934345a63Smrg        if (lookup)
64034345a63Smrg        {
64134345a63Smrg            ok = (*lookup) (lookupPriv,
64234345a63Smrg                            expr->value.field.element,
64334345a63Smrg                            expr->value.field.field, TypeInt, val_rtrn);
64434345a63Smrg        }
64534345a63Smrg        if (!ok)
64634345a63Smrg            ERROR2("Default \"%s.%s\" of type int is unknown\n",
64734345a63Smrg                   XkbAtomText(NULL, expr->value.field.element, XkbMessage),
64834345a63Smrg                   XkbAtomText(NULL, expr->value.field.field, XkbMessage));
64934345a63Smrg        return ok;
65034345a63Smrg    case OpAdd:
65134345a63Smrg    case OpSubtract:
65234345a63Smrg    case OpMultiply:
65334345a63Smrg    case OpDivide:
65434345a63Smrg        left = expr->value.binary.left;
65534345a63Smrg        right = expr->value.binary.right;
65634345a63Smrg        if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv) &&
65734345a63Smrg            ExprResolveInteger(right, &rightRtrn, lookup, lookupPriv))
65834345a63Smrg        {
65934345a63Smrg            switch (expr->op)
66034345a63Smrg            {
66134345a63Smrg            case OpAdd:
66234345a63Smrg                val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
66334345a63Smrg                break;
66434345a63Smrg            case OpSubtract:
66534345a63Smrg                val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
66634345a63Smrg                break;
66734345a63Smrg            case OpMultiply:
66834345a63Smrg                val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
66934345a63Smrg                break;
67034345a63Smrg            case OpDivide:
67134345a63Smrg                val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
67234345a63Smrg                break;
67334345a63Smrg            }
67434345a63Smrg            return True;
67534345a63Smrg        }
67634345a63Smrg        return False;
67734345a63Smrg    case OpAssign:
67834345a63Smrg        WSGO("Assignment operator not implemented yet\n");
67934345a63Smrg        break;
68034345a63Smrg    case OpNot:
68134345a63Smrg        left = expr->value.child;
68234345a63Smrg        if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
68334345a63Smrg        {
68434345a63Smrg            ERROR("The ! operator cannot be applied to an integer\n");
68534345a63Smrg        }
68634345a63Smrg        return False;
68734345a63Smrg    case OpInvert:
68834345a63Smrg    case OpNegate:
68934345a63Smrg        left = expr->value.child;
69034345a63Smrg        if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
69134345a63Smrg        {
69234345a63Smrg            if (expr->op == OpNegate)
69334345a63Smrg                val_rtrn->ival = -leftRtrn.ival;
69434345a63Smrg            else
69534345a63Smrg                val_rtrn->ival = ~leftRtrn.ival;
69634345a63Smrg            return True;
69734345a63Smrg        }
69834345a63Smrg        return False;
69934345a63Smrg    case OpUnaryPlus:
70034345a63Smrg        left = expr->value.child;
70134345a63Smrg        return ExprResolveInteger(left, val_rtrn, lookup, lookupPriv);
70234345a63Smrg    default:
70334345a63Smrg        WSGO1("Unknown operator %d in ResolveInteger\n", expr->op);
70434345a63Smrg        break;
705f46a6179Smrg    }
706f46a6179Smrg    return False;
707f46a6179Smrg}
708f46a6179Smrg
709f46a6179Smrgint
71034345a63SmrgExprResolveString(ExprDef * expr,
71134345a63Smrg                  ExprResult * val_rtrn,
71234345a63Smrg                  IdentLookupFunc lookup, XPointer lookupPriv)
713f46a6179Smrg{
71434345a63Smrg    int ok = 0;
71534345a63Smrg    ExprResult leftRtrn, rightRtrn;
71634345a63Smrg    ExprDef *left;
71734345a63Smrg    ExprDef *right;
718c82dfdfbSmrg    const char *bogus = NULL;
71934345a63Smrg
72034345a63Smrg    switch (expr->op)
72134345a63Smrg    {
72234345a63Smrg    case ExprValue:
72334345a63Smrg        if (expr->type != TypeString)
72434345a63Smrg        {
72534345a63Smrg            ERROR1("Found constant of type %s, expected a string\n",
72634345a63Smrg                   exprTypeText(expr->type));
72734345a63Smrg            return False;
72834345a63Smrg        }
72934345a63Smrg        val_rtrn->str = XkbAtomGetString(NULL, expr->value.str);
73034345a63Smrg        if (val_rtrn->str == NULL)
73134345a63Smrg        {
732319fa471Smrg            static char empty_char = '\0';
733319fa471Smrg            val_rtrn->str = &empty_char;
73434345a63Smrg        }
73534345a63Smrg        return True;
73634345a63Smrg    case ExprIdent:
73734345a63Smrg        if (lookup)
73834345a63Smrg        {
73934345a63Smrg            ok = (*lookup) (lookupPriv,
74034345a63Smrg                            None, expr->value.str, TypeString, val_rtrn);
74134345a63Smrg        }
74234345a63Smrg        if (!ok)
74334345a63Smrg            ERROR1("Identifier \"%s\" of type string not found\n",
74434345a63Smrg                   XkbAtomText(NULL, expr->value.str, XkbMessage));
74534345a63Smrg        return ok;
74634345a63Smrg    case ExprFieldRef:
74734345a63Smrg        if (lookup)
74834345a63Smrg        {
74934345a63Smrg            ok = (*lookup) (lookupPriv,
75034345a63Smrg                            expr->value.field.element,
75134345a63Smrg                            expr->value.field.field, TypeString, val_rtrn);
75234345a63Smrg        }
75334345a63Smrg        if (!ok)
75434345a63Smrg            ERROR2("Default \"%s.%s\" of type string not found\n",
75534345a63Smrg                   XkbAtomText(NULL, expr->value.field.element, XkbMessage),
75634345a63Smrg                   XkbAtomText(NULL, expr->value.field.field, XkbMessage));
75734345a63Smrg        return ok;
75834345a63Smrg    case OpAdd:
75934345a63Smrg        left = expr->value.binary.left;
76034345a63Smrg        right = expr->value.binary.right;
76134345a63Smrg        if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv) &&
76234345a63Smrg            ExprResolveString(right, &rightRtrn, lookup, lookupPriv))
76334345a63Smrg        {
76434345a63Smrg            int len;
76534345a63Smrg            char *new;
76634345a63Smrg            len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
76734345a63Smrg            new = (char *) uAlloc(len);
76834345a63Smrg            if (new)
76934345a63Smrg            {
770c82dfdfbSmrg                snprintf(new, len, "%s%s", leftRtrn.str, rightRtrn.str);
77134345a63Smrg                val_rtrn->str = new;
77234345a63Smrg                return True;
77334345a63Smrg            }
77434345a63Smrg        }
77534345a63Smrg        return False;
77634345a63Smrg    case OpSubtract:
77734345a63Smrg        if (bogus == NULL)
77834345a63Smrg            bogus = "Subtraction";
77934345a63Smrg    case OpMultiply:
78034345a63Smrg        if (bogus == NULL)
78134345a63Smrg            bogus = "Multiplication";
78234345a63Smrg    case OpDivide:
78334345a63Smrg        if (bogus == NULL)
78434345a63Smrg            bogus = "Division";
78534345a63Smrg    case OpAssign:
78634345a63Smrg        if (bogus == NULL)
78734345a63Smrg            bogus = "Assignment";
78834345a63Smrg    case OpNegate:
78934345a63Smrg        if (bogus == NULL)
79034345a63Smrg            bogus = "Negation";
79134345a63Smrg    case OpInvert:
79234345a63Smrg        if (bogus == NULL)
79334345a63Smrg            bogus = "Bitwise complement";
79434345a63Smrg        ERROR1("%s of string values not permitted\n", bogus);
79534345a63Smrg        return False;
79634345a63Smrg    case OpNot:
79734345a63Smrg        left = expr->value.child;
79834345a63Smrg        if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
79934345a63Smrg        {
80034345a63Smrg            ERROR("The ! operator cannot be applied to a string\n");
80134345a63Smrg        }
80234345a63Smrg        return False;
80334345a63Smrg    case OpUnaryPlus:
80434345a63Smrg        left = expr->value.child;
80534345a63Smrg        if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
80634345a63Smrg        {
80734345a63Smrg            ERROR("The + operator cannot be applied to a string\n");
80834345a63Smrg        }
80934345a63Smrg        return False;
81034345a63Smrg    default:
81134345a63Smrg        WSGO1("Unknown operator %d in ResolveString\n", expr->op);
81234345a63Smrg        break;
813f46a6179Smrg    }
814f46a6179Smrg    return False;
815f46a6179Smrg}
816f46a6179Smrg
817f46a6179Smrgint
81834345a63SmrgExprResolveKeyName(ExprDef * expr,
81934345a63Smrg                   ExprResult * val_rtrn,
82034345a63Smrg                   IdentLookupFunc lookup, XPointer lookupPriv)
821f46a6179Smrg{
82234345a63Smrg    int ok = 0;
82334345a63Smrg    ExprDef *left;
82434345a63Smrg    ExprResult leftRtrn;
825c82dfdfbSmrg    const char *bogus = NULL;
82634345a63Smrg
82734345a63Smrg    switch (expr->op)
82834345a63Smrg    {
82934345a63Smrg    case ExprValue:
83034345a63Smrg        if (expr->type != TypeKeyName)
83134345a63Smrg        {
83234345a63Smrg            ERROR1("Found constant of type %s, expected a key name\n",
83334345a63Smrg                   exprTypeText(expr->type));
83434345a63Smrg            return False;
83534345a63Smrg        }
83634345a63Smrg        memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
83734345a63Smrg        return True;
83834345a63Smrg    case ExprIdent:
83934345a63Smrg        if (lookup)
84034345a63Smrg        {
84134345a63Smrg            ok = (*lookup) (lookupPriv,
84234345a63Smrg                            None, expr->value.str, TypeString, val_rtrn);
84334345a63Smrg        }
84434345a63Smrg        if (!ok)
84534345a63Smrg            ERROR1("Identifier \"%s\" of type string not found\n",
84634345a63Smrg                   XkbAtomText(NULL, expr->value.str, XkbMessage));
84734345a63Smrg        return ok;
84834345a63Smrg    case ExprFieldRef:
84934345a63Smrg        if (lookup)
85034345a63Smrg        {
85134345a63Smrg            ok = (*lookup) (lookupPriv,
85234345a63Smrg                            expr->value.field.element,
85334345a63Smrg                            expr->value.field.field, TypeString, val_rtrn);
85434345a63Smrg        }
85534345a63Smrg        if (!ok)
85634345a63Smrg            ERROR2("Default \"%s.%s\" of type key name not found\n",
85734345a63Smrg                   XkbAtomText(NULL, expr->value.field.element, XkbMessage),
85834345a63Smrg                   XkbAtomText(NULL, expr->value.field.field, XkbMessage));
85934345a63Smrg        return ok;
86034345a63Smrg    case OpAdd:
86134345a63Smrg        if (bogus == NULL)
86234345a63Smrg            bogus = "Addition";
86334345a63Smrg    case OpSubtract:
86434345a63Smrg        if (bogus == NULL)
86534345a63Smrg            bogus = "Subtraction";
86634345a63Smrg    case OpMultiply:
86734345a63Smrg        if (bogus == NULL)
86834345a63Smrg            bogus = "Multiplication";
86934345a63Smrg    case OpDivide:
87034345a63Smrg        if (bogus == NULL)
87134345a63Smrg            bogus = "Division";
87234345a63Smrg    case OpAssign:
87334345a63Smrg        if (bogus == NULL)
87434345a63Smrg            bogus = "Assignment";
87534345a63Smrg    case OpNegate:
87634345a63Smrg        if (bogus == NULL)
87734345a63Smrg            bogus = "Negation";
87834345a63Smrg    case OpInvert:
87934345a63Smrg        if (bogus == NULL)
88034345a63Smrg            bogus = "Bitwise complement";
88134345a63Smrg        ERROR1("%s of key name values not permitted\n", bogus);
88234345a63Smrg        return False;
88334345a63Smrg    case OpNot:
88434345a63Smrg        left = expr->value.binary.left;
88534345a63Smrg        if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
88634345a63Smrg        {
88734345a63Smrg            ERROR("The ! operator cannot be applied to a key name\n");
88834345a63Smrg        }
88934345a63Smrg        return False;
89034345a63Smrg    case OpUnaryPlus:
89134345a63Smrg        left = expr->value.binary.left;
89234345a63Smrg        if (ExprResolveString(left, &leftRtrn, lookup, lookupPriv))
89334345a63Smrg        {
89434345a63Smrg            ERROR("The + operator cannot be applied to a key name\n");
89534345a63Smrg        }
89634345a63Smrg        return False;
89734345a63Smrg    default:
89834345a63Smrg        WSGO1("Unknown operator %d in ResolveKeyName\n", expr->op);
89934345a63Smrg        break;
900f46a6179Smrg    }
901f46a6179Smrg    return False;
902f46a6179Smrg}
903f46a6179Smrg
904f46a6179Smrg/***====================================================================***/
905f46a6179Smrg
906f46a6179Smrgint
90734345a63SmrgExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, LookupEntry * values)
908f46a6179Smrg{
90934345a63Smrg    if (expr->op != ExprIdent)
91034345a63Smrg    {
91134345a63Smrg        ERROR1("Found a %s where an enumerated value was expected\n",
91234345a63Smrg               exprOpText(expr->op));
91334345a63Smrg        return False;
914f46a6179Smrg    }
91534345a63Smrg    if (!SimpleLookup((XPointer) values, (Atom) None, expr->value.str,
91634345a63Smrg                      (unsigned) TypeInt, val_rtrn))
91734345a63Smrg    {
91834345a63Smrg        int nOut = 0;
91934345a63Smrg        ERROR1("Illegal identifier %s (expected one of: ",
92034345a63Smrg               XkbAtomText(NULL, expr->value.str, XkbMessage));
92134345a63Smrg        while (values && values->name)
92234345a63Smrg        {
92334345a63Smrg            if (nOut != 0)
92434345a63Smrg                INFO1(", %s", values->name);
92534345a63Smrg            else
92634345a63Smrg                INFO1("%s", values->name);
92734345a63Smrg            values++;
92834345a63Smrg            nOut++;
92934345a63Smrg        }
93034345a63Smrg        INFO(")\n");
93134345a63Smrg        return False;
932f46a6179Smrg    }
933f46a6179Smrg    return True;
934f46a6179Smrg}
935f46a6179Smrg
936f46a6179Smrgint
93734345a63SmrgExprResolveMask(ExprDef * expr,
93834345a63Smrg                ExprResult * val_rtrn,
93934345a63Smrg                IdentLookupFunc lookup, XPointer lookupPriv)
940f46a6179Smrg{
94134345a63Smrg    int ok = 0;
94234345a63Smrg    ExprResult leftRtrn, rightRtrn;
94334345a63Smrg    ExprDef *left, *right;
944c82dfdfbSmrg    const char *bogus = NULL;
94534345a63Smrg
94634345a63Smrg    switch (expr->op)
94734345a63Smrg    {
94834345a63Smrg    case ExprValue:
94934345a63Smrg        if (expr->type != TypeInt)
95034345a63Smrg        {
95134345a63Smrg            ERROR1
95234345a63Smrg                ("Found constant of type %s where a mask was expected\n",
95334345a63Smrg                 exprTypeText(expr->type));
95434345a63Smrg            return False;
95534345a63Smrg        }
95634345a63Smrg        val_rtrn->ival = expr->value.ival;
95734345a63Smrg        return True;
95834345a63Smrg    case ExprIdent:
95934345a63Smrg        if (lookup)
96034345a63Smrg        {
96134345a63Smrg            ok = (*lookup) (lookupPriv,
96234345a63Smrg                            None, expr->value.str, TypeInt, val_rtrn);
96334345a63Smrg        }
96434345a63Smrg        if (!ok)
96534345a63Smrg            ERROR1("Identifier \"%s\" of type int is unknown\n",
96634345a63Smrg                   XkbAtomText(NULL, expr->value.str, XkbMessage));
96734345a63Smrg        return ok;
96834345a63Smrg    case ExprFieldRef:
96934345a63Smrg        if (lookup)
97034345a63Smrg        {
97134345a63Smrg            ok = (*lookup) (lookupPriv,
97234345a63Smrg                            expr->value.field.element,
97334345a63Smrg                            expr->value.field.field, TypeInt, val_rtrn);
97434345a63Smrg        }
97534345a63Smrg        if (!ok)
97634345a63Smrg            ERROR2("Default \"%s.%s\" of type int is unknown\n",
97734345a63Smrg                   XkbAtomText(NULL, expr->value.field.element, XkbMessage),
97834345a63Smrg                   XkbAtomText(NULL, expr->value.field.field, XkbMessage));
97934345a63Smrg        return ok;
98034345a63Smrg    case ExprArrayRef:
98134345a63Smrg        bogus = "array reference";
98234345a63Smrg    case ExprActionDecl:
98334345a63Smrg        if (bogus == NULL)
98434345a63Smrg            bogus = "function use";
98534345a63Smrg        ERROR1("Unexpected %s in mask expression\n", bogus);
98634345a63Smrg        ACTION("Expression ignored\n");
98734345a63Smrg        return False;
98834345a63Smrg    case OpAdd:
98934345a63Smrg    case OpSubtract:
99034345a63Smrg    case OpMultiply:
99134345a63Smrg    case OpDivide:
99234345a63Smrg        left = expr->value.binary.left;
99334345a63Smrg        right = expr->value.binary.right;
99434345a63Smrg        if (ExprResolveMask(left, &leftRtrn, lookup, lookupPriv) &&
99534345a63Smrg            ExprResolveMask(right, &rightRtrn, lookup, lookupPriv))
99634345a63Smrg        {
99734345a63Smrg            switch (expr->op)
99834345a63Smrg            {
99934345a63Smrg            case OpAdd:
100034345a63Smrg                val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
100134345a63Smrg                break;
100234345a63Smrg            case OpSubtract:
100334345a63Smrg                val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
100434345a63Smrg                break;
100534345a63Smrg            case OpMultiply:
100634345a63Smrg            case OpDivide:
100734345a63Smrg                ERROR1("Cannot %s masks\n",
100834345a63Smrg                       expr->op == OpDivide ? "divide" : "multiply");
100934345a63Smrg                ACTION("Illegal operation ignored\n");
101034345a63Smrg                return False;
101134345a63Smrg            }
101234345a63Smrg            return True;
101334345a63Smrg        }
101434345a63Smrg        return False;
101534345a63Smrg    case OpAssign:
101634345a63Smrg        WSGO("Assignment operator not implemented yet\n");
101734345a63Smrg        break;
101834345a63Smrg    case OpInvert:
101934345a63Smrg        left = expr->value.child;
102034345a63Smrg        if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
102134345a63Smrg        {
102234345a63Smrg            val_rtrn->ival = ~leftRtrn.ival;
102334345a63Smrg            return True;
102434345a63Smrg        }
102534345a63Smrg        return False;
102634345a63Smrg    case OpUnaryPlus:
102734345a63Smrg    case OpNegate:
102834345a63Smrg    case OpNot:
102934345a63Smrg        left = expr->value.child;
103034345a63Smrg        if (ExprResolveInteger(left, &leftRtrn, lookup, lookupPriv))
103134345a63Smrg        {
103234345a63Smrg            ERROR1("The %s operator cannot be used with a mask\n",
103334345a63Smrg                   (expr->op == OpNegate ? "-" : "!"));
103434345a63Smrg        }
103534345a63Smrg        return False;
103634345a63Smrg    default:
103734345a63Smrg        WSGO1("Unknown operator %d in ResolveMask\n", expr->op);
103834345a63Smrg        break;
1039f46a6179Smrg    }
1040f46a6179Smrg    return False;
1041f46a6179Smrg}
1042f46a6179Smrg
1043f46a6179Smrgint
104434345a63SmrgExprResolveKeySym(ExprDef * expr,
104534345a63Smrg                  ExprResult * val_rtrn,
104634345a63Smrg                  IdentLookupFunc lookup, XPointer lookupPriv)
1047f46a6179Smrg{
104834345a63Smrg    int ok = 0;
104934345a63Smrg    KeySym sym;
105034345a63Smrg
105134345a63Smrg    if (expr->op == ExprIdent)
105234345a63Smrg    {
105334345a63Smrg        char *str;
105434345a63Smrg        str = XkbAtomGetString(NULL, expr->value.str);
105534345a63Smrg        if ((str != NULL) && ((sym = XStringToKeysym(str)) != NoSymbol))
105634345a63Smrg        {
105734345a63Smrg            val_rtrn->uval = sym;
105834345a63Smrg            return True;
105934345a63Smrg        }
1060f46a6179Smrg    }
106134345a63Smrg    ok = ExprResolveInteger(expr, val_rtrn, lookup, lookupPriv);
106234345a63Smrg    if ((ok) && (val_rtrn->uval < 10))
106334345a63Smrg        val_rtrn->uval += '0';
1064f46a6179Smrg    return ok;
1065f46a6179Smrg}
1066