Constify the syms_out argument to xkb_key_get_syms()
[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 */ ,
392                              struct xkb_keymap * /* xkb */ ,
393                              unsigned /* merge */ ,
394                              CompatInfo *       /* info */
395     );
396
397 static Bool
398 HandleIncludeCompatMap(IncludeStmt * stmt,
399                        struct xkb_keymap * xkb, CompatInfo * info, FileHandler hndlr)
400 {
401     unsigned newMerge;
402     XkbFile *rtrn;
403     CompatInfo included;
404     Bool haveSelf;
405
406     haveSelf = False;
407     if ((stmt->file == NULL) && (stmt->map == NULL))
408     {
409         haveSelf = True;
410         included = *info;
411         memset(info, 0, sizeof(CompatInfo));
412     }
413     else if (ProcessIncludeFile(xkb->context, stmt, XkmCompatMapIndex, &rtrn,
414                                 &newMerge))
415     {
416         InitCompatInfo(&included, xkb);
417         included.fileID = rtrn->id;
418         included.dflt = info->dflt;
419         included.dflt.defs.fileID = rtrn->id;
420         included.dflt.defs.merge = newMerge;
421         included.ledDflt.defs.fileID = rtrn->id;
422         included.ledDflt.defs.merge = newMerge;
423         included.act = info->act;
424         (*hndlr) (rtrn, xkb, MergeOverride, &included);
425         if (stmt->stmt != NULL)
426         {
427             free(included.name);
428             included.name = stmt->stmt;
429             stmt->stmt = NULL;
430         }
431         if (info->act != NULL)
432                 included.act = NULL;
433         FreeXKBFile(rtrn);
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(xkb->context, next, XkmCompatMapIndex,
455                                         &rtrn, &op))
456             {
457                 InitCompatInfo(&next_incl, xkb);
458                 next_incl.fileID = rtrn->id;
459                 next_incl.dflt = info->dflt;
460                 next_incl.dflt.defs.fileID = rtrn->id;
461                 next_incl.dflt.defs.merge = op;
462                 next_incl.ledDflt.defs.fileID = rtrn->id;
463                 next_incl.ledDflt.defs.merge = op;
464                 next_incl.act = info->act;
465                 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
466                 MergeIncludedCompatMaps(&included, &next_incl, op);
467                 if (info->act != NULL)
468                         next_incl.act = NULL;
469                 ClearCompatInfo(&next_incl, xkb);
470                 FreeXKBFile(rtrn);
471             }
472             else
473             {
474                 info->errorCount += 10;
475                 return False;
476             }
477         }
478     }
479     if (haveSelf)
480         *info = included;
481     else
482     {
483         MergeIncludedCompatMaps(info, &included, newMerge);
484         ClearCompatInfo(&included, xkb);
485     }
486     return (info->errorCount == 0);
487 }
488
489 static const LookupEntry useModMapValues[] = {
490     {"levelone", 1},
491     {"level1", 1},
492     {"anylevel", 0},
493     {"any", 0},
494     {NULL, 0}
495 };
496
497 static int
498 SetInterpField(SymInterpInfo * si,
499                struct xkb_keymap * xkb,
500                char *field,
501                ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
502 {
503     int ok = 1;
504     ExprResult tmp;
505
506     if (strcasecmp(field, "action") == 0)
507     {
508         if (arrayNdx != NULL)
509             return ReportSINotArray(si, field, info);
510         ok = HandleActionDef(value, xkb, &si->interp.act.any, si->defs.merge,
511                              info->act);
512         if (ok)
513             si->defs.defined |= _SI_Action;
514     }
515     else if ((strcasecmp(field, "virtualmodifier") == 0) ||
516              (strcasecmp(field, "virtualmod") == 0))
517     {
518         if (arrayNdx != NULL)
519             return ReportSINotArray(si, field, info);
520         ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
521         if (ok)
522         {
523             si->interp.virtual_mod = tmp.uval;
524             si->defs.defined |= _SI_VirtualMod;
525         }
526         else
527             return ReportSIBadType(si, field, "virtual modifier", info);
528     }
529     else if (strcasecmp(field, "repeat") == 0)
530     {
531         if (arrayNdx != NULL)
532             return ReportSINotArray(si, field, info);
533         ok = ExprResolveBoolean(value, &tmp);
534         if (ok)
535         {
536             if (tmp.uval)
537                 si->interp.flags |= XkbSI_AutoRepeat;
538             else
539                 si->interp.flags &= ~XkbSI_AutoRepeat;
540             si->defs.defined |= _SI_AutoRepeat;
541         }
542         else
543             return ReportSIBadType(si, field, "boolean", info);
544     }
545     else if (strcasecmp(field, "locking") == 0)
546     {
547         if (arrayNdx != NULL)
548             return ReportSINotArray(si, field, info);
549         ok = ExprResolveBoolean(value, &tmp);
550         if (ok)
551         {
552             if (tmp.uval)
553                 si->interp.flags |= XkbSI_LockingKey;
554             else
555                 si->interp.flags &= ~XkbSI_LockingKey;
556             si->defs.defined |= _SI_LockingKey;
557         }
558         else
559             return ReportSIBadType(si, field, "boolean", info);
560     }
561     else if ((strcasecmp(field, "usemodmap") == 0) ||
562              (strcasecmp(field, "usemodmapmods") == 0))
563     {
564         if (arrayNdx != NULL)
565             return ReportSINotArray(si, field, info);
566         ok = ExprResolveEnum(value, &tmp, useModMapValues);
567         if (ok)
568         {
569             if (tmp.uval)
570                 si->interp.match |= XkbSI_LevelOneOnly;
571             else
572                 si->interp.match &= ~XkbSI_LevelOneOnly;
573             si->defs.defined |= _SI_LevelOneOnly;
574         }
575         else
576             return ReportSIBadType(si, field, "level specification", info);
577     }
578     else
579     {
580         ok = ReportBadField("symbol interpretation", field, siText(si, info));
581     }
582     return ok;
583 }
584
585 static int
586 HandleInterpVar(VarDef * stmt, struct xkb_keymap * xkb, CompatInfo * info)
587 {
588     ExprResult elem, field;
589     ExprDef *ndx;
590     int ret;
591
592     if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
593         ret = 0;               /* internal error, already reported */
594     else if (elem.str && (strcasecmp(elem.str, "interpret") == 0))
595         ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
596                               info);
597     else if (elem.str && (strcasecmp(elem.str, "indicator") == 0))
598         ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
599                                   stmt->value);
600     else
601         ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
602                             &info->act);
603     free(elem.str);
604     free(field.str);
605     return ret;
606 }
607
608 static int
609 HandleInterpBody(VarDef * def, struct xkb_keymap * xkb, SymInterpInfo * si,
610                  CompatInfo * info)
611 {
612     int ok = 1;
613     ExprResult tmp, field;
614     ExprDef *arrayNdx;
615
616     for (; def != NULL; def = (VarDef *) def->common.next)
617     {
618         if ((def->name) && (def->name->type == ExprFieldRef))
619         {
620             ok = HandleInterpVar(def, xkb, info);
621             continue;
622         }
623         ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
624         if (ok) {
625             ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
626                                 info);
627             free(field.str);
628         }
629     }
630     return ok;
631 }
632
633 static int
634 HandleInterpDef(InterpDef * def, struct xkb_keymap * xkb, unsigned merge,
635                 CompatInfo * info)
636 {
637     unsigned pred, mods;
638     SymInterpInfo si;
639
640     if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
641     {
642         ERROR("Couldn't determine matching modifiers\n");
643         ACTION("Symbol interpretation ignored\n");
644         return False;
645     }
646     if (def->merge != MergeDefault)
647         merge = def->merge;
648
649     si = info->dflt;
650     si.defs.merge = merge;
651     if (!LookupKeysym(def->sym, &si.interp.sym))
652     {
653         ERROR("Could not resolve keysym %s\n", def->sym);
654         ACTION("Symbol interpretation ignored\n");
655         return False;
656     }
657     si.interp.match = pred & XkbSI_OpMask;
658     si.interp.mods = mods;
659     if (!HandleInterpBody(def->def, xkb, &si, info))
660     {
661         info->errorCount++;
662         return False;
663     }
664
665     if (!AddInterp(info, &si))
666     {
667         info->errorCount++;
668         return False;
669     }
670     return True;
671 }
672
673 static int
674 HandleGroupCompatDef(GroupCompatDef * def,
675                      struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
676 {
677     ExprResult val;
678     GroupCompatInfo tmp;
679
680     if (def->merge != MergeDefault)
681         merge = def->merge;
682     if (!XkbIsLegalGroup(def->group - 1))
683     {
684         ERROR("Keyboard group must be in the range 1..%d\n",
685                XkbNumKbdGroups + 1);
686         ACTION("Compatibility map for illegal group %d ignored\n",
687                 def->group);
688         return False;
689     }
690     tmp.fileID = info->fileID;
691     tmp.merge = merge;
692     if (!ExprResolveVModMask(def->def, &val, xkb))
693     {
694         ERROR("Expected a modifier mask in group compatibility definition\n");
695         ACTION("Ignoring illegal compatibility map for group %d\n",
696                 def->group);
697         return False;
698     }
699     tmp.real_mods = val.uval & 0xff;
700     tmp.vmods = (val.uval >> 8) & 0xffff;
701     tmp.defined = True;
702     return AddGroupCompat(info, def->group - 1, &tmp);
703 }
704
705 static void
706 HandleCompatMapFile(XkbFile * file,
707                     struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
708 {
709     ParseCommon *stmt;
710
711     if (merge == MergeDefault)
712         merge = MergeAugment;
713     free(info->name);
714     info->name = uDupString(file->name);
715     stmt = file->defs;
716     while (stmt)
717     {
718         switch (stmt->stmtType)
719         {
720         case StmtInclude:
721             if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
722                                         HandleCompatMapFile))
723                 info->errorCount++;
724             break;
725         case StmtInterpDef:
726             if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
727                 info->errorCount++;
728             break;
729         case StmtGroupCompatDef:
730             if (!HandleGroupCompatDef
731                 ((GroupCompatDef *) stmt, xkb, merge, info))
732                 info->errorCount++;
733             break;
734         case StmtIndicatorMapDef:
735         {
736             LEDInfo *rtrn;
737             rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
738                                          &info->ledDflt, info->leds, merge);
739             if (rtrn != NULL)
740                 info->leds = rtrn;
741             else
742                 info->errorCount++;
743         }
744             break;
745         case StmtVarDef:
746             if (!HandleInterpVar((VarDef *) stmt, xkb, info))
747                 info->errorCount++;
748             break;
749         case StmtVModDef:
750             if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
751                 info->errorCount++;
752             break;
753         case StmtKeycodeDef:
754             ERROR("Interpretation files may not include other types\n");
755             ACTION("Ignoring definition of key name\n");
756             info->errorCount++;
757             break;
758         default:
759             WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
760                   stmt->stmtType);
761             break;
762         }
763         stmt = stmt->next;
764         if (info->errorCount > 10)
765         {
766 #ifdef NOISY
767             ERROR("Too many errors\n");
768 #endif
769             ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
770             break;
771         }
772     }
773 }
774
775 static void
776 CopyInterps(CompatInfo * info,
777             struct xkb_compat_map * compat, Bool needSymbol, unsigned pred)
778 {
779     SymInterpInfo *si;
780
781     for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
782     {
783         if (((si->interp.match & XkbSI_OpMask) != pred) ||
784             (needSymbol && (si->interp.sym == XKB_KEYSYM_NO_SYMBOL)) ||
785             ((!needSymbol) && (si->interp.sym != XKB_KEYSYM_NO_SYMBOL)))
786             continue;
787         if (compat->num_si >= compat->size_si)
788         {
789             WSGO("No room to merge symbol interpretations\n");
790             ACTION("Symbol interpretations lost\n");
791             return;
792         }
793         compat->sym_interpret[compat->num_si++] = si->interp;
794     }
795 }
796
797 Bool
798 CompileCompatMap(XkbFile *file, struct xkb_keymap * xkb, unsigned merge,
799                  LEDInfoPtr *unboundLEDs)
800 {
801     int i;
802     CompatInfo info;
803     GroupCompatInfo *gcm;
804
805     InitCompatInfo(&info, xkb);
806     info.dflt.defs.merge = merge;
807     info.ledDflt.defs.merge = merge;
808     HandleCompatMapFile(file, xkb, merge, &info);
809
810     if (info.errorCount == 0)
811     {
812         int size;
813         if (XkbcAllocCompatMap(xkb, XkbAllCompatMask, info.nInterps) !=
814             Success)
815         {
816             WSGO("Couldn't allocate compatibility map\n");
817             return False;
818         }
819         size = info.nInterps * sizeof(struct xkb_sym_interpret);
820         if (size > 0)
821         {
822             CopyInterps(&info, xkb->compat, True, XkbSI_Exactly);
823             CopyInterps(&info, xkb->compat, True, XkbSI_AllOf | XkbSI_NoneOf);
824             CopyInterps(&info, xkb->compat, True, XkbSI_AnyOf);
825             CopyInterps(&info, xkb->compat, True, XkbSI_AnyOfOrNone);
826             CopyInterps(&info, xkb->compat, False, XkbSI_Exactly);
827             CopyInterps(&info, xkb->compat, False,
828                         XkbSI_AllOf | XkbSI_NoneOf);
829             CopyInterps(&info, xkb->compat, False, XkbSI_AnyOf);
830             CopyInterps(&info, xkb->compat, False, XkbSI_AnyOfOrNone);
831         }
832         for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups;
833              i++, gcm++)
834         {
835             if ((gcm->fileID != 0) || (gcm->real_mods != 0)
836                 || (gcm->vmods != 0))
837             {
838                 xkb->compat->groups[i].mask = gcm->real_mods;
839                 xkb->compat->groups[i].real_mods = gcm->real_mods;
840                 xkb->compat->groups[i].vmods = gcm->vmods;
841             }
842         }
843         if (info.leds != NULL)
844         {
845             if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
846                 info.errorCount++;
847             info.leds = NULL;
848         }
849         ClearCompatInfo(&info, xkb);
850         return True;
851     }
852     free(info.interps);
853     return False;
854 }
855
856 static uint32_t
857 VModsToReal(struct xkb_keymap *xkb, uint32_t vmodmask)
858 {
859     uint32_t ret = 0;
860     int i;
861
862     if (!vmodmask)
863         return 0;
864
865     for (i = 0; i < XkbNumVirtualMods; i++) {
866         if (!(vmodmask & (1 << i)))
867             continue;
868         ret |= xkb->server->vmods[i];
869     }
870
871     return ret;
872 }
873
874 static void
875 UpdateActionMods(struct xkb_keymap *xkb, union xkb_action *act, uint32_t rmodmask)
876 {
877     switch (act->type) {
878     case XkbSA_SetMods:
879     case XkbSA_LatchMods:
880     case XkbSA_LockMods:
881         if (act->mods.flags & XkbSA_UseModMapMods)
882             act->mods.real_mods = rmodmask;
883         act->mods.mask = act->mods.real_mods;
884         act->mods.mask |= VModsToReal(xkb, act->mods.vmods);
885         break;
886     case XkbSA_ISOLock:
887         if (act->iso.flags & XkbSA_UseModMapMods)
888             act->iso.real_mods = rmodmask;
889         act->iso.mask = act->iso.real_mods;
890         act->iso.mask |= VModsToReal(xkb, act->iso.vmods);
891         break;
892     default:
893         break;
894     }
895 }
896
897 /**
898  * Find an interpretation which applies to this particular level, either by
899  * finding an exact match for the symbol and modifier combination, or a
900  * generic XKB_KEYSYM_NO_SYMBOL match.
901  */
902 static struct xkb_sym_interpret *
903 FindInterpForKey(struct xkb_keymap *xkb, xkb_keycode_t key, uint32_t group, uint32_t level)
904 {
905     struct xkb_sym_interpret *ret = NULL;
906     const xkb_keysym_t *syms;
907     int num_syms;
908     int i;
909
910     num_syms = xkb_key_get_syms_by_level(xkb, key, group, level, &syms);
911     if (num_syms == 0)
912         return NULL;
913
914     for (i = 0; i < xkb->compat->num_si; i++) {
915         struct xkb_sym_interpret *interp = &xkb->compat->sym_interpret[i];
916         uint32_t mods;
917         Bool found;
918
919         if ((num_syms > 1 || interp->sym != syms[0]) &&
920             interp->sym != XKB_KEYSYM_NO_SYMBOL)
921             continue;
922
923         if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
924             mods = xkb->map->modmap[key];
925         else
926             mods = 0;
927
928         switch (interp->match & XkbSI_OpMask) {
929         case XkbSI_NoneOf:
930             found = !(interp->mods & mods);
931             break;
932         case XkbSI_AnyOfOrNone:
933             found = (!mods || (interp->mods & mods));
934             break;
935         case XkbSI_AnyOf:
936             found = !!(interp->mods & mods);
937             break;
938         case XkbSI_AllOf:
939             found = ((interp->mods & mods) == mods);
940             break;
941         case XkbSI_Exactly:
942             found = (interp->mods == mods);
943             break;
944         default:
945             found = False;
946             break;
947         }
948
949         if (found && interp->sym != XKB_KEYSYM_NO_SYMBOL)
950             return interp;
951         else if (found && !ret)
952             ret = interp;
953     }
954
955     return ret;
956 }
957
958 /**
959  */
960 static Bool
961 ApplyInterpsToKey(struct xkb_keymap *xkb, xkb_keycode_t key)
962 {
963 #define INTERP_SIZE (8 * 4)
964     struct xkb_sym_interpret *interps[INTERP_SIZE];
965     union xkb_action *acts;
966     uint32_t vmodmask = 0;
967     int num_acts = 0;
968     int group, level;
969     int width = XkbKeyGroupsWidth(xkb, key);
970     int i;
971
972     /* If we've been told not to bind interps to this key, then don't. */
973     if (xkb->server->explicit[key] & XkbExplicitInterpretMask)
974         return True;
975
976     for (i = 0; i < INTERP_SIZE; i++)
977         interps[i] = NULL;
978
979     for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
980         for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
981             i = (group * width) + level;
982             if (i >= INTERP_SIZE) /* XXX FIXME */
983                 return False;
984             interps[i] = FindInterpForKey(xkb, key, group, level);
985             if (interps[i])
986                 num_acts++;
987         }
988     }
989
990     if (num_acts)
991         num_acts = XkbKeyNumGroups(xkb, key) * width;
992     acts = XkbcResizeKeyActions(xkb, key, num_acts);
993     if (!num_acts)
994         return True;
995     else if (!acts)
996         return False;
997
998     for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
999         for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
1000             struct xkb_sym_interpret *interp;
1001
1002             i = (group * width) + level;
1003             interp = interps[i];
1004
1005             /* Infer default key behaviours from the base level. */
1006             if (group == 0 && level == 0) {
1007                 if (!(xkb->server->explicit[key] & XkbExplicitAutoRepeatMask) &&
1008                     (!interp || interp->flags & XkbSI_AutoRepeat))
1009                     xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8));
1010                 if (!(xkb->server->explicit[key] & XkbExplicitBehaviorMask) &&
1011                     interp && (interp->flags & XkbSI_LockingKey))
1012                     xkb->server->behaviors[key].type = XkbKB_Lock;
1013             }
1014
1015             if (!interp)
1016                 continue;
1017
1018             if ((group == 0 && level == 0) ||
1019                 !(interp->match & XkbSI_LevelOneOnly)) {
1020                 if (interp->virtual_mod != XkbNoModifier)
1021                     vmodmask |= (1 << interp->virtual_mod);
1022             }
1023             acts[i] = interp->act;
1024         }
1025     }
1026
1027     if (!(xkb->server->explicit[key] & XkbExplicitVModMapMask))
1028         xkb->server->vmodmap[key] = vmodmask;
1029
1030     return True;
1031 #undef INTERP_SIZE
1032 }
1033
1034 /**
1035  * This collects a bunch of disparate functions which was done in the server
1036  * at various points that really should've been done within xkbcomp.  Turns out
1037  * your actions and types are a lot more useful when any of your modifiers
1038  * other than Shift actually do something ...
1039  */
1040 Bool
1041 UpdateModifiersFromCompat(struct xkb_keymap *xkb)
1042 {
1043     xkb_keycode_t key;
1044     int i;
1045
1046     /* Find all the interprets for the key and bind them to actions,
1047      * which will also update the vmodmap. */
1048     for (key = xkb->min_key_code; key <= xkb->max_key_code; key++)
1049         if (!ApplyInterpsToKey(xkb, key))
1050             return False;
1051
1052     /* Update xkb->server->vmods, the virtual -> real mod mapping. */
1053     for (i = 0; i < XkbNumVirtualMods; i++)
1054         xkb->server->vmods[i] = 0;
1055     for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1056         if (!xkb->server->vmodmap[key])
1057             continue;
1058         for (i = 0; i < XkbNumVirtualMods; i++) {
1059             if (!(xkb->server->vmodmap[key] & (1 << i)))
1060                 continue;
1061             xkb->server->vmods[i] |= xkb->map->modmap[key];
1062         }
1063     }
1064
1065     /* Now update the level masks for all the types to reflect the vmods. */
1066     for (i = 0; i < xkb->map->num_types; i++) {
1067         struct xkb_key_type *type = &xkb->map->types[i];
1068         uint32_t mask = 0;
1069         int j;
1070         type->mods.mask = type->mods.real_mods;
1071         type->mods.mask |= VModsToReal(xkb, type->mods.vmods);
1072         for (j = 0; j < XkbNumVirtualMods; j++) {
1073             if (!(type->mods.vmods & (1 << j)))
1074                 continue;
1075             mask |= xkb->server->vmods[j];
1076         }
1077         for (j = 0; j < type->map_count; j++) {
1078             struct xkb_mods *mods = &type->map[j].mods;
1079             mods->mask = mods->real_mods | VModsToReal(xkb, mods->vmods);
1080         }
1081     }
1082
1083     /* Update action modifiers. */
1084     for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1085         union xkb_action *acts = XkbKeyActionsPtr(xkb, key);
1086         for (i = 0; i < XkbKeyNumActions(xkb, key); i++) {
1087             if (acts[i].any.type == XkbSA_NoAction)
1088                 continue;
1089             UpdateActionMods(xkb, &acts[i], xkb->map->modmap[key]);
1090         }
1091     }
1092
1093     /* Update group modifiers. */
1094     for (i = 0; i < XkbNumKbdGroups; i++) {
1095         struct xkb_mods *group = &xkb->compat->groups[i];
1096         group->mask = group->real_mods | VModsToReal(xkb, group->vmods);
1097     }
1098
1099     /* Update vmod -> indicator maps. */
1100     for (i = 0; i < XkbNumIndicators; i++) {
1101         struct xkb_mods *led = &xkb->indicators->maps[i].mods;
1102         led->mask = led->real_mods | VModsToReal(xkb, led->vmods);
1103     }
1104
1105     return True;
1106 }