summaryrefslogtreecommitdiff
path: root/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'expr.c')
-rw-r--r--expr.c1106
1 files changed, 1106 insertions, 0 deletions
diff --git a/expr.c b/expr.c
new file mode 100644
index 0000000..0e1bded
--- /dev/null
+++ b/expr.c
@@ -0,0 +1,1106 @@
+/* $Xorg: expr.c,v 1.5 2000/08/17 19:54:30 cpqbld Exp $ */
+/************************************************************
+ 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
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ 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
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "xkbcomp.h"
+#include "tokens.h"
+#include "expr.h"
+
+#include <ctype.h>
+
+/***====================================================================***/
+
+char *
+#if NeedFunctionPrototypes
+exprOpText(unsigned type)
+#else
+exprOpText(type)
+ unsigned type;
+#endif
+{
+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:
+ sprintf(buf,"illegal(%d)",type);
+ break;
+ }
+ return buf;
+}
+
+char *
+#if NeedFunctionPrototypes
+exprTypeText(unsigned type)
+#else
+exprTypeText(type)
+ unsigned type;
+#endif
+{
+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:
+ sprintf(buf,"illegal(%d)",type);
+ break;
+ }
+ return buf;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveLhs( ExprDef * expr,
+ ExprResult * elem_rtrn,
+ ExprResult * field_rtrn,
+ ExprDef ** index_rtrn)
+#else
+ExprResolveLhs(expr,elem_rtrn,field_rtrn,index_rtrn)
+ ExprDef * expr;
+ ExprResult * elem_rtrn;
+ ExprResult * field_rtrn;
+ ExprDef ** index_rtrn;
+#endif
+{
+ switch (expr->op) {
+ case ExprIdent:
+ elem_rtrn->str= NULL;
+ field_rtrn->str= XkbAtomGetString(NULL,expr->value.str);
+ *index_rtrn= NULL;
+ return True;
+ case ExprFieldRef:
+ elem_rtrn->str= XkbAtomGetString(NULL,expr->value.field.element);
+ field_rtrn->str= XkbAtomGetString(NULL,expr->value.field.field);
+ *index_rtrn= NULL;
+ return True;
+ case ExprArrayRef:
+ elem_rtrn->str= XkbAtomGetString(NULL,expr->value.array.element);
+ field_rtrn->str= XkbAtomGetString(NULL,expr->value.array.field);
+ *index_rtrn= expr->value.array.entry;
+ return True;
+ }
+ WSGO1("Unexpected operator %d in ResolveLhs\n",expr->op);
+ return False;
+}
+
+Bool
+#if NeedFunctionPrototypes
+SimpleLookup( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+SimpleLookup(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+LookupEntry * entry;
+register char * str;
+
+ if ((priv==NULL)||
+ (field==None)||(elem!=None)||
+ ((type!=TypeInt)&&(type!=TypeFloat))) {
+ return False;
+ }
+ str= XkbAtomGetString(NULL,field);
+ for (entry=(LookupEntry *)priv;(entry!=NULL)&&(entry->name!=NULL);entry++) {
+ if (uStrCaseCmp(str,entry->name)==0) {
+ val_rtrn->uval= entry->result;
+ if (type==TypeFloat)
+ val_rtrn->uval*= XkbGeomPtsPerMM;
+ return True;
+ }
+ }
+ return False;
+}
+
+Bool
+#if NeedFunctionPrototypes
+RadioLookup( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+RadioLookup(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+register char * str;
+int rg;
+
+ if ((field==None)||(elem!=None)||(type!=TypeInt))
+ return False;
+ str= XkbAtomGetString(NULL,field);
+ if (str) {
+ if (uStrCasePrefix("group",str))
+ str+= strlen("group");
+ else if (uStrCasePrefix("radiogroup",str))
+ str+= strlen("radiogroup");
+ else if (uStrCasePrefix("rg",str))
+ str+= strlen("rg");
+ else if (!isdigit(str[0]))
+ str= NULL;
+ }
+ if ((!str)||(sscanf(str,"%i",&rg)<1)||(rg<1)||(rg>XkbMaxRadioGroups))
+ return False;
+ val_rtrn->uval= rg;
+ return True;
+}
+
+int
+#if NeedFunctionPrototypes
+TableLookup( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+TableLookup(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+LookupTable * tbl= (LookupTable *)priv;
+register char * str;
+
+ if ((priv==NULL)||(field==None)||(type!=TypeInt))
+ return False;
+ str= XkbAtomGetString(NULL,elem);
+ while (tbl) {
+ if (((str==NULL)&&(tbl->element==NULL))||
+ ((str!=NULL)&&(tbl->element!=NULL)&&
+ (uStrCaseCmp(str,tbl->element)==0))) {
+ break;
+ }
+ tbl= tbl->nextElement;
+ }
+ if (tbl==NULL) /* didn't find a matching element */
+ return False;
+ priv= (XPointer)tbl->entries;
+ return SimpleLookup(priv,(Atom)None,field,type,val_rtrn);
+}
+
+static LookupEntry modIndexNames[] = {
+ { "shift", ShiftMapIndex },
+ { "control", ControlMapIndex },
+ { "lock", LockMapIndex },
+ { "mod1", Mod1MapIndex },
+ { "mod2", Mod2MapIndex },
+ { "mod3", Mod3MapIndex },
+ { "mod4", Mod4MapIndex },
+ { "mod5", Mod5MapIndex },
+ { NULL, 0 }
+};
+
+int
+#if NeedFunctionPrototypes
+LookupModIndex( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+LookupModIndex(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+ return SimpleLookup((XPointer)modIndexNames,elem,field,type,val_rtrn);
+}
+
+int
+#if NeedFunctionPrototypes
+LookupModMask( XPointer priv,
+ Atom elem,
+ Atom field,
+ unsigned type,
+ ExprResult * val_rtrn)
+#else
+LookupModMask(priv,elem,field,type,val_rtrn)
+ XPointer priv;
+ Atom elem;
+ Atom field;
+ unsigned type;
+ ExprResult * val_rtrn;
+#endif
+{
+char *str;
+
+ if ((elem!=None)||(type!=TypeInt))
+ return False;
+ str= XkbAtomGetString(NULL,field);
+ if (str==NULL)
+ return False;
+ if (uStrCaseCmp(str,"all")==0)
+ val_rtrn->uval= 0xff;
+ else if (uStrCaseCmp(str,"none")==0)
+ val_rtrn->uval= 0;
+ else if (LookupModIndex(priv,elem,field,type,val_rtrn))
+ val_rtrn->uval= (1<<val_rtrn->uval);
+ else if (priv != NULL) {
+ LookupPriv *lpriv= (LookupPriv *)priv;
+ if ((lpriv->chain==NULL)||
+ (!(*lpriv->chain)(lpriv->chainPriv,elem,field,type,val_rtrn)))
+ return False;
+ }
+ else return False;
+ return True;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveModIndex( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveModIndex(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+char *bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeInt) {
+ ERROR1("Found constant of type %s where a modifier mask was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ else if ((expr->value.ival>=XkbNumModifiers)||(expr->value.ival<0)){
+ ERROR2("Illegal modifier index (%d, must be 0..%d)\n",
+ expr->value.ival,XkbNumModifiers-1);
+ return False;
+ }
+ val_rtrn->ival= expr->value.ival;
+ return True;
+ case ExprIdent:
+ if (LookupModIndex(lookupPriv,(Atom)None,expr->value.str,
+ (unsigned)TypeInt,val_rtrn)) {
+ return True;
+ }
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Cannot determine modifier index for \"%s\"\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ break;
+ case ExprFieldRef:
+ bogus= "field reference";
+ break;
+ case ExprArrayRef:
+ bogus= "array reference";
+ break;
+ case ExprActionDecl:
+ bogus= "function";
+ break;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ case OpInvert:
+ case OpNegate:
+ case OpNot:
+ case OpUnaryPlus:
+ bogus= "arithmetic operations";
+ break;
+ case OpAssign:
+ bogus= "assignment";
+ break;
+ default:
+ WSGO1("Unknown operator %d in ResolveModIndex\n",expr->op);
+ return False;
+ }
+ if (bogus) {
+ ERROR1("Modifier index must be a name or number, %s ignored\n",bogus);
+ return False;
+ }
+ return ok;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveModMask( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveModMask(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+LookupPriv priv;
+
+ priv.priv= NULL;
+ priv.chain= lookup;
+ priv.chainPriv= lookupPriv;
+ return ExprResolveMask(expr,val_rtrn,LookupModMask,(XPointer)&priv);
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveBoolean( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveBoolean(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+char * bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeBoolean) {
+ ERROR1("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:
+ bogus= XkbAtomGetString(NULL,expr->value.str);
+ 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;
+ }
+ }
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeBoolean,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeBoolean,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type boolean is unknown\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case OpInvert:
+ case OpNot:
+ ok= ExprResolveBoolean(expr,val_rtrn,lookup,lookupPriv);
+ 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";
+ ERROR1("%s of boolean values not permitted\n",bogus);
+ break;
+ case OpUnaryPlus:
+ ERROR("Unary \"+\" operator not permitted for boolean values\n");
+ break;
+ default:
+ WSGO1("Unknown operator %d in ResolveBoolean\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveFloat( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveFloat(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprResult leftRtrn,rightRtrn;
+ExprDef *left,*right;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type==TypeString) {
+ register char *str;
+ str= XkbAtomGetString(NULL,expr->value.str);
+ if ((str!=None)&&(strlen(str)==1)) {
+ val_rtrn->uval= str[0]*XkbGeomPtsPerMM;
+ return True;
+ }
+ }
+ if ((expr->type!=TypeInt)&&(expr->type!=TypeFloat)) {
+ ERROR1("Found constant of type %s, expected a number\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival= expr->value.ival;
+ if (expr->type==TypeInt)
+ val_rtrn->ival*= XkbGeomPtsPerMM;
+ return True;
+ case ExprIdent:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeFloat,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Numeric identifier \"%s\" unknown\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeFloat,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Numeric default \"%s.%s\" unknown\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ left= expr->value.binary.left;
+ right= expr->value.binary.right;
+ if (ExprResolveFloat(left,&leftRtrn,lookup,lookupPriv)&&
+ ExprResolveFloat(right,&rightRtrn,lookup,lookupPriv)) {
+ 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:
+ left= expr->value.child;
+ if (ExprResolveFloat(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The ! operator cannot be applied to a number\n");
+ }
+ return False;
+ case OpInvert:
+ case OpNegate:
+ left= expr->value.child;
+ if (ExprResolveFloat(left,&leftRtrn,lookup,lookupPriv)) {
+ 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;
+ return ExprResolveFloat(left,val_rtrn,lookup,lookupPriv);
+ default:
+ WSGO1("Unknown operator %d in ResolveFloat\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveInteger( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveInteger(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprResult leftRtrn,rightRtrn;
+ExprDef *left,*right;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type==TypeString) {
+ register char *str;
+ str= XkbAtomGetString(NULL,expr->value.str);
+ if ((str!=None)&&(strlen(str)==1)) {
+ val_rtrn->uval= str[0];
+ return True;
+ }
+ }
+ if ((expr->type!=TypeInt)&&(expr->type!=TypeFloat)) {
+ ERROR1("Found constant of type %s where an int was expected\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->ival= expr->value.ival;
+ if (expr->type==TypeFloat)
+ val_rtrn->ival/= XkbGeomPtsPerMM;
+ return True;
+ case ExprIdent:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ left= expr->value.binary.left;
+ right= expr->value.binary.right;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)&&
+ ExprResolveInteger(right,&rightRtrn,lookup,lookupPriv)) {
+ 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:
+ left= expr->value.child;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The ! operator cannot be applied to an integer\n");
+ }
+ return False;
+ case OpInvert:
+ case OpNegate:
+ left= expr->value.child;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)) {
+ 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;
+ return ExprResolveInteger(left,val_rtrn,lookup,lookupPriv);
+ default:
+ WSGO1("Unknown operator %d in ResolveInteger\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveString( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveString(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprResult leftRtrn,rightRtrn;
+ExprDef * left;
+ExprDef * right;
+char * bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeString) {
+ ERROR1("Found constant of type %s, expected a string\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ val_rtrn->str= XkbAtomGetString(NULL,expr->value.str);
+ if (val_rtrn->str==NULL) {
+ static char *empty= "";
+ val_rtrn->str= empty;
+ }
+ return True;
+ case ExprIdent:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeString,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type string not found\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeString,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type string not found\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case OpAdd:
+ left= expr->value.binary.left;
+ right= expr->value.binary.right;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)&&
+ ExprResolveString(right,&rightRtrn,lookup,lookupPriv)) {
+ int len;
+ char *new;
+ len= strlen(leftRtrn.str)+strlen(rightRtrn.str)+1;
+ new= (char *)uAlloc(len);
+ if (new) {
+ sprintf(new,"%s%s",leftRtrn.str,rightRtrn.str);
+ val_rtrn->str= new;
+ return True;
+ }
+ }
+ 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";
+ ERROR1("%s of string values not permitted\n",bogus);
+ return False;
+ case OpNot:
+ left= expr->value.child;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The ! operator cannot be applied to a string\n");
+ }
+ return False;
+ case OpUnaryPlus:
+ left= expr->value.child;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The + operator cannot be applied to a string\n");
+ }
+ return False;
+ default:
+ WSGO1("Unknown operator %d in ResolveString\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveKeyName( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveKeyName(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprDef * left;
+ExprResult leftRtrn;
+char * bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeKeyName) {
+ ERROR1("Found constant of type %s, expected a key name\n",
+ exprTypeText(expr->type));
+ return False;
+ }
+ memcpy(val_rtrn->keyName.name,expr->value.keyName,XkbKeyNameLength);
+ return True;
+ case ExprIdent:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeString,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type string not found\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeString,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type key name not found\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ 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";
+ case OpInvert: if (bogus==NULL) bogus= "Bitwise complement";
+ ERROR1("%s of key name values not permitted\n",bogus);
+ return False;
+ case OpNot:
+ left= expr->value.binary.left;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The ! operator cannot be applied to a key name\n");
+ }
+ return False;
+ case OpUnaryPlus:
+ left= expr->value.binary.left;
+ if (ExprResolveString(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR("The + operator cannot be applied to a key name\n");
+ }
+ return False;
+ default:
+ WSGO1("Unknown operator %d in ResolveKeyName\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+/***====================================================================***/
+
+int
+#if NeedFunctionPrototypes
+ExprResolveEnum(ExprDef *expr,ExprResult *val_rtrn,LookupEntry *values)
+#else
+ExprResolveEnum(expr,val_rtrn,values)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ LookupEntry * values;
+#endif
+{
+ if (expr->op!=ExprIdent) {
+ ERROR1("Found a %s where an enumerated value was expected\n",
+ exprOpText(expr->op));
+ return False;
+ }
+ if (!SimpleLookup((XPointer)values,(Atom)None,expr->value.str,
+ (unsigned)TypeInt,val_rtrn)) {
+ int nOut=0;
+ ERROR1("Illegal identifier %s (expected one of: ",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ while (values && values->name) {
+ if (nOut!=0) INFO1(", %s",values->name);
+ else INFO1("%s",values->name);
+ }
+ INFO(")\n");
+ return False;
+ }
+ return True;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveMask( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveMask(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+ExprResult leftRtrn,rightRtrn;
+ExprDef *left,*right;
+char * bogus= NULL;
+
+ switch (expr->op) {
+ case ExprValue:
+ if (expr->type!=TypeInt) {
+ ERROR1("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:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ None,expr->value.str,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR1("Identifier \"%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.str,XkbMessage));
+ return ok;
+ case ExprFieldRef:
+ if (lookup) {
+ ok= (*lookup)(lookupPriv,
+ expr->value.field.element,expr->value.field.field,
+ TypeInt,val_rtrn);
+ }
+ if (!ok)
+ ERROR2("Default \"%s.%s\" of type int is unknown\n",
+ XkbAtomText(NULL,expr->value.field.element,XkbMessage),
+ XkbAtomText(NULL,expr->value.field.field,XkbMessage));
+ return ok;
+ case ExprArrayRef:
+ bogus= "array reference";
+ case ExprActionDecl:
+ if (bogus==NULL)
+ bogus= "function use";
+ ERROR1("Unexpected %s in mask expression\n",bogus);
+ ACTION("Expression ignored\n");
+ return False;
+ case OpAdd:
+ case OpSubtract:
+ case OpMultiply:
+ case OpDivide:
+ left= expr->value.binary.left;
+ right= expr->value.binary.right;
+ if (ExprResolveMask(left,&leftRtrn,lookup,lookupPriv)&&
+ ExprResolveMask(right,&rightRtrn,lookup,lookupPriv)) {
+ 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:
+ ERROR1("Cannot %s masks\n",
+ 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;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)) {
+ val_rtrn->ival= ~leftRtrn.ival;
+ return True;
+ }
+ return False;
+ case OpUnaryPlus:
+ case OpNegate:
+ case OpNot:
+ left= expr->value.child;
+ if (ExprResolveInteger(left,&leftRtrn,lookup,lookupPriv)) {
+ ERROR1("The %s operator cannot be used with a mask\n",
+ (expr->op==OpNegate?"-":"!"));
+ }
+ return False;
+ default:
+ WSGO1("Unknown operator %d in ResolveMask\n",expr->op);
+ break;
+ }
+ return False;
+}
+
+int
+#if NeedFunctionPrototypes
+ExprResolveKeySym( ExprDef * expr,
+ ExprResult * val_rtrn,
+ IdentLookupFunc lookup,
+ XPointer lookupPriv)
+#else
+ExprResolveKeySym(expr,val_rtrn,lookup,lookupPriv)
+ ExprDef * expr;
+ ExprResult * val_rtrn;
+ IdentLookupFunc lookup;
+ XPointer lookupPriv;
+#endif
+{
+int ok= 0;
+KeySym sym;
+
+ if (expr->op==ExprIdent) {
+ char *str;
+ str= XkbAtomGetString(NULL,expr->value.str);
+ if ((str!=NULL)&&((sym= XStringToKeysym(str))!=NoSymbol)) {
+ val_rtrn->uval= sym;
+ return True;
+ }
+ }
+ ok= ExprResolveInteger(expr,val_rtrn,lookup,lookupPriv);
+ if ((ok)&&(val_rtrn->uval<10))
+ val_rtrn->uval+= '0';
+ return ok;
+}