xkbcomp: Atom text and expr leak fixes part #973
[profile/ivi/libxkbcommon.git] / src / xkbcomp / symbols.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 "tokens.h"
31 #include "expr.h"
32
33 #include <X11/extensions/XKBfilecommon.h>
34 #include <X11/keysym.h>
35 #include <stdlib.h>
36
37 #include "expr.h"
38 #include "vmod.h"
39 #include "action.h"
40 #include "keycodes.h"
41 #include "misc.h"
42 #include "alias.h"
43
44 extern Atom tok_ONE_LEVEL;
45 extern Atom tok_TWO_LEVEL;
46 extern Atom tok_KEYPAD;
47
48 /***====================================================================***/
49
50 #define RepeatYes       1
51 #define RepeatNo        0
52 #define RepeatUndefined ~((unsigned)0)
53
54 #define _Key_Syms       (1<<0)
55 #define _Key_Acts       (1<<1)
56 #define _Key_Repeat     (1<<2)
57 #define _Key_Behavior   (1<<3)
58 #define _Key_Type_Dflt  (1<<4)
59 #define _Key_Types      (1<<5)
60 #define _Key_GroupInfo  (1<<6)
61 #define _Key_VModMap    (1<<7)
62
63 typedef struct _KeyInfo
64 {
65     CommonInfo defs;
66     unsigned long name; /* the 4 chars of the key name, as long */
67     unsigned char groupInfo;
68     unsigned char typesDefined;
69     unsigned char symsDefined;
70     unsigned char actsDefined;
71     short numLevels[XkbNumKbdGroups];
72     KeySym *syms[XkbNumKbdGroups];
73     XkbcAction *acts[XkbNumKbdGroups];
74     Atom types[XkbNumKbdGroups];
75     unsigned repeat;
76     XkbBehavior behavior;
77     unsigned short vmodmap;
78     unsigned long nameForOverlayKey;
79     unsigned long allowNone;
80     Atom dfltType;
81 } KeyInfo;
82
83 /**
84  * Init the given key info to sane values.
85  */
86 static void
87 InitKeyInfo(KeyInfo * info)
88 {
89     register int i;
90     static char dflt[4] = "*";
91
92     info->defs.defined = 0;
93     info->defs.fileID = 0;
94     info->defs.merge = MergeOverride;
95     info->defs.next = NULL;
96     info->name = KeyNameToLong(dflt);
97     info->groupInfo = 0;
98     info->typesDefined = info->symsDefined = info->actsDefined = 0;
99     for (i = 0; i < XkbNumKbdGroups; i++)
100     {
101         info->numLevels[i] = 0;
102         info->types[i] = None;
103         info->syms[i] = NULL;
104         info->acts[i] = NULL;
105     }
106     info->dfltType = None;
107     info->behavior.type = XkbKB_Default;
108     info->behavior.data = 0;
109     info->vmodmap = 0;
110     info->nameForOverlayKey = 0;
111     info->repeat = RepeatUndefined;
112     info->allowNone = 0;
113     return;
114 }
115
116 /**
117  * Free memory associated with this key info and reset to sane values.
118  */
119 static void
120 FreeKeyInfo(KeyInfo * info)
121 {
122     register int i;
123
124     info->defs.defined = 0;
125     info->defs.fileID = 0;
126     info->defs.merge = MergeOverride;
127     info->defs.next = NULL;
128     info->groupInfo = 0;
129     info->typesDefined = info->symsDefined = info->actsDefined = 0;
130     for (i = 0; i < XkbNumKbdGroups; i++)
131     {
132         info->numLevels[i] = 0;
133         info->types[i] = None;
134         if (info->syms[i] != NULL)
135             uFree(info->syms[i]);
136         info->syms[i] = NULL;
137         if (info->acts[i] != NULL)
138             uFree(info->acts[i]);
139         info->acts[i] = NULL;
140     }
141     info->dfltType = None;
142     info->behavior.type = XkbKB_Default;
143     info->behavior.data = 0;
144     info->vmodmap = 0;
145     info->nameForOverlayKey = 0;
146     info->repeat = RepeatUndefined;
147     info->allowNone = 0;
148     return;
149 }
150
151 /**
152  * Copy old into new, optionally reset old to 0.
153  * If old is reset, new simply re-uses old's memory. Otherwise, the memory is
154  * newly allocated and new points to the new memory areas.
155  */
156 static Bool
157 CopyKeyInfo(KeyInfo * old, KeyInfo * new, Bool clearOld)
158 {
159     register int i;
160
161     *new = *old;
162     new->defs.next = NULL;
163     if (clearOld)
164     {
165         for (i = 0; i < XkbNumKbdGroups; i++)
166         {
167             old->numLevels[i] = 0;
168             old->syms[i] = NULL;
169             old->acts[i] = NULL;
170         }
171     }
172     else
173     {
174         int width;
175         for (i = 0; i < XkbNumKbdGroups; i++)
176         {
177             width = new->numLevels[i];
178             if (old->syms[i] != NULL)
179             {
180                 new->syms[i] = uTypedCalloc(width, KeySym);
181                 if (!new->syms[i])
182                 {
183                     new->syms[i] = NULL;
184                     new->numLevels[i] = 0;
185                     return False;
186                 }
187                 memcpy((char *) new->syms[i], (char *) old->syms[i],
188                        width * sizeof(KeySym));
189             }
190             if (old->acts[i] != NULL)
191             {
192                 new->acts[i] = uTypedCalloc(width, XkbcAction);
193                 if (!new->acts[i])
194                 {
195                     new->acts[i] = NULL;
196                     return False;
197                 }
198                 memcpy((char *) new->acts[i], (char *) old->acts[i],
199                        width * sizeof(XkbcAction));
200             }
201         }
202     }
203     return True;
204 }
205
206 /***====================================================================***/
207
208 typedef struct _ModMapEntry
209 {
210     CommonInfo defs;
211     Bool haveSymbol;
212     int modifier;
213     union
214     {
215         unsigned long keyName;
216         KeySym keySym;
217     } u;
218 } ModMapEntry;
219
220 #define SYMBOLS_INIT_SIZE       110
221 #define SYMBOLS_CHUNK           20
222 typedef struct _SymbolsInfo
223 {
224     char *name;         /* e.g. pc+us+inet(evdev) */
225     int errorCount;
226     unsigned fileID;
227     unsigned merge;
228     unsigned explicit_group;
229     unsigned groupInfo;
230     unsigned szKeys;
231     unsigned nKeys;
232     KeyInfo *keys;
233     KeyInfo dflt;
234     VModInfo vmods;
235     ActionInfo *action;
236     Atom groupNames[XkbNumKbdGroups];
237
238     ModMapEntry *modMap;
239     AliasInfo *aliases;
240 } SymbolsInfo;
241
242 static void
243 InitSymbolsInfo(SymbolsInfo * info, XkbcDescPtr xkb)
244 {
245     register int i;
246
247     tok_ONE_LEVEL = XkbcInternAtom("ONE_LEVEL", False);
248     tok_TWO_LEVEL = XkbcInternAtom("TWO_LEVEL", False);
249     tok_KEYPAD = XkbcInternAtom("KEYPAD", False);
250     info->name = NULL;
251     info->explicit_group = 0;
252     info->errorCount = 0;
253     info->fileID = 0;
254     info->merge = MergeOverride;
255     info->groupInfo = 0;
256     info->szKeys = SYMBOLS_INIT_SIZE;
257     info->nKeys = 0;
258     info->keys = uTypedCalloc(SYMBOLS_INIT_SIZE, KeyInfo);
259     info->modMap = NULL;
260     for (i = 0; i < XkbNumKbdGroups; i++)
261         info->groupNames[i] = None;
262     InitKeyInfo(&info->dflt);
263     InitVModInfo(&info->vmods, xkb);
264     info->action = NULL;
265     info->aliases = NULL;
266     return;
267 }
268
269 static void
270 FreeSymbolsInfo(SymbolsInfo * info)
271 {
272     register int i;
273
274     if (info->name)
275         uFree(info->name);
276     info->name = NULL;
277     if (info->keys)
278     {
279         for (i = 0; i < info->nKeys; i++)
280         {
281             FreeKeyInfo(&info->keys[i]);
282         }
283         uFree(info->keys);
284         info->keys = NULL;
285     }
286     if (info->modMap)
287     {
288         ClearCommonInfo(&info->modMap->defs);
289         info->modMap = NULL;
290     }
291     if (info->aliases)
292     {
293         ClearAliases(&info->aliases);
294         info->aliases = NULL;
295     }
296     bzero((char *) info, sizeof(SymbolsInfo));
297     return;
298 }
299
300 static Bool
301 ResizeKeyGroup(KeyInfo * key,
302                unsigned group, unsigned atLeastSize, Bool forceActions)
303 {
304     Bool tooSmall;
305     unsigned newWidth;
306
307     tooSmall = (key->numLevels[group] < atLeastSize);
308     if (tooSmall)
309         newWidth = atLeastSize;
310     else
311         newWidth = key->numLevels[group];
312
313     if ((key->syms[group] == NULL) || tooSmall)
314     {
315         key->syms[group] = uTypedRecalloc(key->syms[group],
316                                           key->numLevels[group], newWidth,
317                                           KeySym);
318         if (!key->syms[group])
319             return False;
320     }
321     if (((forceActions) && (tooSmall || (key->acts[group] == NULL))) ||
322         (tooSmall && (key->acts[group] != NULL)))
323     {
324         key->acts[group] = uTypedRecalloc(key->acts[group],
325                                           key->numLevels[group], newWidth,
326                                           XkbcAction);
327         if (!key->acts[group])
328             return False;
329     }
330     key->numLevels[group] = newWidth;
331     return True;
332 }
333
334 static Bool
335 MergeKeyGroups(SymbolsInfo * info,
336                KeyInfo * into, KeyInfo * from, unsigned group)
337 {
338     KeySym *resultSyms;
339     XkbcAction *resultActs;
340     int resultWidth;
341     register int i;
342     Bool report, clobber;
343
344     clobber = (from->defs.merge != MergeAugment);
345     report = (warningLevel > 9) ||
346         ((into->defs.fileID == from->defs.fileID) && (warningLevel > 0));
347     if (into->numLevels[group] >= from->numLevels[group])
348     {
349         resultSyms = into->syms[group];
350         resultActs = into->acts[group];
351         resultWidth = into->numLevels[group];
352     }
353     else
354     {
355         resultSyms = from->syms[group];
356         resultActs = from->acts[group];
357         resultWidth = from->numLevels[group];
358     }
359     if (resultSyms == NULL)
360     {
361         resultSyms = uTypedCalloc(resultWidth, KeySym);
362         if (!resultSyms)
363         {
364             WSGO("Could not allocate symbols for group merge\n");
365             ACTION("Group %d of key %s not merged\n", group,
366                     longText(into->name));
367             return False;
368         }
369     }
370     if ((resultActs == NULL) && (into->acts[group] || from->acts[group]))
371     {
372         resultActs = uTypedCalloc(resultWidth, XkbcAction);
373         if (!resultActs)
374         {
375             WSGO("Could not allocate actions for group merge\n");
376             ACTION("Group %d of key %s not merged\n", group,
377                     longText(into->name));
378             return False;
379         }
380     }
381     for (i = 0; i < resultWidth; i++)
382     {
383         KeySym fromSym, toSym;
384         if (from->syms[group] && (i < from->numLevels[group]))
385             fromSym = from->syms[group][i];
386         else
387             fromSym = NoSymbol;
388         if (into->syms[group] && (i < into->numLevels[group]))
389             toSym = into->syms[group][i];
390         else
391             toSym = NoSymbol;
392         if ((fromSym == NoSymbol) || (fromSym == toSym))
393             resultSyms[i] = toSym;
394         else if (toSym == NoSymbol)
395             resultSyms[i] = fromSym;
396         else
397         {
398             KeySym use, ignore;
399             if (clobber)
400             {
401                 use = fromSym;
402                 ignore = toSym;
403             }
404             else
405             {
406                 use = toSym;
407                 ignore = fromSym;
408             }
409             if (report)
410             {
411                 WARN
412                     ("Multiple symbols for level %d/group %d on key %s\n",
413                      i + 1, group + 1, longText(into->name));
414                 ACTION("Using %s, ignoring %s\n",
415                         XkbcKeysymText(use), XkbcKeysymText(ignore));
416             }
417             resultSyms[i] = use;
418         }
419         if (resultActs != NULL)
420         {
421             XkbcAction *fromAct, *toAct;
422             fromAct = (from->acts[group] ? &from->acts[group][i] : NULL);
423             toAct = (into->acts[group] ? &into->acts[group][i] : NULL);
424             if (((fromAct == NULL) || (fromAct->type == XkbSA_NoAction))
425                 && (toAct != NULL))
426             {
427                 resultActs[i] = *toAct;
428             }
429             else if (((toAct == NULL) || (toAct->type == XkbSA_NoAction))
430                      && (fromAct != NULL))
431             {
432                 resultActs[i] = *fromAct;
433             }
434             else
435             {
436                 XkbcAction *use, *ignore;
437                 if (clobber)
438                 {
439                     use = fromAct;
440                     ignore = toAct;
441                 }
442                 else
443                 {
444                     use = toAct;
445                     ignore = fromAct;
446                 }
447                 if (report)
448                 {
449                     WARN
450                         ("Multiple actions for level %d/group %d on key %s\n",
451                          i + 1, group + 1, longText(into->name));
452                     ACTION("Using %s, ignoring %s\n",
453                             XkbcActionTypeText(use->type),
454                             XkbcActionTypeText(ignore->type));
455                 }
456                 resultActs[i] = *use;
457             }
458         }
459     }
460     if ((into->syms[group] != NULL) && (resultSyms != into->syms[group]))
461         uFree(into->syms[group]);
462     if ((from->syms[group] != NULL) && (resultSyms != from->syms[group]))
463         uFree(from->syms[group]);
464     if ((into->acts[group] != NULL) && (resultActs != into->acts[group]))
465         uFree(into->acts[group]);
466     if ((from->acts[group] != NULL) && (resultActs != from->acts[group]))
467         uFree(from->acts[group]);
468     into->numLevels[group] = resultWidth;
469     into->syms[group] = resultSyms;
470     from->syms[group] = NULL;
471     into->acts[group] = resultActs;
472     from->acts[group] = NULL;
473     into->symsDefined |= (1 << group);
474     from->symsDefined &= ~(1 << group);
475     into->actsDefined |= (1 << group);
476     from->actsDefined &= ~(1 << group);
477     return True;
478 }
479
480 static Bool
481 MergeKeys(SymbolsInfo * info, KeyInfo * into, KeyInfo * from)
482 {
483     register int i;
484     unsigned collide = 0;
485     Bool report;
486
487     if (from->defs.merge == MergeReplace)
488     {
489         for (i = 0; i < XkbNumKbdGroups; i++)
490         {
491             if (into->numLevels[i] != 0)
492             {
493                 if (into->syms[i])
494                     uFree(into->syms[i]);
495                 if (into->acts[i])
496                     uFree(into->acts[i]);
497             }
498         }
499         *into = *from;
500         bzero(from, sizeof(KeyInfo));
501         return True;
502     }
503     report = ((warningLevel > 9) ||
504               ((into->defs.fileID == from->defs.fileID)
505                && (warningLevel > 0)));
506     for (i = 0; i < XkbNumKbdGroups; i++)
507     {
508         if (from->numLevels[i] > 0)
509         {
510             if (into->numLevels[i] == 0)
511             {
512                 into->numLevels[i] = from->numLevels[i];
513                 into->syms[i] = from->syms[i];
514                 into->acts[i] = from->acts[i];
515                 into->symsDefined |= (1 << i);
516                 from->syms[i] = NULL;
517                 from->acts[i] = NULL;
518                 from->numLevels[i] = 0;
519                 from->symsDefined &= ~(1 << i);
520                 if (into->syms[i])
521                     into->defs.defined |= _Key_Syms;
522                 if (into->acts[i])
523                     into->defs.defined |= _Key_Acts;
524             }
525             else
526             {
527                 if (report)
528                 {
529                     if (into->syms[i])
530                         collide |= _Key_Syms;
531                     if (into->acts[i])
532                         collide |= _Key_Acts;
533                 }
534                 MergeKeyGroups(info, into, from, (unsigned) i);
535             }
536         }
537         if (from->types[i] != None)
538         {
539             if ((into->types[i] != None) && (report) &&
540                 (into->types[i] != from->types[i]))
541             {
542                 Atom use, ignore;
543                 collide |= _Key_Types;
544                 if (from->defs.merge != MergeAugment)
545                 {
546                     use = from->types[i];
547                     ignore = into->types[i];
548                 }
549                 else
550                 {
551                     use = into->types[i];
552                     ignore = from->types[i];
553                 }
554                 WARN
555                     ("Multiple definitions for group %d type of key %s\n",
556                      i, longText(into->name));
557                 ACTION("Using %s, ignoring %s\n",
558                         XkbcAtomText(use),
559                         XkbcAtomText(ignore));
560             }
561             if ((from->defs.merge != MergeAugment)
562                 || (into->types[i] == None))
563             {
564                 into->types[i] = from->types[i];
565             }
566         }
567     }
568     if (UseNewField(_Key_Behavior, &into->defs, &from->defs, &collide))
569     {
570         into->behavior = from->behavior;
571         into->nameForOverlayKey = from->nameForOverlayKey;
572         into->defs.defined |= _Key_Behavior;
573     }
574     if (UseNewField(_Key_VModMap, &into->defs, &from->defs, &collide))
575     {
576         into->vmodmap = from->vmodmap;
577         into->defs.defined |= _Key_VModMap;
578     }
579     if (UseNewField(_Key_Repeat, &into->defs, &from->defs, &collide))
580     {
581         into->repeat = from->repeat;
582         into->defs.defined |= _Key_Repeat;
583     }
584     if (UseNewField(_Key_Type_Dflt, &into->defs, &from->defs, &collide))
585     {
586         into->dfltType = from->dfltType;
587         into->defs.defined |= _Key_Type_Dflt;
588     }
589     if (UseNewField(_Key_GroupInfo, &into->defs, &from->defs, &collide))
590     {
591         into->groupInfo = from->groupInfo;
592         into->defs.defined |= _Key_GroupInfo;
593     }
594     if (collide)
595     {
596         WARN("Symbol map for key %s redefined\n",
597               longText(into->name));
598         ACTION("Using %s definition for conflicting fields\n",
599                 (from->defs.merge == MergeAugment ? "first" : "last"));
600     }
601     return True;
602 }
603
604 static Bool
605 AddKeySymbols(SymbolsInfo * info, KeyInfo * key, XkbcDescPtr xkb)
606 {
607     register int i;
608     unsigned long real_name;
609
610     for (i = 0; i < info->nKeys; i++)
611     {
612         if (info->keys[i].name == key->name)
613             return MergeKeys(info, &info->keys[i], key);
614     }
615     if (FindKeyNameForAlias(xkb, key->name, &real_name))
616     {
617         for (i = 0; i < info->nKeys; i++)
618         {
619             if (info->keys[i].name == real_name)
620                 return MergeKeys(info, &info->keys[i], key);
621         }
622     }
623     if (info->nKeys >= info->szKeys)
624     {
625         info->szKeys += SYMBOLS_CHUNK;
626         info->keys =
627             uTypedRecalloc(info->keys, info->nKeys, info->szKeys, KeyInfo);
628         if (!info->keys)
629         {
630             WSGO("Could not allocate key symbols descriptions\n");
631             ACTION("Some key symbols definitions may be lost\n");
632             return False;
633         }
634     }
635     return CopyKeyInfo(key, &info->keys[info->nKeys++], True);
636 }
637
638 static Bool
639 AddModMapEntry(SymbolsInfo * info, ModMapEntry * new)
640 {
641     ModMapEntry *mm;
642     Bool clobber;
643
644     clobber = (new->defs.merge != MergeAugment);
645     for (mm = info->modMap; mm != NULL; mm = (ModMapEntry *) mm->defs.next)
646     {
647         if (new->haveSymbol && mm->haveSymbol
648             && (new->u.keySym == mm->u.keySym))
649         {
650             unsigned use, ignore;
651             if (mm->modifier != new->modifier)
652             {
653                 if (clobber)
654                 {
655                     use = new->modifier;
656                     ignore = mm->modifier;
657                 }
658                 else
659                 {
660                     use = mm->modifier;
661                     ignore = new->modifier;
662                 }
663                 ERROR
664                     ("%s added to symbol map for multiple modifiers\n",
665                      XkbcKeysymText(new->u.keySym));
666                 ACTION("Using %s, ignoring %s.\n",
667                         XkbcModIndexText(use),
668                         XkbcModIndexText(ignore));
669                 mm->modifier = use;
670             }
671             return True;
672         }
673         if ((!new->haveSymbol) && (!mm->haveSymbol) &&
674             (new->u.keyName == mm->u.keyName))
675         {
676             unsigned use, ignore;
677             if (mm->modifier != new->modifier)
678             {
679                 if (clobber)
680                 {
681                     use = new->modifier;
682                     ignore = mm->modifier;
683                 }
684                 else
685                 {
686                     use = mm->modifier;
687                     ignore = new->modifier;
688                 }
689                 ERROR("Key %s added to map for multiple modifiers\n",
690                        longText(new->u.keyName));
691                 ACTION("Using %s, ignoring %s.\n",
692                         XkbcModIndexText(use),
693                         XkbcModIndexText(ignore));
694                 mm->modifier = use;
695             }
696             return True;
697         }
698     }
699     mm = uTypedAlloc(ModMapEntry);
700     if (mm == NULL)
701     {
702         WSGO("Could not allocate modifier map entry\n");
703         ACTION("Modifier map for %s will be incomplete\n",
704                 XkbcModIndexText(new->modifier));
705         return False;
706     }
707     *mm = *new;
708     mm->defs.next = &info->modMap->defs;
709     info->modMap = mm;
710     return True;
711 }
712
713 /***====================================================================***/
714
715 static void
716 MergeIncludedSymbols(SymbolsInfo * into, SymbolsInfo * from,
717                      unsigned merge, XkbcDescPtr xkb)
718 {
719     register int i;
720     KeyInfo *key;
721
722     if (from->errorCount > 0)
723     {
724         into->errorCount += from->errorCount;
725         return;
726     }
727     if (into->name == NULL)
728     {
729         into->name = from->name;
730         from->name = NULL;
731     }
732     for (i = 0; i < XkbNumKbdGroups; i++)
733     {
734         if (from->groupNames[i] != None)
735         {
736             if ((merge != MergeAugment) || (into->groupNames[i] == None))
737                 into->groupNames[i] = from->groupNames[i];
738         }
739     }
740     for (i = 0, key = from->keys; i < from->nKeys; i++, key++)
741     {
742         if (merge != MergeDefault)
743             key->defs.merge = merge;
744         if (!AddKeySymbols(into, key, xkb))
745             into->errorCount++;
746     }
747     if (from->modMap != NULL)
748     {
749         ModMapEntry *mm, *next;
750         for (mm = from->modMap; mm != NULL; mm = next)
751         {
752             if (merge != MergeDefault)
753                 mm->defs.merge = merge;
754             if (!AddModMapEntry(into, mm))
755                 into->errorCount++;
756             next = (ModMapEntry *) mm->defs.next;
757             uFree(mm);
758         }
759         from->modMap = NULL;
760     }
761     if (!MergeAliases(&into->aliases, &from->aliases, merge))
762         into->errorCount++;
763     return;
764 }
765
766 typedef void (*FileHandler) (XkbFile * /* rtrn */ ,
767                              XkbcDescPtr /* xkb */ ,
768                              unsigned /* merge */ ,
769                              SymbolsInfo *      /* included */
770     );
771
772 static Bool
773 HandleIncludeSymbols(IncludeStmt * stmt,
774                      XkbcDescPtr xkb, SymbolsInfo * info, FileHandler hndlr)
775 {
776     unsigned newMerge;
777     XkbFile *rtrn;
778     SymbolsInfo included;
779     Bool haveSelf;
780
781     haveSelf = False;
782     if ((stmt->file == NULL) && (stmt->map == NULL))
783     {
784         haveSelf = True;
785         included = *info;
786         bzero(info, sizeof(SymbolsInfo));
787     }
788     else if (ProcessIncludeFile(stmt, XkmSymbolsIndex, &rtrn, &newMerge))
789     {
790         InitSymbolsInfo(&included, xkb);
791         included.fileID = included.dflt.defs.fileID = rtrn->id;
792         included.merge = included.dflt.defs.merge = MergeOverride;
793         if (stmt->modifier)
794         {
795             included.explicit_group = atoi(stmt->modifier) - 1;
796         }
797         else
798         {
799             included.explicit_group = info->explicit_group;
800         }
801         (*hndlr) (rtrn, xkb, MergeOverride, &included);
802         if (stmt->stmt != NULL)
803         {
804             if (included.name != NULL)
805                 uFree(included.name);
806             included.name = stmt->stmt;
807             stmt->stmt = NULL;
808         }
809     }
810     else
811     {
812         info->errorCount += 10;
813         return False;
814     }
815     if ((stmt->next != NULL) && (included.errorCount < 1))
816     {
817         IncludeStmt *next;
818         unsigned op;
819         SymbolsInfo next_incl;
820
821         for (next = stmt->next; next != NULL; next = next->next)
822         {
823             if ((next->file == NULL) && (next->map == NULL))
824             {
825                 haveSelf = True;
826                 MergeIncludedSymbols(&included, info, next->merge, xkb);
827                 FreeSymbolsInfo(info);
828             }
829             else if (ProcessIncludeFile(next, XkmSymbolsIndex, &rtrn, &op))
830             {
831                 InitSymbolsInfo(&next_incl, xkb);
832                 next_incl.fileID = next_incl.dflt.defs.fileID = rtrn->id;
833                 next_incl.merge = next_incl.dflt.defs.merge = MergeOverride;
834                 if (next->modifier)
835                 {
836                     next_incl.explicit_group = atoi(next->modifier) - 1;
837                 }
838                 else
839                 {
840                     next_incl.explicit_group = info->explicit_group;
841                 }
842                 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
843                 MergeIncludedSymbols(&included, &next_incl, op, xkb);
844                 FreeSymbolsInfo(&next_incl);
845             }
846             else
847             {
848                 info->errorCount += 10;
849                 return False;
850             }
851         }
852     }
853     if (haveSelf)
854         *info = included;
855     else
856     {
857         MergeIncludedSymbols(info, &included, newMerge, xkb);
858         FreeSymbolsInfo(&included);
859     }
860     return (info->errorCount == 0);
861 }
862
863 static LookupEntry groupNames[] = {
864     {"group1", 1},
865     {"group2", 2},
866     {"group3", 3},
867     {"group4", 4},
868     {"group5", 5},
869     {"group6", 6},
870     {"group7", 7},
871     {"group8", 8},
872     {NULL, 0}
873 };
874
875
876 #define SYMBOLS 1
877 #define ACTIONS 2
878
879 static Bool
880 GetGroupIndex(KeyInfo * key,
881               ExprDef * arrayNdx, unsigned what, unsigned *ndx_rtrn)
882 {
883     const char *name;
884     ExprResult tmp;
885
886     if (what == SYMBOLS)
887         name = "symbols";
888     else
889         name = "actions";
890
891     if (arrayNdx == NULL)
892     {
893         register int i;
894         unsigned defined;
895         if (what == SYMBOLS)
896             defined = key->symsDefined;
897         else
898             defined = key->actsDefined;
899
900         for (i = 0; i < XkbNumKbdGroups; i++)
901         {
902             if ((defined & (1 << i)) == 0)
903             {
904                 *ndx_rtrn = i;
905                 return True;
906             }
907         }
908         ERROR("Too many groups of %s for key %s (max %d)\n", name,
909                longText(key->name), XkbNumKbdGroups + 1);
910         ACTION("Ignoring %s defined for extra groups\n", name);
911         return False;
912     }
913     if (!ExprResolveInteger
914         (arrayNdx, &tmp, SimpleLookup, (char *) groupNames))
915     {
916         ERROR("Illegal group index for %s of key %s\n", name,
917                longText(key->name));
918         ACTION("Definition with non-integer array index ignored\n");
919         return False;
920     }
921     if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
922     {
923         ERROR("Group index for %s of key %s is out of range (1..%d)\n",
924                name, longText(key->name), XkbNumKbdGroups + 1);
925         ACTION("Ignoring %s for group %d\n", name, tmp.uval);
926         return False;
927     }
928     *ndx_rtrn = tmp.uval - 1;
929     return True;
930 }
931
932 static Bool
933 AddSymbolsToKey(KeyInfo * key,
934                 XkbcDescPtr xkb,
935                 char *field,
936                 ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
937 {
938     unsigned ndx, nSyms;
939     int i;
940
941     if (!GetGroupIndex(key, arrayNdx, SYMBOLS, &ndx))
942         return False;
943     if (value == NULL)
944     {
945         key->symsDefined |= (1 << ndx);
946         return True;
947     }
948     if (value->op != ExprKeysymList)
949     {
950         ERROR("Expected a list of symbols, found %s\n",
951                exprOpText(value->op));
952         ACTION("Ignoring symbols for group %d of %s\n", ndx,
953                 longText(key->name));
954         return False;
955     }
956     if (key->syms[ndx] != NULL)
957     {
958         WSGO("Symbols for key %s, group %d already defined\n",
959               longText(key->name), ndx);
960         return False;
961     }
962     nSyms = value->value.list.nSyms;
963     if (((key->numLevels[ndx] < nSyms) || (key->syms[ndx] == NULL)) &&
964         (!ResizeKeyGroup(key, ndx, nSyms, False)))
965     {
966         WSGO("Could not resize group %d of key %s\n", ndx,
967               longText(key->name));
968         ACTION("Symbols lost\n");
969         return False;
970     }
971     key->symsDefined |= (1 << ndx);
972     memcpy((char *) key->syms[ndx], (char *) value->value.list.syms,
973            nSyms * sizeof(KeySym));
974     for (i = key->numLevels[ndx] - 1;
975          (i >= 0) && (key->syms[ndx][i] == NoSymbol); i--)
976     {
977         key->numLevels[ndx]--;
978     }
979     return True;
980 }
981
982 static Bool
983 AddActionsToKey(KeyInfo * key,
984                 XkbcDescPtr xkb,
985                 char *field,
986                 ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
987 {
988     register int i;
989     unsigned ndx, nActs;
990     ExprDef *act;
991     XkbAnyAction *toAct;
992
993     if (!GetGroupIndex(key, arrayNdx, ACTIONS, &ndx))
994         return False;
995
996     if (value == NULL)
997     {
998         key->actsDefined |= (1 << ndx);
999         return True;
1000     }
1001     if (value->op != ExprActionList)
1002     {
1003         WSGO("Bad expression type (%d) for action list value\n", value->op);
1004         ACTION("Ignoring actions for group %d of %s\n", ndx,
1005                 longText(key->name));
1006         return False;
1007     }
1008     if (key->acts[ndx] != NULL)
1009     {
1010         WSGO("Actions for key %s, group %d already defined\n",
1011               longText(key->name), ndx);
1012         return False;
1013     }
1014     for (nActs = 0, act = value->value.child; act != NULL; nActs++)
1015     {
1016         act = (ExprDef *) act->common.next;
1017     }
1018     if (nActs < 1)
1019     {
1020         WSGO("Action list but not actions in AddActionsToKey\n");
1021         return False;
1022     }
1023     if (((key->numLevels[ndx] < nActs) || (key->acts[ndx] == NULL)) &&
1024         (!ResizeKeyGroup(key, ndx, nActs, True)))
1025     {
1026         WSGO("Could not resize group %d of key %s\n", ndx,
1027               longText(key->name));
1028         ACTION("Actions lost\n");
1029         return False;
1030     }
1031     key->actsDefined |= (1 << ndx);
1032
1033     toAct = (XkbAnyAction *) key->acts[ndx];
1034     act = value->value.child;
1035     for (i = 0; i < nActs; i++, toAct++)
1036     {
1037         if (!HandleActionDef(act, xkb, toAct, MergeOverride, info->action))
1038         {
1039             ERROR("Illegal action definition for %s\n",
1040                    longText(key->name));
1041             ACTION("Action for group %d/level %d ignored\n", ndx + 1, i + 1);
1042         }
1043         act = (ExprDef *) act->common.next;
1044     }
1045     return True;
1046 }
1047
1048 static int
1049 SetAllowNone(KeyInfo * key, ExprDef * arrayNdx, ExprDef * value)
1050 {
1051     ExprResult tmp;
1052     unsigned radio_groups = 0;
1053
1054     if (arrayNdx == NULL)
1055     {
1056         radio_groups = XkbAllRadioGroupsMask;
1057     }
1058     else
1059     {
1060         if (!ExprResolveInteger(arrayNdx, &tmp, RadioLookup, NULL))
1061         {
1062             ERROR("Illegal index in group name definition\n");
1063             ACTION("Definition with non-integer array index ignored\n");
1064             return False;
1065         }
1066         if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups))
1067         {
1068             ERROR("Illegal radio group specified (must be 1..%d)\n",
1069                    XkbMaxRadioGroups + 1);
1070             ACTION("Value of \"allow none\" for group %d ignored\n",
1071                     tmp.uval);
1072             return False;
1073         }
1074         radio_groups |= (1 << (tmp.uval - 1));
1075     }
1076     if (!ExprResolveBoolean(value, &tmp, NULL, NULL))
1077     {
1078         ERROR("Illegal \"allow none\" value for %s\n",
1079                longText(key->name));
1080         ACTION("Non-boolean value ignored\n");
1081         return False;
1082     }
1083     if (tmp.uval)
1084         key->allowNone |= radio_groups;
1085     else
1086         key->allowNone &= ~radio_groups;
1087     return True;
1088 }
1089
1090
1091 static LookupEntry lockingEntries[] = {
1092     {"true", XkbKB_Lock},
1093     {"yes", XkbKB_Lock},
1094     {"on", XkbKB_Lock},
1095     {"false", XkbKB_Default},
1096     {"no", XkbKB_Default},
1097     {"off", XkbKB_Default},
1098     {"permanent", XkbKB_Lock | XkbKB_Permanent},
1099     {NULL, 0}
1100 };
1101
1102 static LookupEntry repeatEntries[] = {
1103     {"true", RepeatYes},
1104     {"yes", RepeatYes},
1105     {"on", RepeatYes},
1106     {"false", RepeatNo},
1107     {"no", RepeatNo},
1108     {"off", RepeatNo},
1109     {"default", RepeatUndefined},
1110     {NULL, 0}
1111 };
1112
1113 static LookupEntry rgEntries[] = {
1114     {"none", 0},
1115     {NULL, 0}
1116 };
1117
1118 static Bool
1119 SetSymbolsField(KeyInfo * key,
1120                 XkbcDescPtr xkb,
1121                 char *field,
1122                 ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
1123 {
1124     Bool ok = True;
1125     ExprResult tmp;
1126
1127     if (uStrCaseCmp(field, "type") == 0)
1128     {
1129         ExprResult ndx;
1130         if ((!ExprResolveString(value, &tmp, NULL, NULL))
1131             && (warningLevel > 0))
1132         {
1133             WARN("The type field of a key symbol map must be a string\n");
1134             ACTION("Ignoring illegal type definition\n");
1135         }
1136         if (arrayNdx == NULL)
1137         {
1138             key->dfltType = XkbcInternAtom(tmp.str, False);
1139             key->defs.defined |= _Key_Type_Dflt;
1140         }
1141         else if (!ExprResolveInteger(arrayNdx, &ndx, SimpleLookup,
1142                                      (char *) groupNames))
1143         {
1144             ERROR("Illegal group index for type of key %s\n",
1145                    longText(key->name));
1146             ACTION("Definition with non-integer array index ignored\n");
1147             free(tmp.str);
1148             return False;
1149         }
1150         else if ((ndx.uval < 1) || (ndx.uval > XkbNumKbdGroups))
1151         {
1152             ERROR
1153                 ("Group index for type of key %s is out of range (1..%d)\n",
1154                  longText(key->name), XkbNumKbdGroups + 1);
1155             ACTION("Ignoring type for group %d\n", ndx.uval);
1156             free(tmp.str);
1157             return False;
1158         }
1159         else
1160         {
1161             key->types[ndx.uval - 1] = XkbcInternAtom(tmp.str, False);
1162             key->typesDefined |= (1 << (ndx.uval - 1));
1163         }
1164         free(tmp.str);
1165     }
1166     else if (uStrCaseCmp(field, "symbols") == 0)
1167         return AddSymbolsToKey(key, xkb, field, arrayNdx, value, info);
1168     else if (uStrCaseCmp(field, "actions") == 0)
1169         return AddActionsToKey(key, xkb, field, arrayNdx, value, info);
1170     else if ((uStrCaseCmp(field, "vmods") == 0) ||
1171              (uStrCaseCmp(field, "virtualmods") == 0) ||
1172              (uStrCaseCmp(field, "virtualmodifiers") == 0))
1173     {
1174         ok = ExprResolveModMask(value, &tmp, LookupVModMask, (char *) xkb);
1175         if (ok)
1176         {
1177             key->vmodmap = (tmp.uval >> 8);
1178             key->defs.defined |= _Key_VModMap;
1179         }
1180         else
1181         {
1182             ERROR("Expected a virtual modifier mask, found %s\n",
1183                    exprOpText(value->op));
1184             ACTION("Ignoring virtual modifiers definition for key %s\n",
1185                     longText(key->name));
1186         }
1187     }
1188     else if ((uStrCaseCmp(field, "locking") == 0)
1189              || (uStrCaseCmp(field, "lock") == 0)
1190              || (uStrCaseCmp(field, "locks") == 0))
1191     {
1192         ok = ExprResolveEnum(value, &tmp, lockingEntries);
1193         if (ok)
1194             key->behavior.type = tmp.uval;
1195         key->defs.defined |= _Key_Behavior;
1196     }
1197     else if ((uStrCaseCmp(field, "radiogroup") == 0) ||
1198              (uStrCaseCmp(field, "permanentradiogroup") == 0))
1199     {
1200         Bool permanent = False;
1201         if (uStrCaseCmp(field, "permanentradiogroup") == 0)
1202             permanent = True;
1203         ok = ExprResolveInteger(value, &tmp, SimpleLookup,
1204                                 (char *) rgEntries);
1205         if (!ok)
1206         {
1207             ERROR("Illegal radio group specification for %s\n",
1208                    longText(key->name));
1209             ACTION("Non-integer radio group ignored\n");
1210             return False;
1211         }
1212         if (tmp.uval == 0)
1213         {
1214             key->behavior.type = XkbKB_Default;
1215             key->behavior.data = 0;
1216             return ok;
1217         }
1218         if ((tmp.uval < 1) || (tmp.uval > XkbMaxRadioGroups))
1219         {
1220             ERROR
1221                 ("Radio group specification for %s out of range (1..32)\n",
1222                  longText(key->name));
1223             ACTION("Illegal radio group %d ignored\n", tmp.uval);
1224             return False;
1225         }
1226         key->behavior.type =
1227             XkbKB_RadioGroup | (permanent ? XkbKB_Permanent : 0);
1228         key->behavior.data = tmp.uval - 1;
1229         if (key->allowNone & (1 << (tmp.uval - 1)))
1230             key->behavior.data |= XkbKB_RGAllowNone;
1231         key->defs.defined |= _Key_Behavior;
1232     }
1233     else if (uStrCaseEqual(field, "allownone"))
1234     {
1235         ok = SetAllowNone(key, arrayNdx, value);
1236     }
1237     else if (uStrCasePrefix("overlay", field) ||
1238              uStrCasePrefix("permanentoverlay", field))
1239     {
1240         Bool permanent = False;
1241         char *which;
1242         int overlayNdx;
1243         if (uStrCasePrefix("permanent", field))
1244         {
1245             permanent = True;
1246             which = &field[sizeof("permanentoverlay") - 1];
1247         }
1248         else
1249         {
1250             which = &field[sizeof("overlay") - 1];
1251         }
1252         if (sscanf(which, "%d", &overlayNdx) == 1)
1253         {
1254             if (((overlayNdx < 1) || (overlayNdx > 2)) && (warningLevel > 0))
1255             {
1256                 ERROR("Illegal overlay %d specified for %s\n",
1257                        overlayNdx, longText(key->name));
1258                 ACTION("Ignored\n");
1259                 return False;
1260             }
1261         }
1262         else if (*which == '\0')
1263             overlayNdx = 1;
1264         else if (warningLevel > 0)
1265         {
1266             ERROR("Illegal overlay \"%s\" specified for %s\n",
1267                    which, longText(key->name));
1268             ACTION("Ignored\n");
1269             return False;
1270         }
1271         ok = ExprResolveKeyName(value, &tmp, NULL, NULL);
1272         if (!ok)
1273         {
1274             ERROR("Illegal overlay key specification for %s\n",
1275                    longText(key->name));
1276             ACTION("Overlay key must be specified by name\n");
1277             return False;
1278         }
1279         if (overlayNdx == 1)
1280             key->behavior.type = XkbKB_Overlay1;
1281         else
1282             key->behavior.type = XkbKB_Overlay2;
1283         if (permanent)
1284             key->behavior.type |= XkbKB_Permanent;
1285
1286         key->behavior.data = 0;
1287         key->nameForOverlayKey = KeyNameToLong(tmp.keyName.name);
1288         key->defs.defined |= _Key_Behavior;
1289     }
1290     else if ((uStrCaseCmp(field, "repeating") == 0) ||
1291              (uStrCaseCmp(field, "repeats") == 0) ||
1292              (uStrCaseCmp(field, "repeat") == 0))
1293     {
1294         ok = ExprResolveEnum(value, &tmp, repeatEntries);
1295         if (!ok)
1296         {
1297             ERROR("Illegal repeat setting for %s\n",
1298                    longText(key->name));
1299             ACTION("Non-boolean repeat setting ignored\n");
1300             return False;
1301         }
1302         key->repeat = tmp.uval;
1303         key->defs.defined |= _Key_Repeat;
1304     }
1305     else if ((uStrCaseCmp(field, "groupswrap") == 0) ||
1306              (uStrCaseCmp(field, "wrapgroups") == 0))
1307     {
1308         ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
1309         if (!ok)
1310         {
1311             ERROR("Illegal groupsWrap setting for %s\n",
1312                    longText(key->name));
1313             ACTION("Non-boolean value ignored\n");
1314             return False;
1315         }
1316         if (tmp.uval)
1317             key->groupInfo = XkbWrapIntoRange;
1318         else
1319             key->groupInfo = XkbClampIntoRange;
1320         key->defs.defined |= _Key_GroupInfo;
1321     }
1322     else if ((uStrCaseCmp(field, "groupsclamp") == 0) ||
1323              (uStrCaseCmp(field, "clampgroups") == 0))
1324     {
1325         ok = ExprResolveBoolean(value, &tmp, NULL, NULL);
1326         if (!ok)
1327         {
1328             ERROR("Illegal groupsClamp setting for %s\n",
1329                    longText(key->name));
1330             ACTION("Non-boolean value ignored\n");
1331             return False;
1332         }
1333         if (tmp.uval)
1334             key->groupInfo = XkbClampIntoRange;
1335         else
1336             key->groupInfo = XkbWrapIntoRange;
1337         key->defs.defined |= _Key_GroupInfo;
1338     }
1339     else if ((uStrCaseCmp(field, "groupsredirect") == 0) ||
1340              (uStrCaseCmp(field, "redirectgroups") == 0))
1341     {
1342         if (!ExprResolveInteger
1343             (value, &tmp, SimpleLookup, (char *) groupNames))
1344         {
1345             ERROR("Illegal group index for redirect of key %s\n",
1346                    longText(key->name));
1347             ACTION("Definition with non-integer group ignored\n");
1348             return False;
1349         }
1350         if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1351         {
1352             ERROR("Out-of-range (1..%d) group for redirect of key %s\n",
1353                    XkbNumKbdGroups, longText(key->name));
1354             ERROR("Ignoring illegal group %d\n", tmp.uval);
1355             return False;
1356         }
1357         key->groupInfo =
1358             XkbSetGroupInfo(0, XkbRedirectIntoRange, tmp.uval - 1);
1359         key->defs.defined |= _Key_GroupInfo;
1360     }
1361     else
1362     {
1363         ERROR("Unknown field %s in a symbol interpretation\n", field);
1364         ACTION("Definition ignored\n");
1365         ok = False;
1366     }
1367     return ok;
1368 }
1369
1370 static int
1371 SetGroupName(SymbolsInfo * info, ExprDef * arrayNdx, ExprDef * value)
1372 {
1373     ExprResult tmp, name;
1374
1375     if ((arrayNdx == NULL) && (warningLevel > 0))
1376     {
1377         WARN("You must specify an index when specifying a group name\n");
1378         ACTION("Group name definition without array subscript ignored\n");
1379         return False;
1380     }
1381     if (!ExprResolveInteger
1382         (arrayNdx, &tmp, SimpleLookup, (char *) groupNames))
1383     {
1384         ERROR("Illegal index in group name definition\n");
1385         ACTION("Definition with non-integer array index ignored\n");
1386         return False;
1387     }
1388     if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1389     {
1390         ERROR
1391             ("Attempt to specify name for illegal group (must be 1..%d)\n",
1392              XkbNumKbdGroups + 1);
1393         ACTION("Name for group %d ignored\n", tmp.uval);
1394         return False;
1395     }
1396     if (!ExprResolveString(value, &name, NULL, NULL))
1397     {
1398         ERROR("Group name must be a string\n");
1399         ACTION("Illegal name for group %d ignored\n", tmp.uval);
1400         return False;
1401     }
1402     info->groupNames[tmp.uval - 1 + info->explicit_group] =
1403         XkbcInternAtom(name.str, False);
1404
1405     return True;
1406 }
1407
1408 static int
1409 HandleSymbolsVar(VarDef * stmt, XkbcDescPtr xkb, SymbolsInfo * info)
1410 {
1411     ExprResult elem, field, tmp;
1412     ExprDef *arrayNdx;
1413     Bool ret;
1414
1415     if (ExprResolveLhs(stmt->name, &elem, &field, &arrayNdx) == 0)
1416         return 0;               /* internal error, already reported */
1417     if (elem.str && (uStrCaseCmp(elem.str, "key") == 0))
1418     {
1419         ret = SetSymbolsField(&info->dflt, xkb, field.str, arrayNdx,
1420                               stmt->value, info);
1421     }
1422     else if ((elem.str == NULL) && ((uStrCaseCmp(field.str, "name") == 0) ||
1423                                     (uStrCaseCmp(field.str, "groupname") ==
1424                                      0)))
1425     {
1426         ret = SetGroupName(info, arrayNdx, stmt->value);
1427     }
1428     else if ((elem.str == NULL)
1429              && ((uStrCaseCmp(field.str, "groupswrap") == 0)
1430                  || (uStrCaseCmp(field.str, "wrapgroups") == 0)))
1431     {
1432         if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL))
1433         {
1434             ERROR("Illegal setting for global groupsWrap\n");
1435             ACTION("Non-boolean value ignored\n");
1436             ret = False;
1437         }
1438         else {
1439             if (tmp.uval)
1440                 info->groupInfo = XkbWrapIntoRange;
1441             else
1442                 info->groupInfo = XkbClampIntoRange;
1443             ret = True;
1444         }
1445     }
1446     else if ((elem.str == NULL)
1447              && ((uStrCaseCmp(field.str, "groupsclamp") == 0)
1448                  || (uStrCaseCmp(field.str, "clampgroups") == 0)))
1449     {
1450         if (!ExprResolveBoolean(stmt->value, &tmp, NULL, NULL))
1451         {
1452             ERROR("Illegal setting for global groupsClamp\n");
1453             ACTION("Non-boolean value ignored\n");
1454             return False;
1455         }
1456         else {
1457             if (tmp.uval)
1458                 info->groupInfo = XkbClampIntoRange;
1459             else
1460                 info->groupInfo = XkbWrapIntoRange;
1461             ret = True;
1462         }
1463     }
1464     else if ((elem.str == NULL)
1465              && ((uStrCaseCmp(field.str, "groupsredirect") == 0)
1466                  || (uStrCaseCmp(field.str, "redirectgroups") == 0)))
1467     {
1468         if (!ExprResolveInteger(stmt->value, &tmp,
1469                                 SimpleLookup, (char *) groupNames))
1470         {
1471             ERROR("Illegal group index for global groupsRedirect\n");
1472             ACTION("Definition with non-integer group ignored\n");
1473             ret = False;
1474         }
1475         else {
1476             if ((tmp.uval < 1) || (tmp.uval > XkbNumKbdGroups))
1477             {
1478                 ERROR
1479                     ("Out-of-range (1..%d) group for global groupsRedirect\n",
1480                      XkbNumKbdGroups);
1481                 ACTION("Ignoring illegal group %d\n", tmp.uval);
1482                 ret = False;
1483             }
1484             else {
1485                 info->groupInfo = XkbSetGroupInfo(0, XkbRedirectIntoRange,
1486                                                   tmp.uval);
1487                 ret = True;
1488             }
1489         }
1490     }
1491     else if ((elem.str == NULL) && (uStrCaseCmp(field.str, "allownone") == 0))
1492     {
1493         ret = SetAllowNone(&info->dflt, arrayNdx, stmt->value);
1494     }
1495     else {
1496         ret = SetActionField(xkb, elem.str, field.str, arrayNdx, stmt->value,
1497                              &info->action);
1498     }
1499
1500     free(elem.str);
1501     free(field.str);
1502     return ret;
1503 }
1504
1505 static Bool
1506 HandleSymbolsBody(VarDef * def,
1507                   XkbcDescPtr xkb, KeyInfo * key, SymbolsInfo * info)
1508 {
1509     Bool ok = True;
1510     ExprResult tmp, field;
1511     ExprDef *arrayNdx;
1512
1513     for (; def != NULL; def = (VarDef *) def->common.next)
1514     {
1515         if ((def->name) && (def->name->type == ExprFieldRef))
1516         {
1517             ok = HandleSymbolsVar(def, xkb, info);
1518             continue;
1519         }
1520         else
1521         {
1522             if (def->name == NULL)
1523             {
1524                 if ((def->value == NULL)
1525                     || (def->value->op == ExprKeysymList))
1526                     field.str = "symbols";
1527                 else
1528                     field.str = "actions";
1529                 arrayNdx = NULL;
1530             }
1531             else
1532             {
1533                 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
1534             }
1535             if (ok)
1536                 ok = SetSymbolsField(key, xkb, field.str, arrayNdx,
1537                                      def->value, info);
1538         }
1539     }
1540     return ok;
1541 }
1542
1543 static Bool
1544 SetExplicitGroup(SymbolsInfo * info, KeyInfo * key)
1545 {
1546     unsigned group = info->explicit_group;
1547
1548     if (group == 0)
1549         return True;
1550
1551     if ((key->typesDefined | key->symsDefined | key->actsDefined) & ~1)
1552     {
1553         int i;
1554         WARN("For the map %s an explicit group specified\n", info->name);
1555         WARN("but key %s has more than one group defined\n",
1556               longText(key->name));
1557         ACTION("All groups except first one will be ignored\n");
1558         for (i = 1; i < XkbNumKbdGroups; i++)
1559         {
1560             key->numLevels[i] = 0;
1561             if (key->syms[i] != NULL)
1562                 uFree(key->syms[i]);
1563             key->syms[i] = (KeySym *) NULL;
1564             if (key->acts[i] != NULL)
1565                 uFree(key->acts[i]);
1566             key->acts[i] = (XkbcAction *) NULL;
1567             key->types[i] = (Atom) 0;
1568         }
1569     }
1570     key->typesDefined = key->symsDefined = key->actsDefined = 1 << group;
1571
1572     key->numLevels[group] = key->numLevels[0];
1573     key->numLevels[0] = 0;
1574     key->syms[group] = key->syms[0];
1575     key->syms[0] = (KeySym *) NULL;
1576     key->acts[group] = key->acts[0];
1577     key->acts[0] = (XkbcAction *) NULL;
1578     key->types[group] = key->types[0];
1579     key->types[0] = (Atom) 0;
1580     return True;
1581 }
1582
1583 static int
1584 HandleSymbolsDef(SymbolsDef * stmt,
1585                  XkbcDescPtr xkb, unsigned merge, SymbolsInfo * info)
1586 {
1587     KeyInfo key;
1588
1589     InitKeyInfo(&key);
1590     CopyKeyInfo(&info->dflt, &key, False);
1591     key.defs.merge = stmt->merge;
1592     key.name = KeyNameToLong(stmt->keyName);
1593     if (!HandleSymbolsBody((VarDef *) stmt->symbols, xkb, &key, info))
1594     {
1595         info->errorCount++;
1596         return False;
1597     }
1598
1599     if (!SetExplicitGroup(info, &key))
1600     {
1601         info->errorCount++;
1602         return False;
1603     }
1604
1605     if (!AddKeySymbols(info, &key, xkb))
1606     {
1607         info->errorCount++;
1608         return False;
1609     }
1610     return True;
1611 }
1612
1613 static Bool
1614 HandleModMapDef(ModMapDef * def,
1615                 XkbcDescPtr xkb, unsigned merge, SymbolsInfo * info)
1616 {
1617     ExprDef *key;
1618     ModMapEntry tmp;
1619     ExprResult rtrn;
1620     Bool ok;
1621
1622     if (!LookupModIndex(NULL, None, def->modifier, TypeInt, &rtrn))
1623     {
1624         ERROR("Illegal modifier map definition\n");
1625         ACTION("Ignoring map for non-modifier \"%s\"\n",
1626                 XkbcAtomText(def->modifier));
1627         return False;
1628     }
1629     ok = True;
1630     tmp.modifier = rtrn.uval;
1631     for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next)
1632     {
1633         if ((key->op == ExprValue) && (key->type == TypeKeyName))
1634         {
1635             tmp.haveSymbol = False;
1636             tmp.u.keyName = KeyNameToLong(key->value.keyName);
1637         }
1638         else if (ExprResolveKeySym(key, &rtrn, NULL, NULL))
1639         {
1640             tmp.haveSymbol = True;
1641             tmp.u.keySym = rtrn.uval;
1642         }
1643         else
1644         {
1645             ERROR("Modmap entries may contain only key names or keysyms\n");
1646             ACTION("Illegal definition for %s modifier ignored\n",
1647                     XkbcModIndexText(tmp.modifier));
1648             continue;
1649         }
1650
1651         ok = AddModMapEntry(info, &tmp) && ok;
1652     }
1653     return ok;
1654 }
1655
1656 static void
1657 HandleSymbolsFile(XkbFile * file,
1658                   XkbcDescPtr xkb, unsigned merge, SymbolsInfo * info)
1659 {
1660     ParseCommon *stmt;
1661
1662     info->name = _XkbDupString(file->name);
1663     stmt = file->defs;
1664     while (stmt)
1665     {
1666         switch (stmt->stmtType)
1667         {
1668         case StmtInclude:
1669             if (!HandleIncludeSymbols((IncludeStmt *) stmt, xkb, info,
1670                                       HandleSymbolsFile))
1671                 info->errorCount++;
1672             break;
1673         case StmtSymbolsDef:
1674             if (!HandleSymbolsDef((SymbolsDef *) stmt, xkb, merge, info))
1675                 info->errorCount++;
1676             break;
1677         case StmtVarDef:
1678             if (!HandleSymbolsVar((VarDef *) stmt, xkb, info))
1679                 info->errorCount++;
1680             break;
1681         case StmtVModDef:
1682             if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods))
1683                 info->errorCount++;
1684             break;
1685         case StmtInterpDef:
1686             ERROR("Interpretation files may not include other types\n");
1687             ACTION("Ignoring definition of symbol interpretation\n");
1688             info->errorCount++;
1689             break;
1690         case StmtKeycodeDef:
1691             ERROR("Interpretation files may not include other types\n");
1692             ACTION("Ignoring definition of key name\n");
1693             info->errorCount++;
1694             break;
1695         case StmtModMapDef:
1696             if (!HandleModMapDef((ModMapDef *) stmt, xkb, merge, info))
1697                 info->errorCount++;
1698             break;
1699         default:
1700             WSGO("Unexpected statement type %d in HandleSymbolsFile\n",
1701                   stmt->stmtType);
1702             break;
1703         }
1704         stmt = stmt->next;
1705         if (info->errorCount > 10)
1706         {
1707 #ifdef NOISY
1708             ERROR("Too many errors\n");
1709 #endif
1710             ACTION("Abandoning symbols file \"%s\"\n", file->topName);
1711             break;
1712         }
1713     }
1714     return;
1715 }
1716
1717 static Bool
1718 FindKeyForSymbol(XkbcDescPtr xkb, KeySym sym, unsigned int *kc_rtrn)
1719 {
1720     register int i, j;
1721     register Bool gotOne;
1722
1723     j = 0;
1724     do
1725     {
1726         gotOne = False;
1727         for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++)
1728         {
1729             if (j < (int) XkbKeyNumSyms(xkb, i))
1730             {
1731                 gotOne = True;
1732                 if ((XkbKeySym(xkb, i, j) == sym))
1733                 {
1734                     *kc_rtrn = i;
1735                     return True;
1736                 }
1737             }
1738         }
1739         j++;
1740     }
1741     while (gotOne);
1742     return False;
1743 }
1744
1745 /**
1746  * Find the given name in the xkb->map->types and return its index.
1747  *
1748  * @param name The atom to search for.
1749  * @param type_rtrn Set to the index of the name if found.
1750  *
1751  * @return True if found, False otherwise.
1752  */
1753 static Bool
1754 FindNamedType(XkbcDescPtr xkb, Atom name, unsigned *type_rtrn)
1755 {
1756     register unsigned n;
1757
1758     if (xkb && xkb->map && xkb->map->types)
1759     {
1760         for (n = 0; n < xkb->map->num_types; n++)
1761         {
1762             if (xkb->map->types[n].name == (Atom) name)
1763             {
1764                 *type_rtrn = n;
1765                 return True;
1766             }
1767         }
1768     }
1769     return False;
1770 }
1771
1772 /**
1773  * Assign a type to the given sym and return the Atom for the type assigned.
1774  *
1775  * Simple recipe:
1776  * - ONE_LEVEL for width 0/1
1777  * - ALPHABETIC for 2 shift levels, with lower/upercase
1778  * - KEYPAD for keypad keys.
1779  * - TWO_LEVEL for other 2 shift level keys.
1780  * and the same for four level keys.
1781  *
1782  * @param width Number of sysms in syms.
1783  * @param syms The keysyms for the given key (must be size width).
1784  * @param typeNameRtrn Set to the Atom of the type name.
1785  *
1786  * @returns True if a type could be found, False otherwise.
1787  */
1788 static Bool
1789 FindAutomaticType(int width, KeySym * syms, Atom * typeNameRtrn,
1790                   Bool * autoType)
1791 {
1792     *autoType = False;
1793     if ((width == 1) || (width == 0))
1794     {
1795         *typeNameRtrn = XkbcInternAtom("ONE_LEVEL", False);
1796         *autoType = True;
1797     }
1798     else if (width == 2)
1799     {
1800         if (syms && XkbcKSIsLower(syms[0]) && XkbcKSIsUpper(syms[1]))
1801         {
1802             *typeNameRtrn = XkbcInternAtom("ALPHABETIC", False);
1803         }
1804         else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])))
1805         {
1806             *typeNameRtrn = XkbcInternAtom("KEYPAD", False);
1807             *autoType = True;
1808         }
1809         else
1810         {
1811             *typeNameRtrn = XkbcInternAtom("TWO_LEVEL", False);
1812             *autoType = True;
1813         }
1814     }
1815     else if (width <= 4)
1816     {
1817         if (syms && XkbcKSIsLower(syms[0]) && XkbcKSIsUpper(syms[1]))
1818             if (XkbcKSIsLower(syms[2]) && XkbcKSIsUpper(syms[3]))
1819                 *typeNameRtrn =
1820                     XkbcInternAtom("FOUR_LEVEL_ALPHABETIC", False);
1821             else
1822                 *typeNameRtrn = XkbcInternAtom("FOUR_LEVEL_SEMIALPHABETIC",
1823                                               False);
1824
1825         else if (syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])))
1826             *typeNameRtrn = XkbcInternAtom("FOUR_LEVEL_KEYPAD", False);
1827         else
1828             *typeNameRtrn = XkbcInternAtom("FOUR_LEVEL", False);
1829         /* XXX: why not set autoType here? */
1830     }
1831     return ((width >= 0) && (width <= 4));
1832 }
1833
1834 /**
1835  * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the
1836  * groups, and reduce to one group if all groups are identical anyway.
1837  */
1838 static void
1839 PrepareKeyDef(KeyInfo * key)
1840 {
1841     int i, j, width, defined, lastGroup;
1842     Bool identical;
1843
1844     defined = key->symsDefined | key->actsDefined | key->typesDefined;
1845     /* get highest group number */
1846     for (i = XkbNumKbdGroups - 1; i >= 0; i--)
1847     {
1848         if (defined & (1 << i))
1849             break;
1850     }
1851     lastGroup = i;
1852
1853     if (lastGroup == 0)
1854         return;
1855
1856     /* If there are empty groups between non-empty ones fill them with data */
1857     /* from the first group. */
1858     /* We can make a wrong assumption here. But leaving gaps is worse. */
1859     for (i = lastGroup; i > 0; i--)
1860     {
1861         if (defined & (1 << i))
1862             continue;
1863         width = key->numLevels[0];
1864         if (key->typesDefined & 1)
1865         {
1866             for (j = 0; j < width; j++)
1867             {
1868                 key->types[i] = key->types[0];
1869             }
1870             key->typesDefined |= 1 << i;
1871         }
1872         if ((key->actsDefined & 1) && key->acts[0])
1873         {
1874             key->acts[i] = uTypedCalloc(width, XkbcAction);
1875             if (key->acts[i] == NULL)
1876                 continue;
1877             memcpy((void *) key->acts[i], (void *) key->acts[0],
1878                    width * sizeof(XkbcAction));
1879             key->actsDefined |= 1 << i;
1880         }
1881         if ((key->symsDefined & 1) && key->syms[0])
1882         {
1883             key->syms[i] = uTypedCalloc(width, KeySym);
1884             if (key->syms[i] == NULL)
1885                 continue;
1886             memcpy((void *) key->syms[i], (void *) key->syms[0],
1887                    width * sizeof(KeySym));
1888             key->symsDefined |= 1 << i;
1889         }
1890         if (defined & 1)
1891         {
1892             key->numLevels[i] = key->numLevels[0];
1893         }
1894     }
1895     /* If all groups are completely identical remove them all */
1896     /* exept the first one. */
1897     identical = True;
1898     for (i = lastGroup; i > 0; i--)
1899     {
1900         if ((key->numLevels[i] != key->numLevels[0]) ||
1901             (key->types[i] != key->types[0]))
1902         {
1903             identical = False;
1904             break;
1905         }
1906         if ((key->syms[i] != key->syms[0]) &&
1907             (key->syms[i] == NULL || key->syms[0] == NULL ||
1908              memcmp((void *) key->syms[i], (void *) key->syms[0],
1909                     sizeof(KeySym) * key->numLevels[0])))
1910         {
1911             identical = False;
1912             break;
1913         }
1914         if ((key->acts[i] != key->acts[0]) &&
1915             (key->acts[i] == NULL || key->acts[0] == NULL ||
1916              memcmp((void *) key->acts[i], (void *) key->acts[0],
1917                     sizeof(XkbcAction) * key->numLevels[0])))
1918         {
1919             identical = False;
1920             break;
1921         }
1922     }
1923     if (identical)
1924     {
1925         for (i = lastGroup; i > 0; i--)
1926         {
1927             key->numLevels[i] = 0;
1928             if (key->syms[i] != NULL)
1929                 uFree(key->syms[i]);
1930             key->syms[i] = (KeySym *) NULL;
1931             if (key->acts[i] != NULL)
1932                 uFree(key->acts[i]);
1933             key->acts[i] = (XkbcAction *) NULL;
1934             key->types[i] = (Atom) 0;
1935         }
1936         key->symsDefined &= 1;
1937         key->actsDefined &= 1;
1938         key->typesDefined &= 1;
1939     }
1940     return;
1941 }
1942
1943 /**
1944  * Copy the KeyInfo into the keyboard description.
1945  *
1946  * This function recurses.
1947  */
1948 static Bool
1949 CopySymbolsDef(XkbcDescPtr xkb, KeyInfo *key, int start_from)
1950 {
1951     register int i;
1952     unsigned okc, kc, width, tmp, nGroups;
1953     XkbKeyTypePtr type;
1954     Bool haveActions, autoType, useAlias;
1955     KeySym *outSyms;
1956     XkbcAction *outActs;
1957     unsigned types[XkbNumKbdGroups];
1958
1959     useAlias = (start_from == 0);
1960
1961     /* get the keycode for the key. */
1962     if (!FindNamedKey(xkb, key->name, &kc, useAlias, CreateKeyNames(xkb),
1963                       start_from))
1964     {
1965         if ((start_from == 0) && (warningLevel >= 5))
1966         {
1967             WARN("Key %s not found in %s keycodes\n",
1968                   longText(key->name),
1969                   XkbcAtomText(xkb->names->keycodes));
1970             ACTION("Symbols ignored\n");
1971         }
1972         return False;
1973     }
1974
1975     haveActions = False;
1976     for (i = width = nGroups = 0; i < XkbNumKbdGroups; i++)
1977     {
1978         if (((i + 1) > nGroups)
1979             && (((key->symsDefined | key->actsDefined) & (1 << i))
1980                 || (key->typesDefined) & (1 << i)))
1981             nGroups = i + 1;
1982         if (key->acts[i])
1983             haveActions = True;
1984         autoType = False;
1985         /* Assign the type to the key, if it is missing. */
1986         if (key->types[i] == None)
1987         {
1988             if (key->dfltType != None)
1989                 key->types[i] = key->dfltType;
1990             else if (FindAutomaticType(key->numLevels[i], key->syms[i],
1991                                        &key->types[i], &autoType))
1992             {
1993             }
1994             else
1995             {
1996                 if (warningLevel >= 5)
1997                 {
1998                     WARN("No automatic type for %d symbols\n",
1999                           (unsigned int) key->numLevels[i]);
2000                     ACTION("Using %s for the %s key (keycode %d)\n",
2001                             XkbcAtomText(key->types[i]),
2002                             longText(key->name), kc);
2003                 }
2004             }
2005         }
2006         if (FindNamedType(xkb, key->types[i], &types[i]))
2007         {
2008             if (!autoType || key->numLevels[i] > 2)
2009                 xkb->server->explicit[kc] |= (1 << i);
2010         }
2011         else
2012         {
2013             if (warningLevel >= 3)
2014             {
2015                 WARN("Type \"%s\" is not defined\n",
2016                       XkbcAtomText(key->types[i]));
2017                 ACTION("Using TWO_LEVEL for the %s key (keycode %d)\n",
2018                         longText(key->name), kc);
2019             }
2020             types[i] = XkbTwoLevelIndex;
2021         }
2022         /* if the type specifies less syms than the key has, shrink the key */
2023         type = &xkb->map->types[types[i]];
2024         if (type->num_levels < key->numLevels[i])
2025         {
2026             if (warningLevel > 0)
2027             {
2028                 WARN
2029                     ("Type \"%s\" has %d levels, but %s has %d symbols\n",
2030                      XkbcAtomText(type->name),
2031                      (unsigned int) type->num_levels,
2032                      longText(key->name),
2033                      (unsigned int) key->numLevels[i]);
2034                 ACTION("Ignoring extra symbols\n");
2035             }
2036             key->numLevels[i] = type->num_levels;
2037         }
2038         if (key->numLevels[i] > width)
2039             width = key->numLevels[i];
2040         if (type->num_levels > width)
2041             width = type->num_levels;
2042     }
2043
2044     /* width is now the largest width found */
2045
2046     i = width * nGroups;
2047     outSyms = XkbcResizeKeySyms(xkb, kc, i);
2048     if (outSyms == NULL)
2049     {
2050         WSGO("Could not enlarge symbols for %s (keycode %d)\n",
2051               longText(key->name), kc);
2052         return False;
2053     }
2054     if (haveActions)
2055     {
2056         outActs = XkbcResizeKeyActions(xkb, kc, i);
2057         if (outActs == NULL)
2058         {
2059             WSGO("Could not enlarge actions for %s (key %d)\n",
2060                   longText(key->name), kc);
2061             return False;
2062         }
2063         xkb->server->explicit[kc] |= XkbExplicitInterpretMask;
2064     }
2065     else
2066         outActs = NULL;
2067     if (key->defs.defined & _Key_GroupInfo)
2068         i = key->groupInfo;
2069     else
2070         i = xkb->map->key_sym_map[kc].group_info;
2071
2072     xkb->map->key_sym_map[kc].group_info = XkbSetNumGroups(i, nGroups);
2073     xkb->map->key_sym_map[kc].width = width;
2074     for (i = 0; i < nGroups; i++)
2075     {
2076         /* assign kt_index[i] to the index of the type in map->types.
2077          * kt_index[i] may have been set by a previous run (if we have two
2078          * layouts specified). Let's not overwrite it with the ONE_LEVEL
2079          * default group if we dont even have keys for this group anyway.
2080          *
2081          * FIXME: There should be a better fix for this.
2082          */
2083         if (key->numLevels[i])
2084             xkb->map->key_sym_map[kc].kt_index[i] = types[i];
2085         if (key->syms[i] != NULL)
2086         {
2087             /* fill key to "width" symbols*/
2088             for (tmp = 0; tmp < width; tmp++)
2089             {
2090                 if (tmp < key->numLevels[i])
2091                     outSyms[tmp] = key->syms[i][tmp];
2092                 else
2093                     outSyms[tmp] = NoSymbol;
2094                 if ((outActs != NULL) && (key->acts[i] != NULL))
2095                 {
2096                     if (tmp < key->numLevels[i])
2097                         outActs[tmp] = key->acts[i][tmp];
2098                     else
2099                         outActs[tmp].type = XkbSA_NoAction;
2100                 }
2101             }
2102         }
2103         outSyms += width;
2104         if (outActs)
2105             outActs += width;
2106     }
2107     switch (key->behavior.type & XkbKB_OpMask)
2108     {
2109     case XkbKB_Default:
2110         break;
2111     case XkbKB_Overlay1:
2112     case XkbKB_Overlay2:
2113         /* find key by name! */
2114         if (!FindNamedKey(xkb, key->nameForOverlayKey, &okc, True,
2115                           CreateKeyNames(xkb), 0))
2116         {
2117             if (warningLevel >= 1)
2118             {
2119                 WARN("Key %s not found in %s keycodes\n",
2120                       longText(key->nameForOverlayKey),
2121                       XkbcAtomText(xkb->names->keycodes));
2122                 ACTION("Not treating %s as an overlay key \n",
2123                         longText(key->name));
2124             }
2125             break;
2126         }
2127         key->behavior.data = okc;
2128     default:
2129         xkb->server->behaviors[kc] = key->behavior;
2130         xkb->server->explicit[kc] |= XkbExplicitBehaviorMask;
2131         break;
2132     }
2133     if (key->defs.defined & _Key_VModMap)
2134     {
2135         xkb->server->vmodmap[kc] = key->vmodmap;
2136         xkb->server->explicit[kc] |= XkbExplicitVModMapMask;
2137     }
2138     if (key->repeat != RepeatUndefined)
2139     {
2140         if (key->repeat == RepeatYes)
2141             xkb->ctrls->per_key_repeat[kc / 8] |= (1 << (kc % 8));
2142         else
2143             xkb->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8));
2144         xkb->server->explicit[kc] |= XkbExplicitAutoRepeatMask;
2145     }
2146
2147     /* do the same thing for the next key */
2148     CopySymbolsDef(xkb, key, kc + 1);
2149     return True;
2150 }
2151
2152 static Bool
2153 CopyModMapDef(XkbcDescPtr xkb, ModMapEntry *entry)
2154 {
2155     unsigned kc;
2156
2157     if ((!entry->haveSymbol)
2158         &&
2159         (!FindNamedKey
2160          (xkb, entry->u.keyName, &kc, True, CreateKeyNames(xkb), 0)))
2161     {
2162         if (warningLevel >= 5)
2163         {
2164             WARN("Key %s not found in %s keycodes\n",
2165                   longText(entry->u.keyName),
2166                   XkbcAtomText(xkb->names->keycodes));
2167             ACTION("Modifier map entry for %s not updated\n",
2168                     XkbcModIndexText(entry->modifier));
2169         }
2170         return False;
2171     }
2172     else if (entry->haveSymbol
2173              && (!FindKeyForSymbol(xkb, entry->u.keySym, &kc)))
2174     {
2175         if (warningLevel > 5)
2176         {
2177             WARN("Key \"%s\" not found in %s symbol map\n",
2178                   XkbcKeysymText(entry->u.keySym),
2179                   XkbcAtomText(xkb->names->symbols));
2180             ACTION("Modifier map entry for %s not updated\n",
2181                     XkbcModIndexText(entry->modifier));
2182         }
2183         return False;
2184     }
2185     xkb->map->modmap[kc] |= (1 << entry->modifier);
2186     return True;
2187 }
2188
2189 /**
2190  * Handle the xkb_symbols section of an xkb file.
2191  *
2192  * @param file The parsed xkb_symbols section of the xkb file.
2193  * @param xkb Handle to the keyboard description to store the symbols in.
2194  * @param merge Merge strategy (e.g. MergeOverride).
2195  */
2196 Bool
2197 CompileSymbols(XkbFile *file, XkbcDescPtr xkb, unsigned merge)
2198 {
2199     register int i;
2200     SymbolsInfo info;
2201
2202     InitSymbolsInfo(&info, xkb);
2203     info.dflt.defs.fileID = file->id;
2204     info.dflt.defs.merge = merge;
2205     HandleSymbolsFile(file, xkb, merge, &info);
2206
2207     if (info.nKeys == 0)
2208         return True;
2209     if (info.errorCount == 0)
2210     {
2211         KeyInfo *key;
2212
2213         /* alloc memory in the xkb struct */
2214         if (XkbcAllocNames(xkb, XkbSymbolsNameMask | XkbGroupNamesMask, 0, 0)
2215             != Success)
2216         {
2217             WSGO("Can not allocate names in CompileSymbols\n");
2218             ACTION("Symbols not added\n");
2219             return False;
2220         }
2221         if (XkbcAllocClientMap(xkb, XkbKeySymsMask | XkbModifierMapMask, 0)
2222             != Success)
2223         {
2224             WSGO("Could not allocate client map in CompileSymbols\n");
2225             ACTION("Symbols not added\n");
2226             return False;
2227         }
2228         if (XkbcAllocServerMap(xkb, XkbAllServerInfoMask, 32) != Success)
2229         {
2230             WSGO("Could not allocate server map in CompileSymbols\n");
2231             ACTION("Symbols not added\n");
2232             return False;
2233         }
2234         if (XkbcAllocControls(xkb, XkbPerKeyRepeatMask) != Success)
2235         {
2236             WSGO("Could not allocate controls in CompileSymbols\n");
2237             ACTION("Symbols not added\n");
2238             return False;
2239         }
2240
2241         /* now copy info into xkb. */
2242         xkb->names->symbols = XkbcInternAtom(info.name, False);
2243         if (info.aliases)
2244             ApplyAliases(xkb, False, &info.aliases);
2245         for (i = 0; i < XkbNumKbdGroups; i++)
2246         {
2247             if (info.groupNames[i] != None)
2248                 xkb->names->groups[i] = info.groupNames[i];
2249         }
2250         /* sanitize keys */
2251         for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
2252         {
2253             PrepareKeyDef(key);
2254         }
2255         /* copy! */
2256         for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
2257         {
2258             if (!CopySymbolsDef(xkb, key, 0))
2259                 info.errorCount++;
2260         }
2261         if (warningLevel > 3)
2262         {
2263             for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
2264             {
2265                 if (xkb->names->keys[i].name[0] == '\0')
2266                     continue;
2267                 if (XkbKeyNumGroups(xkb, i) < 1)
2268                 {
2269                     char buf[5];
2270                     memcpy(buf, xkb->names->keys[i].name, 4);
2271                     buf[4] = '\0';
2272                     WARN
2273                         ("No symbols defined for <%s> (keycode %d)\n",
2274                          buf, i);
2275                 }
2276             }
2277         }
2278         if (info.modMap)
2279         {
2280             ModMapEntry *mm, *next;
2281             for (mm = info.modMap; mm != NULL; mm = next)
2282             {
2283                 if (!CopyModMapDef(xkb, mm))
2284                     info.errorCount++;
2285                 next = (ModMapEntry *) mm->defs.next;
2286             }
2287         }
2288         return True;
2289     }
2290     return False;
2291 }