158dc131989a05935ab9b630f21b6ddc25efc961
[profile/ivi/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, uint32_t * sym_rtrn)
612 {
613     uint32_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 IncludeStmt *
637 IncludeCreate(char *str, unsigned merge)
638 {
639     IncludeStmt *incl, *first;
640     char *file, *map, *stmt, *tmp, *extra_data;
641     char nextop;
642     Bool haveSelf;
643
644     haveSelf = False;
645     incl = first = NULL;
646     file = map = NULL;
647     tmp = str;
648     stmt = _XkbDupString(str);
649     while ((tmp) && (*tmp))
650     {
651         if (XkbParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data))
652         {
653             if ((file == NULL) && (map == NULL))
654             {
655                 if (haveSelf)
656                     goto BAIL;
657                 haveSelf = True;
658             }
659             if (first == NULL)
660                 first = incl = uTypedAlloc(IncludeStmt);
661             else
662             {
663                 incl->next = uTypedAlloc(IncludeStmt);
664                 incl = incl->next;
665             }
666             if (incl)
667             {
668                 incl->common.stmtType = StmtInclude;
669                 incl->common.next = NULL;
670                 incl->merge = merge;
671                 incl->stmt = NULL;
672                 incl->file = file;
673                 incl->map = map;
674                 incl->modifier = extra_data;
675                 incl->path = NULL;
676                 incl->next = NULL;
677             }
678             else
679             {
680                 WSGO("Allocation failure in IncludeCreate\n");
681                 ACTION("Using only part of the include\n");
682                 break;
683             }
684             if (nextop == '|')
685                 merge = MergeAugment;
686             else
687                 merge = MergeOverride;
688         }
689         else
690         {
691             goto BAIL;
692         }
693     }
694     if (first)
695         first->stmt = stmt;
696     else
697         free(stmt);
698     return first;
699   BAIL:
700     ERROR("Illegal include statement \"%s\"\n", stmt);
701     ACTION("Ignored\n");
702     while (first)
703     {
704         incl = first->next;
705         free(first->file);
706         free(first->map);
707         free(first->modifier);
708         free(first->path);
709         first->file = first->map = first->path = NULL;
710         free(first);
711         first = incl;
712     }
713     free(stmt);
714     return NULL;
715 }
716
717 #ifdef DEBUG
718 void
719 PrintStmtAddrs(ParseCommon * stmt)
720 {
721     fprintf(stderr, "0x%x", stmt);
722     if (stmt)
723     {
724         do
725         {
726             fprintf(stderr, "->0x%x", stmt->next);
727             stmt = stmt->next;
728         }
729         while (stmt);
730     }
731     fprintf(stderr, "\n");
732 }
733 #endif
734
735 void
736 CheckDefaultMap(XkbFile * maps)
737 {
738     XkbFile *dflt, *tmp;
739
740     dflt = NULL;
741     for (tmp = maps, dflt = NULL; tmp != NULL;
742          tmp = (XkbFile *) tmp->common.next)
743     {
744         if (tmp->flags & XkbLC_Default)
745         {
746             if (dflt == NULL)
747                 dflt = tmp;
748             else
749             {
750                 if (warningLevel > 2)
751                 {
752                     WARN("Multiple default components in %s\n",
753                           (scanFile ? scanFile : "(unknown)"));
754                     ACTION("Using %s, ignoring %s\n",
755                             (dflt->name ? dflt->name : "(first)"),
756                             (tmp->name ? tmp->name : "(subsequent)"));
757                 }
758                 tmp->flags &= (~XkbLC_Default);
759             }
760         }
761     }
762 }
763
764 XkbFile *
765 CreateXKBFile(int type, char *name, ParseCommon * defs, unsigned flags)
766 {
767     XkbFile *file;
768     static int fileID;
769
770     file = uTypedAlloc(XkbFile);
771     if (file)
772     {
773         XkbcEnsureSafeMapName(name);
774         memset(file, 0, sizeof(XkbFile));
775         file->type = type;
776         file->topName = _XkbDupString(name);
777         file->name = name;
778         file->defs = defs;
779         file->id = fileID++;
780         file->compiled = False;
781         file->flags = flags;
782     }
783     return file;
784 }
785
786 unsigned
787 StmtSetMerge(ParseCommon * stmt, unsigned merge)
788 {
789     if ((merge == MergeAltForm) && (stmt->stmtType != StmtKeycodeDef))
790     {
791         yyerror("illegal use of 'alternate' merge mode");
792         merge = MergeDefault;
793     }
794     return merge;
795 }
796
797 static void
798 FreeStmt(ParseCommon *stmt);
799
800 static void
801 FreeExpr(ExprDef *expr)
802 {
803     int i;
804
805     if (!expr)
806         return;
807
808     switch (expr->op)
809     {
810     case ExprActionList:
811     case OpNegate:
812     case OpUnaryPlus:
813     case OpNot:
814     case OpInvert:
815         FreeStmt(&expr->value.child->common);
816         break;
817     case OpDivide:
818     case OpAdd:
819     case OpSubtract:
820     case OpMultiply:
821     case OpAssign:
822         FreeStmt(&expr->value.binary.left->common);
823         FreeStmt(&expr->value.binary.right->common);
824         break;
825     case ExprActionDecl:
826         FreeStmt(&expr->value.action.args->common);
827         break;
828     case ExprArrayRef:
829         FreeStmt(&expr->value.array.entry->common);
830         break;
831     case ExprKeysymList:
832         for (i = 0; i < expr->value.list.nSyms; i++)
833             free(expr->value.list.syms[i]);
834         free(expr->value.list.syms);
835         break;
836     default:
837         break;
838     }
839 }
840
841 static void
842 FreeInclude(IncludeStmt *incl)
843 {
844     IncludeStmt *next;
845
846     while (incl)
847     {
848         next = incl->next;
849
850         free(incl->file);
851         free(incl->map);
852         free(incl->modifier);
853         free(incl->path);
854         free(incl->stmt);
855
856         free(incl);
857         incl = next;
858     }
859 }
860
861 static void
862 FreeStmt(ParseCommon *stmt)
863 {
864     ParseCommon *next;
865     YYSTYPE u;
866
867     while (stmt)
868     {
869         next = stmt->next;
870         u.any = stmt;
871
872         switch (stmt->stmtType)
873         {
874         case StmtInclude:
875             FreeInclude((IncludeStmt *)stmt);
876             stmt = NULL;
877             break;
878         case StmtExpr:
879             FreeExpr(u.expr);
880             break;
881         case StmtVarDef:
882             FreeStmt(&u.var->name->common);
883             FreeStmt(&u.var->value->common);
884             break;
885         case StmtKeyTypeDef:
886             FreeStmt(&u.keyType->body->common);
887             break;
888         case StmtInterpDef:
889             free(u.interp->sym);
890             FreeStmt(&u.interp->match->common);
891             FreeStmt(&u.interp->def->common);
892             break;
893         case StmtVModDef:
894             FreeStmt(&u.vmod->value->common);
895             break;
896         case StmtSymbolsDef:
897             FreeStmt(&u.syms->symbols->common);
898             break;
899         case StmtModMapDef:
900             FreeStmt(&u.modMask->keys->common);
901             break;
902         case StmtGroupCompatDef:
903             FreeStmt(&u.groupCompat->def->common);
904             break;
905         case StmtIndicatorMapDef:
906             FreeStmt(&u.ledMap->body->common);
907             break;
908         case StmtIndicatorNameDef:
909             FreeStmt(&u.ledName->name->common);
910             break;
911         case StmtOutlineDef:
912             FreeStmt(&u.outline->points->common);
913             break;
914         case StmtShapeDef:
915             FreeStmt(&u.shape->outlines->common);
916             break;
917         case StmtKeyDef:
918             free(u.key->name);
919             FreeStmt(&u.key->expr->common);
920             break;
921         case StmtRowDef:
922             FreeStmt(&u.row->keys->common);
923             break;
924         case StmtSectionDef:
925             FreeStmt(&u.section->rows->common);
926             break;
927         case StmtOverlayKeyDef:
928             break;
929         case StmtOverlayDef:
930             FreeStmt(&u.overlay->keys->common);
931             break;
932         case StmtDoodadDef:
933             FreeStmt(&u.doodad->body->common);
934             break;
935         default:
936             break;
937         }
938
939         free(stmt);
940         stmt = next;
941     }
942 }
943
944 void
945 FreeXKBFile(XkbFile *file)
946 {
947     XkbFile *next;
948
949     while (file)
950     {
951         next = (XkbFile *)file->common.next;
952
953         switch (file->type)
954         {
955         case XkmKeymapFile:
956         case XkmSemanticsFile:
957         case XkmLayoutFile:
958             FreeXKBFile((XkbFile *)file->defs);
959             break;
960         case XkmTypesIndex:
961         case XkmCompatMapIndex:
962         case XkmSymbolsIndex:
963         case XkmKeyNamesIndex:
964         case XkmGeometryIndex:
965             FreeStmt(file->defs);
966             break;
967         }
968
969         free(file->name);
970         /* free(file->topName); */
971         free(file);
972         file = next;
973     }
974 }