7148aad0a24b21c7d65dc5edfdc2c8f2a3310145
[platform/upstream/libxkbcommon.git] / src / xkbcomp / parseutils.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 "parseutils.h"
28 #include "xkbmisc.h"
29 #include "xkbpath.h"
30 #include "xkbparse.h"
31 #include <X11/keysym.h>
32 #include <X11/Xalloca.h>
33
34 XkbFile *rtrnValue;
35
36 ParseCommon *
37 AppendStmt(ParseCommon * to, ParseCommon * append)
38 {
39     ParseCommon *start = to;
40
41     if (append == NULL)
42         return to;
43     while ((to != NULL) && (to->next != NULL))
44     {
45         to = to->next;
46     }
47     if (to)
48     {
49         to->next = append;
50         return start;
51     }
52     return append;
53 }
54
55 ExprDef *
56 ExprCreate(unsigned op, unsigned type)
57 {
58     ExprDef *expr;
59     expr = uTypedAlloc(ExprDef);
60     if (expr)
61     {
62         expr->common.stmtType = StmtExpr;
63         expr->common.next = NULL;
64         expr->op = op;
65         expr->type = type;
66     }
67     else
68     {
69         FATAL("Couldn't allocate expression in parser\n");
70         /* NOTREACHED */
71     }
72     return expr;
73 }
74
75 ExprDef *
76 ExprCreateUnary(unsigned op, unsigned type, ExprDef * child)
77 {
78     ExprDef *expr;
79     expr = uTypedAlloc(ExprDef);
80     if (expr)
81     {
82         expr->common.stmtType = StmtExpr;
83         expr->common.next = NULL;
84         expr->op = op;
85         expr->type = type;
86         expr->value.child = child;
87     }
88     else
89     {
90         FATAL("Couldn't allocate expression in parser\n");
91         /* NOTREACHED */
92     }
93     return expr;
94 }
95
96 ExprDef *
97 ExprCreateBinary(unsigned op, ExprDef * left, ExprDef * right)
98 {
99     ExprDef *expr;
100     expr = uTypedAlloc(ExprDef);
101     if (expr)
102     {
103         expr->common.stmtType = StmtExpr;
104         expr->common.next = NULL;
105         expr->op = op;
106         if ((op == OpAssign) || (left->type == TypeUnknown))
107             expr->type = right->type;
108         else if ((left->type == right->type) || (right->type == TypeUnknown))
109             expr->type = left->type;
110         else
111             expr->type = TypeUnknown;
112         expr->value.binary.left = left;
113         expr->value.binary.right = right;
114     }
115     else
116     {
117         FATAL("Couldn't allocate expression in parser\n");
118         /* NOTREACHED */
119     }
120     return expr;
121 }
122
123 KeycodeDef *
124 KeycodeCreate(char *name, unsigned long value)
125 {
126     KeycodeDef *def;
127
128     def = uTypedAlloc(KeycodeDef);
129     if (def)
130     {
131         def->common.stmtType = StmtKeycodeDef;
132         def->common.next = NULL;
133         strncpy(def->name, name, XkbKeyNameLength);
134         def->name[XkbKeyNameLength] = '\0';
135         def->value = value;
136     }
137     else
138     {
139         FATAL("Couldn't allocate key name definition in parser\n");
140         /* NOTREACHED */
141     }
142     return def;
143 }
144
145 KeyAliasDef *
146 KeyAliasCreate(char *alias, char *real)
147 {
148     KeyAliasDef *def;
149
150     def = uTypedAlloc(KeyAliasDef);
151     if (def)
152     {
153         def->common.stmtType = StmtKeyAliasDef;
154         def->common.next = NULL;
155         strncpy(def->alias, alias, XkbKeyNameLength);
156         def->alias[XkbKeyNameLength] = '\0';
157         strncpy(def->real, real, XkbKeyNameLength);
158         def->real[XkbKeyNameLength] = '\0';
159     }
160     else
161     {
162         FATAL("Couldn't allocate key alias definition in parser\n");
163         /* NOTREACHED */
164     }
165     return def;
166 }
167
168 VModDef *
169 VModCreate(uint32_t name, ExprDef * value)
170 {
171     VModDef *def;
172     def = uTypedAlloc(VModDef);
173     if (def)
174     {
175         def->common.stmtType = StmtVModDef;
176         def->common.next = NULL;
177         def->name = name;
178         def->value = value;
179     }
180     else
181     {
182         FATAL("Couldn't allocate variable definition in parser\n");
183         /* NOTREACHED */
184     }
185     return def;
186 }
187
188 VarDef *
189 VarCreate(ExprDef * name, ExprDef * value)
190 {
191     VarDef *def;
192     def = uTypedAlloc(VarDef);
193     if (def)
194     {
195         def->common.stmtType = StmtVarDef;
196         def->common.next = NULL;
197         def->name = name;
198         def->value = value;
199     }
200     else
201     {
202         FATAL("Couldn't allocate variable definition in parser\n");
203         /* NOTREACHED */
204     }
205     return def;
206 }
207
208 VarDef *
209 BoolVarCreate(uint32_t nameToken, unsigned set)
210 {
211     ExprDef *name, *value;
212
213     name = ExprCreate(ExprIdent, TypeUnknown);
214     name->value.str = nameToken;
215     value = ExprCreate(ExprValue, TypeBoolean);
216     value->value.uval = set;
217     return VarCreate(name, value);
218 }
219
220 InterpDef *
221 InterpCreate(char *sym, ExprDef * match)
222 {
223     InterpDef *def;
224
225     def = uTypedAlloc(InterpDef);
226     if (def)
227     {
228         def->common.stmtType = StmtInterpDef;
229         def->common.next = NULL;
230         def->sym = sym;
231         def->match = match;
232     }
233     else
234     {
235         FATAL("Couldn't allocate interp definition in parser\n");
236         /* NOTREACHED */
237     }
238     return def;
239 }
240
241 KeyTypeDef *
242 KeyTypeCreate(uint32_t name, VarDef * body)
243 {
244     KeyTypeDef *def;
245
246     def = uTypedAlloc(KeyTypeDef);
247     if (def)
248     {
249         def->common.stmtType = StmtKeyTypeDef;
250         def->common.next = NULL;
251         def->merge = MergeDefault;
252         def->name = name;
253         def->body = body;
254     }
255     else
256     {
257         FATAL("Couldn't allocate key type definition in parser\n");
258         /* NOTREACHED */
259     }
260     return def;
261 }
262
263 SymbolsDef *
264 SymbolsCreate(char *keyName, ExprDef * symbols)
265 {
266     SymbolsDef *def;
267
268     def = uTypedAlloc(SymbolsDef);
269     if (def)
270     {
271         def->common.stmtType = StmtSymbolsDef;
272         def->common.next = NULL;
273         def->merge = MergeDefault;
274         memset(def->keyName, 0, 5);
275         strncpy(def->keyName, keyName, 4);
276         def->symbols = symbols;
277     }
278     else
279     {
280         FATAL("Couldn't allocate symbols definition in parser\n");
281         /* NOTREACHED */
282     }
283     return def;
284 }
285
286 GroupCompatDef *
287 GroupCompatCreate(int group, ExprDef * val)
288 {
289     GroupCompatDef *def;
290
291     def = uTypedAlloc(GroupCompatDef);
292     if (def)
293     {
294         def->common.stmtType = StmtGroupCompatDef;
295         def->common.next = NULL;
296         def->merge = MergeDefault;
297         def->group = group;
298         def->def = val;
299     }
300     else
301     {
302         FATAL("Couldn't allocate group compat definition in parser\n");
303         /* NOTREACHED */
304     }
305     return def;
306 }
307
308 ModMapDef *
309 ModMapCreate(uint32_t modifier, ExprDef * keys)
310 {
311     ModMapDef *def;
312
313     def = uTypedAlloc(ModMapDef);
314     if (def)
315     {
316         def->common.stmtType = StmtModMapDef;
317         def->common.next = NULL;
318         def->merge = MergeDefault;
319         def->modifier = modifier;
320         def->keys = keys;
321     }
322     else
323     {
324         FATAL("Couldn't allocate mod mask definition in parser\n");
325         /* NOTREACHED */
326     }
327     return def;
328 }
329
330 IndicatorMapDef *
331 IndicatorMapCreate(uint32_t name, VarDef * body)
332 {
333     IndicatorMapDef *def;
334
335     def = uTypedAlloc(IndicatorMapDef);
336     if (def)
337     {
338         def->common.stmtType = StmtIndicatorMapDef;
339         def->common.next = NULL;
340         def->merge = MergeDefault;
341         def->name = name;
342         def->body = body;
343     }
344     else
345     {
346         FATAL("Couldn't allocate indicator map definition in parser\n");
347         /* NOTREACHED */
348     }
349     return def;
350 }
351
352 IndicatorNameDef *
353 IndicatorNameCreate(int ndx, ExprDef * name, Bool virtual)
354 {
355     IndicatorNameDef *def;
356
357     def = uTypedAlloc(IndicatorNameDef);
358     if (def)
359     {
360         def->common.stmtType = StmtIndicatorNameDef;
361         def->common.next = NULL;
362         def->merge = MergeDefault;
363         def->ndx = ndx;
364         def->name = name;
365         def->virtual = virtual;
366     }
367     else
368     {
369         FATAL("Couldn't allocate indicator index definition in parser\n");
370         /* NOTREACHED */
371     }
372     return def;
373 }
374
375 ExprDef *
376 ActionCreate(uint32_t name, ExprDef * args)
377 {
378     ExprDef *act;
379
380     act = uTypedAlloc(ExprDef);
381     if (act)
382     {
383         act->common.stmtType = StmtExpr;
384         act->common.next = NULL;
385         act->op = ExprActionDecl;
386         act->value.action.name = name;
387         act->value.action.args = args;
388         return act;
389     }
390     FATAL("Couldn't allocate ActionDef in parser\n");
391     return NULL;
392 }
393
394 ExprDef *
395 CreateKeysymList(char *sym)
396 {
397     ExprDef *def;
398
399     def = ExprCreate(ExprKeysymList, TypeSymbols);
400     if (def)
401     {
402         def->value.list.nSyms = 1;
403         def->value.list.szSyms = 4;
404         def->value.list.syms = uTypedCalloc(4, char *);
405         if (def->value.list.syms != NULL)
406         {
407             def->value.list.syms[0] = sym;
408             return def;
409         }
410     }
411     FATAL("Couldn't allocate expression for keysym list in parser\n");
412     return NULL;
413 }
414
415 ShapeDef *
416 ShapeDeclCreate(uint32_t name, OutlineDef * outlines)
417 {
418     ShapeDef *shape;
419     OutlineDef *ol;
420
421     shape = uTypedAlloc(ShapeDef);
422     if (shape != NULL)
423     {
424         memset(shape, 0, sizeof(ShapeDef));
425         shape->common.stmtType = StmtShapeDef;
426         shape->common.next = NULL;
427         shape->merge = MergeDefault;
428         shape->name = name;
429         shape->nOutlines = 0;
430         shape->outlines = outlines;
431         for (ol = outlines; ol != NULL; ol = (OutlineDef *) ol->common.next)
432         {
433             if (ol->nPoints > 0)
434                 shape->nOutlines++;
435         }
436     }
437     return shape;
438 }
439
440 OutlineDef *
441 OutlineCreate(uint32_t field, ExprDef * points)
442 {
443     OutlineDef *outline;
444     ExprDef *pt;
445
446     outline = uTypedAlloc(OutlineDef);
447     if (outline != NULL)
448     {
449         memset(outline, 0, sizeof(OutlineDef));
450         outline->common.stmtType = StmtOutlineDef;
451         outline->common.next = NULL;
452         outline->field = field;
453         outline->nPoints = 0;
454         if (points->op == ExprCoord)
455         {
456             for (pt = points; pt != NULL; pt = (ExprDef *) pt->common.next)
457             {
458                 outline->nPoints++;
459             }
460         }
461         outline->points = points;
462     }
463     return outline;
464 }
465
466 KeyDef *
467 KeyDeclCreate(char *name, ExprDef * expr)
468 {
469     KeyDef *key;
470
471     key = uTypedAlloc(KeyDef);
472     if (key != NULL)
473     {
474         memset(key, 0, sizeof(KeyDef));
475         key->common.stmtType = StmtKeyDef;
476         key->common.next = NULL;
477         if (name)
478             key->name = name;
479         else
480             key->expr = expr;
481     }
482     return key;
483 }
484
485 RowDef *
486 RowDeclCreate(KeyDef * keys)
487 {
488     RowDef *row;
489     KeyDef *key;
490
491     row = uTypedAlloc(RowDef);
492     if (row != NULL)
493     {
494         memset(row, 0, sizeof(RowDef));
495         row->common.stmtType = StmtRowDef;
496         row->common.next = NULL;
497         row->nKeys = 0;
498         row->keys = keys;
499         for (key = keys; key != NULL; key = (KeyDef *) key->common.next)
500         {
501             if (key->common.stmtType == StmtKeyDef)
502                 row->nKeys++;
503         }
504     }
505     return row;
506 }
507
508 SectionDef *
509 SectionDeclCreate(uint32_t name, RowDef * rows)
510 {
511     SectionDef *section;
512     RowDef *row;
513
514     section = uTypedAlloc(SectionDef);
515     if (section != NULL)
516     {
517         memset(section, 0, sizeof(SectionDef));
518         section->common.stmtType = StmtSectionDef;
519         section->common.next = NULL;
520         section->name = name;
521         section->nRows = 0;
522         section->rows = rows;
523         for (row = rows; row != NULL; row = (RowDef *) row->common.next)
524         {
525             if (row->common.stmtType == StmtRowDef)
526                 section->nRows++;
527         }
528     }
529     return section;
530 }
531
532 OverlayKeyDef *
533 OverlayKeyCreate(char *under, char *over)
534 {
535     OverlayKeyDef *key;
536
537     key = uTypedAlloc(OverlayKeyDef);
538     if (key != NULL)
539     {
540         memset(key, 0, sizeof(OverlayKeyDef));
541         key->common.stmtType = StmtOverlayKeyDef;
542         strncpy(key->over, over, XkbKeyNameLength);
543         strncpy(key->under, under, XkbKeyNameLength);
544         free(over);
545         free(under);
546     }
547     return key;
548 }
549
550 OverlayDef *
551 OverlayDeclCreate(uint32_t name, OverlayKeyDef * keys)
552 {
553     OverlayDef *ol;
554     OverlayKeyDef *key;
555
556     ol = uTypedAlloc(OverlayDef);
557     if (ol != NULL)
558     {
559         memset(ol, 0, sizeof(OverlayDef));
560         ol->common.stmtType = StmtOverlayDef;
561         ol->name = name;
562         ol->keys = keys;
563         for (key = keys; key != NULL;
564              key = (OverlayKeyDef *) key->common.next)
565         {
566             ol->nKeys++;
567         }
568     }
569     return ol;
570 }
571
572 DoodadDef *
573 DoodadCreate(unsigned type, uint32_t name, VarDef * body)
574 {
575     DoodadDef *doodad;
576
577     doodad = uTypedAlloc(DoodadDef);
578     if (doodad != NULL)
579     {
580         memset(doodad, 0, sizeof(DoodadDef));
581         doodad->common.stmtType = StmtDoodadDef;
582         doodad->common.next = NULL;
583         doodad->type = type;
584         doodad->name = name;
585         doodad->body = body;
586     }
587     return doodad;
588 }
589
590 ExprDef *
591 AppendKeysymList(ExprDef * list, char *sym)
592 {
593     if (list->value.list.nSyms >= list->value.list.szSyms)
594     {
595         list->value.list.szSyms *= 2;
596         list->value.list.syms = uTypedRecalloc(list->value.list.syms,
597                                                list->value.list.nSyms,
598                                                list->value.list.szSyms,
599                                                char *);
600         if (list->value.list.syms == NULL)
601         {
602             FATAL("Couldn't resize list of symbols for append\n");
603             return NULL;
604         }
605     }
606     list->value.list.syms[list->value.list.nSyms++] = sym;
607     return list;
608 }
609
610 int
611 LookupKeysym(char *str, xkb_keysym_t * sym_rtrn)
612 {
613     xkb_keysym_t sym;
614
615     if ((!str) || (uStrCaseCmp(str, "any") == 0)
616         || (uStrCaseCmp(str, "nosymbol") == 0))
617     {
618         *sym_rtrn = NoSymbol;
619         return 1;
620     }
621     else if ((uStrCaseCmp(str, "none") == 0)
622              || (uStrCaseCmp(str, "voidsymbol") == 0))
623     {
624         *sym_rtrn = XK_VoidSymbol;
625         return 1;
626     }
627     sym = xkb_string_to_keysym(str);
628     if (sym != NoSymbol)
629     {
630         *sym_rtrn = sym;
631         return 1;
632     }
633     return 0;
634 }
635
636 static void
637 FreeInclude(IncludeStmt *incl);
638
639 IncludeStmt *
640 IncludeCreate(char *str, unsigned merge)
641 {
642     IncludeStmt *incl, *first;
643     char *file, *map, *stmt, *tmp, *extra_data;
644     char nextop;
645     Bool haveSelf;
646
647     haveSelf = False;
648     incl = first = NULL;
649     file = map = NULL;
650     tmp = str;
651     stmt = _XkbDupString(str);
652     while ((tmp) && (*tmp))
653     {
654         if (XkbParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data))
655         {
656             if ((file == NULL) && (map == NULL))
657             {
658                 if (haveSelf)
659                     goto BAIL;
660                 haveSelf = True;
661             }
662             if (first == NULL)
663                 first = incl = uTypedAlloc(IncludeStmt);
664             else
665             {
666                 incl->next = uTypedAlloc(IncludeStmt);
667                 incl = incl->next;
668             }
669             if (incl)
670             {
671                 incl->common.stmtType = StmtInclude;
672                 incl->common.next = NULL;
673                 incl->merge = merge;
674                 incl->stmt = NULL;
675                 incl->file = file;
676                 incl->map = map;
677                 incl->modifier = extra_data;
678                 incl->path = NULL;
679                 incl->next = NULL;
680             }
681             else
682             {
683                 WSGO("Allocation failure in IncludeCreate\n");
684                 ACTION("Using only part of the include\n");
685                 break;
686             }
687             if (nextop == '|')
688                 merge = MergeAugment;
689             else
690                 merge = MergeOverride;
691         }
692         else
693         {
694             goto BAIL;
695         }
696     }
697     if (first)
698         first->stmt = stmt;
699     else
700         free(stmt);
701     return first;
702
703 BAIL:
704     ERROR("Illegal include statement \"%s\"\n", stmt);
705     ACTION("Ignored\n");
706     FreeInclude(first);
707     free(stmt);
708     return NULL;
709 }
710
711 #ifdef DEBUG
712 void
713 PrintStmtAddrs(ParseCommon * stmt)
714 {
715     fprintf(stderr, "0x%x", stmt);
716     if (stmt)
717     {
718         do
719         {
720             fprintf(stderr, "->0x%x", stmt->next);
721             stmt = stmt->next;
722         }
723         while (stmt);
724     }
725     fprintf(stderr, "\n");
726 }
727 #endif
728
729 void
730 CheckDefaultMap(XkbFile * maps)
731 {
732     XkbFile *dflt, *tmp;
733
734     dflt = NULL;
735     for (tmp = maps, dflt = NULL; tmp != NULL;
736          tmp = (XkbFile *) tmp->common.next)
737     {
738         if (tmp->flags & XkbLC_Default)
739         {
740             if (dflt == NULL)
741                 dflt = tmp;
742             else
743             {
744                 if (warningLevel > 2)
745                 {
746                     WARN("Multiple default components in %s\n",
747                           (scanFile ? scanFile : "(unknown)"));
748                     ACTION("Using %s, ignoring %s\n",
749                             (dflt->name ? dflt->name : "(first)"),
750                             (tmp->name ? tmp->name : "(subsequent)"));
751                 }
752                 tmp->flags &= (~XkbLC_Default);
753             }
754         }
755     }
756 }
757
758 XkbFile *
759 CreateXKBFile(int type, char *name, ParseCommon * defs, unsigned flags)
760 {
761     XkbFile *file;
762     static int fileID;
763
764     file = uTypedAlloc(XkbFile);
765     if (file)
766     {
767         XkbcEnsureSafeMapName(name);
768         memset(file, 0, sizeof(XkbFile));
769         file->type = type;
770         file->topName = _XkbDupString(name);
771         file->name = name;
772         file->defs = defs;
773         file->id = fileID++;
774         file->compiled = False;
775         file->flags = flags;
776     }
777     return file;
778 }
779
780 unsigned
781 StmtSetMerge(ParseCommon * stmt, unsigned merge)
782 {
783     if ((merge == MergeAltForm) && (stmt->stmtType != StmtKeycodeDef))
784     {
785         yyerror("illegal use of 'alternate' merge mode");
786         merge = MergeDefault;
787     }
788     return merge;
789 }
790
791 static void
792 FreeStmt(ParseCommon *stmt);
793
794 static void
795 FreeExpr(ExprDef *expr)
796 {
797     int i;
798
799     if (!expr)
800         return;
801
802     switch (expr->op)
803     {
804     case ExprActionList:
805     case OpNegate:
806     case OpUnaryPlus:
807     case OpNot:
808     case OpInvert:
809         FreeStmt(&expr->value.child->common);
810         break;
811     case OpDivide:
812     case OpAdd:
813     case OpSubtract:
814     case OpMultiply:
815     case OpAssign:
816         FreeStmt(&expr->value.binary.left->common);
817         FreeStmt(&expr->value.binary.right->common);
818         break;
819     case ExprActionDecl:
820         FreeStmt(&expr->value.action.args->common);
821         break;
822     case ExprArrayRef:
823         FreeStmt(&expr->value.array.entry->common);
824         break;
825     case ExprKeysymList:
826         for (i = 0; i < expr->value.list.nSyms; i++)
827             free(expr->value.list.syms[i]);
828         free(expr->value.list.syms);
829         break;
830     default:
831         break;
832     }
833 }
834
835 static void
836 FreeInclude(IncludeStmt *incl)
837 {
838     IncludeStmt *next;
839
840     while (incl)
841     {
842         next = incl->next;
843
844         free(incl->file);
845         free(incl->map);
846         free(incl->modifier);
847         free(incl->path);
848         free(incl->stmt);
849
850         free(incl);
851         incl = next;
852     }
853 }
854
855 static void
856 FreeStmt(ParseCommon *stmt)
857 {
858     ParseCommon *next;
859     YYSTYPE u;
860
861     while (stmt)
862     {
863         next = stmt->next;
864         u.any = stmt;
865
866         switch (stmt->stmtType)
867         {
868         case StmtInclude:
869             FreeInclude((IncludeStmt *)stmt);
870             /* stmt is already free'd here. */
871             stmt = NULL;
872             break;
873         case StmtExpr:
874             FreeExpr(u.expr);
875             break;
876         case StmtVarDef:
877             FreeStmt(&u.var->name->common);
878             FreeStmt(&u.var->value->common);
879             break;
880         case StmtKeyTypeDef:
881             FreeStmt(&u.keyType->body->common);
882             break;
883         case StmtInterpDef:
884             free(u.interp->sym);
885             FreeStmt(&u.interp->match->common);
886             FreeStmt(&u.interp->def->common);
887             break;
888         case StmtVModDef:
889             FreeStmt(&u.vmod->value->common);
890             break;
891         case StmtSymbolsDef:
892             FreeStmt(&u.syms->symbols->common);
893             break;
894         case StmtModMapDef:
895             FreeStmt(&u.modMask->keys->common);
896             break;
897         case StmtGroupCompatDef:
898             FreeStmt(&u.groupCompat->def->common);
899             break;
900         case StmtIndicatorMapDef:
901             FreeStmt(&u.ledMap->body->common);
902             break;
903         case StmtIndicatorNameDef:
904             FreeStmt(&u.ledName->name->common);
905             break;
906         case StmtOutlineDef:
907             FreeStmt(&u.outline->points->common);
908             break;
909         case StmtShapeDef:
910             FreeStmt(&u.shape->outlines->common);
911             break;
912         case StmtKeyDef:
913             free(u.key->name);
914             FreeStmt(&u.key->expr->common);
915             break;
916         case StmtRowDef:
917             FreeStmt(&u.row->keys->common);
918             break;
919         case StmtSectionDef:
920             FreeStmt(&u.section->rows->common);
921             break;
922         case StmtOverlayKeyDef:
923             break;
924         case StmtOverlayDef:
925             FreeStmt(&u.overlay->keys->common);
926             break;
927         case StmtDoodadDef:
928             FreeStmt(&u.doodad->body->common);
929             break;
930         default:
931             break;
932         }
933
934         free(stmt);
935         stmt = next;
936     }
937 }
938
939 void
940 FreeXKBFile(XkbFile *file)
941 {
942     XkbFile *next;
943
944     while (file)
945     {
946         next = (XkbFile *)file->common.next;
947
948         switch (file->type)
949         {
950         case XkmKeymapFile:
951         case XkmSemanticsFile:
952         case XkmLayoutFile:
953             FreeXKBFile((XkbFile *)file->defs);
954             break;
955         case XkmTypesIndex:
956         case XkmCompatMapIndex:
957         case XkmSymbolsIndex:
958         case XkmKeyNamesIndex:
959         case XkmGeometryIndex:
960         case XkmGeometryFile:
961             FreeStmt(file->defs);
962             break;
963         }
964
965         free(file->name);
966         free(file->topName);
967         free(file);
968         file = next;
969     }
970 }