compat.c revision f46a6179
1f46a6179Smrg/* $Xorg: compat.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */ 2f46a6179Smrg/************************************************************ 3f46a6179Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 4f46a6179Smrg 5f46a6179Smrg Permission to use, copy, modify, and distribute this 6f46a6179Smrg software and its documentation for any purpose and without 7f46a6179Smrg fee is hereby granted, provided that the above copyright 8f46a6179Smrg notice appear in all copies and that both that copyright 9f46a6179Smrg notice and this permission notice appear in supporting 10f46a6179Smrg documentation, and that the name of Silicon Graphics not be 11f46a6179Smrg used in advertising or publicity pertaining to distribution 12f46a6179Smrg of the software without specific prior written permission. 13f46a6179Smrg Silicon Graphics makes no representation about the suitability 14f46a6179Smrg of this software for any purpose. It is provided "as is" 15f46a6179Smrg without any express or implied warranty. 16f46a6179Smrg 17f46a6179Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 18f46a6179Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 19f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 20f46a6179Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 21f46a6179Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22f46a6179Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 23f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 24f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 25f46a6179Smrg 26f46a6179Smrg ********************************************************/ 27f46a6179Smrg/* $XFree86: xc/programs/xkbcomp/compat.c,v 3.3 2001/01/17 23:45:43 dawes Exp $ */ 28f46a6179Smrg 29f46a6179Smrg#include <X11/Xos.h> 30f46a6179Smrg#include "xkbcomp.h" 31f46a6179Smrg#include "tokens.h" 32f46a6179Smrg#include "expr.h" 33f46a6179Smrg#include "vmod.h" 34f46a6179Smrg#include "misc.h" 35f46a6179Smrg#include "indicators.h" 36f46a6179Smrg#include "action.h" 37f46a6179Smrg 38f46a6179Smrgtypedef struct _SymInterpInfo { 39f46a6179Smrg CommonInfo defs; 40f46a6179Smrg XkbSymInterpretRec interp; 41f46a6179Smrg} SymInterpInfo; 42f46a6179Smrg 43f46a6179Smrg#define _SI_VirtualMod (1<<0) 44f46a6179Smrg#define _SI_Action (1<<1) 45f46a6179Smrg#define _SI_AutoRepeat (1<<2) 46f46a6179Smrg#define _SI_LockingKey (1<<3) 47f46a6179Smrg#define _SI_LevelOneOnly (1<<4) 48f46a6179Smrg 49f46a6179Smrgtypedef struct _GroupCompatInfo { 50f46a6179Smrg unsigned char fileID; 51f46a6179Smrg unsigned char merge; 52f46a6179Smrg unsigned char real_mods; 53f46a6179Smrg unsigned short vmods; 54f46a6179Smrg} GroupCompatInfo; 55f46a6179Smrg 56f46a6179Smrgtypedef struct _CompatInfo { 57f46a6179Smrg char * name; 58f46a6179Smrg unsigned fileID; 59f46a6179Smrg int errorCount; 60f46a6179Smrg int nInterps; 61f46a6179Smrg SymInterpInfo * interps; 62f46a6179Smrg SymInterpInfo dflt; 63f46a6179Smrg LEDInfo ledDflt; 64f46a6179Smrg GroupCompatInfo groupCompat[XkbNumKbdGroups]; 65f46a6179Smrg LEDInfo * leds; 66f46a6179Smrg VModInfo vmods; 67f46a6179Smrg ActionInfo * act; 68f46a6179Smrg XkbDescPtr xkb; 69f46a6179Smrg} CompatInfo; 70f46a6179Smrg 71f46a6179Smrg/***====================================================================***/ 72f46a6179Smrg 73f46a6179Smrg#define ReportSINotArray(si,f,i) \ 74f46a6179Smrg ReportNotArray("symbol interpretation",(f),siText((si),(i))) 75f46a6179Smrg#define ReportSIBadType(si,f,w,i) \ 76f46a6179Smrg ReportBadType("symbol interpretation",(f),siText((si),(i)),(w)) 77f46a6179Smrg 78f46a6179Smrg/***====================================================================***/ 79f46a6179Smrg 80f46a6179Smrgstatic char * 81f46a6179SmrgsiText(SymInterpInfo * si,CompatInfo * info) 82f46a6179Smrg{ 83f46a6179Smrgstatic char buf[128]; 84f46a6179Smrg 85f46a6179Smrg if (si==&info->dflt) { 86f46a6179Smrg sprintf(buf,"default"); 87f46a6179Smrg } 88f46a6179Smrg else { 89f46a6179Smrg sprintf(buf,"%s+%s(%s)",XkbKeysymText(si->interp.sym,XkbMessage), 90f46a6179Smrg XkbSIMatchText(si->interp.match,XkbMessage), 91f46a6179Smrg XkbModMaskText(si->interp.mods,XkbMessage)); 92f46a6179Smrg } 93f46a6179Smrg return buf; 94f46a6179Smrg} 95f46a6179Smrg 96f46a6179Smrgstatic void 97f46a6179SmrgInitCompatInfo(CompatInfo *info,XkbDescPtr xkb) 98f46a6179Smrg{ 99f46a6179Smrgregister int i; 100f46a6179Smrg 101f46a6179Smrg info->xkb= xkb; 102f46a6179Smrg info->name= NULL; 103f46a6179Smrg info->fileID= 0; 104f46a6179Smrg info->errorCount= 0; 105f46a6179Smrg info->nInterps= 0; 106f46a6179Smrg info->interps= NULL; 107f46a6179Smrg info->act= NULL; 108f46a6179Smrg info->dflt.defs.fileID= info->fileID; 109f46a6179Smrg info->dflt.defs.defined= 0; 110f46a6179Smrg info->dflt.defs.merge= MergeOverride; 111f46a6179Smrg info->dflt.interp.flags= 0; 112f46a6179Smrg info->dflt.interp.virtual_mod= XkbNoModifier; 113f46a6179Smrg info->dflt.interp.act.type= XkbSA_NoAction; 114f46a6179Smrg for (i=0;i<XkbAnyActionDataSize;i++) { 115f46a6179Smrg info->dflt.interp.act.data[i]= 0; 116f46a6179Smrg } 117f46a6179Smrg ClearIndicatorMapInfo(xkb->dpy,&info->ledDflt); 118f46a6179Smrg info->ledDflt.defs.fileID= info->fileID; 119f46a6179Smrg info->ledDflt.defs.defined= 0; 120f46a6179Smrg info->ledDflt.defs.merge= MergeOverride; 121f46a6179Smrg bzero((char *)&info->groupCompat[0],XkbNumKbdGroups*sizeof(GroupCompatInfo)); 122f46a6179Smrg info->leds= NULL; 123f46a6179Smrg InitVModInfo(&info->vmods,xkb); 124f46a6179Smrg return; 125f46a6179Smrg} 126f46a6179Smrg 127f46a6179Smrgstatic void 128f46a6179SmrgClearCompatInfo(CompatInfo *info,XkbDescPtr xkb) 129f46a6179Smrg{ 130f46a6179Smrgregister int i; 131f46a6179Smrg 132f46a6179Smrg if (info->name!=NULL) 133f46a6179Smrg uFree(info->name); 134f46a6179Smrg info->name= NULL; 135f46a6179Smrg info->dflt.defs.defined= 0; 136f46a6179Smrg info->dflt.defs.merge= MergeAugment; 137f46a6179Smrg info->dflt.interp.flags= 0; 138f46a6179Smrg info->dflt.interp.virtual_mod= XkbNoModifier; 139f46a6179Smrg info->dflt.interp.act.type= XkbSA_NoAction; 140f46a6179Smrg for (i=0;i<XkbAnyActionDataSize;i++) { 141f46a6179Smrg info->dflt.interp.act.data[i]= 0; 142f46a6179Smrg } 143f46a6179Smrg ClearIndicatorMapInfo(xkb->dpy,&info->ledDflt); 144f46a6179Smrg info->nInterps= 0; 145f46a6179Smrg info->interps= (SymInterpInfo *)ClearCommonInfo(&info->interps->defs); 146f46a6179Smrg bzero((char *)&info->groupCompat[0],XkbNumKbdGroups*sizeof(GroupCompatInfo)); 147f46a6179Smrg info->leds= (LEDInfo *)ClearCommonInfo(&info->leds->defs); 148f46a6179Smrg /* 3/30/94 (ef) -- XXX! Should free action info here */ 149f46a6179Smrg ClearVModInfo(&info->vmods,xkb); 150f46a6179Smrg return; 151f46a6179Smrg} 152f46a6179Smrg 153f46a6179Smrgstatic SymInterpInfo * 154f46a6179SmrgNextInterp(CompatInfo *info) 155f46a6179Smrg{ 156f46a6179SmrgSymInterpInfo * si; 157f46a6179Smrg 158f46a6179Smrg si= uTypedAlloc(SymInterpInfo); 159f46a6179Smrg if (si) { 160f46a6179Smrg bzero((char *)si,sizeof(SymInterpInfo)); 161f46a6179Smrg info->interps= (SymInterpInfo *)AddCommonInfo(&info->interps->defs, 162f46a6179Smrg (CommonInfo *)si); 163f46a6179Smrg info->nInterps++; 164f46a6179Smrg } 165f46a6179Smrg return si; 166f46a6179Smrg} 167f46a6179Smrg 168f46a6179Smrgstatic SymInterpInfo * 169f46a6179SmrgFindMatchingInterp(CompatInfo *info,SymInterpInfo *new) 170f46a6179Smrg{ 171f46a6179SmrgSymInterpInfo * old; 172f46a6179Smrg 173f46a6179Smrg for (old= info->interps;old!=NULL;old=(SymInterpInfo *)old->defs.next) { 174f46a6179Smrg if ((old->interp.sym==new->interp.sym)&& 175f46a6179Smrg (old->interp.mods==new->interp.mods)&& 176f46a6179Smrg (old->interp.match==new->interp.match)) { 177f46a6179Smrg return old; 178f46a6179Smrg } 179f46a6179Smrg } 180f46a6179Smrg return NULL; 181f46a6179Smrg} 182f46a6179Smrg 183f46a6179Smrgstatic Bool 184f46a6179SmrgAddInterp(CompatInfo *info,SymInterpInfo *new) 185f46a6179Smrg{ 186f46a6179Smrgunsigned collide; 187f46a6179SmrgSymInterpInfo * old; 188f46a6179Smrg 189f46a6179Smrg collide= 0; 190f46a6179Smrg old= FindMatchingInterp(info,new); 191f46a6179Smrg if (old!=NULL) { 192f46a6179Smrg if (new->defs.merge==MergeReplace) { 193f46a6179Smrg SymInterpInfo *next= (SymInterpInfo *)old->defs.next; 194f46a6179Smrg if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 195f46a6179Smrg (warningLevel>9)) { 196f46a6179Smrg WARN1("Multiple definitions for \"%s\"\n",siText(new,info)); 197f46a6179Smrg ACTION("Earlier interpretation ignored\n"); 198f46a6179Smrg } 199f46a6179Smrg *old= *new; 200f46a6179Smrg old->defs.next= &next->defs; 201f46a6179Smrg return True; 202f46a6179Smrg } 203f46a6179Smrg if (UseNewField(_SI_VirtualMod,&old->defs,&new->defs,&collide)) { 204f46a6179Smrg old->interp.virtual_mod= new->interp.virtual_mod; 205f46a6179Smrg old->defs.defined|= _SI_VirtualMod; 206f46a6179Smrg } 207f46a6179Smrg if (UseNewField(_SI_Action,&old->defs,&new->defs,&collide)) { 208f46a6179Smrg old->interp.act= new->interp.act; 209f46a6179Smrg old->defs.defined|= _SI_Action; 210f46a6179Smrg } 211f46a6179Smrg if (UseNewField(_SI_AutoRepeat,&old->defs,&new->defs,&collide)) { 212f46a6179Smrg old->interp.flags&= ~XkbSI_AutoRepeat; 213f46a6179Smrg old->interp.flags|= (new->interp.flags&XkbSI_AutoRepeat); 214f46a6179Smrg old->defs.defined|= _SI_AutoRepeat; 215f46a6179Smrg } 216f46a6179Smrg if (UseNewField(_SI_LockingKey,&old->defs,&new->defs,&collide)) { 217f46a6179Smrg old->interp.flags&= ~XkbSI_LockingKey; 218f46a6179Smrg old->interp.flags|= (new->interp.flags&XkbSI_LockingKey); 219f46a6179Smrg old->defs.defined|= _SI_LockingKey; 220f46a6179Smrg } 221f46a6179Smrg if (UseNewField(_SI_LevelOneOnly,&old->defs,&new->defs,&collide)) { 222f46a6179Smrg old->interp.match&= ~XkbSI_LevelOneOnly; 223f46a6179Smrg old->interp.match|= (new->interp.match&XkbSI_LevelOneOnly); 224f46a6179Smrg old->defs.defined|= _SI_LevelOneOnly; 225f46a6179Smrg } 226f46a6179Smrg if (collide) { 227f46a6179Smrg WARN1("Multiple interpretations of \"%s\"\n",siText(new,info)); 228f46a6179Smrg ACTION1("Using %s definition for duplicate fields\n", 229f46a6179Smrg (new->defs.merge!=MergeAugment?"last":"first")); 230f46a6179Smrg } 231f46a6179Smrg return True; 232f46a6179Smrg } 233f46a6179Smrg old= new; 234f46a6179Smrg if ((new= NextInterp(info))==NULL) 235f46a6179Smrg return False; 236f46a6179Smrg *new= *old; 237f46a6179Smrg new->defs.next= NULL; 238f46a6179Smrg return True; 239f46a6179Smrg} 240f46a6179Smrg 241f46a6179Smrgstatic Bool 242f46a6179SmrgAddGroupCompat(CompatInfo *info,unsigned group,GroupCompatInfo *newGC) 243f46a6179Smrg{ 244f46a6179SmrgGroupCompatInfo * gc; 245f46a6179Smrgunsigned merge; 246f46a6179Smrg 247f46a6179Smrg merge= newGC->merge; 248f46a6179Smrg gc= &info->groupCompat[group]; 249f46a6179Smrg if (((gc->real_mods==newGC->real_mods)&&(gc->vmods==newGC->vmods))) { 250f46a6179Smrg return True; 251f46a6179Smrg } 252f46a6179Smrg if (((gc->fileID==newGC->fileID)&&(warningLevel>0))||(warningLevel>9)) { 253f46a6179Smrg WARN1("Compat map for group %d redefined\n",group+1); 254f46a6179Smrg ACTION1("Using %s definition\n",(merge==MergeAugment?"old":"new")); 255f46a6179Smrg } 256f46a6179Smrg if (merge!=MergeAugment) 257f46a6179Smrg *gc= *newGC; 258f46a6179Smrg return True; 259f46a6179Smrg} 260f46a6179Smrg 261f46a6179Smrg/***====================================================================***/ 262f46a6179Smrg 263f46a6179Smrgstatic Bool 264f46a6179SmrgResolveStateAndPredicate( ExprDef * expr, 265f46a6179Smrg unsigned * pred_rtrn, 266f46a6179Smrg unsigned * mods_rtrn, 267f46a6179Smrg CompatInfo * info) 268f46a6179Smrg{ 269f46a6179SmrgExprResult result; 270f46a6179Smrg 271f46a6179Smrg if (expr==NULL) { 272f46a6179Smrg *pred_rtrn= XkbSI_AnyOfOrNone; 273f46a6179Smrg *mods_rtrn= ~0; 274f46a6179Smrg return True; 275f46a6179Smrg } 276f46a6179Smrg 277f46a6179Smrg *pred_rtrn= XkbSI_Exactly; 278f46a6179Smrg if (expr->op==ExprActionDecl) { 279f46a6179Smrg char *pred_txt= XkbAtomText(NULL,expr->value.action.name,XkbMessage); 280f46a6179Smrg if (uStrCaseCmp(pred_txt,"noneof")==0) 281f46a6179Smrg *pred_rtrn= XkbSI_NoneOf; 282f46a6179Smrg else if (uStrCaseCmp(pred_txt,"anyofornone")==0) 283f46a6179Smrg *pred_rtrn= XkbSI_AnyOfOrNone; 284f46a6179Smrg else if (uStrCaseCmp(pred_txt,"anyof")==0) 285f46a6179Smrg *pred_rtrn= XkbSI_AnyOf; 286f46a6179Smrg else if (uStrCaseCmp(pred_txt,"allof")==0) 287f46a6179Smrg *pred_rtrn= XkbSI_AllOf; 288f46a6179Smrg else if (uStrCaseCmp(pred_txt,"exactly")==0) 289f46a6179Smrg *pred_rtrn= XkbSI_Exactly; 290f46a6179Smrg else { 291f46a6179Smrg ERROR1("Illegal modifier predicate \"%s\"\n",pred_txt); 292f46a6179Smrg ACTION("Ignored\n"); 293f46a6179Smrg return False; 294f46a6179Smrg } 295f46a6179Smrg expr= expr->value.action.args; 296f46a6179Smrg } 297f46a6179Smrg else if (expr->op==ExprIdent) { 298f46a6179Smrg char *pred_txt= XkbAtomText(NULL,expr->value.str,XkbMessage); 299f46a6179Smrg if ((pred_txt)&&(uStrCaseCmp(pred_txt,"any")==0)) { 300f46a6179Smrg *pred_rtrn= XkbSI_AnyOf; 301f46a6179Smrg *mods_rtrn= 0xff; 302f46a6179Smrg return True; 303f46a6179Smrg } 304f46a6179Smrg } 305f46a6179Smrg 306f46a6179Smrg if (ExprResolveModMask(expr,&result,NULL,NULL)) { 307f46a6179Smrg *mods_rtrn= result.uval; 308f46a6179Smrg return True; 309f46a6179Smrg } 310f46a6179Smrg return False; 311f46a6179Smrg} 312f46a6179Smrg 313f46a6179Smrg/***====================================================================***/ 314f46a6179Smrg 315f46a6179Smrgstatic void 316f46a6179SmrgMergeIncludedCompatMaps( CompatInfo * into, 317f46a6179Smrg CompatInfo * from, 318f46a6179Smrg unsigned merge) 319f46a6179Smrg{ 320f46a6179SmrgSymInterpInfo * si; 321f46a6179SmrgLEDInfo * led,*rtrn,*next; 322f46a6179SmrgGroupCompatInfo * gcm; 323f46a6179Smrgregister int i; 324f46a6179Smrg 325f46a6179Smrg if (from->errorCount>0) { 326f46a6179Smrg into->errorCount+= from->errorCount; 327f46a6179Smrg return; 328f46a6179Smrg } 329f46a6179Smrg if (into->name==NULL) { 330f46a6179Smrg into->name= from->name; 331f46a6179Smrg from->name= NULL; 332f46a6179Smrg } 333f46a6179Smrg for (si=from->interps;si;si=(SymInterpInfo *)si->defs.next) { 334f46a6179Smrg if (merge!=MergeDefault) 335f46a6179Smrg si->defs.merge= merge; 336f46a6179Smrg if (!AddInterp(into,si)) 337f46a6179Smrg into->errorCount++; 338f46a6179Smrg } 339f46a6179Smrg for (i=0,gcm=&from->groupCompat[0];i<XkbNumKbdGroups;i++,gcm++) { 340f46a6179Smrg if (merge!=MergeDefault) 341f46a6179Smrg gcm->merge= merge; 342f46a6179Smrg if (!AddGroupCompat(into,i,gcm)) 343f46a6179Smrg into->errorCount++; 344f46a6179Smrg } 345f46a6179Smrg for (led=from->leds;led!=NULL;led=next) { 346f46a6179Smrg next= (LEDInfo *)led->defs.next; 347f46a6179Smrg if (merge!=MergeDefault) 348f46a6179Smrg led->defs.merge= merge; 349f46a6179Smrg rtrn= AddIndicatorMap(into->leds,led); 350f46a6179Smrg if (rtrn!=NULL) 351f46a6179Smrg into->leds= rtrn; 352f46a6179Smrg else into->errorCount++; 353f46a6179Smrg } 354f46a6179Smrg return; 355f46a6179Smrg} 356f46a6179Smrg 357f46a6179Smrgtypedef void (*FileHandler)( 358f46a6179Smrg XkbFile * /* rtrn */, 359f46a6179Smrg XkbDescPtr /* xkb */, 360f46a6179Smrg unsigned /* merge */, 361f46a6179Smrg CompatInfo * /* info */ 362f46a6179Smrg); 363f46a6179Smrg 364f46a6179Smrgstatic Bool 365f46a6179SmrgHandleIncludeCompatMap( IncludeStmt * stmt, 366f46a6179Smrg XkbDescPtr xkb, 367f46a6179Smrg CompatInfo * info, 368f46a6179Smrg FileHandler hndlr) 369f46a6179Smrg{ 370f46a6179Smrgunsigned newMerge; 371f46a6179SmrgXkbFile * rtrn; 372f46a6179SmrgCompatInfo included; 373f46a6179SmrgBool haveSelf; 374f46a6179Smrg 375f46a6179Smrg haveSelf= False; 376f46a6179Smrg if ((stmt->file==NULL)&&(stmt->map==NULL)) { 377f46a6179Smrg haveSelf= True; 378f46a6179Smrg included= *info; 379f46a6179Smrg bzero(info,sizeof(CompatInfo)); 380f46a6179Smrg } 381f46a6179Smrg else if (ProcessIncludeFile(stmt,XkmCompatMapIndex,&rtrn,&newMerge)) { 382f46a6179Smrg InitCompatInfo(&included,xkb); 383f46a6179Smrg included.fileID= rtrn->id; 384f46a6179Smrg included.dflt= info->dflt; 385f46a6179Smrg included.dflt.defs.fileID= rtrn->id; 386f46a6179Smrg included.dflt.defs.merge= newMerge; 387f46a6179Smrg included.ledDflt.defs.fileID= rtrn->id; 388f46a6179Smrg included.ledDflt.defs.merge= newMerge; 389f46a6179Smrg included.act= info->act; 390f46a6179Smrg (*hndlr)(rtrn,xkb,MergeOverride,&included); 391f46a6179Smrg if (stmt->stmt!=NULL) { 392f46a6179Smrg if (included.name!=NULL) 393f46a6179Smrg uFree(included.name); 394f46a6179Smrg included.name= stmt->stmt; 395f46a6179Smrg stmt->stmt= NULL; 396f46a6179Smrg } 397f46a6179Smrg } 398f46a6179Smrg else { 399f46a6179Smrg info->errorCount+= 10; 400f46a6179Smrg return False; 401f46a6179Smrg } 402f46a6179Smrg if ((stmt->next!=NULL)&&(included.errorCount<1)) { 403f46a6179Smrg IncludeStmt * next; 404f46a6179Smrg unsigned op; 405f46a6179Smrg CompatInfo next_incl; 406f46a6179Smrg 407f46a6179Smrg for (next=stmt->next;next!=NULL;next=next->next) { 408f46a6179Smrg if ((next->file==NULL)&&(next->map==NULL)) { 409f46a6179Smrg haveSelf= True; 410f46a6179Smrg MergeIncludedCompatMaps(&included,info,next->merge); 411f46a6179Smrg ClearCompatInfo(info,xkb); 412f46a6179Smrg } 413f46a6179Smrg else if (ProcessIncludeFile(next,XkmCompatMapIndex,&rtrn,&op)) { 414f46a6179Smrg InitCompatInfo(&next_incl,xkb); 415f46a6179Smrg next_incl.fileID= rtrn->id; 416f46a6179Smrg next_incl.dflt= info->dflt; 417f46a6179Smrg next_incl.dflt.defs.fileID= rtrn->id; 418f46a6179Smrg next_incl.dflt.defs.merge= op; 419f46a6179Smrg next_incl.ledDflt.defs.fileID= rtrn->id; 420f46a6179Smrg next_incl.ledDflt.defs.merge= op; 421f46a6179Smrg next_incl.act= info->act; 422f46a6179Smrg (*hndlr)(rtrn,xkb,MergeOverride,&next_incl); 423f46a6179Smrg MergeIncludedCompatMaps(&included,&next_incl,op); 424f46a6179Smrg ClearCompatInfo(&next_incl,xkb); 425f46a6179Smrg } 426f46a6179Smrg else { 427f46a6179Smrg info->errorCount+= 10; 428f46a6179Smrg return False; 429f46a6179Smrg } 430f46a6179Smrg } 431f46a6179Smrg } 432f46a6179Smrg if (haveSelf) 433f46a6179Smrg *info= included; 434f46a6179Smrg else { 435f46a6179Smrg MergeIncludedCompatMaps(info,&included,newMerge); 436f46a6179Smrg ClearCompatInfo(&included,xkb); 437f46a6179Smrg } 438f46a6179Smrg return (info->errorCount==0); 439f46a6179Smrg} 440f46a6179Smrg 441f46a6179Smrgstatic LookupEntry useModMapValues[] = { 442f46a6179Smrg { "levelone", 1 }, 443f46a6179Smrg { "level1", 1 }, 444f46a6179Smrg { "anylevel", 0 }, 445f46a6179Smrg { "any", 0 }, 446f46a6179Smrg { NULL, 0 } 447f46a6179Smrg}; 448f46a6179Smrg 449f46a6179Smrgstatic int 450f46a6179SmrgSetInterpField( SymInterpInfo * si, 451f46a6179Smrg XkbDescPtr xkb, 452f46a6179Smrg char * field, 453f46a6179Smrg ExprDef * arrayNdx, 454f46a6179Smrg ExprDef * value, 455f46a6179Smrg CompatInfo * info) 456f46a6179Smrg{ 457f46a6179Smrgint ok= 1; 458f46a6179SmrgExprResult tmp; 459f46a6179Smrg 460f46a6179Smrg if (uStrCaseCmp(field,"action")==0) { 461f46a6179Smrg if (arrayNdx!=NULL) 462f46a6179Smrg return ReportSINotArray(si,field,info); 463f46a6179Smrg ok= HandleActionDef(value,xkb,&si->interp.act,si->defs.merge,info->act); 464f46a6179Smrg if (ok) 465f46a6179Smrg si->defs.defined|= _SI_Action; 466f46a6179Smrg } 467f46a6179Smrg else if ((uStrCaseCmp(field,"virtualmodifier")==0)|| 468f46a6179Smrg (uStrCaseCmp(field,"virtualmod")==0)) { 469f46a6179Smrg if (arrayNdx!=NULL) 470f46a6179Smrg return ReportSINotArray(si,field,info); 471f46a6179Smrg ok= ResolveVirtualModifier(value,&tmp,&info->vmods); 472f46a6179Smrg if (ok) { 473f46a6179Smrg si->interp.virtual_mod= tmp.uval; 474f46a6179Smrg si->defs.defined|= _SI_VirtualMod; 475f46a6179Smrg } 476f46a6179Smrg else return ReportSIBadType(si,field,"virtual modifier",info); 477f46a6179Smrg } 478f46a6179Smrg else if (uStrCaseCmp(field,"repeat")==0) { 479f46a6179Smrg if (arrayNdx!=NULL) 480f46a6179Smrg return ReportSINotArray(si,field,info); 481f46a6179Smrg ok= ExprResolveBoolean(value,&tmp,NULL,NULL); 482f46a6179Smrg if (ok) { 483f46a6179Smrg if (tmp.uval) si->interp.flags|= XkbSI_AutoRepeat; 484f46a6179Smrg else si->interp.flags&= ~XkbSI_AutoRepeat; 485f46a6179Smrg si->defs.defined|= _SI_AutoRepeat; 486f46a6179Smrg } 487f46a6179Smrg else return ReportSIBadType(si,field,"boolean",info); 488f46a6179Smrg } 489f46a6179Smrg else if (uStrCaseCmp(field,"locking")==0) { 490f46a6179Smrg if (arrayNdx!=NULL) 491f46a6179Smrg return ReportSINotArray(si,field,info); 492f46a6179Smrg ok= ExprResolveBoolean(value,&tmp,NULL,NULL); 493f46a6179Smrg if (ok) { 494f46a6179Smrg if (tmp.uval) si->interp.flags|= XkbSI_LockingKey; 495f46a6179Smrg else si->interp.flags&= ~XkbSI_LockingKey; 496f46a6179Smrg si->defs.defined|= _SI_LockingKey; 497f46a6179Smrg } 498f46a6179Smrg else return ReportSIBadType(si,field,"boolean",info); 499f46a6179Smrg } 500f46a6179Smrg else if ((uStrCaseCmp(field,"usemodmap")==0)|| 501f46a6179Smrg (uStrCaseCmp(field,"usemodmapmods")==0)) { 502f46a6179Smrg if (arrayNdx!=NULL) 503f46a6179Smrg return ReportSINotArray(si,field,info); 504f46a6179Smrg ok= ExprResolveEnum(value,&tmp,useModMapValues); 505f46a6179Smrg if (ok) { 506f46a6179Smrg if (tmp.uval) si->interp.match|= XkbSI_LevelOneOnly; 507f46a6179Smrg else si->interp.match&= ~XkbSI_LevelOneOnly; 508f46a6179Smrg si->defs.defined|= _SI_LevelOneOnly; 509f46a6179Smrg } 510f46a6179Smrg else return ReportSIBadType(si,field,"level specification",info); 511f46a6179Smrg } 512f46a6179Smrg else { 513f46a6179Smrg ok= ReportBadField("symbol interpretation",field,siText(si,info)); 514f46a6179Smrg } 515f46a6179Smrg return ok; 516f46a6179Smrg} 517f46a6179Smrg 518f46a6179SmrgLookupEntry groupNames[]= { 519f46a6179Smrg { "group1", 0x01 }, 520f46a6179Smrg { "group2", 0x02 }, 521f46a6179Smrg { "group3", 0x04 }, 522f46a6179Smrg { "group4", 0x08 }, 523f46a6179Smrg { "group5", 0x10 }, 524f46a6179Smrg { "group6", 0x20 }, 525f46a6179Smrg { "group7", 0x40 }, 526f46a6179Smrg { "group8", 0x80 }, 527f46a6179Smrg { "none", 0x00 }, 528f46a6179Smrg { "all", 0xff }, 529f46a6179Smrg { NULL, 0 } 530f46a6179Smrg}; 531f46a6179Smrg 532f46a6179Smrgstatic int 533f46a6179SmrgHandleInterpVar(VarDef *stmt,XkbDescPtr xkb,CompatInfo *info) 534f46a6179Smrg{ 535f46a6179SmrgExprResult elem,field; 536f46a6179SmrgExprDef * ndx; 537f46a6179Smrg 538f46a6179Smrg if (ExprResolveLhs(stmt->name,&elem,&field,&ndx)==0) 539f46a6179Smrg return 0; /* internal error, already reported */ 540f46a6179Smrg if (elem.str&&(uStrCaseCmp(elem.str,"interpret")==0)) 541f46a6179Smrg return SetInterpField(&info->dflt,xkb,field.str,ndx,stmt->value,info); 542f46a6179Smrg if (elem.str&&(uStrCaseCmp(elem.str,"indicator")==0)) { 543f46a6179Smrg return SetIndicatorMapField(&info->ledDflt,xkb,field.str,ndx, 544f46a6179Smrg stmt->value); 545f46a6179Smrg } 546f46a6179Smrg return SetActionField(xkb,elem.str,field.str,ndx,stmt->value,&info->act); 547f46a6179Smrg} 548f46a6179Smrg 549f46a6179Smrgstatic int 550f46a6179SmrgHandleInterpBody(VarDef *def,XkbDescPtr xkb,SymInterpInfo *si,CompatInfo *info) 551f46a6179Smrg{ 552f46a6179Smrgint ok= 1; 553f46a6179SmrgExprResult tmp,field; 554f46a6179SmrgExprDef * arrayNdx; 555f46a6179Smrg 556f46a6179Smrg for (;def!=NULL;def= (VarDef *)def->common.next) { 557f46a6179Smrg if ((def->name)&&(def->name->type==ExprFieldRef)) { 558f46a6179Smrg ok= HandleInterpVar(def,xkb,info); 559f46a6179Smrg continue; 560f46a6179Smrg } 561f46a6179Smrg ok= ExprResolveLhs(def->name,&tmp,&field,&arrayNdx); 562f46a6179Smrg if (ok) 563f46a6179Smrg ok= SetInterpField(si,xkb,field.str,arrayNdx,def->value,info); 564f46a6179Smrg } 565f46a6179Smrg return ok; 566f46a6179Smrg} 567f46a6179Smrg 568f46a6179Smrgstatic int 569f46a6179SmrgHandleInterpDef(InterpDef *def,XkbDescPtr xkb,unsigned merge,CompatInfo *info) 570f46a6179Smrg{ 571f46a6179Smrgunsigned pred,mods; 572f46a6179SmrgSymInterpInfo si; 573f46a6179Smrg 574f46a6179Smrg if (!ResolveStateAndPredicate(def->match,&pred,&mods,info)) { 575f46a6179Smrg ERROR("Couldn't determine matching modifiers\n"); 576f46a6179Smrg ACTION("Symbol interpretation ignored\n"); 577f46a6179Smrg return False; 578f46a6179Smrg } 579f46a6179Smrg if (def->merge!=MergeDefault) 580f46a6179Smrg merge= def->merge; 581f46a6179Smrg 582f46a6179Smrg si= info->dflt; 583f46a6179Smrg si.defs.merge= merge; 584f46a6179Smrg si.interp.sym= def->sym; 585f46a6179Smrg si.interp.match= pred & XkbSI_OpMask; 586f46a6179Smrg si.interp.mods= mods; 587f46a6179Smrg if (!HandleInterpBody(def->def,xkb,&si,info)) { 588f46a6179Smrg info->errorCount++; 589f46a6179Smrg return False; 590f46a6179Smrg } 591f46a6179Smrg 592f46a6179Smrg if (!AddInterp(info,&si)) { 593f46a6179Smrg info->errorCount++; 594f46a6179Smrg return False; 595f46a6179Smrg } 596f46a6179Smrg return True; 597f46a6179Smrg} 598f46a6179Smrg 599f46a6179Smrgstatic int 600f46a6179SmrgHandleGroupCompatDef( GroupCompatDef * def, 601f46a6179Smrg XkbDescPtr xkb, 602f46a6179Smrg unsigned merge, 603f46a6179Smrg CompatInfo * info) 604f46a6179Smrg{ 605f46a6179SmrgExprResult val; 606f46a6179SmrgGroupCompatInfo tmp; 607f46a6179Smrg 608f46a6179Smrg if (def->merge!=MergeDefault) 609f46a6179Smrg merge= def->merge; 610f46a6179Smrg if (!XkbIsLegalGroup(def->group-1)) { 611f46a6179Smrg ERROR1("Keyboard group must be in the range 1..%d\n",XkbNumKbdGroups+1); 612f46a6179Smrg ACTION1("Compatibility map for illegal group %d ignored\n",def->group); 613f46a6179Smrg return False; 614f46a6179Smrg } 615f46a6179Smrg tmp.fileID= info->fileID; 616f46a6179Smrg tmp.merge= merge; 617f46a6179Smrg if (!ExprResolveModMask(def->def,&val,LookupVModMask,(XPointer)xkb)) { 618f46a6179Smrg ERROR("Expected a modifier mask in group compatibility definition\n"); 619f46a6179Smrg ACTION1("Ignoring illegal compatibility map for group %d\n",def->group); 620f46a6179Smrg return False; 621f46a6179Smrg } 622f46a6179Smrg tmp.real_mods= val.uval&0xff; 623f46a6179Smrg tmp.vmods= (val.uval>>8)&0xffff; 624f46a6179Smrg return AddGroupCompat(info,def->group-1,&tmp); 625f46a6179Smrg} 626f46a6179Smrg 627f46a6179Smrgstatic void 628f46a6179SmrgHandleCompatMapFile( XkbFile * file, 629f46a6179Smrg XkbDescPtr xkb, 630f46a6179Smrg unsigned merge, 631f46a6179Smrg CompatInfo * info) 632f46a6179Smrg{ 633f46a6179SmrgParseCommon *stmt; 634f46a6179Smrg 635f46a6179Smrg if (merge==MergeDefault) 636f46a6179Smrg merge= MergeAugment; 637f46a6179Smrg info->name= uStringDup(file->name); 638f46a6179Smrg stmt= file->defs; 639f46a6179Smrg while (stmt) { 640f46a6179Smrg switch (stmt->stmtType) { 641f46a6179Smrg case StmtInclude: 642f46a6179Smrg if (!HandleIncludeCompatMap((IncludeStmt *)stmt,xkb,info, 643f46a6179Smrg HandleCompatMapFile)) 644f46a6179Smrg info->errorCount++; 645f46a6179Smrg break; 646f46a6179Smrg case StmtInterpDef: 647f46a6179Smrg if (!HandleInterpDef((InterpDef *)stmt,xkb,merge,info)) 648f46a6179Smrg info->errorCount++; 649f46a6179Smrg break; 650f46a6179Smrg case StmtGroupCompatDef: 651f46a6179Smrg if (!HandleGroupCompatDef((GroupCompatDef*)stmt,xkb,merge,info)) 652f46a6179Smrg info->errorCount++; 653f46a6179Smrg break; 654f46a6179Smrg case StmtIndicatorMapDef: 655f46a6179Smrg { 656f46a6179Smrg LEDInfo *rtrn; 657f46a6179Smrg rtrn= HandleIndicatorMapDef((IndicatorMapDef *)stmt,xkb, 658f46a6179Smrg &info->ledDflt,info->leds, 659f46a6179Smrg merge); 660f46a6179Smrg if (rtrn!=NULL) 661f46a6179Smrg info->leds= rtrn; 662f46a6179Smrg else info->errorCount++; 663f46a6179Smrg } 664f46a6179Smrg break; 665f46a6179Smrg case StmtVarDef: 666f46a6179Smrg if (!HandleInterpVar((VarDef *)stmt,xkb,info)) 667f46a6179Smrg info->errorCount++; 668f46a6179Smrg break; 669f46a6179Smrg case StmtVModDef: 670f46a6179Smrg if (!HandleVModDef((VModDef *)stmt,merge,&info->vmods)) 671f46a6179Smrg info->errorCount++; 672f46a6179Smrg break; 673f46a6179Smrg case StmtKeycodeDef: 674f46a6179Smrg ERROR("Interpretation files may not include other types\n"); 675f46a6179Smrg ACTION("Ignoring definition of key name\n"); 676f46a6179Smrg info->errorCount++; 677f46a6179Smrg break; 678f46a6179Smrg default: 679f46a6179Smrg WSGO1("Unexpected statement type %d in HandleCompatMapFile\n", 680f46a6179Smrg stmt->stmtType); 681f46a6179Smrg break; 682f46a6179Smrg } 683f46a6179Smrg stmt= stmt->next; 684f46a6179Smrg if (info->errorCount>10) { 685f46a6179Smrg#ifdef NOISY 686f46a6179Smrg ERROR("Too many errors\n"); 687f46a6179Smrg#endif 688f46a6179Smrg ACTION1("Abandoning compatibility map \"%s\"\n",file->topName); 689f46a6179Smrg break; 690f46a6179Smrg } 691f46a6179Smrg } 692f46a6179Smrg return; 693f46a6179Smrg} 694f46a6179Smrg 695f46a6179Smrgstatic void 696f46a6179SmrgCopyInterps( CompatInfo * info, 697f46a6179Smrg XkbCompatMapPtr compat, 698f46a6179Smrg Bool needSymbol, 699f46a6179Smrg unsigned pred) 700f46a6179Smrg{ 701f46a6179SmrgSymInterpInfo * si; 702f46a6179Smrg 703f46a6179Smrg for (si=info->interps;si;si=(SymInterpInfo *)si->defs.next) { 704f46a6179Smrg if (((si->interp.match&XkbSI_OpMask)!=pred)|| 705f46a6179Smrg (needSymbol&&(si->interp.sym==NoSymbol))|| 706f46a6179Smrg ((!needSymbol)&&(si->interp.sym!=NoSymbol))) 707f46a6179Smrg continue; 708f46a6179Smrg if (compat->num_si>=compat->size_si) { 709f46a6179Smrg WSGO("No room to merge symbol interpretations\n"); 710f46a6179Smrg ACTION("Symbol interpretations lost\n"); 711f46a6179Smrg return; 712f46a6179Smrg } 713f46a6179Smrg compat->sym_interpret[compat->num_si++]= si->interp; 714f46a6179Smrg } 715f46a6179Smrg return; 716f46a6179Smrg} 717f46a6179Smrg 718f46a6179SmrgBool 719f46a6179SmrgCompileCompatMap( XkbFile * file, 720f46a6179Smrg XkbFileInfo * result, 721f46a6179Smrg unsigned merge, 722f46a6179Smrg LEDInfo ** unboundLEDs) 723f46a6179Smrg{ 724f46a6179Smrgint i; 725f46a6179SmrgCompatInfo info; 726f46a6179SmrgXkbDescPtr xkb; 727f46a6179SmrgGroupCompatInfo * gcm; 728f46a6179Smrg 729f46a6179Smrg xkb= result->xkb; 730f46a6179Smrg InitCompatInfo(&info,xkb); 731f46a6179Smrg info.dflt.defs.merge= merge; 732f46a6179Smrg info.ledDflt.defs.merge= merge; 733f46a6179Smrg HandleCompatMapFile(file,xkb,merge,&info); 734f46a6179Smrg 735f46a6179Smrg if (info.errorCount==0) { 736f46a6179Smrg int size; 737f46a6179Smrg if (XkbAllocCompatMap(xkb,XkbAllCompatMask,info.nInterps)!=Success) { 738f46a6179Smrg WSGO("Couldn't allocate compatibility map\n"); 739f46a6179Smrg ACTION("Exiting\n"); 740f46a6179Smrg return False; 741f46a6179Smrg } 742f46a6179Smrg if (info.name!=NULL) { 743f46a6179Smrg if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)==Success) 744f46a6179Smrg xkb->names->compat= XkbInternAtom(xkb->dpy,info.name,False); 745f46a6179Smrg else { 746f46a6179Smrg WSGO("Couldn't allocate space for compat name\n"); 747f46a6179Smrg ACTION2("Name \"%s\" (from %s) NOT assigned\n",scanFile, 748f46a6179Smrg info.name); 749f46a6179Smrg } 750f46a6179Smrg } 751f46a6179Smrg size= info.nInterps*sizeof(XkbSymInterpretRec); 752f46a6179Smrg if (size>0) { 753f46a6179Smrg CopyInterps(&info,xkb->compat,True,XkbSI_Exactly); 754f46a6179Smrg CopyInterps(&info,xkb->compat,True,XkbSI_AllOf|XkbSI_NoneOf); 755f46a6179Smrg CopyInterps(&info,xkb->compat,True,XkbSI_AnyOf); 756f46a6179Smrg CopyInterps(&info,xkb->compat,True,XkbSI_AnyOfOrNone); 757f46a6179Smrg CopyInterps(&info,xkb->compat,False,XkbSI_Exactly); 758f46a6179Smrg CopyInterps(&info,xkb->compat,False,XkbSI_AllOf|XkbSI_NoneOf); 759f46a6179Smrg CopyInterps(&info,xkb->compat,False,XkbSI_AnyOf); 760f46a6179Smrg CopyInterps(&info,xkb->compat,False,XkbSI_AnyOfOrNone); 761f46a6179Smrg } 762f46a6179Smrg for (i=0,gcm=&info.groupCompat[0];i<XkbNumKbdGroups;i++,gcm++) { 763f46a6179Smrg if ((gcm->fileID!=0)||(gcm->real_mods!=0)||(gcm->vmods!=0)) { 764f46a6179Smrg xkb->compat->groups[i].mask= gcm->real_mods; 765f46a6179Smrg xkb->compat->groups[i].real_mods= gcm->real_mods; 766f46a6179Smrg xkb->compat->groups[i].vmods= gcm->vmods; 767f46a6179Smrg } 768f46a6179Smrg } 769f46a6179Smrg if (info.leds!=NULL) { 770f46a6179Smrg if (!CopyIndicatorMapDefs(result,info.leds,unboundLEDs)) 771f46a6179Smrg info.errorCount++; 772f46a6179Smrg info.leds= NULL; 773f46a6179Smrg } 774f46a6179Smrg ClearCompatInfo(&info,xkb); 775f46a6179Smrg return True; 776f46a6179Smrg } 777f46a6179Smrg if (info.interps!=NULL) 778f46a6179Smrg uFree(info.interps); 779f46a6179Smrg return False; 780f46a6179Smrg} 781