836 lines
21 KiB
C
836 lines
21 KiB
C
/************************************************************
|
|
* Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this
|
|
* software and its documentation for any purpose and without
|
|
* fee is hereby granted, provided that the above copyright
|
|
* notice appear in all copies and that both that copyright
|
|
* notice and this permission notice appear in supporting
|
|
* documentation, and that the name of Silicon Graphics not be
|
|
* used in advertising or publicity pertaining to distribution
|
|
* of the software without specific prior written permission.
|
|
* Silicon Graphics makes no representation about the suitability
|
|
* of this software for any purpose. It is provided "as is"
|
|
* without any express or implied warranty.
|
|
*
|
|
* SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
|
* GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
|
|
* THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
********************************************************/
|
|
|
|
/*
|
|
* Copyright © 2012 Intel Corporation
|
|
* Copyright © 2012 Ran Benita <ran234@gmail.com>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Author: Daniel Stone <daniel@fooishbar.org>
|
|
* Ran Benita <ran234@gmail.com>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "xkbcomp-priv.h"
|
|
#include "ast-build.h"
|
|
#include "include.h"
|
|
|
|
static ExprDef *
|
|
ExprCreate(enum expr_op_type op, enum expr_value_type type, size_t size)
|
|
{
|
|
ExprDef *expr = malloc(size);
|
|
if (!expr)
|
|
return NULL;
|
|
|
|
expr->common.type = STMT_EXPR;
|
|
expr->common.next = NULL;
|
|
expr->expr.op = op;
|
|
expr->expr.value_type = type;
|
|
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateString(xkb_atom_t str)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_STRING, sizeof(ExprString));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->string.str = str;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateInteger(int ival)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_INT, sizeof(ExprInteger));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->integer.ival = ival;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateFloat(void)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_FLOAT, sizeof(ExprFloat));
|
|
if (!expr)
|
|
return NULL;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateBoolean(bool set)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_BOOLEAN, sizeof(ExprBoolean));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->boolean.set = set;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateKeyName(xkb_atom_t key_name)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_KEYNAME, sizeof(ExprKeyName));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->key_name.key_name = key_name;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateIdent(xkb_atom_t ident)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN, sizeof(ExprIdent));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->ident.ident = ident;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
|
|
ExprDef *child)
|
|
{
|
|
ExprDef *expr = ExprCreate(op, type, sizeof(ExprUnary));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->unary.child = child;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right)
|
|
{
|
|
ExprDef *expr = ExprCreate(op, EXPR_TYPE_UNKNOWN, sizeof(ExprBinary));
|
|
if (!expr)
|
|
return NULL;
|
|
|
|
if (op == EXPR_ASSIGN || left->expr.value_type == EXPR_TYPE_UNKNOWN)
|
|
expr->expr.value_type = right->expr.value_type;
|
|
else if (left->expr.value_type == right->expr.value_type ||
|
|
right->expr.value_type == EXPR_TYPE_UNKNOWN)
|
|
expr->expr.value_type = left->expr.value_type;
|
|
expr->binary.left = left;
|
|
expr->binary.right = right;
|
|
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN, sizeof(ExprFieldRef));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->field_ref.element = element;
|
|
expr->field_ref.field = field;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN, sizeof(ExprArrayRef));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->array_ref.element = element;
|
|
expr->array_ref.field = field;
|
|
expr->array_ref.entry = entry;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateAction(xkb_atom_t name, ExprDef *args)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_ACTION_DECL, EXPR_TYPE_UNKNOWN, sizeof(ExprAction));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->action.name = name;
|
|
expr->action.args = args;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateActionList(ExprDef *actions)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_ACTION_LIST, EXPR_TYPE_ACTIONS, sizeof(ExprActionList));
|
|
if (!expr)
|
|
return NULL;
|
|
expr->actions.actions = actions;
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateKeysymList(xkb_keysym_t sym)
|
|
{
|
|
ExprDef *expr = ExprCreate(EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS, sizeof(ExprKeysymList));
|
|
if (!expr)
|
|
return NULL;
|
|
|
|
darray_init(expr->keysym_list.syms);
|
|
darray_init(expr->keysym_list.symsMapIndex);
|
|
darray_init(expr->keysym_list.symsNumEntries);
|
|
|
|
darray_append(expr->keysym_list.syms, sym);
|
|
darray_append(expr->keysym_list.symsMapIndex, 0);
|
|
darray_append(expr->keysym_list.symsNumEntries, 1);
|
|
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprCreateMultiKeysymList(ExprDef *expr)
|
|
{
|
|
unsigned nLevels = darray_size(expr->keysym_list.symsMapIndex);
|
|
|
|
darray_resize(expr->keysym_list.symsMapIndex, 1);
|
|
darray_resize(expr->keysym_list.symsNumEntries, 1);
|
|
darray_item(expr->keysym_list.symsMapIndex, 0) = 0;
|
|
darray_item(expr->keysym_list.symsNumEntries, 0) = nLevels;
|
|
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprAppendKeysymList(ExprDef *expr, xkb_keysym_t sym)
|
|
{
|
|
unsigned nSyms = darray_size(expr->keysym_list.syms);
|
|
|
|
darray_append(expr->keysym_list.symsMapIndex, nSyms);
|
|
darray_append(expr->keysym_list.symsNumEntries, 1);
|
|
darray_append(expr->keysym_list.syms, sym);
|
|
|
|
return expr;
|
|
}
|
|
|
|
ExprDef *
|
|
ExprAppendMultiKeysymList(ExprDef *expr, ExprDef *append)
|
|
{
|
|
unsigned nSyms = darray_size(expr->keysym_list.syms);
|
|
unsigned numEntries = darray_size(append->keysym_list.syms);
|
|
|
|
darray_append(expr->keysym_list.symsMapIndex, nSyms);
|
|
darray_append(expr->keysym_list.symsNumEntries, numEntries);
|
|
darray_concat(expr->keysym_list.syms, append->keysym_list.syms);
|
|
|
|
FreeStmt((ParseCommon *) append);
|
|
|
|
return expr;
|
|
}
|
|
|
|
KeycodeDef *
|
|
KeycodeCreate(xkb_atom_t name, int64_t value)
|
|
{
|
|
KeycodeDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_KEYCODE;
|
|
def->common.next = NULL;
|
|
def->name = name;
|
|
def->value = value;
|
|
|
|
return def;
|
|
}
|
|
|
|
KeyAliasDef *
|
|
KeyAliasCreate(xkb_atom_t alias, xkb_atom_t real)
|
|
{
|
|
KeyAliasDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_ALIAS;
|
|
def->common.next = NULL;
|
|
def->alias = alias;
|
|
def->real = real;
|
|
|
|
return def;
|
|
}
|
|
|
|
VModDef *
|
|
VModCreate(xkb_atom_t name, ExprDef *value)
|
|
{
|
|
VModDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_VMOD;
|
|
def->common.next = NULL;
|
|
def->name = name;
|
|
def->value = value;
|
|
|
|
return def;
|
|
}
|
|
|
|
VarDef *
|
|
VarCreate(ExprDef *name, ExprDef *value)
|
|
{
|
|
VarDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_VAR;
|
|
def->common.next = NULL;
|
|
def->name = name;
|
|
def->value = value;
|
|
|
|
return def;
|
|
}
|
|
|
|
VarDef *
|
|
BoolVarCreate(xkb_atom_t ident, bool set)
|
|
{
|
|
ExprDef *name, *value;
|
|
VarDef *def;
|
|
if (!(name = ExprCreateIdent(ident))) {
|
|
return NULL;
|
|
}
|
|
if (!(value = ExprCreateBoolean(set))) {
|
|
FreeStmt((ParseCommon *) name);
|
|
return NULL;
|
|
}
|
|
if (!(def = VarCreate(name, value))) {
|
|
FreeStmt((ParseCommon *) name);
|
|
FreeStmt((ParseCommon *) value);
|
|
return NULL;
|
|
}
|
|
return def;
|
|
}
|
|
|
|
InterpDef *
|
|
InterpCreate(xkb_keysym_t sym, ExprDef *match)
|
|
{
|
|
InterpDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_INTERP;
|
|
def->common.next = NULL;
|
|
def->sym = sym;
|
|
def->match = match;
|
|
def->def = NULL;
|
|
|
|
return def;
|
|
}
|
|
|
|
KeyTypeDef *
|
|
KeyTypeCreate(xkb_atom_t name, VarDef *body)
|
|
{
|
|
KeyTypeDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_TYPE;
|
|
def->common.next = NULL;
|
|
def->merge = MERGE_DEFAULT;
|
|
def->name = name;
|
|
def->body = body;
|
|
|
|
return def;
|
|
}
|
|
|
|
SymbolsDef *
|
|
SymbolsCreate(xkb_atom_t keyName, VarDef *symbols)
|
|
{
|
|
SymbolsDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_SYMBOLS;
|
|
def->common.next = NULL;
|
|
def->merge = MERGE_DEFAULT;
|
|
def->keyName = keyName;
|
|
def->symbols = symbols;
|
|
|
|
return def;
|
|
}
|
|
|
|
GroupCompatDef *
|
|
GroupCompatCreate(unsigned group, ExprDef *val)
|
|
{
|
|
GroupCompatDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_GROUP_COMPAT;
|
|
def->common.next = NULL;
|
|
def->merge = MERGE_DEFAULT;
|
|
def->group = group;
|
|
def->def = val;
|
|
|
|
return def;
|
|
}
|
|
|
|
ModMapDef *
|
|
ModMapCreate(xkb_atom_t modifier, ExprDef *keys)
|
|
{
|
|
ModMapDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_MODMAP;
|
|
def->common.next = NULL;
|
|
def->merge = MERGE_DEFAULT;
|
|
def->modifier = modifier;
|
|
def->keys = keys;
|
|
|
|
return def;
|
|
}
|
|
|
|
LedMapDef *
|
|
LedMapCreate(xkb_atom_t name, VarDef *body)
|
|
{
|
|
LedMapDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_LED_MAP;
|
|
def->common.next = NULL;
|
|
def->merge = MERGE_DEFAULT;
|
|
def->name = name;
|
|
def->body = body;
|
|
|
|
return def;
|
|
}
|
|
|
|
LedNameDef *
|
|
LedNameCreate(unsigned ndx, ExprDef *name, bool virtual)
|
|
{
|
|
LedNameDef *def = malloc(sizeof(*def));
|
|
if (!def)
|
|
return NULL;
|
|
|
|
def->common.type = STMT_LED_NAME;
|
|
def->common.next = NULL;
|
|
def->merge = MERGE_DEFAULT;
|
|
def->ndx = ndx;
|
|
def->name = name;
|
|
def->virtual = virtual;
|
|
|
|
return def;
|
|
}
|
|
|
|
static void
|
|
FreeInclude(IncludeStmt *incl);
|
|
|
|
IncludeStmt *
|
|
IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge)
|
|
{
|
|
IncludeStmt *incl, *first;
|
|
char *stmt, *tmp;
|
|
char nextop;
|
|
|
|
incl = first = NULL;
|
|
tmp = str;
|
|
stmt = strdup_safe(str);
|
|
while (tmp && *tmp)
|
|
{
|
|
char *file = NULL, *map = NULL, *extra_data = NULL;
|
|
|
|
if (!ParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data))
|
|
goto err;
|
|
|
|
/*
|
|
* Given an RMLVO (here layout) like 'us,,fr', the rules parser
|
|
* will give out something like 'pc+us+:2+fr:3+inet(evdev)'.
|
|
* We should just skip the ':2' in this case and leave it to the
|
|
* appropriate section to deal with the empty group.
|
|
*/
|
|
if (isempty(file)) {
|
|
free(file);
|
|
free(map);
|
|
free(extra_data);
|
|
continue;
|
|
}
|
|
|
|
if (first == NULL) {
|
|
first = incl = malloc(sizeof(*first));
|
|
} else {
|
|
incl->next_incl = malloc(sizeof(*first));
|
|
incl = incl->next_incl;
|
|
}
|
|
|
|
if (!incl) {
|
|
free(file);
|
|
free(map);
|
|
free(extra_data);
|
|
break;
|
|
}
|
|
|
|
incl->common.type = STMT_INCLUDE;
|
|
incl->common.next = NULL;
|
|
incl->merge = merge;
|
|
incl->stmt = NULL;
|
|
incl->file = file;
|
|
incl->map = map;
|
|
incl->modifier = extra_data;
|
|
incl->next_incl = NULL;
|
|
|
|
if (nextop == '|')
|
|
merge = MERGE_AUGMENT;
|
|
else
|
|
merge = MERGE_OVERRIDE;
|
|
}
|
|
|
|
if (first)
|
|
first->stmt = stmt;
|
|
else
|
|
free(stmt);
|
|
|
|
return first;
|
|
|
|
err:
|
|
log_err(ctx, "Illegal include statement \"%s\"; Ignored\n", stmt);
|
|
FreeInclude(first);
|
|
free(stmt);
|
|
return NULL;
|
|
}
|
|
|
|
XkbFile *
|
|
XkbFileCreate(enum xkb_file_type type, char *name, ParseCommon *defs,
|
|
enum xkb_map_flags flags)
|
|
{
|
|
XkbFile *file;
|
|
|
|
file = calloc(1, sizeof(*file));
|
|
if (!file)
|
|
return NULL;
|
|
|
|
XkbEscapeMapName(name);
|
|
file->file_type = type;
|
|
file->name = name ? name : strdup("(unnamed)");
|
|
file->defs = defs;
|
|
file->flags = flags;
|
|
|
|
return file;
|
|
}
|
|
|
|
XkbFile *
|
|
XkbFileFromComponents(struct xkb_context *ctx,
|
|
const struct xkb_component_names *kkctgs)
|
|
{
|
|
char *const components[] = {
|
|
kkctgs->keycodes, kkctgs->types,
|
|
kkctgs->compat, kkctgs->symbols,
|
|
};
|
|
enum xkb_file_type type;
|
|
IncludeStmt *include = NULL;
|
|
XkbFile *file = NULL;
|
|
ParseCommon *defs = NULL, *defsLast = NULL;
|
|
|
|
for (type = FIRST_KEYMAP_FILE_TYPE; type <= LAST_KEYMAP_FILE_TYPE; type++) {
|
|
include = IncludeCreate(ctx, components[type], MERGE_DEFAULT);
|
|
if (!include)
|
|
goto err;
|
|
|
|
file = XkbFileCreate(type, NULL, (ParseCommon *) include, 0);
|
|
if (!file) {
|
|
FreeInclude(include);
|
|
goto err;
|
|
}
|
|
|
|
if (!defs)
|
|
defsLast = defs = &file->common;
|
|
else
|
|
defsLast = defsLast->next = &file->common;
|
|
}
|
|
|
|
file = XkbFileCreate(FILE_TYPE_KEYMAP, NULL, defs, 0);
|
|
if (!file)
|
|
goto err;
|
|
|
|
return file;
|
|
|
|
err:
|
|
FreeXkbFile((XkbFile *) defs);
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
FreeExpr(ExprDef *expr)
|
|
{
|
|
if (!expr)
|
|
return;
|
|
|
|
switch (expr->expr.op) {
|
|
case EXPR_NEGATE:
|
|
case EXPR_UNARY_PLUS:
|
|
case EXPR_NOT:
|
|
case EXPR_INVERT:
|
|
FreeStmt((ParseCommon *) expr->unary.child);
|
|
break;
|
|
|
|
case EXPR_DIVIDE:
|
|
case EXPR_ADD:
|
|
case EXPR_SUBTRACT:
|
|
case EXPR_MULTIPLY:
|
|
case EXPR_ASSIGN:
|
|
FreeStmt((ParseCommon *) expr->binary.left);
|
|
FreeStmt((ParseCommon *) expr->binary.right);
|
|
break;
|
|
|
|
case EXPR_ACTION_DECL:
|
|
FreeStmt((ParseCommon *) expr->action.args);
|
|
break;
|
|
|
|
case EXPR_ACTION_LIST:
|
|
FreeStmt((ParseCommon *) expr->actions.actions);
|
|
break;
|
|
|
|
case EXPR_ARRAY_REF:
|
|
FreeStmt((ParseCommon *) expr->array_ref.entry);
|
|
break;
|
|
|
|
case EXPR_KEYSYM_LIST:
|
|
darray_free(expr->keysym_list.syms);
|
|
darray_free(expr->keysym_list.symsMapIndex);
|
|
darray_free(expr->keysym_list.symsNumEntries);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
FreeInclude(IncludeStmt *incl)
|
|
{
|
|
IncludeStmt *next;
|
|
|
|
while (incl)
|
|
{
|
|
next = incl->next_incl;
|
|
|
|
free(incl->file);
|
|
free(incl->map);
|
|
free(incl->modifier);
|
|
free(incl->stmt);
|
|
|
|
free(incl);
|
|
incl = next;
|
|
}
|
|
}
|
|
|
|
void
|
|
FreeStmt(ParseCommon *stmt)
|
|
{
|
|
ParseCommon *next;
|
|
|
|
while (stmt)
|
|
{
|
|
next = stmt->next;
|
|
|
|
switch (stmt->type) {
|
|
case STMT_INCLUDE:
|
|
FreeInclude((IncludeStmt *) stmt);
|
|
/* stmt is already free'd here. */
|
|
stmt = NULL;
|
|
break;
|
|
case STMT_EXPR:
|
|
FreeExpr((ExprDef *) stmt);
|
|
break;
|
|
case STMT_VAR:
|
|
FreeStmt((ParseCommon *) ((VarDef *) stmt)->name);
|
|
FreeStmt((ParseCommon *) ((VarDef *) stmt)->value);
|
|
break;
|
|
case STMT_TYPE:
|
|
FreeStmt((ParseCommon *) ((KeyTypeDef *) stmt)->body);
|
|
break;
|
|
case STMT_INTERP:
|
|
FreeStmt((ParseCommon *) ((InterpDef *) stmt)->match);
|
|
FreeStmt((ParseCommon *) ((InterpDef *) stmt)->def);
|
|
break;
|
|
case STMT_VMOD:
|
|
FreeStmt((ParseCommon *) ((VModDef *) stmt)->value);
|
|
break;
|
|
case STMT_SYMBOLS:
|
|
FreeStmt((ParseCommon *) ((SymbolsDef *) stmt)->symbols);
|
|
break;
|
|
case STMT_MODMAP:
|
|
FreeStmt((ParseCommon *) ((ModMapDef *) stmt)->keys);
|
|
break;
|
|
case STMT_GROUP_COMPAT:
|
|
FreeStmt((ParseCommon *) ((GroupCompatDef *) stmt)->def);
|
|
break;
|
|
case STMT_LED_MAP:
|
|
FreeStmt((ParseCommon *) ((LedMapDef *) stmt)->body);
|
|
break;
|
|
case STMT_LED_NAME:
|
|
FreeStmt((ParseCommon *) ((LedNameDef *) stmt)->name);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
free(stmt);
|
|
stmt = next;
|
|
}
|
|
}
|
|
|
|
void
|
|
FreeXkbFile(XkbFile *file)
|
|
{
|
|
XkbFile *next;
|
|
|
|
while (file)
|
|
{
|
|
next = (XkbFile *) file->common.next;
|
|
|
|
switch (file->file_type) {
|
|
case FILE_TYPE_KEYMAP:
|
|
FreeXkbFile((XkbFile *) file->defs);
|
|
break;
|
|
|
|
case FILE_TYPE_TYPES:
|
|
case FILE_TYPE_COMPAT:
|
|
case FILE_TYPE_SYMBOLS:
|
|
case FILE_TYPE_KEYCODES:
|
|
case FILE_TYPE_GEOMETRY:
|
|
FreeStmt(file->defs);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
free(file->name);
|
|
free(file);
|
|
file = next;
|
|
}
|
|
}
|
|
|
|
static const char *xkb_file_type_strings[_FILE_TYPE_NUM_ENTRIES] = {
|
|
[FILE_TYPE_KEYCODES] = "xkb_keycodes",
|
|
[FILE_TYPE_TYPES] = "xkb_types",
|
|
[FILE_TYPE_COMPAT] = "xkb_compatibility",
|
|
[FILE_TYPE_SYMBOLS] = "xkb_symbols",
|
|
[FILE_TYPE_GEOMETRY] = "xkb_geometry",
|
|
[FILE_TYPE_KEYMAP] = "xkb_keymap",
|
|
[FILE_TYPE_RULES] = "rules",
|
|
};
|
|
|
|
const char *
|
|
xkb_file_type_to_string(enum xkb_file_type type)
|
|
{
|
|
if (type >= _FILE_TYPE_NUM_ENTRIES)
|
|
return "unknown";
|
|
return xkb_file_type_strings[type];
|
|
}
|
|
|
|
static const char *stmt_type_strings[_STMT_NUM_VALUES] = {
|
|
[STMT_UNKNOWN] = "unknown statement",
|
|
[STMT_INCLUDE] = "include statement",
|
|
[STMT_KEYCODE] = "key name definition",
|
|
[STMT_ALIAS] = "key alias definition",
|
|
[STMT_EXPR] = "expression",
|
|
[STMT_VAR] = "variable definition",
|
|
[STMT_TYPE] = "key type definition",
|
|
[STMT_INTERP] = "symbol interpretation definition",
|
|
[STMT_VMOD] = "virtual modifiers definition",
|
|
[STMT_SYMBOLS] = "key symbols definition",
|
|
[STMT_MODMAP] = "modifier map declaration",
|
|
[STMT_GROUP_COMPAT] = "group declaration",
|
|
[STMT_LED_MAP] = "indicator map declaration",
|
|
[STMT_LED_NAME] = "indicator name declaration",
|
|
};
|
|
|
|
const char *
|
|
stmt_type_to_string(enum stmt_type type)
|
|
{
|
|
if (type >= _STMT_NUM_VALUES)
|
|
return NULL;
|
|
return stmt_type_strings[type];
|
|
}
|
|
|
|
static const char *expr_op_type_strings[_EXPR_NUM_VALUES] = {
|
|
[EXPR_VALUE] = "literal",
|
|
[EXPR_IDENT] = "identifier",
|
|
[EXPR_ACTION_DECL] = "action declaration",
|
|
[EXPR_FIELD_REF] = "field reference",
|
|
[EXPR_ARRAY_REF] = "array reference",
|
|
[EXPR_KEYSYM_LIST] = "list of keysyms",
|
|
[EXPR_ACTION_LIST] = "list of actions",
|
|
[EXPR_ADD] = "addition",
|
|
[EXPR_SUBTRACT] = "subtraction",
|
|
[EXPR_MULTIPLY] = "multiplication",
|
|
[EXPR_DIVIDE] = "division",
|
|
[EXPR_ASSIGN] = "assignment",
|
|
[EXPR_NOT] = "logical negation",
|
|
[EXPR_NEGATE] = "arithmetic negation",
|
|
[EXPR_INVERT] = "bitwise inversion",
|
|
[EXPR_UNARY_PLUS] = "unary plus",
|
|
};
|
|
|
|
const char *
|
|
expr_op_type_to_string(enum expr_op_type type)
|
|
{
|
|
if (type >= _EXPR_NUM_VALUES)
|
|
return NULL;
|
|
return expr_op_type_strings[type];
|
|
}
|
|
|
|
static const char *expr_value_type_strings[_EXPR_TYPE_NUM_VALUES] = {
|
|
[EXPR_TYPE_UNKNOWN] = "unknown",
|
|
[EXPR_TYPE_BOOLEAN] = "boolean",
|
|
[EXPR_TYPE_INT] = "int",
|
|
[EXPR_TYPE_FLOAT] = "float",
|
|
[EXPR_TYPE_STRING] = "string",
|
|
[EXPR_TYPE_ACTION] = "action",
|
|
[EXPR_TYPE_ACTIONS] = "actions",
|
|
[EXPR_TYPE_KEYNAME] = "keyname",
|
|
[EXPR_TYPE_SYMBOLS] = "symbols",
|
|
};
|
|
|
|
const char *
|
|
expr_value_type_to_string(enum expr_value_type type)
|
|
{
|
|
if (type >= _EXPR_TYPE_NUM_VALUES)
|
|
return NULL;
|
|
return expr_value_type_strings[type];
|
|
}
|