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