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