compat.c revision a57d84fe
1f46a6179Smrg/************************************************************ 2f46a6179Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3f46a6179Smrg 4f46a6179Smrg Permission to use, copy, modify, and distribute this 5f46a6179Smrg software and its documentation for any purpose and without 6f46a6179Smrg fee is hereby granted, provided that the above copyright 7f46a6179Smrg notice appear in all copies and that both that copyright 8f46a6179Smrg notice and this permission notice appear in supporting 9bfe6082cSmrg documentation, and that the name of Silicon Graphics not be 10bfe6082cSmrg used in advertising or publicity pertaining to distribution 11f46a6179Smrg of the software without specific prior written permission. 12bfe6082cSmrg Silicon Graphics makes no representation about the suitability 13f46a6179Smrg of this software for any purpose. It is provided "as is" 14f46a6179Smrg without any express or implied warranty. 15bfe6082cSmrg 16bfe6082cSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17bfe6082cSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19bfe6082cSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20bfe6082cSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21bfe6082cSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 24f46a6179Smrg 25f46a6179Smrg ********************************************************/ 26f46a6179Smrg 27f46a6179Smrg#include <X11/Xos.h> 28f46a6179Smrg#include "xkbcomp.h" 29f46a6179Smrg#include "tokens.h" 30f46a6179Smrg#include "expr.h" 31f46a6179Smrg#include "vmod.h" 32f46a6179Smrg#include "misc.h" 33f46a6179Smrg#include "indicators.h" 34f46a6179Smrg#include "action.h" 3534345a63Smrg#include "compat.h" 36f46a6179Smrg 3734345a63Smrgtypedef struct _SymInterpInfo 3834345a63Smrg{ 3934345a63Smrg CommonInfo defs; 4034345a63Smrg 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 4934345a63Smrgtypedef struct _GroupCompatInfo 5034345a63Smrg{ 5134345a63Smrg unsigned char fileID; 5234345a63Smrg unsigned char merge; 531d8c7986Smrg Bool defined; 5434345a63Smrg unsigned char real_mods; 5534345a63Smrg unsigned short vmods; 56f46a6179Smrg} GroupCompatInfo; 57f46a6179Smrg 5834345a63Smrgtypedef struct _CompatInfo 5934345a63Smrg{ 6034345a63Smrg char *name; 6134345a63Smrg unsigned fileID; 6234345a63Smrg int errorCount; 6334345a63Smrg int nInterps; 6434345a63Smrg SymInterpInfo *interps; 6534345a63Smrg SymInterpInfo dflt; 6634345a63Smrg LEDInfo ledDflt; 6734345a63Smrg GroupCompatInfo groupCompat[XkbNumKbdGroups]; 6834345a63Smrg LEDInfo *leds; 6934345a63Smrg VModInfo vmods; 7034345a63Smrg ActionInfo *act; 7134345a63Smrg XkbDescPtr xkb; 72f46a6179Smrg} CompatInfo; 73f46a6179Smrg 74f46a6179Smrg/***====================================================================***/ 75f46a6179Smrg 76f46a6179Smrg#define ReportSINotArray(si,f,i) \ 77f46a6179Smrg ReportNotArray("symbol interpretation",(f),siText((si),(i))) 78f46a6179Smrg#define ReportSIBadType(si,f,w,i) \ 79f46a6179Smrg ReportBadType("symbol interpretation",(f),siText((si),(i)),(w)) 80f46a6179Smrg 81f46a6179Smrg/***====================================================================***/ 82f46a6179Smrg 83f46a6179Smrgstatic char * 8434345a63SmrgsiText(SymInterpInfo * si, CompatInfo * info) 85f46a6179Smrg{ 8634345a63Smrg static char buf[128]; 87f46a6179Smrg 8834345a63Smrg if (si == &info->dflt) 8934345a63Smrg { 9034345a63Smrg snprintf(buf, sizeof(buf), "default"); 91f46a6179Smrg } 9234345a63Smrg else 9334345a63Smrg { 94bfe6082cSmrg snprintf(buf, sizeof(buf), "%s+%s(%s)", 9534345a63Smrg XkbKeysymText(si->interp.sym, XkbMessage), 9634345a63Smrg XkbSIMatchText(si->interp.match, XkbMessage), 9734345a63Smrg XkbModMaskText(si->interp.mods, XkbMessage)); 98f46a6179Smrg } 99f46a6179Smrg return buf; 100f46a6179Smrg} 101f46a6179Smrg 102f46a6179Smrgstatic void 10334345a63SmrgInitCompatInfo(CompatInfo * info, XkbDescPtr xkb) 104f46a6179Smrg{ 10534345a63Smrg register int i; 10634345a63Smrg 10734345a63Smrg info->xkb = xkb; 10834345a63Smrg info->name = NULL; 10934345a63Smrg info->fileID = 0; 11034345a63Smrg info->errorCount = 0; 11134345a63Smrg info->nInterps = 0; 11234345a63Smrg info->interps = NULL; 11334345a63Smrg info->act = NULL; 11434345a63Smrg info->dflt.defs.fileID = info->fileID; 11534345a63Smrg info->dflt.defs.defined = 0; 11634345a63Smrg info->dflt.defs.merge = MergeOverride; 11734345a63Smrg info->dflt.interp.flags = 0; 11834345a63Smrg info->dflt.interp.virtual_mod = XkbNoModifier; 11934345a63Smrg info->dflt.interp.act.type = XkbSA_NoAction; 12034345a63Smrg for (i = 0; i < XkbAnyActionDataSize; i++) 12134345a63Smrg { 12234345a63Smrg info->dflt.interp.act.data[i] = 0; 12334345a63Smrg } 12434345a63Smrg ClearIndicatorMapInfo(xkb->dpy, &info->ledDflt); 12534345a63Smrg info->ledDflt.defs.fileID = info->fileID; 12634345a63Smrg info->ledDflt.defs.defined = 0; 12734345a63Smrg info->ledDflt.defs.merge = MergeOverride; 12834345a63Smrg bzero((char *) &info->groupCompat[0], 12934345a63Smrg XkbNumKbdGroups * sizeof(GroupCompatInfo)); 13034345a63Smrg info->leds = NULL; 13134345a63Smrg InitVModInfo(&info->vmods, xkb); 132f46a6179Smrg return; 133f46a6179Smrg} 134f46a6179Smrg 135f46a6179Smrgstatic void 13634345a63SmrgClearCompatInfo(CompatInfo * info, XkbDescPtr xkb) 137f46a6179Smrg{ 13834345a63Smrg register int i; 13934345a63Smrg 14034345a63Smrg if (info->name != NULL) 14134345a63Smrg uFree(info->name); 14234345a63Smrg info->name = NULL; 14334345a63Smrg info->dflt.defs.defined = 0; 14434345a63Smrg info->dflt.defs.merge = MergeAugment; 14534345a63Smrg info->dflt.interp.flags = 0; 14634345a63Smrg info->dflt.interp.virtual_mod = XkbNoModifier; 14734345a63Smrg info->dflt.interp.act.type = XkbSA_NoAction; 14834345a63Smrg for (i = 0; i < XkbAnyActionDataSize; i++) 14934345a63Smrg { 15034345a63Smrg info->dflt.interp.act.data[i] = 0; 15134345a63Smrg } 15234345a63Smrg ClearIndicatorMapInfo(xkb->dpy, &info->ledDflt); 15334345a63Smrg info->nInterps = 0; 15434345a63Smrg info->interps = (SymInterpInfo *) ClearCommonInfo(&info->interps->defs); 15534345a63Smrg bzero((char *) &info->groupCompat[0], 15634345a63Smrg XkbNumKbdGroups * sizeof(GroupCompatInfo)); 15734345a63Smrg info->leds = (LEDInfo *) ClearCommonInfo(&info->leds->defs); 158f46a6179Smrg /* 3/30/94 (ef) -- XXX! Should free action info here */ 15934345a63Smrg ClearVModInfo(&info->vmods, xkb); 160f46a6179Smrg return; 161f46a6179Smrg} 162f46a6179Smrg 163f46a6179Smrgstatic SymInterpInfo * 16434345a63SmrgNextInterp(CompatInfo * info) 165f46a6179Smrg{ 16634345a63Smrg SymInterpInfo *si; 167f46a6179Smrg 16834345a63Smrg si = uTypedAlloc(SymInterpInfo); 16934345a63Smrg if (si) 17034345a63Smrg { 17134345a63Smrg bzero((char *) si, sizeof(SymInterpInfo)); 17234345a63Smrg info->interps = 17334345a63Smrg (SymInterpInfo *) AddCommonInfo(&info->interps->defs, 17434345a63Smrg (CommonInfo *) si); 17534345a63Smrg info->nInterps++; 176f46a6179Smrg } 177f46a6179Smrg return si; 178f46a6179Smrg} 179f46a6179Smrg 180f46a6179Smrgstatic SymInterpInfo * 18134345a63SmrgFindMatchingInterp(CompatInfo * info, SymInterpInfo * new) 182f46a6179Smrg{ 18334345a63Smrg SymInterpInfo *old; 18434345a63Smrg 18534345a63Smrg for (old = info->interps; old != NULL; 18634345a63Smrg old = (SymInterpInfo *) old->defs.next) 18734345a63Smrg { 18834345a63Smrg if ((old->interp.sym == new->interp.sym) && 18934345a63Smrg (old->interp.mods == new->interp.mods) && 19034345a63Smrg (old->interp.match == new->interp.match)) 19134345a63Smrg { 19234345a63Smrg return old; 19334345a63Smrg } 194f46a6179Smrg } 195f46a6179Smrg return NULL; 196f46a6179Smrg} 197f46a6179Smrg 198f46a6179Smrgstatic Bool 19934345a63SmrgAddInterp(CompatInfo * info, SymInterpInfo * new) 200f46a6179Smrg{ 20134345a63Smrg unsigned collide; 20234345a63Smrg SymInterpInfo *old; 20334345a63Smrg 20434345a63Smrg collide = 0; 20534345a63Smrg old = FindMatchingInterp(info, new); 20634345a63Smrg if (old != NULL) 20734345a63Smrg { 20834345a63Smrg if (new->defs.merge == MergeReplace) 20934345a63Smrg { 21034345a63Smrg SymInterpInfo *next = (SymInterpInfo *) old->defs.next; 21134345a63Smrg if (((old->defs.fileID == new->defs.fileID) 21234345a63Smrg && (warningLevel > 0)) || (warningLevel > 9)) 21334345a63Smrg { 214bfe6082cSmrg WARN("Multiple definitions for \"%s\"\n", siText(new, info)); 21534345a63Smrg ACTION("Earlier interpretation ignored\n"); 21634345a63Smrg } 21734345a63Smrg *old = *new; 21834345a63Smrg old->defs.next = &next->defs; 21934345a63Smrg return True; 22034345a63Smrg } 22134345a63Smrg if (UseNewField(_SI_VirtualMod, &old->defs, &new->defs, &collide)) 22234345a63Smrg { 22334345a63Smrg old->interp.virtual_mod = new->interp.virtual_mod; 22434345a63Smrg old->defs.defined |= _SI_VirtualMod; 22534345a63Smrg } 22634345a63Smrg if (UseNewField(_SI_Action, &old->defs, &new->defs, &collide)) 22734345a63Smrg { 22834345a63Smrg old->interp.act = new->interp.act; 22934345a63Smrg old->defs.defined |= _SI_Action; 23034345a63Smrg } 23134345a63Smrg if (UseNewField(_SI_AutoRepeat, &old->defs, &new->defs, &collide)) 23234345a63Smrg { 23334345a63Smrg old->interp.flags &= ~XkbSI_AutoRepeat; 23434345a63Smrg old->interp.flags |= (new->interp.flags & XkbSI_AutoRepeat); 23534345a63Smrg old->defs.defined |= _SI_AutoRepeat; 23634345a63Smrg } 23734345a63Smrg if (UseNewField(_SI_LockingKey, &old->defs, &new->defs, &collide)) 23834345a63Smrg { 23934345a63Smrg old->interp.flags &= ~XkbSI_LockingKey; 24034345a63Smrg old->interp.flags |= (new->interp.flags & XkbSI_LockingKey); 24134345a63Smrg old->defs.defined |= _SI_LockingKey; 24234345a63Smrg } 24334345a63Smrg if (UseNewField(_SI_LevelOneOnly, &old->defs, &new->defs, &collide)) 24434345a63Smrg { 24534345a63Smrg old->interp.match &= ~XkbSI_LevelOneOnly; 24634345a63Smrg old->interp.match |= (new->interp.match & XkbSI_LevelOneOnly); 24734345a63Smrg old->defs.defined |= _SI_LevelOneOnly; 24834345a63Smrg } 249a57d84feSmrg if (collide && (warningLevel > 0)) 25034345a63Smrg { 251bfe6082cSmrg WARN("Multiple interpretations of \"%s\"\n", siText(new, info)); 252bfe6082cSmrg ACTION("Using %s definition for duplicate fields\n", 25334345a63Smrg (new->defs.merge != MergeAugment ? "last" : "first")); 25434345a63Smrg } 25534345a63Smrg return True; 25634345a63Smrg } 25734345a63Smrg old = new; 25834345a63Smrg if ((new = NextInterp(info)) == NULL) 25934345a63Smrg return False; 26034345a63Smrg *new = *old; 26134345a63Smrg new->defs.next = NULL; 262f46a6179Smrg return True; 263f46a6179Smrg} 264f46a6179Smrg 265f46a6179Smrgstatic Bool 26634345a63SmrgAddGroupCompat(CompatInfo * info, unsigned group, GroupCompatInfo * newGC) 267f46a6179Smrg{ 26834345a63Smrg GroupCompatInfo *gc; 26934345a63Smrg unsigned merge; 27034345a63Smrg 27134345a63Smrg merge = newGC->merge; 27234345a63Smrg gc = &info->groupCompat[group]; 27334345a63Smrg if (((gc->real_mods == newGC->real_mods) && (gc->vmods == newGC->vmods))) 27434345a63Smrg { 27534345a63Smrg return True; 27634345a63Smrg } 277c82dfdfbSmrg if (((gc->defined && gc->fileID == newGC->fileID) && (warningLevel > 0)) 27834345a63Smrg || (warningLevel > 9)) 27934345a63Smrg { 280bfe6082cSmrg WARN("Compat map for group %d redefined\n", group + 1); 281bfe6082cSmrg ACTION("Using %s definition\n", 28234345a63Smrg (merge == MergeAugment ? "old" : "new")); 28334345a63Smrg } 2841d8c7986Smrg if(newGC->defined && (merge != MergeAugment || !gc->defined)) 2851d8c7986Smrg *gc = *newGC; 286f46a6179Smrg return True; 287f46a6179Smrg} 288f46a6179Smrg 289f46a6179Smrg/***====================================================================***/ 290f46a6179Smrg 291f46a6179Smrgstatic Bool 29234345a63SmrgResolveStateAndPredicate(ExprDef * expr, 29334345a63Smrg unsigned *pred_rtrn, 29434345a63Smrg unsigned *mods_rtrn, CompatInfo * info) 295f46a6179Smrg{ 29634345a63Smrg ExprResult result; 29734345a63Smrg 29834345a63Smrg if (expr == NULL) 29934345a63Smrg { 30034345a63Smrg *pred_rtrn = XkbSI_AnyOfOrNone; 30134345a63Smrg *mods_rtrn = ~0; 30234345a63Smrg return True; 30334345a63Smrg } 30434345a63Smrg 30534345a63Smrg *pred_rtrn = XkbSI_Exactly; 30634345a63Smrg if (expr->op == ExprActionDecl) 30734345a63Smrg { 30834345a63Smrg char *pred_txt = 30934345a63Smrg XkbAtomText(NULL, expr->value.action.name, XkbMessage); 31034345a63Smrg if (uStrCaseCmp(pred_txt, "noneof") == 0) 31134345a63Smrg *pred_rtrn = XkbSI_NoneOf; 31234345a63Smrg else if (uStrCaseCmp(pred_txt, "anyofornone") == 0) 31334345a63Smrg *pred_rtrn = XkbSI_AnyOfOrNone; 31434345a63Smrg else if (uStrCaseCmp(pred_txt, "anyof") == 0) 31534345a63Smrg *pred_rtrn = XkbSI_AnyOf; 31634345a63Smrg else if (uStrCaseCmp(pred_txt, "allof") == 0) 31734345a63Smrg *pred_rtrn = XkbSI_AllOf; 31834345a63Smrg else if (uStrCaseCmp(pred_txt, "exactly") == 0) 31934345a63Smrg *pred_rtrn = XkbSI_Exactly; 32034345a63Smrg else 32134345a63Smrg { 322bfe6082cSmrg ERROR("Illegal modifier predicate \"%s\"\n", pred_txt); 32334345a63Smrg ACTION("Ignored\n"); 32434345a63Smrg return False; 32534345a63Smrg } 32634345a63Smrg expr = expr->value.action.args; 32734345a63Smrg } 32834345a63Smrg else if (expr->op == ExprIdent) 32934345a63Smrg { 33034345a63Smrg char *pred_txt = XkbAtomText(NULL, expr->value.str, XkbMessage); 33134345a63Smrg if ((pred_txt) && (uStrCaseCmp(pred_txt, "any") == 0)) 33234345a63Smrg { 33334345a63Smrg *pred_rtrn = XkbSI_AnyOf; 33434345a63Smrg *mods_rtrn = 0xff; 33534345a63Smrg return True; 33634345a63Smrg } 33734345a63Smrg } 33834345a63Smrg 33934345a63Smrg if (ExprResolveModMask(expr, &result, NULL, NULL)) 34034345a63Smrg { 34134345a63Smrg *mods_rtrn = result.uval; 34234345a63Smrg return True; 343f46a6179Smrg } 344f46a6179Smrg return False; 345f46a6179Smrg} 346f46a6179Smrg 347f46a6179Smrg/***====================================================================***/ 348f46a6179Smrg 349f46a6179Smrgstatic void 35034345a63SmrgMergeIncludedCompatMaps(CompatInfo * into, CompatInfo * from, unsigned merge) 351f46a6179Smrg{ 35234345a63Smrg SymInterpInfo *si; 35334345a63Smrg LEDInfo *led, *rtrn, *next; 35434345a63Smrg GroupCompatInfo *gcm; 35534345a63Smrg register int i; 35634345a63Smrg 35734345a63Smrg if (from->errorCount > 0) 35834345a63Smrg { 35934345a63Smrg into->errorCount += from->errorCount; 36034345a63Smrg return; 36134345a63Smrg } 36234345a63Smrg if (into->name == NULL) 36334345a63Smrg { 36434345a63Smrg into->name = from->name; 36534345a63Smrg from->name = NULL; 36634345a63Smrg } 36734345a63Smrg for (si = from->interps; si; si = (SymInterpInfo *) si->defs.next) 36834345a63Smrg { 36934345a63Smrg if (merge != MergeDefault) 37034345a63Smrg si->defs.merge = merge; 37134345a63Smrg if (!AddInterp(into, si)) 37234345a63Smrg into->errorCount++; 37334345a63Smrg } 37434345a63Smrg for (i = 0, gcm = &from->groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++) 37534345a63Smrg { 37634345a63Smrg if (merge != MergeDefault) 37734345a63Smrg gcm->merge = merge; 37834345a63Smrg if (!AddGroupCompat(into, i, gcm)) 37934345a63Smrg into->errorCount++; 38034345a63Smrg } 38134345a63Smrg for (led = from->leds; led != NULL; led = next) 38234345a63Smrg { 38334345a63Smrg next = (LEDInfo *) led->defs.next; 38434345a63Smrg if (merge != MergeDefault) 38534345a63Smrg led->defs.merge = merge; 38634345a63Smrg rtrn = AddIndicatorMap(into->leds, led); 38734345a63Smrg if (rtrn != NULL) 38834345a63Smrg into->leds = rtrn; 38934345a63Smrg else 39034345a63Smrg into->errorCount++; 391f46a6179Smrg } 392f46a6179Smrg return; 393f46a6179Smrg} 394f46a6179Smrg 39534345a63Smrgtypedef void (*FileHandler) (XkbFile * /* rtrn */ , 39634345a63Smrg XkbDescPtr /* xkb */ , 39734345a63Smrg unsigned /* merge */ , 39834345a63Smrg CompatInfo * /* info */ 39934345a63Smrg ); 400f46a6179Smrg 401f46a6179Smrgstatic Bool 40234345a63SmrgHandleIncludeCompatMap(IncludeStmt * stmt, 40334345a63Smrg XkbDescPtr xkb, CompatInfo * info, FileHandler hndlr) 404f46a6179Smrg{ 40534345a63Smrg unsigned newMerge; 40634345a63Smrg XkbFile *rtrn; 40734345a63Smrg CompatInfo included; 40834345a63Smrg Bool haveSelf; 40934345a63Smrg 41034345a63Smrg haveSelf = False; 41134345a63Smrg if ((stmt->file == NULL) && (stmt->map == NULL)) 41234345a63Smrg { 41334345a63Smrg haveSelf = True; 41434345a63Smrg included = *info; 41534345a63Smrg bzero(info, sizeof(CompatInfo)); 41634345a63Smrg } 41734345a63Smrg else if (ProcessIncludeFile(stmt, XkmCompatMapIndex, &rtrn, &newMerge)) 41834345a63Smrg { 41934345a63Smrg InitCompatInfo(&included, xkb); 42034345a63Smrg included.fileID = rtrn->id; 42134345a63Smrg included.dflt = info->dflt; 42234345a63Smrg included.dflt.defs.fileID = rtrn->id; 42334345a63Smrg included.dflt.defs.merge = newMerge; 42434345a63Smrg included.ledDflt.defs.fileID = rtrn->id; 42534345a63Smrg included.ledDflt.defs.merge = newMerge; 42634345a63Smrg included.act = info->act; 42734345a63Smrg (*hndlr) (rtrn, xkb, MergeOverride, &included); 42834345a63Smrg if (stmt->stmt != NULL) 42934345a63Smrg { 43034345a63Smrg if (included.name != NULL) 43134345a63Smrg uFree(included.name); 43234345a63Smrg included.name = stmt->stmt; 43334345a63Smrg stmt->stmt = NULL; 43434345a63Smrg } 43534345a63Smrg } 43634345a63Smrg else 43734345a63Smrg { 43834345a63Smrg info->errorCount += 10; 43934345a63Smrg return False; 44034345a63Smrg } 44134345a63Smrg if ((stmt->next != NULL) && (included.errorCount < 1)) 44234345a63Smrg { 44334345a63Smrg IncludeStmt *next; 44434345a63Smrg unsigned op; 44534345a63Smrg CompatInfo next_incl; 44634345a63Smrg 44734345a63Smrg for (next = stmt->next; next != NULL; next = next->next) 44834345a63Smrg { 44934345a63Smrg if ((next->file == NULL) && (next->map == NULL)) 45034345a63Smrg { 45134345a63Smrg haveSelf = True; 45234345a63Smrg MergeIncludedCompatMaps(&included, info, next->merge); 45334345a63Smrg ClearCompatInfo(info, xkb); 45434345a63Smrg } 45534345a63Smrg else if (ProcessIncludeFile(next, XkmCompatMapIndex, &rtrn, &op)) 45634345a63Smrg { 45734345a63Smrg InitCompatInfo(&next_incl, xkb); 45834345a63Smrg next_incl.fileID = rtrn->id; 45934345a63Smrg next_incl.dflt = info->dflt; 46034345a63Smrg next_incl.dflt.defs.fileID = rtrn->id; 46134345a63Smrg next_incl.dflt.defs.merge = op; 46234345a63Smrg next_incl.ledDflt.defs.fileID = rtrn->id; 46334345a63Smrg next_incl.ledDflt.defs.merge = op; 46434345a63Smrg next_incl.act = info->act; 46534345a63Smrg (*hndlr) (rtrn, xkb, MergeOverride, &next_incl); 46634345a63Smrg MergeIncludedCompatMaps(&included, &next_incl, op); 46734345a63Smrg ClearCompatInfo(&next_incl, xkb); 46834345a63Smrg } 46934345a63Smrg else 47034345a63Smrg { 47134345a63Smrg info->errorCount += 10; 47234345a63Smrg return False; 47334345a63Smrg } 47434345a63Smrg } 475f46a6179Smrg } 476f46a6179Smrg if (haveSelf) 47734345a63Smrg *info = included; 47834345a63Smrg else 47934345a63Smrg { 48034345a63Smrg MergeIncludedCompatMaps(info, &included, newMerge); 48134345a63Smrg ClearCompatInfo(&included, xkb); 482f46a6179Smrg } 48334345a63Smrg return (info->errorCount == 0); 484f46a6179Smrg} 485f46a6179Smrg 486f46a6179Smrgstatic LookupEntry useModMapValues[] = { 48734345a63Smrg {"levelone", 1}, 48834345a63Smrg {"level1", 1}, 48934345a63Smrg {"anylevel", 0}, 49034345a63Smrg {"any", 0}, 49134345a63Smrg {NULL, 0} 492f46a6179Smrg}; 493f46a6179Smrg 494f46a6179Smrgstatic int 49534345a63SmrgSetInterpField(SymInterpInfo * si, 49634345a63Smrg XkbDescPtr xkb, 497c82dfdfbSmrg const char *field, 49834345a63Smrg ExprDef * arrayNdx, ExprDef * value, CompatInfo * info) 499f46a6179Smrg{ 50034345a63Smrg int ok = 1; 50134345a63Smrg ExprResult tmp; 50234345a63Smrg 50334345a63Smrg if (uStrCaseCmp(field, "action") == 0) 50434345a63Smrg { 50534345a63Smrg if (arrayNdx != NULL) 50634345a63Smrg return ReportSINotArray(si, field, info); 50734345a63Smrg ok = HandleActionDef(value, xkb, &si->interp.act, si->defs.merge, 50834345a63Smrg info->act); 50934345a63Smrg if (ok) 51034345a63Smrg si->defs.defined |= _SI_Action; 51134345a63Smrg } 51234345a63Smrg else if ((uStrCaseCmp(field, "virtualmodifier") == 0) || 51334345a63Smrg (uStrCaseCmp(field, "virtualmod") == 0)) 51434345a63Smrg { 51534345a63Smrg if (arrayNdx != NULL) 51634345a63Smrg return ReportSINotArray(si, field, info); 51734345a63Smrg ok = ResolveVirtualModifier(value, &tmp, &info->vmods); 51834345a63Smrg if (ok) 51934345a63Smrg { 52034345a63Smrg si->interp.virtual_mod = tmp.uval; 52134345a63Smrg si->defs.defined |= _SI_VirtualMod; 52234345a63Smrg } 52334345a63Smrg else 52434345a63Smrg return ReportSIBadType(si, field, "virtual modifier", info); 52534345a63Smrg } 52634345a63Smrg else if (uStrCaseCmp(field, "repeat") == 0) 52734345a63Smrg { 52834345a63Smrg if (arrayNdx != NULL) 52934345a63Smrg return ReportSINotArray(si, field, info); 53034345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 53134345a63Smrg if (ok) 53234345a63Smrg { 53334345a63Smrg if (tmp.uval) 53434345a63Smrg si->interp.flags |= XkbSI_AutoRepeat; 53534345a63Smrg else 53634345a63Smrg si->interp.flags &= ~XkbSI_AutoRepeat; 53734345a63Smrg si->defs.defined |= _SI_AutoRepeat; 53834345a63Smrg } 53934345a63Smrg else 54034345a63Smrg return ReportSIBadType(si, field, "boolean", info); 54134345a63Smrg } 54234345a63Smrg else if (uStrCaseCmp(field, "locking") == 0) 54334345a63Smrg { 54434345a63Smrg if (arrayNdx != NULL) 54534345a63Smrg return ReportSINotArray(si, field, info); 54634345a63Smrg ok = ExprResolveBoolean(value, &tmp, NULL, NULL); 54734345a63Smrg if (ok) 54834345a63Smrg { 54934345a63Smrg if (tmp.uval) 55034345a63Smrg si->interp.flags |= XkbSI_LockingKey; 55134345a63Smrg else 55234345a63Smrg si->interp.flags &= ~XkbSI_LockingKey; 55334345a63Smrg si->defs.defined |= _SI_LockingKey; 55434345a63Smrg } 55534345a63Smrg else 55634345a63Smrg return ReportSIBadType(si, field, "boolean", info); 55734345a63Smrg } 55834345a63Smrg else if ((uStrCaseCmp(field, "usemodmap") == 0) || 55934345a63Smrg (uStrCaseCmp(field, "usemodmapmods") == 0)) 56034345a63Smrg { 56134345a63Smrg if (arrayNdx != NULL) 56234345a63Smrg return ReportSINotArray(si, field, info); 56334345a63Smrg ok = ExprResolveEnum(value, &tmp, useModMapValues); 56434345a63Smrg if (ok) 56534345a63Smrg { 56634345a63Smrg if (tmp.uval) 56734345a63Smrg si->interp.match |= XkbSI_LevelOneOnly; 56834345a63Smrg else 56934345a63Smrg si->interp.match &= ~XkbSI_LevelOneOnly; 57034345a63Smrg si->defs.defined |= _SI_LevelOneOnly; 57134345a63Smrg } 57234345a63Smrg else 57334345a63Smrg return ReportSIBadType(si, field, "level specification", info); 57434345a63Smrg } 57534345a63Smrg else 57634345a63Smrg { 57734345a63Smrg ok = ReportBadField("symbol interpretation", field, siText(si, info)); 578f46a6179Smrg } 579f46a6179Smrg return ok; 580f46a6179Smrg} 581f46a6179Smrg 58234345a63SmrgLookupEntry groupNames[] = { 58334345a63Smrg {"group1", 0x01} 58434345a63Smrg , 58534345a63Smrg {"group2", 0x02} 58634345a63Smrg , 58734345a63Smrg {"group3", 0x04} 58834345a63Smrg , 58934345a63Smrg {"group4", 0x08} 59034345a63Smrg , 59134345a63Smrg {"group5", 0x10} 59234345a63Smrg , 59334345a63Smrg {"group6", 0x20} 59434345a63Smrg , 59534345a63Smrg {"group7", 0x40} 59634345a63Smrg , 59734345a63Smrg {"group8", 0x80} 59834345a63Smrg , 59934345a63Smrg {"none", 0x00} 60034345a63Smrg , 60134345a63Smrg {"all", 0xff} 60234345a63Smrg , 60334345a63Smrg {NULL, 0} 604f46a6179Smrg}; 605f46a6179Smrg 606f46a6179Smrgstatic int 60734345a63SmrgHandleInterpVar(VarDef * stmt, XkbDescPtr xkb, CompatInfo * info) 608f46a6179Smrg{ 60934345a63Smrg ExprResult elem, field; 61034345a63Smrg ExprDef *ndx; 61134345a63Smrg 61234345a63Smrg if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0) 61334345a63Smrg return 0; /* internal error, already reported */ 61434345a63Smrg if (elem.str && (uStrCaseCmp(elem.str, "interpret") == 0)) 61534345a63Smrg return SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value, 61634345a63Smrg info); 61734345a63Smrg if (elem.str && (uStrCaseCmp(elem.str, "indicator") == 0)) 61834345a63Smrg { 61934345a63Smrg return SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx, 62034345a63Smrg stmt->value); 62134345a63Smrg } 62234345a63Smrg return SetActionField(xkb, elem.str, field.str, ndx, stmt->value, 62334345a63Smrg &info->act); 624f46a6179Smrg} 625f46a6179Smrg 626f46a6179Smrgstatic int 62734345a63SmrgHandleInterpBody(VarDef * def, XkbDescPtr xkb, SymInterpInfo * si, 62834345a63Smrg CompatInfo * info) 629f46a6179Smrg{ 63034345a63Smrg int ok = 1; 63134345a63Smrg ExprResult tmp, field; 63234345a63Smrg ExprDef *arrayNdx; 63334345a63Smrg 63434345a63Smrg for (; def != NULL; def = (VarDef *) def->common.next) 63534345a63Smrg { 63634345a63Smrg if ((def->name) && (def->name->type == ExprFieldRef)) 63734345a63Smrg { 63834345a63Smrg ok = HandleInterpVar(def, xkb, info); 63934345a63Smrg continue; 64034345a63Smrg } 64134345a63Smrg ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx); 64234345a63Smrg if (ok) 64334345a63Smrg ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value, 64434345a63Smrg info); 645f46a6179Smrg } 646f46a6179Smrg return ok; 647f46a6179Smrg} 648f46a6179Smrg 649f46a6179Smrgstatic int 65034345a63SmrgHandleInterpDef(InterpDef * def, XkbDescPtr xkb, unsigned merge, 65134345a63Smrg CompatInfo * info) 652f46a6179Smrg{ 65334345a63Smrg unsigned pred, mods; 65434345a63Smrg SymInterpInfo si; 65534345a63Smrg 65634345a63Smrg if (!ResolveStateAndPredicate(def->match, &pred, &mods, info)) 65734345a63Smrg { 65834345a63Smrg ERROR("Couldn't determine matching modifiers\n"); 65934345a63Smrg ACTION("Symbol interpretation ignored\n"); 660690143ccSmrg return True; 66134345a63Smrg } 662690143ccSmrg if (def->ignore) 663690143ccSmrg { 664690143ccSmrg ERROR("Couldn't lookup keysym\n"); 665690143ccSmrg ACTION("Symbol interpretation ignored\n"); 666690143ccSmrg return True; 667690143ccSmrg } 668690143ccSmrg 66934345a63Smrg if (def->merge != MergeDefault) 67034345a63Smrg merge = def->merge; 67134345a63Smrg 67234345a63Smrg si = info->dflt; 67334345a63Smrg si.defs.merge = merge; 67434345a63Smrg si.interp.sym = def->sym; 67534345a63Smrg si.interp.match = pred & XkbSI_OpMask; 67634345a63Smrg si.interp.mods = mods; 67734345a63Smrg if (!HandleInterpBody(def->def, xkb, &si, info)) 67834345a63Smrg { 67934345a63Smrg info->errorCount++; 68034345a63Smrg return False; 68134345a63Smrg } 68234345a63Smrg 68334345a63Smrg if (!AddInterp(info, &si)) 68434345a63Smrg { 68534345a63Smrg info->errorCount++; 68634345a63Smrg return False; 687f46a6179Smrg } 688f46a6179Smrg return True; 689f46a6179Smrg} 690f46a6179Smrg 691f46a6179Smrgstatic int 69234345a63SmrgHandleGroupCompatDef(GroupCompatDef * def, 69334345a63Smrg XkbDescPtr xkb, unsigned merge, CompatInfo * info) 694f46a6179Smrg{ 69534345a63Smrg ExprResult val; 69634345a63Smrg GroupCompatInfo tmp; 69734345a63Smrg 69834345a63Smrg if (def->merge != MergeDefault) 69934345a63Smrg merge = def->merge; 70034345a63Smrg if (!XkbIsLegalGroup(def->group - 1)) 70134345a63Smrg { 702bfe6082cSmrg ERROR("Keyboard group must be in the range 1..%d\n", 70334345a63Smrg XkbNumKbdGroups + 1); 704bfe6082cSmrg ACTION("Compatibility map for illegal group %d ignored\n", 70534345a63Smrg def->group); 70634345a63Smrg return False; 70734345a63Smrg } 70834345a63Smrg tmp.fileID = info->fileID; 70934345a63Smrg tmp.merge = merge; 71034345a63Smrg if (!ExprResolveModMask(def->def, &val, LookupVModMask, (XPointer) xkb)) 71134345a63Smrg { 71234345a63Smrg ERROR("Expected a modifier mask in group compatibility definition\n"); 713bfe6082cSmrg ACTION("Ignoring illegal compatibility map for group %d\n", 71434345a63Smrg def->group); 71534345a63Smrg return False; 71634345a63Smrg } 71734345a63Smrg tmp.real_mods = val.uval & 0xff; 71834345a63Smrg tmp.vmods = (val.uval >> 8) & 0xffff; 7191d8c7986Smrg tmp.defined = True; 72034345a63Smrg return AddGroupCompat(info, def->group - 1, &tmp); 721f46a6179Smrg} 722f46a6179Smrg 723f46a6179Smrgstatic void 72434345a63SmrgHandleCompatMapFile(XkbFile * file, 72534345a63Smrg XkbDescPtr xkb, unsigned merge, CompatInfo * info) 726f46a6179Smrg{ 72734345a63Smrg ParseCommon *stmt; 72834345a63Smrg 72934345a63Smrg if (merge == MergeDefault) 73034345a63Smrg merge = MergeAugment; 73134345a63Smrg info->name = uStringDup(file->name); 73234345a63Smrg stmt = file->defs; 73334345a63Smrg while (stmt) 73434345a63Smrg { 73534345a63Smrg switch (stmt->stmtType) 73634345a63Smrg { 73734345a63Smrg case StmtInclude: 73834345a63Smrg if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info, 73934345a63Smrg HandleCompatMapFile)) 74034345a63Smrg info->errorCount++; 74134345a63Smrg break; 74234345a63Smrg case StmtInterpDef: 74334345a63Smrg if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info)) 74434345a63Smrg info->errorCount++; 74534345a63Smrg break; 74634345a63Smrg case StmtGroupCompatDef: 74734345a63Smrg if (!HandleGroupCompatDef 74834345a63Smrg ((GroupCompatDef *) stmt, xkb, merge, info)) 74934345a63Smrg info->errorCount++; 75034345a63Smrg break; 75134345a63Smrg case StmtIndicatorMapDef: 75234345a63Smrg { 75334345a63Smrg LEDInfo *rtrn; 75434345a63Smrg rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb, 75534345a63Smrg &info->ledDflt, info->leds, merge); 75634345a63Smrg if (rtrn != NULL) 75734345a63Smrg info->leds = rtrn; 75834345a63Smrg else 75934345a63Smrg info->errorCount++; 76034345a63Smrg } 76134345a63Smrg break; 76234345a63Smrg case StmtVarDef: 76334345a63Smrg if (!HandleInterpVar((VarDef *) stmt, xkb, info)) 76434345a63Smrg info->errorCount++; 76534345a63Smrg break; 76634345a63Smrg case StmtVModDef: 76734345a63Smrg if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods)) 76834345a63Smrg info->errorCount++; 76934345a63Smrg break; 77034345a63Smrg case StmtKeycodeDef: 77134345a63Smrg ERROR("Interpretation files may not include other types\n"); 77234345a63Smrg ACTION("Ignoring definition of key name\n"); 77334345a63Smrg info->errorCount++; 77434345a63Smrg break; 77534345a63Smrg default: 776bfe6082cSmrg WSGO("Unexpected statement type %d in HandleCompatMapFile\n", 77734345a63Smrg stmt->stmtType); 77834345a63Smrg break; 77934345a63Smrg } 78034345a63Smrg stmt = stmt->next; 78134345a63Smrg if (info->errorCount > 10) 78234345a63Smrg { 783f46a6179Smrg#ifdef NOISY 78434345a63Smrg ERROR("Too many errors\n"); 785f46a6179Smrg#endif 786bfe6082cSmrg ACTION("Abandoning compatibility map \"%s\"\n", file->topName); 78734345a63Smrg break; 78834345a63Smrg } 789f46a6179Smrg } 790f46a6179Smrg return; 791f46a6179Smrg} 792f46a6179Smrg 793f46a6179Smrgstatic void 79434345a63SmrgCopyInterps(CompatInfo * info, 79534345a63Smrg XkbCompatMapPtr compat, Bool needSymbol, unsigned pred) 796f46a6179Smrg{ 79734345a63Smrg SymInterpInfo *si; 79834345a63Smrg 79934345a63Smrg for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next) 80034345a63Smrg { 80134345a63Smrg if (((si->interp.match & XkbSI_OpMask) != pred) || 80234345a63Smrg (needSymbol && (si->interp.sym == NoSymbol)) || 80334345a63Smrg ((!needSymbol) && (si->interp.sym != NoSymbol))) 80434345a63Smrg continue; 80534345a63Smrg if (compat->num_si >= compat->size_si) 80634345a63Smrg { 80734345a63Smrg WSGO("No room to merge symbol interpretations\n"); 80834345a63Smrg ACTION("Symbol interpretations lost\n"); 80934345a63Smrg return; 81034345a63Smrg } 81134345a63Smrg compat->sym_interpret[compat->num_si++] = si->interp; 812f46a6179Smrg } 813f46a6179Smrg return; 814f46a6179Smrg} 815f46a6179Smrg 816f46a6179SmrgBool 81734345a63SmrgCompileCompatMap(XkbFile * file, 81834345a63Smrg XkbFileInfo * result, unsigned merge, LEDInfo ** unboundLEDs) 819f46a6179Smrg{ 82034345a63Smrg int i; 82134345a63Smrg CompatInfo info; 82234345a63Smrg XkbDescPtr xkb; 82334345a63Smrg GroupCompatInfo *gcm; 82434345a63Smrg 82534345a63Smrg xkb = result->xkb; 82634345a63Smrg InitCompatInfo(&info, xkb); 82734345a63Smrg info.dflt.defs.merge = merge; 82834345a63Smrg info.ledDflt.defs.merge = merge; 82934345a63Smrg HandleCompatMapFile(file, xkb, merge, &info); 83034345a63Smrg 83134345a63Smrg if (info.errorCount == 0) 83234345a63Smrg { 83334345a63Smrg int size; 83434345a63Smrg if (XkbAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) != 83534345a63Smrg Success) 83634345a63Smrg { 83734345a63Smrg WSGO("Couldn't allocate compatibility map\n"); 83834345a63Smrg ACTION("Exiting\n"); 83934345a63Smrg return False; 84034345a63Smrg } 84134345a63Smrg if (info.name != NULL) 84234345a63Smrg { 84334345a63Smrg if (XkbAllocNames(xkb, XkbCompatNameMask, 0, 0) == Success) 84434345a63Smrg xkb->names->compat = 84534345a63Smrg XkbInternAtom(xkb->dpy, info.name, False); 84634345a63Smrg else 84734345a63Smrg { 84834345a63Smrg WSGO("Couldn't allocate space for compat name\n"); 849bfe6082cSmrg ACTION("Name \"%s\" (from %s) NOT assigned\n", 85034345a63Smrg scanFile, info.name); 85134345a63Smrg } 85234345a63Smrg } 85334345a63Smrg size = info.nInterps * sizeof(XkbSymInterpretRec); 85434345a63Smrg if (size > 0) 85534345a63Smrg { 85634345a63Smrg CopyInterps(&info, xkb->compat, True, XkbSI_Exactly); 85734345a63Smrg CopyInterps(&info, xkb->compat, True, XkbSI_AllOf | XkbSI_NoneOf); 85834345a63Smrg CopyInterps(&info, xkb->compat, True, XkbSI_AnyOf); 85934345a63Smrg CopyInterps(&info, xkb->compat, True, XkbSI_AnyOfOrNone); 86034345a63Smrg CopyInterps(&info, xkb->compat, False, XkbSI_Exactly); 86134345a63Smrg CopyInterps(&info, xkb->compat, False, 86234345a63Smrg XkbSI_AllOf | XkbSI_NoneOf); 86334345a63Smrg CopyInterps(&info, xkb->compat, False, XkbSI_AnyOf); 86434345a63Smrg CopyInterps(&info, xkb->compat, False, XkbSI_AnyOfOrNone); 86534345a63Smrg } 86634345a63Smrg for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups; 86734345a63Smrg i++, gcm++) 86834345a63Smrg { 86934345a63Smrg if ((gcm->fileID != 0) || (gcm->real_mods != 0) 87034345a63Smrg || (gcm->vmods != 0)) 87134345a63Smrg { 87234345a63Smrg xkb->compat->groups[i].mask = gcm->real_mods; 87334345a63Smrg xkb->compat->groups[i].real_mods = gcm->real_mods; 87434345a63Smrg xkb->compat->groups[i].vmods = gcm->vmods; 87534345a63Smrg } 87634345a63Smrg } 87734345a63Smrg if (info.leds != NULL) 87834345a63Smrg { 87934345a63Smrg if (!CopyIndicatorMapDefs(result, info.leds, unboundLEDs)) 88034345a63Smrg info.errorCount++; 88134345a63Smrg info.leds = NULL; 88234345a63Smrg } 88334345a63Smrg ClearCompatInfo(&info, xkb); 88434345a63Smrg return True; 88534345a63Smrg } 88634345a63Smrg if (info.interps != NULL) 88734345a63Smrg uFree(info.interps); 888f46a6179Smrg return False; 889f46a6179Smrg} 890