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