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