18d16151648ddcc722a4479edd4d9c1d397a05c7
[platform/upstream/libxkbcommon.git] / src / xkbcomp / compat.c
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 "xkbcomp.h"
28 #include "xkballoc.h"
29 #include "xkbmisc.h"
30 #include "expr.h"
31 #include "vmod.h"
32 #include "misc.h"
33 #include "indicators.h"
34 #include "action.h"
35 #include "parseutils.h"
36
37 typedef struct _SymInterpInfo
38 {
39     CommonInfo defs;
40     struct xkb_sym_interpret 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
49 typedef struct _GroupCompatInfo
50 {
51     unsigned char fileID;
52     unsigned char merge;
53     bool defined;
54     unsigned char real_mods;
55     xkb_atom_t vmods;
56 } GroupCompatInfo;
57
58 typedef struct _CompatInfo
59 {
60     char *name;
61     unsigned fileID;
62     int errorCount;
63     int nInterps;
64     SymInterpInfo *interps;
65     SymInterpInfo dflt;
66     LEDInfo ledDflt;
67     GroupCompatInfo groupCompat[XkbNumKbdGroups];
68     LEDInfo *leds;
69     VModInfo vmods;
70     ActionInfo *act;
71     struct xkb_keymap * xkb;
72 } CompatInfo;
73
74 /***====================================================================***/
75
76 #define ReportSINotArray(si,f,i) \
77         ReportNotArray("symbol interpretation",(f),siText((si),(i)))
78 #define ReportSIBadType(si,f,w,i) \
79         ReportBadType("symbol interpretation",(f),siText((si),(i)),(w))
80
81 /***====================================================================***/
82
83 static const char *
84 siText(SymInterpInfo * si, CompatInfo * info)
85 {
86     static char buf[128];
87
88     if (si == &info->dflt)
89     {
90         snprintf(buf, sizeof(buf), "default");
91     }
92     else
93     {
94         snprintf(buf, sizeof(buf), "%s+%s(%s)",
95                 XkbcKeysymText(si->interp.sym),
96                 XkbcSIMatchText(si->interp.match),
97                 XkbcModMaskText(si->interp.mods, false));
98     }
99     return buf;
100 }
101
102 static void
103 InitCompatInfo(CompatInfo * info, struct xkb_keymap * xkb)
104 {
105     unsigned int i;
106
107     info->xkb = xkb;
108     info->name = NULL;
109     info->fileID = 0;
110     info->errorCount = 0;
111     info->nInterps = 0;
112     info->interps = NULL;
113     info->act = NULL;
114     info->dflt.defs.fileID = info->fileID;
115     info->dflt.defs.defined = 0;
116     info->dflt.defs.merge = MergeOverride;
117     info->dflt.interp.flags = 0;
118     info->dflt.interp.virtual_mod = XkbNoModifier;
119     info->dflt.interp.act.type = XkbSA_NoAction;
120     for (i = 0; i < sizeof(info->dflt.interp.act.any.data); i++)
121         info->dflt.interp.act.any.data[i] = 0;
122     ClearIndicatorMapInfo(&info->ledDflt);
123     info->ledDflt.defs.fileID = info->fileID;
124     info->ledDflt.defs.defined = 0;
125     info->ledDflt.defs.merge = MergeOverride;
126     memset(&info->groupCompat[0], 0,
127            XkbNumKbdGroups * sizeof(GroupCompatInfo));
128     info->leds = NULL;
129     InitVModInfo(&info->vmods, xkb);
130 }
131
132 static void
133 ClearCompatInfo(CompatInfo * info, struct xkb_keymap * xkb)
134 {
135     unsigned int i;
136     ActionInfo *next;
137
138     free(info->name);
139     info->name = NULL;
140     info->dflt.defs.defined = 0;
141     info->dflt.defs.merge = MergeAugment;
142     info->dflt.interp.flags = 0;
143     info->dflt.interp.virtual_mod = XkbNoModifier;
144     info->dflt.interp.act.type = XkbSA_NoAction;
145     for (i = 0; i < sizeof(info->dflt.interp.act.any.data); i++)
146         info->dflt.interp.act.any.data[i] = 0;
147     ClearIndicatorMapInfo(&info->ledDflt);
148     info->nInterps = 0;
149     info->interps = (SymInterpInfo *) ClearCommonInfo(&info->interps->defs);
150     memset(&info->groupCompat[0], 0,
151            XkbNumKbdGroups * sizeof(GroupCompatInfo));
152     info->leds = (LEDInfo *) ClearCommonInfo(&info->leds->defs);
153     while (info->act) {
154             next = info->act->next;
155             free(info->act);
156             info->act = next;
157     }
158     ClearVModInfo(&info->vmods, xkb);
159 }
160
161 static SymInterpInfo *
162 NextInterp(CompatInfo * info)
163 {
164     SymInterpInfo *si;
165
166     si = uTypedAlloc(SymInterpInfo);
167     if (si)
168     {
169         memset(si, 0, sizeof(SymInterpInfo));
170         info->interps =
171             (SymInterpInfo *) AddCommonInfo(&info->interps->defs,
172                                             (CommonInfo *) si);
173         info->nInterps++;
174     }
175     return si;
176 }
177
178 static SymInterpInfo *
179 FindMatchingInterp(CompatInfo * info, SymInterpInfo * new)
180 {
181     SymInterpInfo *old;
182
183     for (old = info->interps; old != NULL;
184          old = (SymInterpInfo *) old->defs.next)
185     {
186         if ((old->interp.sym == new->interp.sym) &&
187             (old->interp.mods == new->interp.mods) &&
188             (old->interp.match == new->interp.match))
189         {
190             return old;
191         }
192     }
193     return NULL;
194 }
195
196 static bool
197 AddInterp(CompatInfo * info, SymInterpInfo * new)
198 {
199     unsigned collide;
200     SymInterpInfo *old;
201
202     collide = 0;
203     old = FindMatchingInterp(info, new);
204     if (old != NULL)
205     {
206         if (new->defs.merge == MergeReplace)
207         {
208             SymInterpInfo *next = (SymInterpInfo *) old->defs.next;
209             if (((old->defs.fileID == new->defs.fileID)
210                  && (warningLevel > 0)) || (warningLevel > 9))
211             {
212                 WARN("Multiple definitions for \"%s\"\n", siText(new, info));
213                 ACTION("Earlier interpretation ignored\n");
214             }
215             *old = *new;
216             old->defs.next = &next->defs;
217             return true;
218         }
219         if (UseNewField(_SI_VirtualMod, &old->defs, &new->defs, &collide))
220         {
221             old->interp.virtual_mod = new->interp.virtual_mod;
222             old->defs.defined |= _SI_VirtualMod;
223         }
224         if (UseNewField(_SI_Action, &old->defs, &new->defs, &collide))
225         {
226             old->interp.act = new->interp.act;
227             old->defs.defined |= _SI_Action;
228         }
229         if (UseNewField(_SI_AutoRepeat, &old->defs, &new->defs, &collide))
230         {
231             old->interp.flags &= ~XkbSI_AutoRepeat;
232             old->interp.flags |= (new->interp.flags & XkbSI_AutoRepeat);
233             old->defs.defined |= _SI_AutoRepeat;
234         }
235         if (UseNewField(_SI_LockingKey, &old->defs, &new->defs, &collide))
236         {
237             old->interp.flags &= ~XkbSI_LockingKey;
238             old->interp.flags |= (new->interp.flags & XkbSI_LockingKey);
239             old->defs.defined |= _SI_LockingKey;
240         }
241         if (UseNewField(_SI_LevelOneOnly, &old->defs, &new->defs, &collide))
242         {
243             old->interp.match &= ~XkbSI_LevelOneOnly;
244             old->interp.match |= (new->interp.match & XkbSI_LevelOneOnly);
245             old->defs.defined |= _SI_LevelOneOnly;
246         }
247         if (collide)
248         {
249             WARN("Multiple interpretations of \"%s\"\n", siText(new, info));
250             ACTION("Using %s definition for duplicate fields\n",
251                     (new->defs.merge != MergeAugment ? "last" : "first"));
252         }
253         return true;
254     }
255     old = new;
256     if ((new = NextInterp(info)) == NULL)
257         return false;
258     *new = *old;
259     new->defs.next = NULL;
260     return true;
261 }
262
263 static bool
264 AddGroupCompat(CompatInfo * info, unsigned group, GroupCompatInfo * newGC)
265 {
266     GroupCompatInfo *gc;
267     unsigned merge;
268
269     merge = newGC->merge;
270     gc = &info->groupCompat[group];
271     if (((gc->real_mods == newGC->real_mods) && (gc->vmods == newGC->vmods)))
272     {
273         return true;
274     }
275     if (((gc->fileID == newGC->fileID) && (warningLevel > 0))
276         || (warningLevel > 9))
277     {
278         WARN("Compat map for group %d redefined\n", group + 1);
279         ACTION("Using %s definition\n",
280                 (merge == MergeAugment ? "old" : "new"));
281     }
282     if (newGC->defined && (merge != MergeAugment || !gc->defined))
283         *gc = *newGC;
284     return true;
285 }
286
287 /***====================================================================***/
288
289 static bool
290 ResolveStateAndPredicate(ExprDef * expr,
291                          unsigned *pred_rtrn,
292                          unsigned *mods_rtrn, CompatInfo * info)
293 {
294     ExprResult result;
295
296     if (expr == NULL)
297     {
298         *pred_rtrn = XkbSI_AnyOfOrNone;
299         *mods_rtrn = ~0;
300         return true;
301     }
302
303     *pred_rtrn = XkbSI_Exactly;
304     if (expr->op == ExprActionDecl)
305     {
306         const char *pred_txt = XkbcAtomText(expr->value.action.name);
307         if (strcasecmp(pred_txt, "noneof") == 0)
308             *pred_rtrn = XkbSI_NoneOf;
309         else if (strcasecmp(pred_txt, "anyofornone") == 0)
310             *pred_rtrn = XkbSI_AnyOfOrNone;
311         else if (strcasecmp(pred_txt, "anyof") == 0)
312             *pred_rtrn = XkbSI_AnyOf;
313         else if (strcasecmp(pred_txt, "allof") == 0)
314             *pred_rtrn = XkbSI_AllOf;
315         else if (strcasecmp(pred_txt, "exactly") == 0)
316             *pred_rtrn = XkbSI_Exactly;
317         else
318         {
319             ERROR("Illegal modifier predicate \"%s\"\n", pred_txt);
320             ACTION("Ignored\n");
321             return false;
322         }
323         expr = expr->value.action.args;
324     }
325     else if (expr->op == ExprIdent)
326     {
327         const char *pred_txt = XkbcAtomText(expr->value.str);
328         if ((pred_txt) && (strcasecmp(pred_txt, "any") == 0))
329         {
330             *pred_rtrn = XkbSI_AnyOf;
331             *mods_rtrn = 0xff;
332             return true;
333         }
334     }
335
336     if (ExprResolveModMask(expr, &result))
337     {
338         *mods_rtrn = result.uval;
339         return true;
340     }
341     return false;
342 }
343
344 /***====================================================================***/
345
346 static void
347 MergeIncludedCompatMaps(CompatInfo * into, CompatInfo * from, unsigned merge)
348 {
349     SymInterpInfo *si;
350     LEDInfo *led, *rtrn, *next;
351     GroupCompatInfo *gcm;
352     int i;
353
354     if (from->errorCount > 0)
355     {
356         into->errorCount += from->errorCount;
357         return;
358     }
359     if (into->name == NULL)
360     {
361         into->name = from->name;
362         from->name = NULL;
363     }
364     for (si = from->interps; si; si = (SymInterpInfo *) si->defs.next)
365     {
366         if (merge != MergeDefault)
367             si->defs.merge = merge;
368         if (!AddInterp(into, si))
369             into->errorCount++;
370     }
371     for (i = 0, gcm = &from->groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++)
372     {
373         if (merge != MergeDefault)
374             gcm->merge = merge;
375         if (!AddGroupCompat(into, i, gcm))
376             into->errorCount++;
377     }
378     for (led = from->leds; led != NULL; led = next)
379     {
380         next = (LEDInfo *) led->defs.next;
381         if (merge != MergeDefault)
382             led->defs.merge = merge;
383         rtrn = AddIndicatorMap(into->leds, led);
384         if (rtrn != NULL)
385             into->leds = rtrn;
386         else
387             into->errorCount++;
388     }
389 }
390
391 typedef void (*FileHandler) (XkbFile *rtrn, struct xkb_keymap *xkb,
392                              unsigned merge, CompatInfo *info);
393
394 static bool
395 HandleIncludeCompatMap(IncludeStmt * stmt,
396                        struct xkb_keymap * xkb, CompatInfo * info, FileHandler hndlr)
397 {
398     unsigned newMerge;
399     XkbFile *rtrn;
400     CompatInfo included;
401     bool haveSelf;
402
403     haveSelf = false;
404     if ((stmt->file == NULL) && (stmt->map == NULL))
405     {
406         haveSelf = true;
407         included = *info;
408         memset(info, 0, sizeof(CompatInfo));
409     }
410     else if (ProcessIncludeFile(xkb->context, stmt, XkmCompatMapIndex, &rtrn,
411                                 &newMerge))
412     {
413         InitCompatInfo(&included, xkb);
414         included.fileID = rtrn->id;
415         included.dflt = info->dflt;
416         included.dflt.defs.fileID = rtrn->id;
417         included.dflt.defs.merge = newMerge;
418         included.ledDflt.defs.fileID = rtrn->id;
419         included.ledDflt.defs.merge = newMerge;
420         included.act = info->act;
421         (*hndlr) (rtrn, xkb, MergeOverride, &included);
422         if (stmt->stmt != NULL)
423         {
424             free(included.name);
425             included.name = stmt->stmt;
426             stmt->stmt = NULL;
427         }
428         if (info->act != NULL)
429                 included.act = NULL;
430         FreeXKBFile(rtrn);
431     }
432     else
433     {
434         info->errorCount += 10;
435         return false;
436     }
437     if ((stmt->next != NULL) && (included.errorCount < 1))
438     {
439         IncludeStmt *next;
440         unsigned op;
441         CompatInfo next_incl;
442
443         for (next = stmt->next; next != NULL; next = next->next)
444         {
445             if ((next->file == NULL) && (next->map == NULL))
446             {
447                 haveSelf = true;
448                 MergeIncludedCompatMaps(&included, info, next->merge);
449                 ClearCompatInfo(info, xkb);
450             }
451             else if (ProcessIncludeFile(xkb->context, next, XkmCompatMapIndex,
452                                         &rtrn, &op))
453             {
454                 InitCompatInfo(&next_incl, xkb);
455                 next_incl.fileID = rtrn->id;
456                 next_incl.dflt = info->dflt;
457                 next_incl.dflt.defs.fileID = rtrn->id;
458                 next_incl.dflt.defs.merge = op;
459                 next_incl.ledDflt.defs.fileID = rtrn->id;
460                 next_incl.ledDflt.defs.merge = op;
461                 next_incl.act = info->act;
462                 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
463                 MergeIncludedCompatMaps(&included, &next_incl, op);
464                 if (info->act != NULL)
465                         next_incl.act = NULL;
466                 ClearCompatInfo(&next_incl, xkb);
467                 FreeXKBFile(rtrn);
468             }
469             else
470             {
471                 info->errorCount += 10;
472                 return false;
473             }
474         }
475     }
476     if (haveSelf)
477         *info = included;
478     else
479     {
480         MergeIncludedCompatMaps(info, &included, newMerge);
481         ClearCompatInfo(&included, xkb);
482     }
483     return (info->errorCount == 0);
484 }
485
486 static const LookupEntry useModMapValues[] = {
487     {"levelone", 1},
488     {"level1", 1},
489     {"anylevel", 0},
490     {"any", 0},
491     {NULL, 0}
492 };
493
494 static int
495 SetInterpField(SymInterpInfo * si,
496                struct xkb_keymap * xkb,
497                char *field,
498                ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
499 {
500     int ok = 1;
501     ExprResult tmp;
502
503     if (strcasecmp(field, "action") == 0)
504     {
505         if (arrayNdx != NULL)
506             return ReportSINotArray(si, field, info);
507         ok = HandleActionDef(value, xkb, &si->interp.act.any, info->act);
508         if (ok)
509             si->defs.defined |= _SI_Action;
510     }
511     else if ((strcasecmp(field, "virtualmodifier") == 0) ||
512              (strcasecmp(field, "virtualmod") == 0))
513     {
514         if (arrayNdx != NULL)
515             return ReportSINotArray(si, field, info);
516         ok = ResolveVirtualModifier(value, xkb, &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 (strcasecmp(field, "repeat") == 0)
526     {
527         if (arrayNdx != NULL)
528             return ReportSINotArray(si, field, info);
529         ok = ExprResolveBoolean(value, &tmp);
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 (strcasecmp(field, "locking") == 0)
542     {
543         if (arrayNdx != NULL)
544             return ReportSINotArray(si, field, info);
545         ok = ExprResolveBoolean(value, &tmp);
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 ((strcasecmp(field, "usemodmap") == 0) ||
558              (strcasecmp(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
581 static int
582 HandleInterpVar(VarDef * stmt, struct xkb_keymap * xkb, CompatInfo * info)
583 {
584     ExprResult elem, field;
585     ExprDef *ndx;
586     int ret;
587
588     if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
589         ret = 0;               /* internal error, already reported */
590     else if (elem.str && (strcasecmp(elem.str, "interpret") == 0))
591         ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
592                               info);
593     else if (elem.str && (strcasecmp(elem.str, "indicator") == 0))
594         ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
595                                   stmt->value);
596     else
597         ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
598                             &info->act);
599     free(elem.str);
600     free(field.str);
601     return ret;
602 }
603
604 static int
605 HandleInterpBody(VarDef * def, struct xkb_keymap * xkb, SymInterpInfo * si,
606                  CompatInfo * info)
607 {
608     int ok = 1;
609     ExprResult tmp, field;
610     ExprDef *arrayNdx;
611
612     for (; def != NULL; def = (VarDef *) def->common.next)
613     {
614         if ((def->name) && (def->name->type == ExprFieldRef))
615         {
616             ok = HandleInterpVar(def, xkb, info);
617             continue;
618         }
619         ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
620         if (ok) {
621             ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
622                                 info);
623             free(field.str);
624         }
625     }
626     return ok;
627 }
628
629 static int
630 HandleInterpDef(InterpDef * def, struct xkb_keymap * xkb, unsigned merge,
631                 CompatInfo * info)
632 {
633     unsigned pred, mods;
634     SymInterpInfo si;
635
636     if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
637     {
638         ERROR("Couldn't determine matching modifiers\n");
639         ACTION("Symbol interpretation ignored\n");
640         return false;
641     }
642     if (def->merge != MergeDefault)
643         merge = def->merge;
644
645     si = info->dflt;
646     si.defs.merge = merge;
647     if (!LookupKeysym(def->sym, &si.interp.sym))
648     {
649         ERROR("Could not resolve keysym %s\n", def->sym);
650         ACTION("Symbol interpretation ignored\n");
651         return false;
652     }
653     si.interp.match = pred & XkbSI_OpMask;
654     si.interp.mods = mods;
655     if (!HandleInterpBody(def->def, xkb, &si, info))
656     {
657         info->errorCount++;
658         return false;
659     }
660
661     if (!AddInterp(info, &si))
662     {
663         info->errorCount++;
664         return false;
665     }
666     return true;
667 }
668
669 static int
670 HandleGroupCompatDef(GroupCompatDef * def,
671                      struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
672 {
673     ExprResult val;
674     GroupCompatInfo tmp;
675
676     if (def->merge != MergeDefault)
677         merge = def->merge;
678     if (!XkbIsLegalGroup(def->group - 1))
679     {
680         ERROR("Keyboard group must be in the range 1..%d\n",
681                XkbNumKbdGroups + 1);
682         ACTION("Compatibility map for illegal group %d ignored\n",
683                 def->group);
684         return false;
685     }
686     tmp.fileID = info->fileID;
687     tmp.merge = merge;
688     if (!ExprResolveVModMask(def->def, &val, xkb))
689     {
690         ERROR("Expected a modifier mask in group compatibility definition\n");
691         ACTION("Ignoring illegal compatibility map for group %d\n",
692                 def->group);
693         return false;
694     }
695     tmp.real_mods = val.uval & 0xff;
696     tmp.vmods = (val.uval >> 8) & 0xffff;
697     tmp.defined = true;
698     return AddGroupCompat(info, def->group - 1, &tmp);
699 }
700
701 static void
702 HandleCompatMapFile(XkbFile * file,
703                     struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
704 {
705     ParseCommon *stmt;
706
707     if (merge == MergeDefault)
708         merge = MergeAugment;
709     free(info->name);
710     info->name = uDupString(file->name);
711     stmt = file->defs;
712     while (stmt)
713     {
714         switch (stmt->stmtType)
715         {
716         case StmtInclude:
717             if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
718                                         HandleCompatMapFile))
719                 info->errorCount++;
720             break;
721         case StmtInterpDef:
722             if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
723                 info->errorCount++;
724             break;
725         case StmtGroupCompatDef:
726             if (!HandleGroupCompatDef
727                 ((GroupCompatDef *) stmt, xkb, merge, info))
728                 info->errorCount++;
729             break;
730         case StmtIndicatorMapDef:
731         {
732             LEDInfo *rtrn;
733             rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
734                                          &info->ledDflt, info->leds, merge);
735             if (rtrn != NULL)
736                 info->leds = rtrn;
737             else
738                 info->errorCount++;
739         }
740             break;
741         case StmtVarDef:
742             if (!HandleInterpVar((VarDef *) stmt, xkb, info))
743                 info->errorCount++;
744             break;
745         case StmtVModDef:
746             if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
747                 info->errorCount++;
748             break;
749         case StmtKeycodeDef:
750             ERROR("Interpretation files may not include other types\n");
751             ACTION("Ignoring definition of key name\n");
752             info->errorCount++;
753             break;
754         default:
755             WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
756                   stmt->stmtType);
757             break;
758         }
759         stmt = stmt->next;
760         if (info->errorCount > 10)
761         {
762 #ifdef NOISY
763             ERROR("Too many errors\n");
764 #endif
765             ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
766             break;
767         }
768     }
769 }
770
771 static void
772 CopyInterps(CompatInfo * info,
773             struct xkb_compat_map * compat, bool needSymbol, unsigned pred)
774 {
775     SymInterpInfo *si;
776
777     for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
778     {
779         if (((si->interp.match & XkbSI_OpMask) != pred) ||
780             (needSymbol && (si->interp.sym == XKB_KEYSYM_NO_SYMBOL)) ||
781             ((!needSymbol) && (si->interp.sym != XKB_KEYSYM_NO_SYMBOL)))
782             continue;
783         if (compat->num_si >= compat->size_si)
784         {
785             WSGO("No room to merge symbol interpretations\n");
786             ACTION("Symbol interpretations lost\n");
787             return;
788         }
789         compat->sym_interpret[compat->num_si++] = si->interp;
790     }
791 }
792
793 bool
794 CompileCompatMap(XkbFile *file, struct xkb_keymap * xkb, unsigned merge,
795                  LEDInfoPtr *unboundLEDs)
796 {
797     int i;
798     CompatInfo info;
799     GroupCompatInfo *gcm;
800
801     InitCompatInfo(&info, xkb);
802     info.dflt.defs.merge = merge;
803     info.ledDflt.defs.merge = merge;
804     HandleCompatMapFile(file, xkb, merge, &info);
805
806     if (info.errorCount == 0)
807     {
808         int size;
809         if (XkbcAllocCompatMap(xkb, info.nInterps) != Success)
810         {
811             WSGO("Couldn't allocate compatibility map\n");
812             return false;
813         }
814         size = info.nInterps * sizeof(struct xkb_sym_interpret);
815         if (size > 0)
816         {
817             CopyInterps(&info, xkb->compat, true, XkbSI_Exactly);
818             CopyInterps(&info, xkb->compat, true, XkbSI_AllOf | XkbSI_NoneOf);
819             CopyInterps(&info, xkb->compat, true, XkbSI_AnyOf);
820             CopyInterps(&info, xkb->compat, true, XkbSI_AnyOfOrNone);
821             CopyInterps(&info, xkb->compat, false, XkbSI_Exactly);
822             CopyInterps(&info, xkb->compat, false,
823                         XkbSI_AllOf | XkbSI_NoneOf);
824             CopyInterps(&info, xkb->compat, false, XkbSI_AnyOf);
825             CopyInterps(&info, xkb->compat, false, XkbSI_AnyOfOrNone);
826         }
827         for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
828              i++, gcm++)
829         {
830             if ((gcm->fileID != 0) || (gcm->real_mods != 0)
831                 || (gcm->vmods != 0))
832             {
833                 xkb->compat->groups[i].mask = gcm->real_mods;
834                 xkb->compat->groups[i].real_mods = gcm->real_mods;
835                 xkb->compat->groups[i].vmods = gcm->vmods;
836             }
837         }
838         if (info.leds != NULL)
839         {
840             if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
841                 info.errorCount++;
842             info.leds = NULL;
843         }
844         ClearCompatInfo(&info, xkb);
845         return true;
846     }
847     free(info.interps);
848     return false;
849 }
850
851 static uint32_t
852 VModsToReal(struct xkb_keymap *xkb, uint32_t vmodmask)
853 {
854     uint32_t ret = 0;
855     int i;
856
857     if (!vmodmask)
858         return 0;
859
860     for (i = 0; i < XkbNumVirtualMods; i++) {
861         if (!(vmodmask & (1 << i)))
862             continue;
863         ret |= xkb->server->vmods[i];
864     }
865
866     return ret;
867 }
868
869 static void
870 UpdateActionMods(struct xkb_keymap *xkb, union xkb_action *act, uint32_t rmodmask)
871 {
872     switch (act->type) {
873     case XkbSA_SetMods:
874     case XkbSA_LatchMods:
875     case XkbSA_LockMods:
876         if (act->mods.flags & XkbSA_UseModMapMods)
877             act->mods.real_mods = rmodmask;
878         act->mods.mask = act->mods.real_mods;
879         act->mods.mask |= VModsToReal(xkb, act->mods.vmods);
880         break;
881     case XkbSA_ISOLock:
882         if (act->iso.flags & XkbSA_UseModMapMods)
883             act->iso.real_mods = rmodmask;
884         act->iso.mask = act->iso.real_mods;
885         act->iso.mask |= VModsToReal(xkb, act->iso.vmods);
886         break;
887     default:
888         break;
889     }
890 }
891
892 /**
893  * Find an interpretation which applies to this particular level, either by
894  * finding an exact match for the symbol and modifier combination, or a
895  * generic XKB_KEYSYM_NO_SYMBOL match.
896  */
897 static struct xkb_sym_interpret *
898 FindInterpForKey(struct xkb_keymap *xkb, xkb_keycode_t key, uint32_t group, uint32_t level)
899 {
900     struct xkb_sym_interpret *ret = NULL;
901     const xkb_keysym_t *syms;
902     int num_syms;
903     int i;
904
905     num_syms = xkb_key_get_syms_by_level(xkb, key, group, level, &syms);
906     if (num_syms == 0)
907         return NULL;
908
909     for (i = 0; i < xkb->compat->num_si; i++) {
910         struct xkb_sym_interpret *interp = &xkb->compat->sym_interpret[i];
911         uint32_t mods;
912         bool found;
913
914         if ((num_syms > 1 || interp->sym != syms[0]) &&
915             interp->sym != XKB_KEYSYM_NO_SYMBOL)
916             continue;
917
918         if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
919             mods = xkb->map->modmap[key];
920         else
921             mods = 0;
922
923         switch (interp->match & XkbSI_OpMask) {
924         case XkbSI_NoneOf:
925             found = !(interp->mods & mods);
926             break;
927         case XkbSI_AnyOfOrNone:
928             found = (!mods || (interp->mods & mods));
929             break;
930         case XkbSI_AnyOf:
931             found = !!(interp->mods & mods);
932             break;
933         case XkbSI_AllOf:
934             found = ((interp->mods & mods) == mods);
935             break;
936         case XkbSI_Exactly:
937             found = (interp->mods == mods);
938             break;
939         default:
940             found = false;
941             break;
942         }
943
944         if (found && interp->sym != XKB_KEYSYM_NO_SYMBOL)
945             return interp;
946         else if (found && !ret)
947             ret = interp;
948     }
949
950     return ret;
951 }
952
953 /**
954  */
955 static bool
956 ApplyInterpsToKey(struct xkb_keymap *xkb, xkb_keycode_t key)
957 {
958 #define INTERP_SIZE (8 * 4)
959     struct xkb_sym_interpret *interps[INTERP_SIZE];
960     union xkb_action *acts;
961     uint32_t vmodmask = 0;
962     int num_acts = 0;
963     int group, level;
964     int width = XkbKeyGroupsWidth(xkb, key);
965     int i;
966
967     /* If we've been told not to bind interps to this key, then don't. */
968     if (xkb->server->explicit[key] & XkbExplicitInterpretMask)
969         return true;
970
971     for (i = 0; i < INTERP_SIZE; i++)
972         interps[i] = NULL;
973
974     for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
975         for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
976             i = (group * width) + level;
977             if (i >= INTERP_SIZE) /* XXX FIXME */
978                 return false;
979             interps[i] = FindInterpForKey(xkb, key, group, level);
980             if (interps[i])
981                 num_acts++;
982         }
983     }
984
985     if (num_acts)
986         num_acts = XkbKeyNumGroups(xkb, key) * width;
987     acts = XkbcResizeKeyActions(xkb, key, num_acts);
988     if (!num_acts)
989         return true;
990     else if (!acts)
991         return false;
992
993     for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
994         for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
995             struct xkb_sym_interpret *interp;
996
997             i = (group * width) + level;
998             interp = interps[i];
999
1000             /* Infer default key behaviours from the base level. */
1001             if (group == 0 && level == 0) {
1002                 if (!(xkb->server->explicit[key] & XkbExplicitAutoRepeatMask) &&
1003                     (!interp || interp->flags & XkbSI_AutoRepeat))
1004                     xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8));
1005                 if (!(xkb->server->explicit[key] & XkbExplicitBehaviorMask) &&
1006                     interp && (interp->flags & XkbSI_LockingKey))
1007                     xkb->server->behaviors[key].type = XkbKB_Lock;
1008             }
1009
1010             if (!interp)
1011                 continue;
1012
1013             if ((group == 0 && level == 0) ||
1014                 !(interp->match & XkbSI_LevelOneOnly)) {
1015                 if (interp->virtual_mod != XkbNoModifier)
1016                     vmodmask |= (1 << interp->virtual_mod);
1017             }
1018             acts[i] = interp->act;
1019         }
1020     }
1021
1022     if (!(xkb->server->explicit[key] & XkbExplicitVModMapMask))
1023         xkb->server->vmodmap[key] = vmodmask;
1024
1025     return true;
1026 #undef INTERP_SIZE
1027 }
1028
1029 /**
1030  * This collects a bunch of disparate functions which was done in the server
1031  * at various points that really should've been done within xkbcomp.  Turns out
1032  * your actions and types are a lot more useful when any of your modifiers
1033  * other than Shift actually do something ...
1034  */
1035 bool
1036 UpdateModifiersFromCompat(struct xkb_keymap *xkb)
1037 {
1038     xkb_keycode_t key;
1039     int i;
1040
1041     /* Find all the interprets for the key and bind them to actions,
1042      * which will also update the vmodmap. */
1043     for (key = xkb->min_key_code; key <= xkb->max_key_code; key++)
1044         if (!ApplyInterpsToKey(xkb, key))
1045             return false;
1046
1047     /* Update xkb->server->vmods, the virtual -> real mod mapping. */
1048     for (i = 0; i < XkbNumVirtualMods; i++)
1049         xkb->server->vmods[i] = 0;
1050     for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1051         if (!xkb->server->vmodmap[key])
1052             continue;
1053         for (i = 0; i < XkbNumVirtualMods; i++) {
1054             if (!(xkb->server->vmodmap[key] & (1 << i)))
1055                 continue;
1056             xkb->server->vmods[i] |= xkb->map->modmap[key];
1057         }
1058     }
1059
1060     /* Now update the level masks for all the types to reflect the vmods. */
1061     for (i = 0; i < xkb->map->num_types; i++) {
1062         struct xkb_key_type *type = &xkb->map->types[i];
1063         uint32_t mask = 0;
1064         int j;
1065         type->mods.mask = type->mods.real_mods;
1066         type->mods.mask |= VModsToReal(xkb, type->mods.vmods);
1067         for (j = 0; j < XkbNumVirtualMods; j++) {
1068             if (!(type->mods.vmods & (1 << j)))
1069                 continue;
1070             mask |= xkb->server->vmods[j];
1071         }
1072         for (j = 0; j < type->map_count; j++) {
1073             struct xkb_mods *mods = &type->map[j].mods;
1074             mods->mask = mods->real_mods | VModsToReal(xkb, mods->vmods);
1075         }
1076     }
1077
1078     /* Update action modifiers. */
1079     for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1080         union xkb_action *acts = XkbKeyActionsPtr(xkb, key);
1081         for (i = 0; i < XkbKeyNumActions(xkb, key); i++) {
1082             if (acts[i].any.type == XkbSA_NoAction)
1083                 continue;
1084             UpdateActionMods(xkb, &acts[i], xkb->map->modmap[key]);
1085         }
1086     }
1087
1088     /* Update group modifiers. */
1089     for (i = 0; i < XkbNumKbdGroups; i++) {
1090         struct xkb_mods *group = &xkb->compat->groups[i];
1091         group->mask = group->real_mods | VModsToReal(xkb, group->vmods);
1092     }
1093
1094     /* Update vmod -> indicator maps. */
1095     for (i = 0; i < XkbNumIndicators; i++) {
1096         struct xkb_mods *led = &xkb->indicators->maps[i].mods;
1097         led->mask = led->real_mods | VModsToReal(xkb, led->vmods);
1098     }
1099
1100     return true;
1101 }