Home | History | Annotate | Download | only in xkbcomp
      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 (at) 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 (at) fooishbar.org>
     51  *         Ran Benita <ran234 (at) gmail.com>
     52  */
     53 
     54 #include "xkbcomp-priv.h"
     55 #include "ast-build.h"
     56 #include "include.h"
     57 
     58 ParseCommon *
     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 *
     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 *
     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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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
    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
    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
    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
    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 *
    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 *
    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 *
    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 *
    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