2009-03-27 07:55:32 -06:00
|
|
|
/************************************************************
|
|
|
|
Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and distribute this
|
|
|
|
software and its documentation for any purpose and without
|
|
|
|
fee is hereby granted, provided that the above copyright
|
|
|
|
notice appear in all copies and that both that copyright
|
|
|
|
notice and this permission notice appear in supporting
|
2009-04-04 10:19:51 -06:00
|
|
|
documentation, and that the name of Silicon Graphics not be
|
|
|
|
used in advertising or publicity pertaining to distribution
|
2009-03-27 07:55:32 -06:00
|
|
|
of the software without specific prior written permission.
|
2009-04-04 10:19:51 -06:00
|
|
|
Silicon Graphics makes no representation about the suitability
|
2009-03-27 07:55:32 -06:00
|
|
|
of this software for any purpose. It is provided "as is"
|
|
|
|
without any express or implied warranty.
|
2009-04-04 10:19:51 -06:00
|
|
|
|
|
|
|
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
|
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
2009-03-27 07:55:32 -06:00
|
|
|
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
2009-04-04 10:19:51 -06:00
|
|
|
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
|
|
|
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
|
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
2009-03-27 07:55:32 -06:00
|
|
|
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
|
|
|
|
THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
|
|
********************************************************/
|
|
|
|
|
|
|
|
#include "xkbcomp.h"
|
2009-04-08 08:46:25 -06:00
|
|
|
#include "xkbmisc.h"
|
2009-03-27 07:55:32 -06:00
|
|
|
#include "expr.h"
|
2012-02-20 06:32:09 -07:00
|
|
|
#include "vmod.h"
|
2009-03-27 07:55:32 -06:00
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
2012-03-02 08:40:19 -07:00
|
|
|
typedef Bool(*IdentLookupFunc) (const void * /* priv */ ,
|
2012-03-09 12:09:25 -07:00
|
|
|
xkb_atom_t /* field */ ,
|
2012-02-20 09:59:51 -07:00
|
|
|
unsigned /* type */ ,
|
|
|
|
ExprResult * /* val_rtrn */
|
|
|
|
);
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
2012-03-02 13:31:29 -07:00
|
|
|
const char *
|
2009-03-27 07:55:32 -06:00
|
|
|
exprOpText(unsigned type)
|
|
|
|
{
|
|
|
|
static char buf[32];
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case ExprValue:
|
|
|
|
strcpy(buf, "literal");
|
|
|
|
break;
|
|
|
|
case ExprIdent:
|
|
|
|
strcpy(buf, "identifier");
|
|
|
|
break;
|
|
|
|
case ExprActionDecl:
|
|
|
|
strcpy(buf, "action declaration");
|
|
|
|
break;
|
|
|
|
case ExprFieldRef:
|
|
|
|
strcpy(buf, "field reference");
|
|
|
|
break;
|
|
|
|
case ExprArrayRef:
|
|
|
|
strcpy(buf, "array reference");
|
|
|
|
break;
|
|
|
|
case ExprKeysymList:
|
|
|
|
strcpy(buf, "list of keysyms");
|
|
|
|
break;
|
|
|
|
case ExprActionList:
|
|
|
|
strcpy(buf, "list of actions");
|
|
|
|
break;
|
|
|
|
case OpAdd:
|
|
|
|
strcpy(buf, "addition");
|
|
|
|
break;
|
|
|
|
case OpSubtract:
|
|
|
|
strcpy(buf, "subtraction");
|
|
|
|
break;
|
|
|
|
case OpMultiply:
|
|
|
|
strcpy(buf, "multiplication");
|
|
|
|
break;
|
|
|
|
case OpDivide:
|
|
|
|
strcpy(buf, "division");
|
|
|
|
break;
|
|
|
|
case OpAssign:
|
|
|
|
strcpy(buf, "assignment");
|
|
|
|
break;
|
|
|
|
case OpNot:
|
|
|
|
strcpy(buf, "logical not");
|
|
|
|
break;
|
|
|
|
case OpNegate:
|
|
|
|
strcpy(buf, "arithmetic negation");
|
|
|
|
break;
|
|
|
|
case OpInvert:
|
|
|
|
strcpy(buf, "bitwise inversion");
|
|
|
|
break;
|
|
|
|
case OpUnaryPlus:
|
|
|
|
strcpy(buf, "plus sign");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
snprintf(buf, sizeof(buf), "illegal(%d)", type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2012-03-02 13:31:29 -07:00
|
|
|
static const char *
|
2009-03-27 07:55:32 -06:00
|
|
|
exprTypeText(unsigned type)
|
|
|
|
{
|
|
|
|
static char buf[20];
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case TypeUnknown:
|
|
|
|
strcpy(buf, "unknown");
|
|
|
|
break;
|
|
|
|
case TypeBoolean:
|
|
|
|
strcpy(buf, "boolean");
|
|
|
|
break;
|
|
|
|
case TypeInt:
|
|
|
|
strcpy(buf, "int");
|
|
|
|
break;
|
|
|
|
case TypeString:
|
|
|
|
strcpy(buf, "string");
|
|
|
|
break;
|
|
|
|
case TypeAction:
|
|
|
|
strcpy(buf, "action");
|
|
|
|
break;
|
|
|
|
case TypeKeyName:
|
|
|
|
strcpy(buf, "keyname");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
snprintf(buf, sizeof(buf), "illegal(%d)", type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ExprResolveLhs(ExprDef * expr,
|
|
|
|
ExprResult * elem_rtrn,
|
|
|
|
ExprResult * field_rtrn, ExprDef ** index_rtrn)
|
|
|
|
{
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case ExprIdent:
|
|
|
|
elem_rtrn->str = NULL;
|
2009-03-28 07:56:26 -06:00
|
|
|
field_rtrn->str = XkbcAtomGetString(expr->value.str);
|
2009-03-27 07:55:32 -06:00
|
|
|
*index_rtrn = NULL;
|
|
|
|
return True;
|
|
|
|
case ExprFieldRef:
|
2009-03-28 07:56:26 -06:00
|
|
|
elem_rtrn->str = XkbcAtomGetString(expr->value.field.element);
|
|
|
|
field_rtrn->str = XkbcAtomGetString(expr->value.field.field);
|
2009-03-27 07:55:32 -06:00
|
|
|
*index_rtrn = NULL;
|
|
|
|
return True;
|
|
|
|
case ExprArrayRef:
|
2009-03-28 07:56:26 -06:00
|
|
|
elem_rtrn->str = XkbcAtomGetString(expr->value.array.element);
|
|
|
|
field_rtrn->str = XkbcAtomGetString(expr->value.array.field);
|
2009-03-27 07:55:32 -06:00
|
|
|
*index_rtrn = expr->value.array.entry;
|
|
|
|
return True;
|
|
|
|
}
|
2009-03-31 08:21:20 -06:00
|
|
|
WSGO("Unexpected operator %d in ResolveLhs\n", expr->op);
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
2012-02-20 09:59:51 -07:00
|
|
|
static Bool
|
2012-03-09 12:09:25 -07:00
|
|
|
SimpleLookup(const void * priv, xkb_atom_t field, unsigned type,
|
2012-02-20 09:54:54 -07:00
|
|
|
ExprResult * val_rtrn)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
2012-03-02 08:40:19 -07:00
|
|
|
const LookupEntry *entry;
|
2010-06-30 15:20:56 -06:00
|
|
|
const char *str;
|
2009-03-27 07:55:32 -06:00
|
|
|
|
2012-03-15 03:33:56 -06:00
|
|
|
if ((priv == NULL) || (field == None) || (type != TypeInt))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
return False;
|
|
|
|
}
|
2010-06-15 08:22:05 -06:00
|
|
|
str = XkbcAtomText(field);
|
2012-02-20 10:14:04 -07:00
|
|
|
for (entry = priv; (entry != NULL) && (entry->name != NULL); entry++)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
if (uStrCaseCmp(str, entry->name) == 0)
|
|
|
|
{
|
|
|
|
val_rtrn->uval = entry->result;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
2012-03-02 08:40:19 -07:00
|
|
|
static const LookupEntry modIndexNames[] = {
|
2012-03-13 06:46:37 -06:00
|
|
|
{"shift", ShiftMapIndex},
|
|
|
|
{"control", ControlMapIndex},
|
|
|
|
{"lock", LockMapIndex},
|
|
|
|
{"mod1", Mod1MapIndex},
|
|
|
|
{"mod2", Mod2MapIndex},
|
|
|
|
{"mod3", Mod3MapIndex},
|
|
|
|
{"mod4", Mod4MapIndex},
|
|
|
|
{"mod5", Mod5MapIndex},
|
|
|
|
{"none", XkbNoModifier},
|
2009-03-27 07:55:32 -06:00
|
|
|
{NULL, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
int
|
2012-03-09 12:09:25 -07:00
|
|
|
LookupModIndex(const void * priv, xkb_atom_t field, unsigned type,
|
2012-02-20 09:54:54 -07:00
|
|
|
ExprResult * val_rtrn)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
2012-02-20 10:14:04 -07:00
|
|
|
return SimpleLookup(modIndexNames, field, type, val_rtrn);
|
2009-03-27 07:55:32 -06:00
|
|
|
}
|
|
|
|
|
2012-02-20 10:07:48 -07:00
|
|
|
int
|
2012-03-09 12:09:25 -07:00
|
|
|
LookupModMask(const void * priv, xkb_atom_t field, unsigned type,
|
2012-02-20 09:54:54 -07:00
|
|
|
ExprResult * val_rtrn)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
char *str;
|
2010-06-15 08:22:05 -06:00
|
|
|
Bool ret = True;
|
2009-03-27 07:55:32 -06:00
|
|
|
|
2012-02-20 09:54:54 -07:00
|
|
|
if (type != TypeInt)
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
2009-03-28 07:56:26 -06:00
|
|
|
str = XkbcAtomGetString(field);
|
2009-03-27 07:55:32 -06:00
|
|
|
if (str == NULL)
|
|
|
|
return False;
|
|
|
|
if (uStrCaseCmp(str, "all") == 0)
|
|
|
|
val_rtrn->uval = 0xff;
|
|
|
|
else if (uStrCaseCmp(str, "none") == 0)
|
|
|
|
val_rtrn->uval = 0;
|
2012-02-20 09:54:54 -07:00
|
|
|
else if (LookupModIndex(priv, field, type, val_rtrn))
|
2009-03-27 07:55:32 -06:00
|
|
|
val_rtrn->uval = (1 << val_rtrn->uval);
|
|
|
|
else
|
2010-06-15 08:22:05 -06:00
|
|
|
ret = False;
|
|
|
|
free(str);
|
|
|
|
return ret;
|
2009-03-27 07:55:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ExprResolveBoolean(ExprDef * expr,
|
2012-02-20 06:44:27 -07:00
|
|
|
ExprResult * val_rtrn)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
int ok = 0;
|
2010-06-30 15:20:56 -06:00
|
|
|
const char *bogus = NULL;
|
2009-03-27 07:55:32 -06:00
|
|
|
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case ExprValue:
|
|
|
|
if (expr->type != TypeBoolean)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR
|
2009-03-27 07:55:32 -06:00
|
|
|
("Found constant of type %s where boolean was expected\n",
|
|
|
|
exprTypeText(expr->type));
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
val_rtrn->ival = expr->value.ival;
|
|
|
|
return True;
|
|
|
|
case ExprIdent:
|
2010-06-15 08:22:05 -06:00
|
|
|
bogus = XkbcAtomText(expr->value.str);
|
2009-03-27 07:55:32 -06:00
|
|
|
if (bogus)
|
|
|
|
{
|
|
|
|
if ((uStrCaseCmp(bogus, "true") == 0) ||
|
|
|
|
(uStrCaseCmp(bogus, "yes") == 0) ||
|
|
|
|
(uStrCaseCmp(bogus, "on") == 0))
|
|
|
|
{
|
|
|
|
val_rtrn->uval = 1;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
else if ((uStrCaseCmp(bogus, "false") == 0) ||
|
|
|
|
(uStrCaseCmp(bogus, "no") == 0) ||
|
|
|
|
(uStrCaseCmp(bogus, "off") == 0))
|
|
|
|
{
|
|
|
|
val_rtrn->uval = 0;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
}
|
2012-02-20 06:44:27 -07:00
|
|
|
ERROR("Identifier \"%s\" of type int is unknown\n",
|
|
|
|
XkbcAtomText(expr->value.str));
|
|
|
|
return False;
|
2009-03-27 07:55:32 -06:00
|
|
|
case ExprFieldRef:
|
2012-02-20 06:44:27 -07:00
|
|
|
ERROR("Default \"%s.%s\" of type boolean is unknown\n",
|
|
|
|
XkbcAtomText(expr->value.field.element),
|
|
|
|
XkbcAtomText(expr->value.field.field));
|
|
|
|
return False;
|
2009-03-27 07:55:32 -06:00
|
|
|
case OpInvert:
|
|
|
|
case OpNot:
|
2012-02-20 06:44:27 -07:00
|
|
|
ok = ExprResolveBoolean(expr, val_rtrn);
|
2009-03-27 07:55:32 -06:00
|
|
|
if (ok)
|
|
|
|
val_rtrn->uval = !val_rtrn->uval;
|
|
|
|
return ok;
|
|
|
|
case OpAdd:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Addition";
|
|
|
|
case OpSubtract:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Subtraction";
|
|
|
|
case OpMultiply:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Multiplication";
|
|
|
|
case OpDivide:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Division";
|
|
|
|
case OpAssign:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Assignment";
|
|
|
|
case OpNegate:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Negation";
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("%s of boolean values not permitted\n", bogus);
|
2009-03-27 07:55:32 -06:00
|
|
|
break;
|
|
|
|
case OpUnaryPlus:
|
|
|
|
ERROR("Unary \"+\" operator not permitted for boolean values\n");
|
|
|
|
break;
|
|
|
|
default:
|
2009-03-31 08:21:20 -06:00
|
|
|
WSGO("Unknown operator %d in ResolveBoolean\n", expr->op);
|
2009-03-27 07:55:32 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ExprResolveFloat(ExprDef * expr,
|
2012-02-20 06:40:34 -07:00
|
|
|
ExprResult * val_rtrn)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
int ok = 0;
|
|
|
|
ExprResult leftRtrn, rightRtrn;
|
|
|
|
ExprDef *left, *right;
|
|
|
|
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case ExprValue:
|
|
|
|
if (expr->type == TypeString)
|
|
|
|
{
|
2010-06-30 15:20:56 -06:00
|
|
|
const char *str;
|
2010-06-15 08:22:05 -06:00
|
|
|
str = XkbcAtomText(expr->value.str);
|
2009-03-27 07:55:32 -06:00
|
|
|
if ((str != NULL) && (strlen(str) == 1))
|
|
|
|
{
|
|
|
|
val_rtrn->uval = str[0] * XkbGeomPtsPerMM;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
}
|
2012-03-15 03:33:56 -06:00
|
|
|
if (expr->type != TypeInt)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Found constant of type %s, expected a number\n",
|
2009-03-27 07:55:32 -06:00
|
|
|
exprTypeText(expr->type));
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
val_rtrn->ival = expr->value.ival;
|
|
|
|
if (expr->type == TypeInt)
|
|
|
|
val_rtrn->ival *= XkbGeomPtsPerMM;
|
|
|
|
return True;
|
|
|
|
case ExprIdent:
|
2012-02-20 06:40:34 -07:00
|
|
|
ERROR("Numeric identifier \"%s\" unknown\n",
|
|
|
|
XkbcAtomText(expr->value.str));
|
2009-03-27 07:55:32 -06:00
|
|
|
return ok;
|
|
|
|
case ExprFieldRef:
|
2012-02-20 06:40:34 -07:00
|
|
|
ERROR("Numeric default \"%s.%s\" unknown\n",
|
|
|
|
XkbcAtomText(expr->value.field.element),
|
|
|
|
XkbcAtomText(expr->value.field.field));
|
2012-02-20 09:54:54 -07:00
|
|
|
return False;
|
2009-03-27 07:55:32 -06:00
|
|
|
case OpAdd:
|
|
|
|
case OpSubtract:
|
|
|
|
case OpMultiply:
|
|
|
|
case OpDivide:
|
|
|
|
left = expr->value.binary.left;
|
|
|
|
right = expr->value.binary.right;
|
2012-02-20 06:40:34 -07:00
|
|
|
if (ExprResolveFloat(left, &leftRtrn) &&
|
|
|
|
ExprResolveFloat(right, &rightRtrn))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case OpAdd:
|
|
|
|
val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
|
|
|
|
break;
|
|
|
|
case OpSubtract:
|
|
|
|
val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
|
|
|
|
break;
|
|
|
|
case OpMultiply:
|
|
|
|
val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
|
|
|
|
break;
|
|
|
|
case OpDivide:
|
|
|
|
val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
case OpAssign:
|
|
|
|
WSGO("Assignment operator not implemented yet\n");
|
|
|
|
break;
|
|
|
|
case OpNot:
|
2012-02-20 06:40:34 -07:00
|
|
|
ERROR("The ! operator cannot be applied to a number\n");
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
case OpInvert:
|
|
|
|
case OpNegate:
|
|
|
|
left = expr->value.child;
|
2012-02-20 06:40:34 -07:00
|
|
|
if (ExprResolveFloat(left, &leftRtrn))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
if (expr->op == OpNegate)
|
|
|
|
val_rtrn->ival = -leftRtrn.ival;
|
|
|
|
else
|
|
|
|
val_rtrn->ival = ~leftRtrn.ival;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
case OpUnaryPlus:
|
|
|
|
left = expr->value.child;
|
2012-02-20 06:40:34 -07:00
|
|
|
return ExprResolveFloat(left, val_rtrn);
|
2009-03-27 07:55:32 -06:00
|
|
|
default:
|
2009-03-31 08:21:20 -06:00
|
|
|
WSGO("Unknown operator %d in ResolveFloat\n", expr->op);
|
2009-03-27 07:55:32 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
2012-02-15 07:34:08 -07:00
|
|
|
int
|
|
|
|
ExprResolveKeyCode(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn)
|
|
|
|
{
|
|
|
|
ExprResult leftRtrn, rightRtrn;
|
|
|
|
ExprDef *left, *right;
|
|
|
|
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case ExprValue:
|
|
|
|
if (expr->type != TypeInt)
|
|
|
|
{
|
|
|
|
ERROR
|
|
|
|
("Found constant of type %s where an int was expected\n",
|
|
|
|
exprTypeText(expr->type));
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
val_rtrn->uval = expr->value.uval;
|
|
|
|
return True;
|
|
|
|
case OpAdd:
|
|
|
|
case OpSubtract:
|
|
|
|
case OpMultiply:
|
|
|
|
case OpDivide:
|
|
|
|
left = expr->value.binary.left;
|
|
|
|
right = expr->value.binary.right;
|
|
|
|
if (ExprResolveKeyCode(left, &leftRtrn) &&
|
|
|
|
ExprResolveKeyCode(right, &rightRtrn))
|
|
|
|
{
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case OpAdd:
|
|
|
|
val_rtrn->uval = leftRtrn.uval + rightRtrn.uval;
|
|
|
|
break;
|
|
|
|
case OpSubtract:
|
|
|
|
val_rtrn->uval = leftRtrn.uval - rightRtrn.uval;
|
|
|
|
break;
|
|
|
|
case OpMultiply:
|
|
|
|
val_rtrn->uval = leftRtrn.uval * rightRtrn.uval;
|
|
|
|
break;
|
|
|
|
case OpDivide:
|
|
|
|
val_rtrn->uval = leftRtrn.uval / rightRtrn.uval;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
case OpNegate:
|
|
|
|
left = expr->value.child;
|
|
|
|
if (ExprResolveKeyCode(left, &leftRtrn))
|
|
|
|
{
|
|
|
|
val_rtrn->uval = ~leftRtrn.uval;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
case OpUnaryPlus:
|
|
|
|
left = expr->value.child;
|
|
|
|
return ExprResolveKeyCode(left, val_rtrn);
|
|
|
|
default:
|
2012-02-20 10:47:46 -07:00
|
|
|
WSGO("Unknown operator %d in ResolveKeyCode\n", expr->op);
|
2012-02-15 07:34:08 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
2012-02-20 09:24:02 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This function returns ... something. It's a bit of a guess, really.
|
|
|
|
*
|
|
|
|
* If a string is given in value context, its first character will be
|
|
|
|
* returned in uval. If an integer is given in value context, it will be
|
|
|
|
* returned in ival. If a float is given in value context, it will be
|
|
|
|
* returned as millimetres (rather than points) in ival.
|
|
|
|
*
|
|
|
|
* If an ident or field reference is given, the lookup function (if given)
|
2012-03-10 07:27:06 -07:00
|
|
|
* will be called. At the moment, only SimpleLookup use this, and they both
|
|
|
|
* return the results in uval. And don't support field references.
|
2012-02-20 09:24:02 -07:00
|
|
|
*
|
|
|
|
* Cool.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ExprResolveIntegerLookup(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn,
|
2012-03-02 08:40:19 -07:00
|
|
|
IdentLookupFunc lookup, const void * lookupPriv)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
int ok = 0;
|
|
|
|
ExprResult leftRtrn, rightRtrn;
|
|
|
|
ExprDef *left, *right;
|
|
|
|
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case ExprValue:
|
|
|
|
if (expr->type == TypeString)
|
|
|
|
{
|
2010-06-30 15:20:56 -06:00
|
|
|
const char *str;
|
2010-06-15 08:22:05 -06:00
|
|
|
str = XkbcAtomText(expr->value.str);
|
2009-03-27 07:55:32 -06:00
|
|
|
if (str != NULL)
|
|
|
|
switch (strlen(str))
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
val_rtrn->uval = 0;
|
|
|
|
return True;
|
|
|
|
case 1:
|
|
|
|
val_rtrn->uval = str[0];
|
|
|
|
return True;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-03-15 03:33:56 -06:00
|
|
|
if (expr->type != TypeInt)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR
|
2009-03-27 07:55:32 -06:00
|
|
|
("Found constant of type %s where an int was expected\n",
|
|
|
|
exprTypeText(expr->type));
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
val_rtrn->ival = expr->value.ival;
|
|
|
|
return True;
|
|
|
|
case ExprIdent:
|
|
|
|
if (lookup)
|
|
|
|
{
|
2012-02-20 09:54:54 -07:00
|
|
|
ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
|
2009-03-27 07:55:32 -06:00
|
|
|
}
|
|
|
|
if (!ok)
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Identifier \"%s\" of type int is unknown\n",
|
2009-03-28 15:06:26 -06:00
|
|
|
XkbcAtomText(expr->value.str));
|
2009-03-27 07:55:32 -06:00
|
|
|
return ok;
|
|
|
|
case ExprFieldRef:
|
2012-02-20 09:54:54 -07:00
|
|
|
ERROR("Default \"%s.%s\" of type int is unknown\n",
|
|
|
|
XkbcAtomText(expr->value.field.element),
|
|
|
|
XkbcAtomText(expr->value.field.field));
|
|
|
|
return False;
|
2009-03-27 07:55:32 -06:00
|
|
|
case OpAdd:
|
|
|
|
case OpSubtract:
|
|
|
|
case OpMultiply:
|
|
|
|
case OpDivide:
|
|
|
|
left = expr->value.binary.left;
|
|
|
|
right = expr->value.binary.right;
|
2012-02-20 09:24:02 -07:00
|
|
|
if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv) &&
|
|
|
|
ExprResolveIntegerLookup(right, &rightRtrn, lookup, lookupPriv))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case OpAdd:
|
|
|
|
val_rtrn->ival = leftRtrn.ival + rightRtrn.ival;
|
|
|
|
break;
|
|
|
|
case OpSubtract:
|
|
|
|
val_rtrn->ival = leftRtrn.ival - rightRtrn.ival;
|
|
|
|
break;
|
|
|
|
case OpMultiply:
|
|
|
|
val_rtrn->ival = leftRtrn.ival * rightRtrn.ival;
|
|
|
|
break;
|
|
|
|
case OpDivide:
|
|
|
|
val_rtrn->ival = leftRtrn.ival / rightRtrn.ival;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
case OpAssign:
|
|
|
|
WSGO("Assignment operator not implemented yet\n");
|
|
|
|
break;
|
|
|
|
case OpNot:
|
2012-02-20 09:24:02 -07:00
|
|
|
ERROR("The ! operator cannot be applied to an integer\n");
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
case OpInvert:
|
|
|
|
case OpNegate:
|
|
|
|
left = expr->value.child;
|
2012-02-20 09:24:02 -07:00
|
|
|
if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
if (expr->op == OpNegate)
|
|
|
|
val_rtrn->ival = -leftRtrn.ival;
|
|
|
|
else
|
|
|
|
val_rtrn->ival = ~leftRtrn.ival;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
case OpUnaryPlus:
|
|
|
|
left = expr->value.child;
|
2012-02-20 09:24:02 -07:00
|
|
|
return ExprResolveIntegerLookup(left, val_rtrn, lookup, lookupPriv);
|
2009-03-27 07:55:32 -06:00
|
|
|
default:
|
2009-03-31 08:21:20 -06:00
|
|
|
WSGO("Unknown operator %d in ResolveInteger\n", expr->op);
|
2009-03-27 07:55:32 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
2012-02-20 09:24:02 -07:00
|
|
|
int
|
|
|
|
ExprResolveInteger(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn)
|
|
|
|
{
|
|
|
|
return ExprResolveIntegerLookup(expr, val_rtrn, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2012-02-20 08:47:57 -07:00
|
|
|
int
|
|
|
|
ExprResolveGroup(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn)
|
|
|
|
{
|
2012-02-20 10:33:39 -07:00
|
|
|
int ret;
|
2012-03-02 08:40:19 -07:00
|
|
|
static const LookupEntry group_names[] = {
|
2012-02-20 08:47:57 -07:00
|
|
|
{ "group1", 1 },
|
|
|
|
{ "group2", 2 },
|
|
|
|
{ "group3", 3 },
|
|
|
|
{ "group4", 4 },
|
|
|
|
{ "group5", 5 },
|
|
|
|
{ "group6", 6 },
|
|
|
|
{ "group7", 7 },
|
|
|
|
{ "group8", 8 },
|
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
|
|
|
|
2012-02-20 10:33:39 -07:00
|
|
|
ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, group_names);
|
|
|
|
if (ret == False)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (val_rtrn->uval == 0 || val_rtrn->uval > XkbNumKbdGroups) {
|
|
|
|
ERROR("Group index %d is out of range (1..%d)\n",
|
|
|
|
val_rtrn->uval, XkbNumKbdGroups);
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
return True;
|
2012-02-20 08:47:57 -07:00
|
|
|
}
|
|
|
|
|
2012-02-20 08:37:53 -07:00
|
|
|
int
|
|
|
|
ExprResolveLevel(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn)
|
|
|
|
{
|
2012-02-20 11:07:29 -07:00
|
|
|
int ret;
|
2012-03-02 08:40:19 -07:00
|
|
|
static const LookupEntry level_names[] = {
|
2012-02-20 08:37:53 -07:00
|
|
|
{ "level1", 1 },
|
|
|
|
{ "level2", 2 },
|
|
|
|
{ "level3", 3 },
|
|
|
|
{ "level4", 4 },
|
|
|
|
{ "level5", 5 },
|
|
|
|
{ "level6", 6 },
|
|
|
|
{ "level7", 7 },
|
|
|
|
{ "level8", 8 },
|
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
|
|
|
|
2012-02-20 11:07:29 -07:00
|
|
|
ret = ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup, level_names);
|
|
|
|
if (ret == False)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (val_rtrn->ival < 1 || val_rtrn->ival > XkbMaxShiftLevel) {
|
|
|
|
ERROR("Shift level %d is out of range (1..%d)\n", val_rtrn->ival,
|
|
|
|
XkbMaxShiftLevel);
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
return True;
|
2012-02-20 08:37:53 -07:00
|
|
|
}
|
|
|
|
|
2012-02-20 08:47:38 -07:00
|
|
|
int
|
|
|
|
ExprResolveButton(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn)
|
|
|
|
{
|
2012-03-02 08:40:19 -07:00
|
|
|
static const LookupEntry button_names[] = {
|
2012-02-20 08:47:38 -07:00
|
|
|
{ "button1", 1 },
|
|
|
|
{ "button2", 2 },
|
|
|
|
{ "button3", 3 },
|
|
|
|
{ "button4", 4 },
|
|
|
|
{ "button5", 5 },
|
|
|
|
{ "default", 0 },
|
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
|
|
|
|
2012-02-20 09:24:02 -07:00
|
|
|
return ExprResolveIntegerLookup(expr, val_rtrn, SimpleLookup,
|
2012-02-20 10:14:04 -07:00
|
|
|
button_names);
|
2012-02-20 08:47:38 -07:00
|
|
|
}
|
|
|
|
|
2009-03-27 07:55:32 -06:00
|
|
|
int
|
|
|
|
ExprResolveString(ExprDef * expr,
|
2012-02-20 07:15:08 -07:00
|
|
|
ExprResult * val_rtrn)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
ExprResult leftRtrn, rightRtrn;
|
|
|
|
ExprDef *left;
|
|
|
|
ExprDef *right;
|
2012-02-24 07:07:17 -07:00
|
|
|
const char *bogus = NULL;
|
2009-03-27 07:55:32 -06:00
|
|
|
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case ExprValue:
|
|
|
|
if (expr->type != TypeString)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Found constant of type %s, expected a string\n",
|
2009-03-27 07:55:32 -06:00
|
|
|
exprTypeText(expr->type));
|
|
|
|
return False;
|
|
|
|
}
|
2009-03-28 07:56:26 -06:00
|
|
|
val_rtrn->str = XkbcAtomGetString(expr->value.str);
|
2009-03-27 07:55:32 -06:00
|
|
|
if (val_rtrn->str == NULL)
|
2012-02-15 17:22:11 -07:00
|
|
|
val_rtrn->str = strdup("");
|
2009-03-27 07:55:32 -06:00
|
|
|
return True;
|
|
|
|
case ExprIdent:
|
2012-02-20 07:15:08 -07:00
|
|
|
ERROR("Identifier \"%s\" of type string not found\n",
|
|
|
|
XkbcAtomText(expr->value.str));
|
|
|
|
return False;
|
2009-03-27 07:55:32 -06:00
|
|
|
case ExprFieldRef:
|
2012-02-20 07:15:08 -07:00
|
|
|
ERROR("Default \"%s.%s\" of type string not found\n",
|
|
|
|
XkbcAtomText(expr->value.field.element),
|
|
|
|
XkbcAtomText(expr->value.field.field));
|
|
|
|
return False;
|
2009-03-27 07:55:32 -06:00
|
|
|
case OpAdd:
|
|
|
|
left = expr->value.binary.left;
|
|
|
|
right = expr->value.binary.right;
|
2012-02-20 07:15:08 -07:00
|
|
|
if (ExprResolveString(left, &leftRtrn) &&
|
|
|
|
ExprResolveString(right, &rightRtrn))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char *new;
|
|
|
|
len = strlen(leftRtrn.str) + strlen(rightRtrn.str) + 1;
|
2012-02-29 12:26:28 -07:00
|
|
|
new = malloc(len);
|
2009-03-27 07:55:32 -06:00
|
|
|
if (new)
|
2012-02-20 07:15:08 -07:00
|
|
|
{ sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
|
2012-02-15 17:22:11 -07:00
|
|
|
free(leftRtrn.str);
|
|
|
|
free(rightRtrn.str);
|
2009-03-27 07:55:32 -06:00
|
|
|
val_rtrn->str = new;
|
|
|
|
return True;
|
|
|
|
}
|
2012-02-15 17:22:11 -07:00
|
|
|
free(leftRtrn.str);
|
|
|
|
free(rightRtrn.str);
|
2009-03-27 07:55:32 -06:00
|
|
|
}
|
|
|
|
return False;
|
|
|
|
case OpSubtract:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Subtraction";
|
|
|
|
case OpMultiply:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Multiplication";
|
|
|
|
case OpDivide:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Division";
|
|
|
|
case OpAssign:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Assignment";
|
|
|
|
case OpNegate:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Negation";
|
|
|
|
case OpInvert:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Bitwise complement";
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("%s of string values not permitted\n", bogus);
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
case OpNot:
|
2012-02-20 07:15:08 -07:00
|
|
|
ERROR("The ! operator cannot be applied to a string\n");
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
case OpUnaryPlus:
|
2012-02-20 07:15:08 -07:00
|
|
|
ERROR("The + operator cannot be applied to a string\n");
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
default:
|
2009-03-31 08:21:20 -06:00
|
|
|
WSGO("Unknown operator %d in ResolveString\n", expr->op);
|
2009-03-27 07:55:32 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ExprResolveKeyName(ExprDef * expr,
|
2012-02-20 07:08:55 -07:00
|
|
|
ExprResult * val_rtrn)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
2012-02-24 07:07:17 -07:00
|
|
|
const char *bogus = NULL;
|
2009-03-27 07:55:32 -06:00
|
|
|
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case ExprValue:
|
|
|
|
if (expr->type != TypeKeyName)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Found constant of type %s, expected a key name\n",
|
2009-03-27 07:55:32 -06:00
|
|
|
exprTypeText(expr->type));
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
memcpy(val_rtrn->keyName.name, expr->value.keyName, XkbKeyNameLength);
|
|
|
|
return True;
|
|
|
|
case ExprIdent:
|
2012-02-20 07:08:55 -07:00
|
|
|
ERROR("Identifier \"%s\" of type string not found\n",
|
|
|
|
XkbcAtomText(expr->value.str));
|
|
|
|
return False;
|
2009-03-27 07:55:32 -06:00
|
|
|
case ExprFieldRef:
|
2012-02-20 07:08:55 -07:00
|
|
|
ERROR("Default \"%s.%s\" of type key name not found\n",
|
|
|
|
XkbcAtomText(expr->value.field.element),
|
|
|
|
XkbcAtomText(expr->value.field.field));
|
|
|
|
return False;
|
2009-03-27 07:55:32 -06:00
|
|
|
case OpAdd:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Addition";
|
|
|
|
case OpSubtract:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Subtraction";
|
|
|
|
case OpMultiply:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Multiplication";
|
|
|
|
case OpDivide:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Division";
|
|
|
|
case OpAssign:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Assignment";
|
|
|
|
case OpNegate:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Negation";
|
|
|
|
case OpInvert:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "Bitwise complement";
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("%s of key name values not permitted\n", bogus);
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
case OpNot:
|
2012-02-20 07:08:55 -07:00
|
|
|
ERROR("The ! operator cannot be applied to a key name\n");
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
case OpUnaryPlus:
|
2012-02-20 07:08:55 -07:00
|
|
|
ERROR("The + operator cannot be applied to a key name\n");
|
2009-03-27 07:55:32 -06:00
|
|
|
return False;
|
|
|
|
default:
|
2009-03-31 08:21:20 -06:00
|
|
|
WSGO("Unknown operator %d in ResolveKeyName\n", expr->op);
|
2009-03-27 07:55:32 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***====================================================================***/
|
|
|
|
|
|
|
|
int
|
2012-03-02 08:40:19 -07:00
|
|
|
ExprResolveEnum(ExprDef * expr, ExprResult * val_rtrn, const LookupEntry * values)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
if (expr->op != ExprIdent)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Found a %s where an enumerated value was expected\n",
|
2009-03-27 07:55:32 -06:00
|
|
|
exprOpText(expr->op));
|
|
|
|
return False;
|
|
|
|
}
|
2012-02-20 10:14:04 -07:00
|
|
|
if (!SimpleLookup(values, expr->value.str, TypeInt, val_rtrn))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
int nOut = 0;
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Illegal identifier %s (expected one of: ",
|
2009-03-28 15:06:26 -06:00
|
|
|
XkbcAtomText(expr->value.str));
|
2009-03-27 07:55:32 -06:00
|
|
|
while (values && values->name)
|
|
|
|
{
|
|
|
|
if (nOut != 0)
|
2009-03-31 08:21:20 -06:00
|
|
|
INFO(", %s", values->name);
|
2009-03-27 07:55:32 -06:00
|
|
|
else
|
2009-03-31 08:21:20 -06:00
|
|
|
INFO("%s", values->name);
|
2009-03-27 07:55:32 -06:00
|
|
|
values++;
|
|
|
|
nOut++;
|
|
|
|
}
|
|
|
|
INFO(")\n");
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
|
2012-02-20 09:54:54 -07:00
|
|
|
static int
|
|
|
|
ExprResolveMaskLookup(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn,
|
|
|
|
IdentLookupFunc lookup,
|
2012-03-02 08:40:19 -07:00
|
|
|
const void * lookupPriv)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
int ok = 0;
|
|
|
|
ExprResult leftRtrn, rightRtrn;
|
|
|
|
ExprDef *left, *right;
|
2012-02-24 07:07:17 -07:00
|
|
|
const char *bogus = NULL;
|
2009-03-27 07:55:32 -06:00
|
|
|
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case ExprValue:
|
|
|
|
if (expr->type != TypeInt)
|
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR
|
2009-03-27 07:55:32 -06:00
|
|
|
("Found constant of type %s where a mask was expected\n",
|
|
|
|
exprTypeText(expr->type));
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
val_rtrn->ival = expr->value.ival;
|
|
|
|
return True;
|
|
|
|
case ExprIdent:
|
2012-02-20 09:54:54 -07:00
|
|
|
ok = (*lookup) (lookupPriv, expr->value.str, TypeInt, val_rtrn);
|
2009-03-27 07:55:32 -06:00
|
|
|
if (!ok)
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Identifier \"%s\" of type int is unknown\n",
|
2009-03-28 15:06:26 -06:00
|
|
|
XkbcAtomText(expr->value.str));
|
2009-03-27 07:55:32 -06:00
|
|
|
return ok;
|
|
|
|
case ExprFieldRef:
|
2012-02-20 09:54:54 -07:00
|
|
|
ERROR("Default \"%s.%s\" of type int is unknown\n",
|
|
|
|
XkbcAtomText(expr->value.field.element),
|
|
|
|
XkbcAtomText(expr->value.field.field));
|
|
|
|
return False;
|
2009-03-27 07:55:32 -06:00
|
|
|
case ExprArrayRef:
|
|
|
|
bogus = "array reference";
|
|
|
|
case ExprActionDecl:
|
|
|
|
if (bogus == NULL)
|
|
|
|
bogus = "function use";
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Unexpected %s in mask expression\n", bogus);
|
2009-03-27 07:55:32 -06:00
|
|
|
ACTION("Expression ignored\n");
|
|
|
|
return False;
|
|
|
|
case OpAdd:
|
|
|
|
case OpSubtract:
|
|
|
|
case OpMultiply:
|
|
|
|
case OpDivide:
|
|
|
|
left = expr->value.binary.left;
|
|
|
|
right = expr->value.binary.right;
|
2012-02-20 09:54:54 -07:00
|
|
|
if (ExprResolveMaskLookup(left, &leftRtrn, lookup, lookupPriv) &&
|
|
|
|
ExprResolveMaskLookup(right, &rightRtrn, lookup, lookupPriv))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
switch (expr->op)
|
|
|
|
{
|
|
|
|
case OpAdd:
|
|
|
|
val_rtrn->ival = leftRtrn.ival | rightRtrn.ival;
|
|
|
|
break;
|
|
|
|
case OpSubtract:
|
|
|
|
val_rtrn->ival = leftRtrn.ival & (~rightRtrn.ival);
|
|
|
|
break;
|
|
|
|
case OpMultiply:
|
|
|
|
case OpDivide:
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("Cannot %s masks\n",
|
2009-03-27 07:55:32 -06:00
|
|
|
expr->op == OpDivide ? "divide" : "multiply");
|
|
|
|
ACTION("Illegal operation ignored\n");
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
case OpAssign:
|
|
|
|
WSGO("Assignment operator not implemented yet\n");
|
|
|
|
break;
|
|
|
|
case OpInvert:
|
|
|
|
left = expr->value.child;
|
2012-02-20 09:24:02 -07:00
|
|
|
if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
val_rtrn->ival = ~leftRtrn.ival;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
case OpUnaryPlus:
|
|
|
|
case OpNegate:
|
|
|
|
case OpNot:
|
|
|
|
left = expr->value.child;
|
2012-02-20 09:24:02 -07:00
|
|
|
if (ExprResolveIntegerLookup(left, &leftRtrn, lookup, lookupPriv))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
2009-03-31 08:21:20 -06:00
|
|
|
ERROR("The %s operator cannot be used with a mask\n",
|
2009-03-27 07:55:32 -06:00
|
|
|
(expr->op == OpNegate ? "-" : "!"));
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
default:
|
2009-03-31 08:21:20 -06:00
|
|
|
WSGO("Unknown operator %d in ResolveMask\n", expr->op);
|
2009-03-27 07:55:32 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
2012-02-20 09:54:54 -07:00
|
|
|
int
|
|
|
|
ExprResolveMask(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn,
|
2012-03-02 08:40:19 -07:00
|
|
|
const LookupEntry * values)
|
2012-02-20 09:54:54 -07:00
|
|
|
{
|
2012-02-20 10:14:04 -07:00
|
|
|
return ExprResolveMaskLookup(expr, val_rtrn, SimpleLookup, values);
|
2012-02-20 09:54:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ExprResolveModMask(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn)
|
|
|
|
{
|
2012-02-20 10:07:48 -07:00
|
|
|
return ExprResolveMaskLookup(expr, val_rtrn, LookupModMask, NULL);
|
2012-02-20 09:54:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ExprResolveVModMask(ExprDef * expr,
|
|
|
|
ExprResult * val_rtrn,
|
|
|
|
struct xkb_desc *xkb)
|
|
|
|
{
|
2012-02-20 10:14:04 -07:00
|
|
|
return ExprResolveMaskLookup(expr, val_rtrn, LookupVModMask, xkb);
|
2012-02-20 09:54:54 -07:00
|
|
|
}
|
|
|
|
|
2009-03-27 07:55:32 -06:00
|
|
|
int
|
|
|
|
ExprResolveKeySym(ExprDef * expr,
|
2012-02-20 07:10:41 -07:00
|
|
|
ExprResult * val_rtrn)
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
int ok = 0;
|
2012-03-09 12:03:59 -07:00
|
|
|
xkb_keysym_t sym;
|
2009-03-27 07:55:32 -06:00
|
|
|
|
|
|
|
if (expr->op == ExprIdent)
|
|
|
|
{
|
2010-06-30 15:20:56 -06:00
|
|
|
const char *str;
|
2010-06-15 08:22:05 -06:00
|
|
|
str = XkbcAtomText(expr->value.str);
|
2010-07-02 09:50:01 -06:00
|
|
|
if ((str != NULL) && ((sym = xkb_string_to_keysym(str)) != NoSymbol))
|
2009-03-27 07:55:32 -06:00
|
|
|
{
|
|
|
|
val_rtrn->uval = sym;
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
}
|
2012-02-20 09:24:02 -07:00
|
|
|
ok = ExprResolveInteger(expr, val_rtrn);
|
2009-03-27 07:55:32 -06:00
|
|
|
if ((ok) && (val_rtrn->uval < 10))
|
|
|
|
val_rtrn->uval += '0';
|
|
|
|
return ok;
|
|
|
|
}
|