• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /*
28  * Copyright © 2012 Intel Corporation
29  * Copyright © 2012 Ran Benita <ran234@gmail.com>
30  *
31  * Permission is hereby granted, free of charge, to any person obtaining a
32  * copy of this software and associated documentation files (the "Software"),
33  * to deal in the Software without restriction, including without limitation
34  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35  * and/or sell copies of the Software, and to permit persons to whom the
36  * Software is furnished to do so, subject to the following conditions:
37  *
38  * The above copyright notice and this permission notice (including the next
39  * paragraph) shall be included in all copies or substantial portions of the
40  * Software.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
45  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
47  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
48  * DEALINGS IN THE SOFTWARE.
49  *
50  * Author: Daniel Stone <daniel@fooishbar.org>
51  *         Ran Benita <ran234@gmail.com>
52  */
53 
54 #include "xkbcomp-priv.h"
55 #include "ast-build.h"
56 #include "include.h"
57 
58 ParseCommon *
AppendStmt(ParseCommon * to,ParseCommon * append)59 AppendStmt(ParseCommon *to, ParseCommon *append)
60 {
61     ParseCommon *iter;
62 
63     if (!to)
64         return append;
65 
66     for (iter = to; iter->next; iter = iter->next);
67 
68     iter->next = append;
69     return to;
70 }
71 
72 static ExprDef *
ExprCreate(enum expr_op_type op,enum expr_value_type type,size_t size)73 ExprCreate(enum expr_op_type op, enum expr_value_type type, size_t size)
74 {
75     ExprDef *expr = malloc(size);
76     if (!expr)
77         return NULL;
78 
79     expr->common.type = STMT_EXPR;
80     expr->common.next = NULL;
81     expr->expr.op = op;
82     expr->expr.value_type = type;
83 
84     return expr;
85 }
86 
87 #define EXPR_CREATE(type_, name_, op_, value_type_) \
88     ExprDef *name_ = ExprCreate(op_, value_type_, sizeof(type_)); \
89     if (!name_) \
90         return NULL;
91 
92 ExprDef *
ExprCreateString(xkb_atom_t str)93 ExprCreateString(xkb_atom_t str)
94 {
95     EXPR_CREATE(ExprString, expr, EXPR_VALUE, EXPR_TYPE_STRING);
96     expr->string.str = str;
97     return expr;
98 }
99 
100 ExprDef *
ExprCreateInteger(int ival)101 ExprCreateInteger(int ival)
102 {
103     EXPR_CREATE(ExprInteger, expr, EXPR_VALUE, EXPR_TYPE_INT);
104     expr->integer.ival = ival;
105     return expr;
106 }
107 
108 ExprDef *
ExprCreateBoolean(bool set)109 ExprCreateBoolean(bool set)
110 {
111     EXPR_CREATE(ExprBoolean, expr, EXPR_VALUE, EXPR_TYPE_BOOLEAN);
112     expr->boolean.set = set;
113     return expr;
114 }
115 
116 ExprDef *
ExprCreateKeyName(xkb_atom_t key_name)117 ExprCreateKeyName(xkb_atom_t key_name)
118 {
119     EXPR_CREATE(ExprKeyName, expr, EXPR_VALUE, EXPR_TYPE_KEYNAME);
120     expr->key_name.key_name = key_name;
121     return expr;
122 }
123 
124 ExprDef *
ExprCreateIdent(xkb_atom_t ident)125 ExprCreateIdent(xkb_atom_t ident)
126 {
127     EXPR_CREATE(ExprIdent, expr, EXPR_IDENT, EXPR_TYPE_UNKNOWN);
128     expr->ident.ident = ident;
129     return expr;
130 }
131 
132 ExprDef *
ExprCreateUnary(enum expr_op_type op,enum expr_value_type type,ExprDef * child)133 ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
134                 ExprDef *child)
135 {
136     EXPR_CREATE(ExprUnary, expr, op, type);
137     expr->unary.child = child;
138     return expr;
139 }
140 
141 ExprDef *
ExprCreateBinary(enum expr_op_type op,ExprDef * left,ExprDef * right)142 ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right)
143 {
144     EXPR_CREATE(ExprBinary, expr, op, EXPR_TYPE_UNKNOWN);
145 
146     if (op == EXPR_ASSIGN || left->expr.value_type == EXPR_TYPE_UNKNOWN)
147         expr->expr.value_type = right->expr.value_type;
148     else if (left->expr.value_type == right->expr.value_type ||
149              right->expr.value_type == EXPR_TYPE_UNKNOWN)
150         expr->expr.value_type = left->expr.value_type;
151     expr->binary.left = left;
152     expr->binary.right = right;
153 
154     return expr;
155 }
156 
157 ExprDef *
ExprCreateFieldRef(xkb_atom_t element,xkb_atom_t field)158 ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field)
159 {
160     EXPR_CREATE(ExprFieldRef, expr, EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN);
161     expr->field_ref.element = element;
162     expr->field_ref.field = field;
163     return expr;
164 }
165 
166 ExprDef *
ExprCreateArrayRef(xkb_atom_t element,xkb_atom_t field,ExprDef * entry)167 ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry)
168 {
169     EXPR_CREATE(ExprArrayRef, expr, EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
170     expr->array_ref.element = element;
171     expr->array_ref.field = field;
172     expr->array_ref.entry = entry;
173     return expr;
174 }
175 
176 ExprDef *
ExprCreateAction(xkb_atom_t name,ExprDef * args)177 ExprCreateAction(xkb_atom_t name, ExprDef *args)
178 {
179     EXPR_CREATE(ExprAction, expr, EXPR_ACTION_DECL, EXPR_TYPE_UNKNOWN);
180     expr->action.name = name;
181     expr->action.args = args;
182     return expr;
183 }
184 
185 ExprDef *
ExprCreateKeysymList(xkb_keysym_t sym)186 ExprCreateKeysymList(xkb_keysym_t sym)
187 {
188     EXPR_CREATE(ExprKeysymList, expr, EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS);
189 
190     darray_init(expr->keysym_list.syms);
191     darray_init(expr->keysym_list.symsMapIndex);
192     darray_init(expr->keysym_list.symsNumEntries);
193 
194     darray_append(expr->keysym_list.syms, sym);
195     darray_append(expr->keysym_list.symsMapIndex, 0);
196     darray_append(expr->keysym_list.symsNumEntries, 1);
197 
198     return expr;
199 }
200 
201 ExprDef *
ExprCreateMultiKeysymList(ExprDef * expr)202 ExprCreateMultiKeysymList(ExprDef *expr)
203 {
204     unsigned nLevels = darray_size(expr->keysym_list.symsMapIndex);
205 
206     darray_resize(expr->keysym_list.symsMapIndex, 1);
207     darray_resize(expr->keysym_list.symsNumEntries, 1);
208     darray_item(expr->keysym_list.symsMapIndex, 0) = 0;
209     darray_item(expr->keysym_list.symsNumEntries, 0) = nLevels;
210 
211     return expr;
212 }
213 
214 ExprDef *
ExprAppendKeysymList(ExprDef * expr,xkb_keysym_t sym)215 ExprAppendKeysymList(ExprDef *expr, xkb_keysym_t sym)
216 {
217     unsigned nSyms = darray_size(expr->keysym_list.syms);
218 
219     darray_append(expr->keysym_list.symsMapIndex, nSyms);
220     darray_append(expr->keysym_list.symsNumEntries, 1);
221     darray_append(expr->keysym_list.syms, sym);
222 
223     return expr;
224 }
225 
226 ExprDef *
ExprAppendMultiKeysymList(ExprDef * expr,ExprDef * append)227 ExprAppendMultiKeysymList(ExprDef *expr, ExprDef *append)
228 {
229     xkb_keysym_t *syms;
230     unsigned nSyms = darray_size(expr->keysym_list.syms);
231     unsigned numEntries = darray_size(append->keysym_list.syms);
232 
233     darray_append(expr->keysym_list.symsMapIndex, nSyms);
234     darray_append(expr->keysym_list.symsNumEntries, numEntries);
235     darray_steal(append->keysym_list.syms, &syms, NULL);
236     darray_append_items(expr->keysym_list.syms, syms, numEntries);
237 
238     FreeStmt((ParseCommon *) &append);
239 
240     return expr;
241 }
242 
243 KeycodeDef *
KeycodeCreate(xkb_atom_t name,int64_t value)244 KeycodeCreate(xkb_atom_t name, int64_t value)
245 {
246     KeycodeDef *def = malloc(sizeof(*def));
247     if (!def)
248         return NULL;
249 
250     def->common.type = STMT_KEYCODE;
251     def->common.next = NULL;
252     def->name = name;
253     def->value = value;
254 
255     return def;
256 }
257 
258 KeyAliasDef *
KeyAliasCreate(xkb_atom_t alias,xkb_atom_t real)259 KeyAliasCreate(xkb_atom_t alias, xkb_atom_t real)
260 {
261     KeyAliasDef *def = malloc(sizeof(*def));
262     if (!def)
263         return NULL;
264 
265     def->common.type = STMT_ALIAS;
266     def->common.next = NULL;
267     def->alias = alias;
268     def->real = real;
269 
270     return def;
271 }
272 
273 VModDef *
VModCreate(xkb_atom_t name,ExprDef * value)274 VModCreate(xkb_atom_t name, ExprDef *value)
275 {
276     VModDef *def = malloc(sizeof(*def));
277     if (!def)
278         return NULL;
279 
280     def->common.type = STMT_VMOD;
281     def->common.next = NULL;
282     def->name = name;
283     def->value = value;
284 
285     return def;
286 }
287 
288 VarDef *
VarCreate(ExprDef * name,ExprDef * value)289 VarCreate(ExprDef *name, ExprDef *value)
290 {
291     VarDef *def = malloc(sizeof(*def));
292     if (!def)
293         return NULL;
294 
295     def->common.type = STMT_VAR;
296     def->common.next = NULL;
297     def->name = name;
298     def->value = value;
299 
300     return def;
301 }
302 
303 VarDef *
BoolVarCreate(xkb_atom_t ident,bool set)304 BoolVarCreate(xkb_atom_t ident, bool set)
305 {
306     ExprDef *name, *value;
307     VarDef *def;
308     if (!(name = ExprCreateIdent(ident))) {
309         return NULL;
310     }
311     if (!(value = ExprCreateBoolean(set))) {
312         FreeStmt((ParseCommon *) name);
313         return NULL;
314     }
315     if (!(def = VarCreate(name, value))) {
316         FreeStmt((ParseCommon *) name);
317         FreeStmt((ParseCommon *) value);
318         return NULL;
319     }
320     return def;
321 }
322 
323 InterpDef *
InterpCreate(xkb_keysym_t sym,ExprDef * match)324 InterpCreate(xkb_keysym_t sym, ExprDef *match)
325 {
326     InterpDef *def = malloc(sizeof(*def));
327     if (!def)
328         return NULL;
329 
330     def->common.type = STMT_INTERP;
331     def->common.next = NULL;
332     def->sym = sym;
333     def->match = match;
334     def->def = NULL;
335 
336     return def;
337 }
338 
339 KeyTypeDef *
KeyTypeCreate(xkb_atom_t name,VarDef * body)340 KeyTypeCreate(xkb_atom_t name, VarDef *body)
341 {
342     KeyTypeDef *def = malloc(sizeof(*def));
343     if (!def)
344         return NULL;
345 
346     def->common.type = STMT_TYPE;
347     def->common.next = NULL;
348     def->merge = MERGE_DEFAULT;
349     def->name = name;
350     def->body = body;
351 
352     return def;
353 }
354 
355 SymbolsDef *
SymbolsCreate(xkb_atom_t keyName,VarDef * symbols)356 SymbolsCreate(xkb_atom_t keyName, VarDef *symbols)
357 {
358     SymbolsDef *def = malloc(sizeof(*def));
359     if (!def)
360         return NULL;
361 
362     def->common.type = STMT_SYMBOLS;
363     def->common.next = NULL;
364     def->merge = MERGE_DEFAULT;
365     def->keyName = keyName;
366     def->symbols = symbols;
367 
368     return def;
369 }
370 
371 GroupCompatDef *
GroupCompatCreate(unsigned group,ExprDef * val)372 GroupCompatCreate(unsigned group, ExprDef *val)
373 {
374     GroupCompatDef *def = malloc(sizeof(*def));
375     if (!def)
376         return NULL;
377 
378     def->common.type = STMT_GROUP_COMPAT;
379     def->common.next = NULL;
380     def->merge = MERGE_DEFAULT;
381     def->group = group;
382     def->def = val;
383 
384     return def;
385 }
386 
387 ModMapDef *
ModMapCreate(xkb_atom_t modifier,ExprDef * keys)388 ModMapCreate(xkb_atom_t modifier, ExprDef *keys)
389 {
390     ModMapDef *def = malloc(sizeof(*def));
391     if (!def)
392         return NULL;
393 
394     def->common.type = STMT_MODMAP;
395     def->common.next = NULL;
396     def->merge = MERGE_DEFAULT;
397     def->modifier = modifier;
398     def->keys = keys;
399 
400     return def;
401 }
402 
403 LedMapDef *
LedMapCreate(xkb_atom_t name,VarDef * body)404 LedMapCreate(xkb_atom_t name, VarDef *body)
405 {
406     LedMapDef *def = malloc(sizeof(*def));
407     if (!def)
408         return NULL;
409 
410     def->common.type = STMT_LED_MAP;
411     def->common.next = NULL;
412     def->merge = MERGE_DEFAULT;
413     def->name = name;
414     def->body = body;
415 
416     return def;
417 }
418 
419 LedNameDef *
LedNameCreate(unsigned ndx,ExprDef * name,bool virtual)420 LedNameCreate(unsigned ndx, ExprDef *name, bool virtual)
421 {
422     LedNameDef *def = malloc(sizeof(*def));
423     if (!def)
424         return NULL;
425 
426     def->common.type = STMT_LED_NAME;
427     def->common.next = NULL;
428     def->merge = MERGE_DEFAULT;
429     def->ndx = ndx;
430     def->name = name;
431     def->virtual = virtual;
432 
433     return def;
434 }
435 
436 static void
437 FreeInclude(IncludeStmt *incl);
438 
439 IncludeStmt *
IncludeCreate(struct xkb_context * ctx,char * str,enum merge_mode merge)440 IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge)
441 {
442     IncludeStmt *incl, *first;
443     char *file, *map, *stmt, *tmp, *extra_data;
444     char nextop;
445 
446     incl = first = NULL;
447     file = map = NULL;
448     tmp = str;
449     stmt = strdup_safe(str);
450     while (tmp && *tmp)
451     {
452         if (!ParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data))
453             goto err;
454 
455         /*
456          * Given an RMLVO (here layout) like 'us,,fr', the rules parser
457          * will give out something like 'pc+us+:2+fr:3+inet(evdev)'.
458          * We should just skip the ':2' in this case and leave it to the
459          * appropriate section to deal with the empty group.
460          */
461         if (isempty(file)) {
462             free(file);
463             free(map);
464             free(extra_data);
465             continue;
466         }
467 
468         if (first == NULL) {
469             first = incl = malloc(sizeof(*first));
470         } else {
471             incl->next_incl = malloc(sizeof(*first));
472             incl = incl->next_incl;
473         }
474 
475         if (!incl) {
476             log_wsgo(ctx,
477                      "Allocation failure in IncludeCreate; "
478                      "Using only part of the include\n");
479             break;
480         }
481 
482         incl->common.type = STMT_INCLUDE;
483         incl->common.next = NULL;
484         incl->merge = merge;
485         incl->stmt = NULL;
486         incl->file = file;
487         incl->map = map;
488         incl->modifier = extra_data;
489         incl->next_incl = NULL;
490 
491         if (nextop == '|')
492             merge = MERGE_AUGMENT;
493         else
494             merge = MERGE_OVERRIDE;
495     }
496 
497     if (first)
498         first->stmt = stmt;
499     else
500         free(stmt);
501 
502     return first;
503 
504 err:
505     log_err(ctx, "Illegal include statement \"%s\"; Ignored\n", stmt);
506     FreeInclude(first);
507     free(stmt);
508     return NULL;
509 }
510 
511 XkbFile *
XkbFileCreate(enum xkb_file_type type,char * name,ParseCommon * defs,enum xkb_map_flags flags)512 XkbFileCreate(enum xkb_file_type type, char *name, ParseCommon *defs,
513               enum xkb_map_flags flags)
514 {
515     XkbFile *file;
516 
517     file = calloc(1, sizeof(*file));
518     if (!file)
519         return NULL;
520 
521     XkbEscapeMapName(name);
522     file->file_type = type;
523     file->topName = strdup_safe(name);
524     file->name = name;
525     file->defs = defs;
526     file->flags = flags;
527 
528     return file;
529 }
530 
531 XkbFile *
XkbFileFromComponents(struct xkb_context * ctx,const struct xkb_component_names * kkctgs)532 XkbFileFromComponents(struct xkb_context *ctx,
533                       const struct xkb_component_names *kkctgs)
534 {
535     char *const components[] = {
536         kkctgs->keycodes, kkctgs->types,
537         kkctgs->compat, kkctgs->symbols,
538     };
539     enum xkb_file_type type;
540     IncludeStmt *include = NULL;
541     XkbFile *file = NULL;
542     ParseCommon *defs = NULL;
543 
544     for (type = FIRST_KEYMAP_FILE_TYPE; type <= LAST_KEYMAP_FILE_TYPE; type++) {
545         include = IncludeCreate(ctx, components[type], MERGE_DEFAULT);
546         if (!include)
547             goto err;
548 
549         file = XkbFileCreate(type, NULL, (ParseCommon *) include, 0);
550         if (!file) {
551             FreeInclude(include);
552             goto err;
553         }
554 
555         defs = AppendStmt(defs, &file->common);
556     }
557 
558     file = XkbFileCreate(FILE_TYPE_KEYMAP, NULL, defs, 0);
559     if (!file)
560         goto err;
561 
562     return file;
563 
564 err:
565     FreeXkbFile((XkbFile *) defs);
566     return NULL;
567 }
568 
569 static void
FreeExpr(ExprDef * expr)570 FreeExpr(ExprDef *expr)
571 {
572     if (!expr)
573         return;
574 
575     switch (expr->expr.op) {
576     case EXPR_ACTION_LIST:
577     case EXPR_NEGATE:
578     case EXPR_UNARY_PLUS:
579     case EXPR_NOT:
580     case EXPR_INVERT:
581         FreeStmt((ParseCommon *) expr->unary.child);
582         break;
583 
584     case EXPR_DIVIDE:
585     case EXPR_ADD:
586     case EXPR_SUBTRACT:
587     case EXPR_MULTIPLY:
588     case EXPR_ASSIGN:
589         FreeStmt((ParseCommon *) expr->binary.left);
590         FreeStmt((ParseCommon *) expr->binary.right);
591         break;
592 
593     case EXPR_ACTION_DECL:
594         FreeStmt((ParseCommon *) expr->action.args);
595         break;
596 
597     case EXPR_ARRAY_REF:
598         FreeStmt((ParseCommon *) expr->array_ref.entry);
599         break;
600 
601     case EXPR_KEYSYM_LIST:
602         darray_free(expr->keysym_list.syms);
603         darray_free(expr->keysym_list.symsMapIndex);
604         darray_free(expr->keysym_list.symsNumEntries);
605         break;
606 
607     default:
608         break;
609     }
610 }
611 
612 static void
FreeInclude(IncludeStmt * incl)613 FreeInclude(IncludeStmt *incl)
614 {
615     IncludeStmt *next;
616 
617     while (incl)
618     {
619         next = incl->next_incl;
620 
621         free(incl->file);
622         free(incl->map);
623         free(incl->modifier);
624         free(incl->stmt);
625 
626         free(incl);
627         incl = next;
628     }
629 }
630 
631 void
FreeStmt(ParseCommon * stmt)632 FreeStmt(ParseCommon *stmt)
633 {
634     ParseCommon *next;
635 
636     while (stmt)
637     {
638         next = stmt->next;
639 
640         switch (stmt->type) {
641         case STMT_INCLUDE:
642             FreeInclude((IncludeStmt *) stmt);
643             /* stmt is already free'd here. */
644             stmt = NULL;
645             break;
646         case STMT_EXPR:
647             FreeExpr((ExprDef *) stmt);
648             break;
649         case STMT_VAR:
650             FreeStmt((ParseCommon *) ((VarDef *) stmt)->name);
651             FreeStmt((ParseCommon *) ((VarDef *) stmt)->value);
652             break;
653         case STMT_TYPE:
654             FreeStmt((ParseCommon *) ((KeyTypeDef *) stmt)->body);
655             break;
656         case STMT_INTERP:
657             FreeStmt((ParseCommon *) ((InterpDef *) stmt)->match);
658             FreeStmt((ParseCommon *) ((InterpDef *) stmt)->def);
659             break;
660         case STMT_VMOD:
661             FreeStmt((ParseCommon *) ((VModDef *) stmt)->value);
662             break;
663         case STMT_SYMBOLS:
664             FreeStmt((ParseCommon *) ((SymbolsDef *) stmt)->symbols);
665             break;
666         case STMT_MODMAP:
667             FreeStmt((ParseCommon *) ((ModMapDef *) stmt)->keys);
668             break;
669         case STMT_GROUP_COMPAT:
670             FreeStmt((ParseCommon *) ((GroupCompatDef *) stmt)->def);
671             break;
672         case STMT_LED_MAP:
673             FreeStmt((ParseCommon *) ((LedMapDef *) stmt)->body);
674             break;
675         case STMT_LED_NAME:
676             FreeStmt((ParseCommon *) ((LedNameDef *) stmt)->name);
677             break;
678         default:
679             break;
680         }
681 
682         free(stmt);
683         stmt = next;
684     }
685 }
686 
687 void
FreeXkbFile(XkbFile * file)688 FreeXkbFile(XkbFile *file)
689 {
690     XkbFile *next;
691 
692     while (file)
693     {
694         next = (XkbFile *) file->common.next;
695 
696         switch (file->file_type) {
697         case FILE_TYPE_KEYMAP:
698             FreeXkbFile((XkbFile *) file->defs);
699             break;
700 
701         case FILE_TYPE_TYPES:
702         case FILE_TYPE_COMPAT:
703         case FILE_TYPE_SYMBOLS:
704         case FILE_TYPE_KEYCODES:
705         case FILE_TYPE_GEOMETRY:
706             FreeStmt(file->defs);
707             break;
708 
709         default:
710             break;
711         }
712 
713         free(file->name);
714         free(file->topName);
715         free(file);
716         file = next;
717     }
718 }
719 
720 static const char *xkb_file_type_strings[_FILE_TYPE_NUM_ENTRIES] = {
721     [FILE_TYPE_KEYCODES] = "xkb_keycodes",
722     [FILE_TYPE_TYPES] = "xkb_types",
723     [FILE_TYPE_COMPAT] = "xkb_compatibility",
724     [FILE_TYPE_SYMBOLS] = "xkb_symbols",
725     [FILE_TYPE_GEOMETRY] = "xkb_geometry",
726     [FILE_TYPE_KEYMAP] = "xkb_keymap",
727     [FILE_TYPE_RULES] = "rules",
728 };
729 
730 const char *
xkb_file_type_to_string(enum xkb_file_type type)731 xkb_file_type_to_string(enum xkb_file_type type)
732 {
733     if (type > _FILE_TYPE_NUM_ENTRIES)
734         return "unknown";
735     return xkb_file_type_strings[type];
736 }
737 
738 static const char *stmt_type_strings[_STMT_NUM_VALUES] = {
739     [STMT_UNKNOWN] = "unknown statement",
740     [STMT_INCLUDE] = "include statement",
741     [STMT_KEYCODE] = "key name definition",
742     [STMT_ALIAS] = "key alias definition",
743     [STMT_EXPR] = "expression",
744     [STMT_VAR] = "variable definition",
745     [STMT_TYPE] = "key type definition",
746     [STMT_INTERP] = "symbol interpretation definition",
747     [STMT_VMOD] = "virtual modifiers definition",
748     [STMT_SYMBOLS] = "key symbols definition",
749     [STMT_MODMAP] = "modifier map declaration",
750     [STMT_GROUP_COMPAT] = "group declaration",
751     [STMT_LED_MAP] = "indicator map declaration",
752     [STMT_LED_NAME] = "indicator name declaration",
753 };
754 
755 const char *
stmt_type_to_string(enum stmt_type type)756 stmt_type_to_string(enum stmt_type type)
757 {
758     if (type >= _STMT_NUM_VALUES)
759         return NULL;
760     return stmt_type_strings[type];
761 }
762 
763 static const char *expr_op_type_strings[_EXPR_NUM_VALUES] = {
764     [EXPR_VALUE] = "literal",
765     [EXPR_IDENT] = "identifier",
766     [EXPR_ACTION_DECL] = "action declaration",
767     [EXPR_FIELD_REF] = "field reference",
768     [EXPR_ARRAY_REF] = "array reference",
769     [EXPR_KEYSYM_LIST] = "list of keysyms",
770     [EXPR_ACTION_LIST] = "list of actions",
771     [EXPR_ADD] = "addition",
772     [EXPR_SUBTRACT] = "subtraction",
773     [EXPR_MULTIPLY] = "multiplication",
774     [EXPR_DIVIDE] = "division",
775     [EXPR_ASSIGN] = "assignment",
776     [EXPR_NOT] = "logical negation",
777     [EXPR_NEGATE] = "arithmetic negation",
778     [EXPR_INVERT] = "bitwise inversion",
779     [EXPR_UNARY_PLUS] = "unary plus",
780 };
781 
782 const char *
expr_op_type_to_string(enum expr_op_type type)783 expr_op_type_to_string(enum expr_op_type type)
784 {
785     if (type >= _EXPR_NUM_VALUES)
786         return NULL;
787     return expr_op_type_strings[type];
788 }
789 
790 static const char *expr_value_type_strings[_EXPR_TYPE_NUM_VALUES] = {
791     [EXPR_TYPE_UNKNOWN] = "unknown",
792     [EXPR_TYPE_BOOLEAN] = "boolean",
793     [EXPR_TYPE_INT] = "int",
794     [EXPR_TYPE_STRING] = "string",
795     [EXPR_TYPE_ACTION] = "action",
796     [EXPR_TYPE_KEYNAME] = "keyname",
797     [EXPR_TYPE_SYMBOLS] = "symbols",
798 };
799 
800 const char *
expr_value_type_to_string(enum expr_value_type type)801 expr_value_type_to_string(enum expr_value_type type)
802 {
803     if (type >= _EXPR_TYPE_NUM_VALUES)
804         return NULL;
805     return expr_value_type_strings[type];
806 }
807