libxkbcommon_la_SOURCES = \
src/xkbcomp/action.c \
src/xkbcomp/action.h \
+ src/xkbcomp/ast.h \
+ src/xkbcomp/ast-build.c \
+ src/xkbcomp/ast-build.h \
src/xkbcomp/compat.c \
src/xkbcomp/expr.c \
src/xkbcomp/expr.h \
+ src/xkbcomp/include.c \
+ src/xkbcomp/include.h \
src/xkbcomp/keycodes.c \
- src/xkbcomp/keytypes.c \
+ src/xkbcomp/keycodes.h \
src/xkbcomp/parser.y \
- src/xkbcomp/parseutils.c \
- src/xkbcomp/parseutils.h \
- src/xkbcomp/path.c \
- src/xkbcomp/path.h \
+ src/xkbcomp/parser-priv.h \
src/xkbcomp/rules.c \
src/xkbcomp/rules.h \
src/xkbcomp/scanner.l \
src/xkbcomp/symbols.c \
+ src/xkbcomp/types.c \
src/xkbcomp/vmod.c \
src/xkbcomp/vmod.h \
src/xkbcomp/xkbcomp.c \
- src/xkbcomp/xkbcomp.h \
src/xkbcomp/xkbcomp-priv.h \
src/atom.c \
src/atom.h \
#include "xkb-priv.h"
#include "text.h"
+struct xkb_keymap *
+xkb_map_new(struct xkb_context *ctx)
+{
+ struct xkb_keymap *keymap;
+
+ keymap = calloc(1, sizeof(*keymap));
+ if (!keymap)
+ return NULL;
+
+ keymap->refcnt = 1;
+ keymap->ctx = xkb_context_ref(ctx);
+
+ return keymap;
+}
+
+XKB_EXPORT struct xkb_keymap *
+xkb_map_ref(struct xkb_keymap *keymap)
+{
+ keymap->refcnt++;
+ return keymap;
+}
+
+XKB_EXPORT void
+xkb_map_unref(struct xkb_keymap *keymap)
+{
+ unsigned int i;
+ struct xkb_key *key;
+
+ if (!keymap || --keymap->refcnt > 0)
+ return;
+
+ for (i = 0; i < keymap->num_types; i++) {
+ free(keymap->types[i].map);
+ free(keymap->types[i].level_names);
+ }
+ free(keymap->types);
+ darray_foreach(key, keymap->keys) {
+ free(key->sym_index);
+ free(key->num_syms);
+ darray_free(key->syms);
+ free(key->actions);
+ }
+ darray_free(keymap->keys);
+ darray_free(keymap->sym_interpret);
+ darray_free(keymap->key_aliases);
+ free(keymap->keycodes_section_name);
+ free(keymap->symbols_section_name);
+ free(keymap->types_section_name);
+ free(keymap->compat_section_name);
+ xkb_context_unref(keymap->ctx);
+ free(keymap);
+}
+
/**
* Returns the total number of modifiers active in the keymap.
*/
return kc >= keymap->min_key_code && kc <= keymap->max_key_code;
}
+struct xkb_keymap *
+xkb_map_new(struct xkb_context *ctx);
+
xkb_atom_t
xkb_atom_intern(struct xkb_context *ctx, const char *string);
*
********************************************************/
+#include "xkbcomp-priv.h"
+#include "text.h"
+#include "expr.h"
#include "action.h"
+#include "keycodes.h"
static const ExprDef constTrue = {
.common = { .type = STMT_EXPR, .next = NULL },
*
********************************************************/
-#ifndef ACTION_H
-#define ACTION_H 1
-
-#include "xkbcomp-priv.h"
-#include "expr.h"
+#ifndef XKBCOMP_ACTION_H
+#define XKBCOMP_ACTION_H
#define F_ClearLocks 0
#define F_LatchToLock 1
struct _ActionInfo *next;
} ActionInfo;
-extern int
+int
HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
- union xkb_action *action,
- ActionInfo *info);
+ union xkb_action *action, ActionInfo *info);
-extern int
+int
SetActionField(struct xkb_keymap *keymap, const char *elem, const char *field,
- ExprDef *index, ExprDef *value,
- ActionInfo **info_rtrn);
+ ExprDef *index, ExprDef *value, ActionInfo **info_rtrn);
extern const LookupEntry ctrlNames[];
-#endif /* ACTION_H */
+#endif
--- /dev/null
+/************************************************************
+ * 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.
+ *
+ ********************************************************/
+
+#include "xkbcomp-priv.h"
+#include "ast-build.h"
+#include "parser-priv.h"
+#include "include.h"
+
+ATTR_MALLOC static void *
+malloc_or_die(size_t size)
+{
+ void *p = malloc(size);
+ if (!p) {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
+ return p;
+}
+
+ParseCommon *
+AppendStmt(ParseCommon * to, ParseCommon * append)
+{
+ ParseCommon *start = to;
+
+ if (append == NULL)
+ return to;
+ while ((to != NULL) && (to->next != NULL))
+ {
+ to = to->next;
+ }
+ if (to) {
+ to->next = append;
+ return start;
+ }
+ return append;
+}
+
+ExprDef *
+ExprCreate(enum expr_op_type op, enum expr_value_type type)
+{
+ ExprDef *expr;
+
+ expr = malloc_or_die(sizeof(*expr));
+
+ expr->common.type = STMT_EXPR;
+ expr->common.next = NULL;
+ expr->op = op;
+ expr->value_type = type;
+ return expr;
+}
+
+ExprDef *
+ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
+ ExprDef *child)
+{
+ ExprDef *expr;
+ expr = malloc_or_die(sizeof(*expr));
+
+ expr->common.type = STMT_EXPR;
+ expr->common.next = NULL;
+ expr->op = op;
+ expr->value_type = type;
+ expr->value.child = child;
+ return expr;
+}
+
+ExprDef *
+ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right)
+{
+ ExprDef *expr;
+
+ expr = malloc_or_die(sizeof(*expr));
+
+ expr->common.type = STMT_EXPR;
+ expr->common.next = NULL;
+ expr->op = op;
+ if (op == EXPR_ASSIGN || left->value_type == EXPR_TYPE_UNKNOWN)
+ expr->value_type = right->value_type;
+ else if (left->value_type == right->value_type ||
+ right->value_type == EXPR_TYPE_UNKNOWN)
+ expr->value_type = left->value_type;
+ else
+ expr->value_type = EXPR_TYPE_UNKNOWN;
+ expr->value.binary.left = left;
+ expr->value.binary.right = right;
+ return expr;
+}
+
+KeycodeDef *
+KeycodeCreate(char keyName[XkbKeyNameLength], unsigned long value)
+{
+ KeycodeDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_KEYCODE;
+ def->common.next = NULL;
+ strncpy(def->name, keyName, XkbKeyNameLength);
+ def->value = value;
+ return def;
+}
+
+KeyAliasDef *
+KeyAliasCreate(char alias[XkbKeyNameLength], char real[XkbKeyNameLength])
+{
+ KeyAliasDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_ALIAS;
+ def->common.next = NULL;
+ strncpy(def->alias, alias, XkbKeyNameLength);
+ strncpy(def->real, real, XkbKeyNameLength);
+ return def;
+}
+
+VModDef *
+VModCreate(xkb_atom_t name, ExprDef * value)
+{
+ VModDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ 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;
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_VAR;
+ def->common.next = NULL;
+ def->name = name;
+ def->value = value;
+ return def;
+}
+
+VarDef *
+BoolVarCreate(xkb_atom_t nameToken, unsigned set)
+{
+ ExprDef *name, *value;
+
+ name = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN);
+ name->value.str = nameToken;
+ value = ExprCreate(EXPR_VALUE, EXPR_TYPE_BOOLEAN);
+ value->value.uval = set;
+ return VarCreate(name, value);
+}
+
+InterpDef *
+InterpCreate(char *sym, ExprDef * match)
+{
+ InterpDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_INTERP;
+ def->common.next = NULL;
+ def->sym = sym;
+ def->match = match;
+ return def;
+}
+
+KeyTypeDef *
+KeyTypeCreate(xkb_atom_t name, VarDef * body)
+{
+ KeyTypeDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_TYPE;
+ def->common.next = NULL;
+ def->merge = MERGE_DEFAULT;
+ def->name = name;
+ def->body = body;
+ return def;
+}
+
+SymbolsDef *
+SymbolsCreate(char keyName[XkbKeyNameLength], ExprDef *symbols)
+{
+ SymbolsDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_SYMBOLS;
+ def->common.next = NULL;
+ def->merge = MERGE_DEFAULT;
+ strncpy(def->keyName, keyName, XkbKeyNameLength);
+ def->symbols = symbols;
+ return def;
+}
+
+GroupCompatDef *
+GroupCompatCreate(int group, ExprDef * val)
+{
+ GroupCompatDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_GROUP_COMPAT;
+ def->common.next = NULL;
+ def->merge = MERGE_DEFAULT;
+ def->group = group;
+ def->def = val;
+ return def;
+}
+
+ModMapDef *
+ModMapCreate(uint32_t modifier, ExprDef * keys)
+{
+ ModMapDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_MODMAP;
+ def->common.next = NULL;
+ def->merge = MERGE_DEFAULT;
+ def->modifier = modifier;
+ def->keys = keys;
+ return def;
+}
+
+IndicatorMapDef *
+IndicatorMapCreate(xkb_atom_t name, VarDef * body)
+{
+ IndicatorMapDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_INDICATOR_MAP;
+ def->common.next = NULL;
+ def->merge = MERGE_DEFAULT;
+ def->name = name;
+ def->body = body;
+ return def;
+}
+
+IndicatorNameDef *
+IndicatorNameCreate(int ndx, ExprDef * name, bool virtual)
+{
+ IndicatorNameDef *def;
+
+ def = malloc_or_die(sizeof(*def));
+
+ def->common.type = STMT_INDICATOR_NAME;
+ def->common.next = NULL;
+ def->merge = MERGE_DEFAULT;
+ def->ndx = ndx;
+ def->name = name;
+ def->virtual = virtual;
+ return def;
+}
+
+ExprDef *
+ActionCreate(xkb_atom_t name, ExprDef * args)
+{
+ ExprDef *act;
+
+ act = malloc_or_die(sizeof(*act));
+
+ act->common.type = STMT_EXPR;
+ act->common.next = NULL;
+ act->op = EXPR_ACTION_DECL;
+ act->value.action.name = name;
+ act->value.action.args = args;
+ return act;
+}
+
+ExprDef *
+CreateKeysymList(char *sym)
+{
+ ExprDef *def;
+
+ def = ExprCreate(EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS);
+
+ darray_init(def->value.list.syms);
+ darray_init(def->value.list.symsMapIndex);
+ darray_init(def->value.list.symsNumEntries);
+
+ darray_append(def->value.list.syms, sym);
+ darray_append(def->value.list.symsMapIndex, 0);
+ darray_append(def->value.list.symsNumEntries, 1);
+
+ return def;
+}
+
+ExprDef *
+CreateMultiKeysymList(ExprDef *list)
+{
+ size_t nLevels = darray_size(list->value.list.symsMapIndex);
+
+ darray_resize(list->value.list.symsMapIndex, 1);
+ darray_resize(list->value.list.symsNumEntries, 1);
+ darray_item(list->value.list.symsMapIndex, 0) = 0;
+ darray_item(list->value.list.symsNumEntries, 0) = nLevels;
+
+ return list;
+}
+
+ExprDef *
+AppendKeysymList(ExprDef * list, char *sym)
+{
+ size_t nSyms = darray_size(list->value.list.syms);
+
+ darray_append(list->value.list.symsMapIndex, nSyms);
+ darray_append(list->value.list.symsNumEntries, 1);
+ darray_append(list->value.list.syms, sym);
+
+ return list;
+}
+
+ExprDef *
+AppendMultiKeysymList(ExprDef * list, ExprDef * append)
+{
+ size_t nSyms = darray_size(list->value.list.syms);
+ size_t numEntries = darray_size(append->value.list.syms);
+
+ darray_append(list->value.list.symsMapIndex, nSyms);
+ darray_append(list->value.list.symsNumEntries, numEntries);
+ darray_append_items(list->value.list.syms,
+ darray_mem(append->value.list.syms, 0),
+ numEntries);
+
+ darray_resize(append->value.list.syms, 0);
+ FreeStmt(&append->common);
+
+ return list;
+}
+
+static void
+FreeInclude(IncludeStmt *incl);
+
+IncludeStmt *
+IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge)
+{
+ IncludeStmt *incl, *first;
+ char *file, *map, *stmt, *tmp, *extra_data;
+ char nextop;
+
+ incl = first = NULL;
+ file = map = NULL;
+ tmp = str;
+ stmt = strdup_safe(str);
+ while (tmp && *tmp)
+ {
+ if (!ParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data))
+ goto err;
+
+ if (first == NULL) {
+ first = incl = malloc(sizeof(*first));
+ } else {
+ incl->next_incl = malloc(sizeof(*first));
+ incl = incl->next_incl;
+ }
+
+ if (!incl) {
+ log_wsgo(ctx,
+ "Allocation failure in IncludeCreate; "
+ "Using only part of the include\n");
+ 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;
+}
+
+/*
+ * All latin-1 alphanumerics, plus parens, slash, minus, underscore and
+ * wildcards.
+ */
+static const unsigned char componentSpecLegal[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83,
+ 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
+};
+
+static void
+EnsureSafeMapName(char *name)
+{
+ if (!name)
+ return;
+
+ while (*name != '\0') {
+ if ((componentSpecLegal[(*name) / 8] & (1 << ((*name) % 8))) == 0)
+ *name = '_';
+ name++;
+ }
+}
+
+XkbFile *
+XkbFileCreate(struct xkb_context *ctx, enum xkb_file_type type, char *name,
+ ParseCommon *defs, unsigned flags)
+{
+ XkbFile *file;
+
+ file = calloc(1, sizeof(*file));
+ if (!file)
+ return NULL;
+
+ EnsureSafeMapName(name);
+ file->file_type = type;
+ file->topName = strdup_safe(name);
+ file->name = name;
+ file->defs = defs;
+ file->id = xkb_context_take_file_id(ctx);
+ file->flags = flags;
+ return file;
+}
+
+XkbFile *
+XkbFileFromComponents(struct xkb_context *ctx,
+ struct xkb_component_names *kkctgs)
+{
+ IncludeStmt *inc;
+ XkbFile *keycodes, *types, *compat, *symbols;
+
+ inc = IncludeCreate(ctx, kkctgs->keycodes, MERGE_DEFAULT);
+ keycodes = XkbFileCreate(ctx, FILE_TYPE_KEYCODES, NULL,
+ (ParseCommon *) inc, 0);
+
+ inc = IncludeCreate(ctx, kkctgs->types, MERGE_DEFAULT);
+ types = XkbFileCreate(ctx, FILE_TYPE_TYPES, NULL,
+ (ParseCommon *) inc, 0);
+ AppendStmt(&keycodes->common, &types->common);
+
+ inc = IncludeCreate(ctx, kkctgs->compat, MERGE_DEFAULT);
+ compat = XkbFileCreate(ctx, FILE_TYPE_COMPAT, NULL,
+ (ParseCommon *) inc, 0);
+ AppendStmt(&keycodes->common, &compat->common);
+
+ inc = IncludeCreate(ctx, kkctgs->symbols, MERGE_DEFAULT);
+ symbols = XkbFileCreate(ctx, FILE_TYPE_SYMBOLS, NULL,
+ (ParseCommon *) inc, 0);
+ AppendStmt(&keycodes->common, &symbols->common);
+
+ return XkbFileCreate(ctx, FILE_TYPE_KEYMAP, strdup(""),
+ &keycodes->common, 0);
+}
+
+static void
+FreeExpr(ExprDef *expr)
+{
+ char **sym;
+
+ if (!expr)
+ return;
+
+ switch (expr->op) {
+ case EXPR_ACTION_LIST:
+ case EXPR_NEGATE:
+ case EXPR_UNARY_PLUS:
+ case EXPR_NOT:
+ case EXPR_INVERT:
+ FreeStmt(&expr->value.child->common);
+ break;
+
+ case EXPR_DIVIDE:
+ case EXPR_ADD:
+ case EXPR_SUBTRACT:
+ case EXPR_MULTIPLY:
+ case EXPR_ASSIGN:
+ FreeStmt(&expr->value.binary.left->common);
+ FreeStmt(&expr->value.binary.right->common);
+ break;
+
+ case EXPR_ACTION_DECL:
+ FreeStmt(&expr->value.action.args->common);
+ break;
+
+ case EXPR_ARRAY_REF:
+ FreeStmt(&expr->value.array.entry->common);
+ break;
+
+ case EXPR_KEYSYM_LIST:
+ darray_foreach(sym, expr->value.list.syms)
+ free(*sym);
+ darray_free(expr->value.list.syms);
+ darray_free(expr->value.list.symsMapIndex);
+ darray_free(expr->value.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;
+ YYSTYPE u;
+
+ while (stmt)
+ {
+ next = stmt->next;
+ u.any = stmt;
+
+ switch (stmt->type) {
+ case STMT_INCLUDE:
+ FreeInclude((IncludeStmt *) stmt);
+ /* stmt is already free'd here. */
+ stmt = NULL;
+ break;
+ case STMT_EXPR:
+ FreeExpr(u.expr);
+ break;
+ case STMT_VAR:
+ FreeStmt(&u.var->name->common);
+ FreeStmt(&u.var->value->common);
+ break;
+ case STMT_TYPE:
+ FreeStmt(&u.keyType->body->common);
+ break;
+ case STMT_INTERP:
+ free(u.interp->sym);
+ FreeStmt(&u.interp->match->common);
+ FreeStmt(&u.interp->def->common);
+ break;
+ case STMT_VMOD:
+ FreeStmt(&u.vmod->value->common);
+ break;
+ case STMT_SYMBOLS:
+ FreeStmt(&u.syms->symbols->common);
+ break;
+ case STMT_MODMAP:
+ FreeStmt(&u.modMask->keys->common);
+ break;
+ case STMT_GROUP_COMPAT:
+ FreeStmt(&u.groupCompat->def->common);
+ break;
+ case STMT_INDICATOR_MAP:
+ FreeStmt(&u.ledMap->body->common);
+ break;
+ case STMT_INDICATOR_NAME:
+ FreeStmt(&u.ledName->name->common);
+ 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->topName);
+ free(file);
+ file = next;
+ }
+}
+
+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_INDICATOR_MAP] = "indicator map declaration",
+ [STMT_INDICATOR_NAME] = "indicator name declaration",
+};
+
+const char *
+StmtTypeToString(enum stmt_type type)
+{
+ if (type >= _STMT_NUM_VALUES)
+ type = STMT_UNKNOWN;
+ return stmt_type_strings[type];
+}
--- /dev/null
+/************************************************************
+ * 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.
+ *
+ ********************************************************/
+
+#ifndef XKBCOMP_AST_BUILD_H
+#define XKBCOMP_AST_BUILD_H
+
+ParseCommon *
+AppendStmt(ParseCommon *to, ParseCommon *append);
+
+ExprDef *
+ExprCreate(enum expr_op_type op, enum expr_value_type type);
+
+ExprDef *
+ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
+ ExprDef *child);
+
+ExprDef *
+ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right);
+
+KeycodeDef *
+KeycodeCreate(char keyName[XkbKeyNameLength], unsigned long value);
+
+KeyAliasDef *
+KeyAliasCreate(char keyName[XkbKeyNameLength], char real[XkbKeyNameLength]);
+
+VModDef *
+VModCreate(xkb_atom_t name, ExprDef *value);
+
+VarDef *
+VarCreate(ExprDef *name, ExprDef *value);
+
+VarDef *
+BoolVarCreate(xkb_atom_t nameToken, unsigned set);
+
+InterpDef *
+InterpCreate(char *sym, ExprDef *match);
+
+KeyTypeDef *
+KeyTypeCreate(xkb_atom_t name, VarDef *body);
+
+SymbolsDef *
+SymbolsCreate(char keyName[XkbKeyNameLength], ExprDef *symbols);
+
+GroupCompatDef *
+GroupCompatCreate(int group, ExprDef *def);
+
+ModMapDef *
+ModMapCreate(uint32_t modifier, ExprDef *keys);
+
+IndicatorMapDef *
+IndicatorMapCreate(xkb_atom_t name, VarDef *body);
+
+IndicatorNameDef *
+IndicatorNameCreate(int ndx, ExprDef *name, bool virtual);
+
+ExprDef *
+ActionCreate(xkb_atom_t name, ExprDef *args);
+
+ExprDef *
+CreateMultiKeysymList(ExprDef *list);
+
+ExprDef *
+CreateKeysymList(char *sym);
+
+ExprDef *
+AppendMultiKeysymList(ExprDef *list, ExprDef *append);
+
+ExprDef *
+AppendKeysymList(ExprDef *list, char *sym);
+
+IncludeStmt *
+IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge);
+
+XkbFile *
+XkbFileCreate(struct xkb_context *ctx, enum xkb_file_type type, char *name,
+ ParseCommon *defs, unsigned flags);
+
+void
+FreeStmt(ParseCommon *stmt);
+
+#endif
--- /dev/null
+/************************************************************
+ * 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.
+ *
+ ********************************************************/
+
+#ifndef XKBCOMP_AST_H
+#define XKBCOMP_AST_H
+
+enum stmt_type {
+ STMT_UNKNOWN = 0,
+ STMT_INCLUDE,
+ STMT_KEYCODE,
+ STMT_ALIAS,
+ STMT_EXPR,
+ STMT_VAR,
+ STMT_TYPE,
+ STMT_INTERP,
+ STMT_VMOD,
+ STMT_SYMBOLS,
+ STMT_MODMAP,
+ STMT_GROUP_COMPAT,
+ STMT_INDICATOR_MAP,
+ STMT_INDICATOR_NAME,
+ _STMT_NUM_VALUES
+};
+
+enum expr_value_type {
+ EXPR_TYPE_UNKNOWN = 0,
+ EXPR_TYPE_BOOLEAN,
+ EXPR_TYPE_INT,
+ EXPR_TYPE_STRING,
+ EXPR_TYPE_ACTION,
+ EXPR_TYPE_KEYNAME,
+ EXPR_TYPE_SYMBOLS,
+};
+
+enum expr_op_type {
+ EXPR_VALUE = 0,
+ EXPR_IDENT,
+ EXPR_ACTION_DECL,
+ EXPR_FIELD_REF,
+ EXPR_ARRAY_REF,
+ EXPR_KEYSYM_LIST,
+ EXPR_ACTION_LIST,
+ EXPR_ADD,
+ EXPR_SUBTRACT,
+ EXPR_MULTIPLY,
+ EXPR_DIVIDE,
+ EXPR_ASSIGN,
+ EXPR_NOT,
+ EXPR_NEGATE,
+ EXPR_INVERT,
+ EXPR_UNARY_PLUS,
+};
+
+enum merge_mode {
+ MERGE_DEFAULT,
+ MERGE_AUGMENT,
+ MERGE_OVERRIDE,
+ MERGE_REPLACE,
+};
+
+typedef struct _ParseCommon {
+ enum stmt_type type;
+ struct _ParseCommon *next;
+} ParseCommon;
+
+typedef struct _IncludeStmt {
+ ParseCommon common;
+ enum merge_mode merge;
+ char *stmt;
+ char *file;
+ char *map;
+ char *modifier;
+ struct _IncludeStmt *next_incl;
+} IncludeStmt;
+
+typedef struct _Expr {
+ ParseCommon common;
+ enum expr_op_type op;
+ enum expr_value_type value_type;
+ union {
+ struct {
+ struct _Expr *left;
+ struct _Expr *right;
+ } binary;
+ struct {
+ xkb_atom_t element;
+ xkb_atom_t field;
+ } field;
+ struct {
+ xkb_atom_t element;
+ xkb_atom_t field;
+ struct _Expr *entry;
+ } array;
+ struct {
+ xkb_atom_t name;
+ struct _Expr *args;
+ } action;
+ struct {
+ darray(char *) syms;
+ darray(int) symsMapIndex;
+ darray(unsigned int) symsNumEntries;
+ } list;
+ struct _Expr *child;
+ xkb_atom_t str;
+ unsigned uval;
+ int ival;
+ char keyName[XkbKeyNameLength];
+ } value;
+} ExprDef;
+
+typedef struct _VarDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ ExprDef *name;
+ ExprDef *value;
+} VarDef;
+
+typedef struct _VModDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ xkb_atom_t name;
+ ExprDef *value;
+} VModDef;
+
+typedef struct _KeycodeDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ char name[XkbKeyNameLength];
+ unsigned long value;
+} KeycodeDef;
+
+typedef struct _KeyAliasDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ char alias[XkbKeyNameLength];
+ char real[XkbKeyNameLength];
+} KeyAliasDef;
+
+typedef struct _KeyTypeDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ xkb_atom_t name;
+ VarDef *body;
+} KeyTypeDef;
+
+typedef struct _SymbolsDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ char keyName[XkbKeyNameLength];
+ ExprDef *symbols;
+} SymbolsDef;
+
+typedef struct _ModMapDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ xkb_atom_t modifier;
+ ExprDef *keys;
+} ModMapDef;
+
+typedef struct _GroupCompatDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ int group;
+ ExprDef *def;
+} GroupCompatDef;
+
+typedef struct _InterpDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ char *sym;
+ ExprDef *match;
+ VarDef *def;
+} InterpDef;
+
+typedef struct _IndicatorNameDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ int ndx;
+ ExprDef *name;
+ bool virtual;
+} IndicatorNameDef;
+
+typedef struct _IndicatorMapDef {
+ ParseCommon common;
+ enum merge_mode merge;
+ xkb_atom_t name;
+ VarDef *body;
+} IndicatorMapDef;
+
+typedef struct _XkbFile {
+ ParseCommon common;
+ enum xkb_file_type file_type;
+ char *topName;
+ char *name;
+ ParseCommon *defs;
+ int id;
+ unsigned flags;
+} XkbFile;
+
+#endif
********************************************************/
#include "xkbcomp-priv.h"
-#include "parseutils.h"
+#include "text.h"
+#include "expr.h"
#include "action.h"
#include "vmod.h"
+#include "include.h"
enum si_field {
SI_FIELD_VIRTUAL_MOD = (1 << 0),
next_incl.act = NULL;
ClearCompatInfo(&next_incl);
- FreeXKBFile(rtrn);
+ FreeXkbFile(rtrn);
}
MergeIncludedCompatMaps(info, &included, merge);
*
********************************************************/
+#include "xkbcomp-priv.h"
+#include "text.h"
#include "expr.h"
typedef bool (*IdentLookupFunc)(struct xkb_context *ctx, const void *priv,
*
********************************************************/
-#ifndef EXPR_H
-#define EXPR_H 1
-
-#include "xkbcomp-priv.h"
+#ifndef XKBCOMP_EXPR_H
+#define XKBCOMP_EXPR_H
typedef struct _LookupEntry {
const char *name;
unsigned int value;
} LookupEntry;
-extern const char *
+const char *
exprOpText(enum expr_op_type op);
bool
ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr,
xkb_keysym_t *sym_rtrn);
-#endif /* EXPR_H */
+#endif
--- /dev/null
+/************************************************************
+ * 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.
+ *
+ ********************************************************/
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "xkbcomp-priv.h"
+#include "text.h"
+#include "include.h"
+
+/**
+ * Extract the first token from an include statement.
+ * @param str_inout Input statement, modified in-place. Can be passed in
+ * repeatedly. If str_inout is NULL, the parsing has completed.
+ * @param file_rtrn Set to the include file to be used.
+ * @param map_rtrn Set to whatever comes after ), if any.
+ * @param nextop_rtrn Set to the next operation in the complete statement.
+ * @param extra_data Set to the string between ( and ), if any.
+ *
+ * @return true if parsing was succcessful, false for an illegal string.
+ *
+ * Example: "evdev+aliases(qwerty)"
+ * str_inout = aliases(qwerty)
+ * nextop_retrn = +
+ * extra_data = NULL
+ * file_rtrn = evdev
+ * map_rtrn = NULL
+ *
+ * 2nd run with "aliases(qwerty)"
+ * str_inout = NULL
+ * file_rtrn = aliases
+ * map_rtrn = qwerty
+ * extra_data = NULL
+ * nextop_retrn = ""
+ *
+ */
+bool
+ParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn,
+ char *nextop_rtrn, char **extra_data)
+{
+ char *tmp, *str, *next;
+
+ str = *str_inout;
+
+ /* search for tokens inside the string */
+ next = strpbrk(str, "|+");
+ if (next) {
+ /* set nextop_rtrn to \0, next to next character */
+ *nextop_rtrn = *next;
+ *next++ = '\0';
+ }
+ else {
+ *nextop_rtrn = '\0';
+ next = NULL;
+ }
+
+ /* search for :, store result in extra_data */
+ tmp = strchr(str, ':');
+ if (tmp != NULL) {
+ *tmp++ = '\0';
+ *extra_data = strdup(tmp);
+ }
+ else {
+ *extra_data = NULL;
+ }
+
+ tmp = strchr(str, '(');
+ if (tmp == NULL) {
+ *file_rtrn = strdup(str);
+ *map_rtrn = NULL;
+ }
+ else if (str[0] == '(') {
+ free(*extra_data);
+ return false;
+ }
+ else {
+ *tmp++ = '\0';
+ *file_rtrn = strdup(str);
+ str = tmp;
+ tmp = strchr(str, ')');
+ if ((tmp == NULL) || (tmp[1] != '\0')) {
+ free(*file_rtrn);
+ free(*extra_data);
+ return false;
+ }
+ *tmp++ = '\0';
+ *map_rtrn = strdup(str);
+ }
+
+ if (*nextop_rtrn == '\0')
+ *str_inout = NULL;
+ else if ((*nextop_rtrn == '|') || (*nextop_rtrn == '+'))
+ *str_inout = next;
+ else
+ return false;
+
+ return true;
+}
+
+/***====================================================================***/
+
+/**
+ * Return the xkb directory based on the type.
+ */
+static const char *
+DirectoryForInclude(enum xkb_file_type type)
+{
+ switch (type) {
+ case FILE_TYPE_KEYMAP:
+ return "keymap";
+
+ case FILE_TYPE_KEYCODES:
+ return "keycodes";
+
+ case FILE_TYPE_TYPES:
+ return "types";
+
+ case FILE_TYPE_SYMBOLS:
+ return "symbols";
+
+ case FILE_TYPE_COMPAT:
+ return "compat";
+
+ case FILE_TYPE_GEOMETRY:
+ return "geometry";
+
+ case FILE_TYPE_RULES:
+ return "rules";
+
+ default:
+ return "";
+ }
+}
+
+/***====================================================================***/
+
+/**
+ * Search for the given file name in the include directories.
+ *
+ * @param ctx the XKB ctx containing the include paths
+ * @param type one of FILE_TYPE_TYPES, FILE_TYPE_COMPAT, ..., or
+ * FILE_TYPE_KEYMAP or FILE_TYPE_RULES
+ * @param pathRtrn is set to the full path of the file if found.
+ *
+ * @return an FD to the file or NULL. If NULL is returned, the value of
+ * pathRtrn is undefined.
+ */
+FILE *
+FindFileInXkbPath(struct xkb_context *ctx, const char *name,
+ enum xkb_file_type type, char **pathRtrn)
+{
+ size_t i;
+ int ret;
+ FILE *file = NULL;
+ char buf[PATH_MAX];
+ const char *typeDir;
+
+ typeDir = DirectoryForInclude(type);
+ for (i = 0; i < xkb_context_num_include_paths(ctx); i++) {
+ ret = snprintf(buf, sizeof(buf), "%s/%s/%s",
+ xkb_context_include_path_get(ctx, i), typeDir, name);
+ if (ret >= (ssize_t) sizeof(buf)) {
+ log_err(ctx, "File name (%s/%s/%s) too long\n",
+ xkb_context_include_path_get(ctx, i), typeDir, name);
+ continue;
+ }
+ file = fopen(buf, "r");
+ if (file == NULL) {
+ log_err(ctx, "Couldn't open file (%s/%s/%s): %s\n",
+ xkb_context_include_path_get(ctx, i), typeDir, name,
+ strerror(errno));
+ continue;
+ }
+ break;
+ }
+
+ if ((file != NULL) && (pathRtrn != NULL))
+ *pathRtrn = strdup(buf);
+ return file;
+}
+
+/**
+ * Open the file given in the include statement and parse it's content.
+ * If the statement defines a specific map to use, this map is returned in
+ * file_rtrn. Otherwise, the default map is returned.
+ *
+ * @param ctx The ctx containing include paths
+ * @param stmt The include statement, specifying the file name to look for.
+ * @param file_type Type of file (FILE_TYPE_KEYCODES, etc.)
+ * @param file_rtrn Returns the key map to be used.
+ * @param merge_rtrn Always returns stmt->merge.
+ *
+ * @return true on success or false otherwise.
+ */
+bool
+ProcessIncludeFile(struct xkb_context *ctx,
+ IncludeStmt * stmt,
+ enum xkb_file_type file_type,
+ XkbFile ** file_rtrn, enum merge_mode *merge_rtrn)
+{
+ FILE *file;
+ XkbFile *rtrn, *mapToUse, *next;
+
+ file = FindFileInXkbPath(ctx, stmt->file, file_type, NULL);
+ if (file == NULL) {
+ log_err(ctx, "Can't find file \"%s\" for %s include\n", stmt->file,
+ DirectoryForInclude(file_type));
+ return false;
+ }
+
+ if (!XkbParseFile(ctx, file, stmt->file, &rtrn)) {
+ log_err(ctx, "Error interpreting include file \"%s\"\n", stmt->file);
+ fclose(file);
+ return false;
+ }
+ fclose(file);
+
+ mapToUse = rtrn;
+ if (stmt->map != NULL) {
+ while (mapToUse)
+ {
+ next = (XkbFile *) mapToUse->common.next;
+ mapToUse->common.next = NULL;
+ if (streq(mapToUse->name, stmt->map) &&
+ mapToUse->file_type == file_type) {
+ FreeXkbFile(next);
+ break;
+ }
+ else {
+ FreeXkbFile(mapToUse);
+ }
+ mapToUse = next;
+ }
+ if (!mapToUse) {
+ log_err(ctx, "No %s named \"%s\" in the include file \"%s\"\n",
+ FileTypeText(file_type), stmt->map, stmt->file);
+ return false;
+ }
+ }
+ else if (rtrn->common.next) {
+ log_lvl(ctx, 5,
+ "No map in include statement, but \"%s\" contains several; "
+ "Using first defined map, \"%s\"\n",
+ stmt->file, rtrn->name);
+ }
+ if (mapToUse->file_type != file_type) {
+ log_err(ctx,
+ "Include file wrong type (expected %s, got %s); "
+ "Include file \"%s\" ignored\n",
+ FileTypeText(file_type), FileTypeText(mapToUse->file_type),
+ stmt->file);
+ return false;
+ }
+ /* FIXME: we have to check recursive includes here (or somewhere) */
+
+ *file_rtrn = mapToUse;
+ *merge_rtrn = stmt->merge;
+ return true;
+}
--- /dev/null
+/************************************************************
+ * 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.
+ *
+ ********************************************************/
+
+#ifndef XKBCOMP_INCLUDE_H
+#define XKBCOMP_INCLUDE_H
+
+bool
+ParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn,
+ char *nextop_rtrn, char **extra_data);
+
+FILE *
+FindFileInXkbPath(struct xkb_context *ctx, const char *name,
+ enum xkb_file_type type, char **pathRtrn);
+
+bool
+ProcessIncludeFile(struct xkb_context *ctx, IncludeStmt *stmt,
+ enum xkb_file_type file_type, XkbFile **file_rtrn,
+ enum merge_mode *merge_rtrn);
+
+#endif
********************************************************/
#include "xkbcomp-priv.h"
+#include "text.h"
#include "expr.h"
-#include "parseutils.h"
+#include "keycodes.h"
+#include "include.h"
/*
* The xkb_keycodes section
MergeIncludedKeycodes(&included, &next_incl, merge);
ClearKeyNamesInfo(&next_incl);
- FreeXKBFile(rtrn);
+ FreeXkbFile(rtrn);
}
MergeIncludedKeycodes(info, &included, merge);
--- /dev/null
+/************************************************************
+ * 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.
+ *
+ ********************************************************/
+
+#ifndef XKBCOMP_KEYCODES_H
+#define XKBCOMP_KEYCODES_H
+
+static inline unsigned long
+KeyNameToLong(const char name[XkbKeyNameLength])
+{
+ return
+ (((unsigned long)name[0]) << 24) |
+ (((unsigned long)name[1]) << 16) |
+ (((unsigned long)name[2]) << 8) |
+ (((unsigned long)name[3]) << 0);
+}
+
+static inline void
+LongToKeyName(unsigned long val, char name[XkbKeyNameLength])
+{
+ name[0] = ((val >> 24) & 0xff);
+ name[1] = ((val >> 16) & 0xff);
+ name[2] = ((val >> 8) & 0xff);
+ name[3] = ((val >> 0) & 0xff);
+}
+
+static inline const char *
+LongKeyNameText(unsigned long val)
+{
+ char buf[XkbKeyNameLength];
+ LongToKeyName(val, buf);
+ return KeyNameText(buf);
+}
+
+struct xkb_key *
+FindNamedKey(struct xkb_keymap *keymap, unsigned long name,
+ bool use_aliases, xkb_keycode_t start_from);
+
+bool
+FindKeyNameForAlias(struct xkb_keymap *keymap, unsigned long lname,
+ unsigned long *real_name);
+
+#endif
+++ /dev/null
-/************************************************************
- * 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.
- *
- ********************************************************/
-
-#include "xkbcomp-priv.h"
-#include "parseutils.h"
-#include "vmod.h"
-
-/*
- * The xkb_types section
- * =====================
- * This section is the second to be processesed, after xkb_keycodes.
- * However, it is completely independent and could have been the first
- * to be processed (it does not refer to specific keys as specified in
- * the xkb_keycodes section).
- *
- * This section defines key types, which, given a key and a keyboard
- * state (i.e. modifier state and group), determine the shift level to
- * be used in translating the key to keysyms. These types are assigned
- * to each group in each key, in the xkb_symbols section.
- *
- * Key types are called this way because, in a way, they really describe
- * the "type" of the key (or more correctly, a specific group of the
- * key). For example, an ordinary keymap will provide a type called
- * "KEYPAD", which consists of two levels, with the second level being
- * chosen according to the state of the Num Lock (or Shift) modifiers.
- * Another example is a type called "ONE_LEVEL", which is usually
- * assigned to keys such as Escape; these have just one level and are
- * not affected by the modifier state. Yet more common examples are
- * "TWO_LEVEL" (with Shift choosing the second level), "ALPHABETIC"
- * (where Caps Lock may also choose the second level), etc.
- *
- * Type definitions
- * ----------------
- * Statements of the form:
- * type "FOUR_LEVEL" { ... }
- *
- * The above would create a new type named "FOUR_LEVEL".
- * The body of the definition may include statements of the following
- * forms:
- *
- * - level_name statements (mandatory for each level in the type):
- * level_name[Level1] = "Base";
- *
- * Gives each level in this type a descriptive name. It isn't used
- * for any thing.
- * Note: A level may be specified as Level[1-8] or just a number (can
- * be more than 8).
- *
- * - modifiers statement (mandatory, should be specified only once):
- * modifiers = Shift+Lock+LevelThree;
- *
- * A mask of real and virtual modifiers. These are the only modifiers
- * being considered when matching the modifier state against the type.
- * The other modifiers, whether active or not, are masked out in the
- * calculation.
- *
- * - map entry statements (should have at least as many mappings as there
- * are levels in the type):
- * map[Shift+LevelThree] = Level4;
- *
- * If the active modifiers, masked with the type's modifiers (as stated
- * above), match (i.e. equal) the modifiers inside the map[] statement,
- * then the level in the right hand side is chosen. For example, in the
- * above, if in the current keyboard state the Shift and LevelThree
- * modifiers are active, while the Lock modifier is not, then the
- * keysym(s) in the 4th level of the group will be returned to the
- * user.
- *
- * - preserve statements:
- * map[Shift+Lock+LevelThree] = Level5;
- * preserve[Shift+Lock+LevelThree] = Lock;
- *
- * When a map entry matches the active modifiers and the level it
- * specified is chosen, then these modifiers are said to be "consumed";
- * for example, in a simple US keymap where the "g" key is assigned an
- * ordinary ALPHABETIC key type, if the Lock (Caps Lock) modifier is
- * active and the key is pressed, then a "G" keysym is produced (as
- * opposed to lower-case "g"). This is because the type definition has
- * a map entry like the following:
- * map[Lock] = Level2;
- * And as such the Lock modifier is consumed. This information is
- * relevant for applications which further process the modifiers,
- * since by then the consumed modifiers have already "done their part"
- * and should be masked out.
- *
- * However, sometimes even if a modifier is actually used to choose
- * the shift level (as Lock above), it should *not* be reported as
- * consumed, for various reasons. In this case, a preserve[] statement
- * can be used to augment the map entry. The modifiers inside the square
- * brackets should match one of the map[] statements in the type. The
- * right hand side should consists of modifiers from the left hand
- * side; these modifiers are then "preserved" and not reported as
- * consumed.
- *
- * Virtual modifier statements
- * ---------------------------
- * Statements of the form:
- * virtual_modifiers LControl;
- *
- * Can appear in the xkb_types, xkb_compat, xkb_symbols sections.
- * TODO
- */
-
-enum type_field {
- TYPE_FIELD_MASK = (1 << 0),
- TYPE_FIELD_MAP = (1 << 1),
- TYPE_FIELD_PRESERVE = (1 << 2),
- TYPE_FIELD_LEVEL_NAME = (1 << 3),
-};
-
-typedef struct _KeyTypeInfo {
- enum type_field defined;
- unsigned file_id;
- enum merge_mode merge;
- struct list entry;
-
- xkb_atom_t name;
- xkb_mod_mask_t mods;
- xkb_level_index_t num_levels;
- darray(struct xkb_kt_map_entry) entries;
- darray(xkb_atom_t) level_names;
-} KeyTypeInfo;
-
-typedef struct _KeyTypesInfo {
- char *name;
- int errorCount;
- unsigned file_id;
- unsigned num_types;
- struct list types;
- VModInfo vmods;
- struct xkb_keymap *keymap;
-} KeyTypesInfo;
-
-/***====================================================================***/
-
-static inline const char *
-MapEntryTxt(KeyTypesInfo *info, struct xkb_kt_map_entry *entry)
-{
- return VModMaskText(info->keymap, entry->mods.mods);
-}
-
-static inline const char *
-TypeTxt(KeyTypesInfo *info, KeyTypeInfo *type)
-{
- return xkb_atom_text(info->keymap->ctx, type->name);
-}
-
-static inline const char *
-TypeMaskTxt(KeyTypesInfo *info, KeyTypeInfo *type)
-{
- return VModMaskText(info->keymap, type->mods);
-}
-
-static inline bool
-ReportTypeShouldBeArray(KeyTypesInfo *info, KeyTypeInfo *type,
- const char *field)
-{
- return ReportShouldBeArray(info->keymap, "key type", field,
- TypeTxt(info, type));
-}
-
-static inline bool
-ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type,
- const char *field, const char *wanted)
-{
- return ReportBadType(info->keymap->ctx, "key type", field,
- TypeTxt(info, type), wanted);
-}
-
-static inline bool
-ReportTypeBadWidth(KeyTypesInfo *info, const char *type, int has, int needs)
-{
- log_err(info->keymap->ctx,
- "Key type \"%s\" has %d levels, must have %d; "
- "Illegal type definition ignored\n",
- type, has, needs);
- return false;
-}
-
-/***====================================================================***/
-
-static void
-InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_keymap *keymap,
- unsigned file_id)
-{
- info->name = strdup("default");
- info->errorCount = 0;
- info->num_types = 0;
- list_init(&info->types);
- info->file_id = file_id;
- InitVModInfo(&info->vmods, keymap);
- info->keymap = keymap;
-}
-
-static void
-FreeKeyTypeInfo(KeyTypeInfo * type)
-{
- darray_free(type->entries);
- darray_free(type->level_names);
-}
-
-static void
-FreeKeyTypesInfo(KeyTypesInfo * info)
-{
- KeyTypeInfo *type, *next_type;
- free(info->name);
- info->name = NULL;
- list_foreach_safe(type, next_type, &info->types, entry) {
- FreeKeyTypeInfo(type);
- free(type);
- }
-}
-
-static KeyTypeInfo *
-NextKeyType(KeyTypesInfo * info)
-{
- KeyTypeInfo *type;
-
- type = calloc(1, sizeof(*type));
- if (!type)
- return NULL;
-
- type->file_id = info->file_id;
-
- list_append(&type->entry, &info->types);
- info->num_types++;
- return type;
-}
-
-static KeyTypeInfo *
-FindMatchingKeyType(KeyTypesInfo *info, xkb_atom_t name)
-{
- KeyTypeInfo *old;
-
- list_foreach(old, &info->types, entry)
- if (old->name == name)
- return old;
-
- return NULL;
-}
-
-static bool
-AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new)
-{
- KeyTypeInfo *old;
- struct list entry;
- int verbosity = xkb_get_log_verbosity(info->keymap->ctx);
-
- old = FindMatchingKeyType(info, new->name);
- if (old) {
- if (new->merge == MERGE_REPLACE || new->merge == MERGE_OVERRIDE) {
- if ((old->file_id == new->file_id && verbosity > 0) ||
- verbosity > 9) {
- log_warn(info->keymap->ctx,
- "Multiple definitions of the %s key type; "
- "Earlier definition ignored\n",
- xkb_atom_text(info->keymap->ctx, new->name));
- }
-
- entry = old->entry;
- FreeKeyTypeInfo(old);
- *old = *new;
- old->entry = entry;
- darray_init(new->entries);
- darray_init(new->level_names);
- return true;
- }
-
- if (old->file_id == new->file_id)
- log_lvl(info->keymap->ctx, 4,
- "Multiple definitions of the %s key type; "
- "Later definition ignored\n",
- xkb_atom_text(info->keymap->ctx, new->name));
-
- FreeKeyTypeInfo(new);
- return true;
- }
-
- old = NextKeyType(info);
- if (!old)
- return false;
-
- entry = old->entry;
- *old = *new;
- old->entry = entry;
- darray_init(new->entries);
- darray_init(new->level_names);
- return true;
-}
-
-/***====================================================================***/
-
-static void
-MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from,
- enum merge_mode merge)
-{
- KeyTypeInfo *type, *next_type;
-
- if (from->errorCount > 0) {
- into->errorCount += from->errorCount;
- return;
- }
-
- if (into->name == NULL) {
- into->name = from->name;
- from->name = NULL;
- }
-
- list_foreach_safe(type, next_type, &from->types, entry) {
- type->merge = (merge == MERGE_DEFAULT ? type->merge : merge);
- if (!AddKeyType(into, type))
- into->errorCount++;
- }
-}
-
-static void
-HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge);
-
-static bool
-HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *stmt)
-{
- enum merge_mode merge = MERGE_DEFAULT;
- XkbFile *rtrn;
- KeyTypesInfo included, next_incl;
-
- InitKeyTypesInfo(&included, info->keymap, info->file_id);
- if (stmt->stmt) {
- free(included.name);
- included.name = stmt->stmt;
- stmt->stmt = NULL;
- }
-
- for (; stmt; stmt = stmt->next_incl) {
- if (!ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_TYPES,
- &rtrn, &merge)) {
- info->errorCount += 10;
- FreeKeyTypesInfo(&included);
- return false;
- }
-
- InitKeyTypesInfo(&next_incl, info->keymap, rtrn->id);
-
- HandleKeyTypesFile(&next_incl, rtrn, merge);
-
- MergeIncludedKeyTypes(&included, &next_incl, merge);
-
- FreeKeyTypesInfo(&next_incl);
- FreeXKBFile(rtrn);
- }
-
- MergeIncludedKeyTypes(info, &included, merge);
- FreeKeyTypesInfo(&included);
-
- return (info->errorCount == 0);
-}
-
-/***====================================================================***/
-
-static bool
-SetModifiers(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
- ExprDef *value)
-{
- xkb_mod_mask_t mods;
-
- if (arrayNdx)
- log_warn(info->keymap->ctx,
- "The modifiers field of a key type is not an array; "
- "Illegal array subscript ignored\n");
-
- /* get modifier mask for current type */
- if (!ExprResolveVModMask(info->keymap, value, &mods)) {
- log_err(info->keymap->ctx,
- "Key type mask field must be a modifier mask; "
- "Key type definition ignored\n");
- return false;
- }
-
- if (type->defined & TYPE_FIELD_MASK) {
- log_warn(info->keymap->ctx,
- "Multiple modifier mask definitions for key type %s; "
- "Using %s, ignoring %s\n",
- xkb_atom_text(info->keymap->ctx, type->name),
- TypeMaskTxt(info, type),
- VModMaskText(info->keymap, mods));
- return false;
- }
-
- type->mods = mods;
- return true;
-}
-
-/***====================================================================***/
-
-static struct xkb_kt_map_entry *
-FindMatchingMapEntry(KeyTypeInfo *type, xkb_mod_mask_t mods)
-{
- struct xkb_kt_map_entry *entry;
-
- darray_foreach(entry, type->entries)
- if (entry->mods.mods == mods)
- return entry;
-
- return NULL;
-}
-
-/**
- * Add a new KTMapEntry to the given key type. If an entry with the same mods
- * already exists, the level is updated (if clobber is TRUE). Otherwise, a new
- * entry is created.
- *
- * @param clobber Overwrite existing entry.
- * @param report true if a warning is to be printed on.
- */
-static bool
-AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
- struct xkb_kt_map_entry *new, bool clobber, bool report)
-{
- struct xkb_kt_map_entry * old;
-
- old = FindMatchingMapEntry(type, new->mods.mods);
- if (old) {
- if (report && old->level != new->level) {
- log_warn(info->keymap->ctx,
- "Multiple map entries for %s in %s; "
- "Using %d, ignoring %d\n",
- MapEntryTxt(info, new), TypeTxt(info, type),
- (clobber ? new->level : old->level) + 1,
- (clobber ? old->level : new->level) + 1);
- }
- else {
- log_lvl(info->keymap->ctx, 10,
- "Multiple occurences of map[%s]= %d in %s; Ignored\n",
- MapEntryTxt(info, new), new->level + 1,
- TypeTxt(info, type));
- return true;
- }
-
- if (clobber) {
- if (new->level >= type->num_levels)
- type->num_levels = new->level + 1;
- old->level = new->level;
- }
-
- return true;
- }
-
- if (new->level >= type->num_levels)
- type->num_levels = new->level + 1;
-
- darray_append(type->entries, *new);
- return true;
-}
-
-static bool
-SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
- ExprDef *value)
-{
- struct xkb_kt_map_entry entry;
-
- if (arrayNdx == NULL)
- return ReportTypeShouldBeArray(info, type, "map entry");
-
- if (!ExprResolveVModMask(info->keymap, arrayNdx, &entry.mods.mods))
- return ReportTypeBadType(info, type, "map entry", "modifier mask");
-
- if (entry.mods.mods & (~type->mods)) {
- log_lvl(info->keymap->ctx, 1,
- "Map entry for unused modifiers in %s; "
- "Using %s instead of %s\n",
- TypeTxt(info, type),
- VModMaskText(info->keymap, entry.mods.mods & type->mods),
- MapEntryTxt(info, &entry));
- entry.mods.mods &= type->mods;
- }
-
- if (!ExprResolveLevel(info->keymap->ctx, value, &entry.level)) {
- log_err(info->keymap->ctx,
- "Level specifications in a key type must be integer; "
- "Ignoring malformed level specification\n");
- return false;
- }
-
- entry.preserve.mods = 0;
-
- return AddMapEntry(info, type, &entry, true, true);
-}
-
-/***====================================================================***/
-
-static bool
-AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type,
- xkb_mod_mask_t mods, xkb_mod_mask_t preserve_mods)
-{
- struct xkb_kt_map_entry *entry;
- struct xkb_kt_map_entry new;
-
- darray_foreach(entry, type->entries) {
- if (entry->mods.mods != mods)
- continue;
-
- /* Map exists without previous preserve (or "None"); override. */
- if (entry->preserve.mods == 0) {
- entry->preserve.mods = preserve_mods;
- return true;
- }
-
- /* Map exists with same preserve; do nothing. */
- if (entry->preserve.mods == preserve_mods) {
- log_lvl(info->keymap->ctx, 10,
- "Identical definitions for preserve[%s] in %s; "
- "Ignored\n",
- VModMaskText(info->keymap, mods),
- TypeTxt(info, type));
- return true;
- }
-
- /* Map exists with different preserve; latter wins. */
- log_lvl(info->keymap->ctx, 1,
- "Multiple definitions for preserve[%s] in %s; "
- "Using %s, ignoring %s\n",
- VModMaskText(info->keymap, mods),
- TypeTxt(info, type),
- VModMaskText(info->keymap, preserve_mods),
- VModMaskText(info->keymap, entry->preserve.mods));
-
- entry->preserve.mods = preserve_mods;
- return true;
- }
-
- /*
- * Map does not exist, i.e. preserve[] came before map[].
- * Create a map with the specified mask mapping to Level1. The level
- * may be overriden later with an explicit map[] statement.
- */
- new.level = 0;
- new.mods.mods = mods;
- new.preserve.mods = preserve_mods;
- darray_append(type->entries, new);
- return true;
-}
-
-static bool
-SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
- ExprDef *value)
-{
- xkb_mod_mask_t mods, preserve_mods;
-
- if (arrayNdx == NULL)
- return ReportTypeShouldBeArray(info, type, "preserve entry");
-
- if (!ExprResolveVModMask(info->keymap, arrayNdx, &mods))
- return ReportTypeBadType(info, type, "preserve entry",
- "modifier mask");
-
- if (mods & ~type->mods) {
- const char *before, *after;
-
- before = VModMaskText(info->keymap, mods);
- mods &= type->mods;
- after = VModMaskText(info->keymap, mods);
-
- log_lvl(info->keymap->ctx, 1,
- "Preserve for modifiers not used by the %s type; "
- "Index %s converted to %s\n",
- TypeTxt(info, type), before, after);
- }
-
- if (!ExprResolveVModMask(info->keymap, value, &preserve_mods)) {
- log_err(info->keymap->ctx,
- "Preserve value in a key type is not a modifier mask; "
- "Ignoring preserve[%s] in type %s\n",
- VModMaskText(info->keymap, mods),
- TypeTxt(info, type));
- return false;
- }
-
- if (preserve_mods & ~mods) {
- const char *before, *after;
-
- before = VModMaskText(info->keymap, preserve_mods);
- preserve_mods &= mods;
- after = VModMaskText(info->keymap, preserve_mods);
-
- log_lvl(info->keymap->ctx, 1,
- "Illegal value for preserve[%s] in type %s; "
- "Converted %s to %s\n",
- VModMaskText(info->keymap, mods),
- TypeTxt(info, type), before, after);
- }
-
- return AddPreserve(info, type, mods, preserve_mods);
-}
-
-/***====================================================================***/
-
-static bool
-AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type,
- xkb_level_index_t level, xkb_atom_t name, bool clobber)
-{
- /* New name. */
- if (level >= darray_size(type->level_names)) {
- darray_resize0(type->level_names, level + 1);
- goto finish;
- }
-
- /* Same level, same name. */
- if (darray_item(type->level_names, level) == name) {
- log_lvl(info->keymap->ctx, 10,
- "Duplicate names for level %d of key type %s; Ignored\n",
- level + 1, TypeTxt(info, type));
- return true;
- }
-
- /* Same level, different name. */
- if (darray_item(type->level_names, level) != XKB_ATOM_NONE) {
- const char *old, *new;
- old = xkb_atom_text(info->keymap->ctx,
- darray_item(type->level_names, level));
- new = xkb_atom_text(info->keymap->ctx, name);
- log_lvl(info->keymap->ctx, 1,
- "Multiple names for level %d of key type %s; "
- "Using %s, ignoring %s\n",
- level + 1, TypeTxt(info, type),
- (clobber ? new : old), (clobber ? old : new));
-
- if (!clobber)
- return true;
- }
-
- /* XXX: What about different level, same name? */
-
-finish:
- darray_item(type->level_names, level) = name;
- return true;
-}
-
-static bool
-SetLevelName(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
- ExprDef *value)
-{
- xkb_level_index_t level;
- xkb_atom_t level_name;
- struct xkb_context *ctx = info->keymap->ctx;
- const char *str;
-
- if (arrayNdx == NULL)
- return ReportTypeShouldBeArray(info, type, "level name");
-
- if (!ExprResolveLevel(ctx, arrayNdx, &level))
- return ReportTypeBadType(info, type, "level name", "integer");
-
- if (!ExprResolveString(ctx, value, &str)) {
- log_err(info->keymap->ctx,
- "Non-string name for level %d in key type %s; "
- "Ignoring illegal level name definition\n",
- level + 1, xkb_atom_text(ctx, type->name));
- return false;
- }
-
- level_name = xkb_atom_intern(ctx, str);
-
- return AddLevelName(info, type, level, level_name, true);
-}
-
-/***====================================================================***/
-
-/**
- * Parses the fields in a type "..." { } description.
- *
- * @param field The field to parse (e.g. modifiers, map, level_name)
- */
-static bool
-SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type,
- const char *field, ExprDef *arrayNdx, ExprDef *value)
-{
- bool ok = false;
- enum type_field type_field = 0;
-
- if (istreq(field, "modifiers")) {
- type_field = TYPE_FIELD_MASK;
- ok = SetModifiers(info, type, arrayNdx, value);
- }
- else if (istreq(field, "map")) {
- type_field = TYPE_FIELD_MAP;
- ok = SetMapEntry(info, type, arrayNdx, value);
- }
- else if (istreq(field, "preserve")) {
- type_field = TYPE_FIELD_PRESERVE;
- ok = SetPreserve(info, type, arrayNdx, value);
- }
- else if (istreq(field, "levelname") || istreq(field, "level_name")) {
- type_field = TYPE_FIELD_LEVEL_NAME;
- ok = SetLevelName(info, type, arrayNdx, value);
- } else {
- log_err(info->keymap->ctx,
- "Unknown field %s in key type %s; Definition ignored\n",
- field, TypeTxt(info, type));
- }
-
- type->defined |= type_field;
- return ok;
-}
-
-static bool
-HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type)
-{
- bool ok = true;
- const char *elem, *field;
- ExprDef *arrayNdx;
-
- for (; def; def = (VarDef *) def->common.next) {
- ok = ExprResolveLhs(info->keymap->ctx, def->name, &elem, &field,
- &arrayNdx);
- if (!ok)
- continue;
-
- if (elem && istreq(elem, "type")) {
- log_err(info->keymap->ctx,
- "Support for changing the default type has been removed; "
- "Statement ignored\n");
- continue;
- }
-
- ok = SetKeyTypeField(info, type, field, arrayNdx, def->value);
- }
-
- return ok;
-}
-
-/**
- * Process a type "XYZ" { } specification in the xkb_types section.
- *
- */
-static bool
-HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge)
-{
- KeyTypeInfo type = {
- .defined = 0,
- .file_id = info->file_id,
- .merge = (def->merge == MERGE_DEFAULT ? merge : def->merge),
- .name = def->name,
- .mods = 0,
- .num_levels = 1,
- .entries = darray_new(),
- .level_names = darray_new(),
- };
-
- /* Parse the actual content. */
- if (!HandleKeyTypeBody(info, def->body, &type)) {
- info->errorCount++;
- return false;
- }
-
- /* Now add the new keytype to the info struct */
- if (!AddKeyType(info, &type)) {
- info->errorCount++;
- return false;
- }
-
- return true;
-}
-
-/**
- * Process an xkb_types section.
- *
- * @param file The parsed xkb_types section.
- * @param merge Merge Strategy (e.g. MERGE_OVERRIDE)
- * @param info Pointer to memory where the outcome will be stored.
- */
-static void
-HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
-{
- bool ok;
- ParseCommon *stmt;
-
- free(info->name);
- info->name = strdup_safe(file->name);
-
- for (stmt = file->defs; stmt; stmt = stmt->next) {
- switch (stmt->type) {
- case STMT_INCLUDE:
- ok = HandleIncludeKeyTypes(info, (IncludeStmt *) stmt);
- break;
- case STMT_TYPE: /* e.g. type "ONE_LEVEL" */
- ok = HandleKeyTypeDef(info, (KeyTypeDef *) stmt, merge);
- break;
- case STMT_VAR:
- log_err(info->keymap->ctx,
- "Support for changing the default type has been removed; "
- "Statement ignored\n");
- ok = true;
- break;
- case STMT_VMOD: /* virtual_modifiers NumLock, ... */
- ok = HandleVModDef((VModDef *) stmt, info->keymap, merge,
- &info->vmods);
- break;
- default:
- log_err(info->keymap->ctx,
- "Key type files may not include other declarations; "
- "Ignoring %s\n", StmtTypeToString(stmt->type));
- ok = false;
- break;
- }
-
- if (!ok)
- info->errorCount++;
-
- if (info->errorCount > 10) {
- log_err(info->keymap->ctx,
- "Abandoning keytypes file \"%s\"\n", file->topName);
- break;
- }
- }
-}
-
-static bool
-CopyDefToKeyType(KeyTypesInfo *info, KeyTypeInfo *def,
- struct xkb_key_type *type)
-{
- type->mods.mods = def->mods;
- type->num_levels = def->num_levels;
- type->map = darray_mem(def->entries, 0);
- type->num_entries = darray_size(def->entries);
- darray_init(def->entries);
- type->name = def->name;
- type->level_names = darray_mem(def->level_names, 0);
- darray_init(def->level_names);
-
- return true;
-}
-
-bool
-CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
- enum merge_mode merge)
-{
- unsigned int i;
- unsigned int num_types;
- KeyTypesInfo info;
- KeyTypeInfo *def;
-
- InitKeyTypesInfo(&info, keymap, file->id);
-
- HandleKeyTypesFile(&info, file, merge);
-
- if (info.errorCount != 0)
- goto err_info;
-
- if (info.name)
- keymap->types_section_name = strdup(info.name);
-
- num_types = info.num_types ? info.num_types : 1;
- keymap->types = calloc(num_types, sizeof(*keymap->types));
- if (!keymap->types)
- goto err_info;
- keymap->num_types = num_types;
-
- /*
- * If no types were specified, a default unnamed one-level type is
- * used for all keys.
- */
- if (info.num_types == 0) {
- KeyTypeInfo dflt = {
- .name = xkb_atom_intern(keymap->ctx, "default"),
- .mods = 0,
- .num_levels = 1,
- .entries = darray_new(),
- .level_names = darray_new(),
- };
-
- if (!CopyDefToKeyType(&info, &dflt, &keymap->types[0]))
- goto err_info;
- } else {
- i = 0;
- list_foreach(def, &info.types, entry)
- if (!CopyDefToKeyType(&info, def, &keymap->types[i++]))
- goto err_info;
- }
-
- FreeKeyTypesInfo(&info);
- return true;
-
-err_info:
- FreeKeyTypesInfo(&info);
- return false;
-}
--- /dev/null
+/************************************************************
+ * 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.
+ *
+ ********************************************************/
+
+#ifndef XKBCOMP_PARSER_PRIV_H
+#define XKBCOMP_PARSER_PRIV_H
+
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+
+struct scanner_extra;
+
+struct parser_param {
+ struct xkb_context *ctx;
+ void *scanner;
+ XkbFile *rtrn;
+};
+
+#include "parser.h"
+
+void
+scanner_error(YYLTYPE *loc, void *scanner, const char *msg);
+
+int
+yylex(YYSTYPE *val, YYLTYPE *loc, void *scanner);
+
+#endif
%{
#include "xkbcomp-priv.h"
-#include "parseutils.h"
-
-#pragma GCC diagnostic ignored "-Wredundant-decls"
-
-extern int yylex(union YYSTYPE *val, struct YYLTYPE *loc, void *scanner);
+#include "ast-build.h"
+#include "parser-priv.h"
static void
yyerror(struct YYLTYPE *loc, struct parser_param *param, const char *msg)
XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE
XkbMapConfigList
CBRACE SEMI
- { $$ = CreateXKBFile(param->ctx, $2, $3, &$5->common, $1); }
+ { $$ = XkbFileCreate(param->ctx, $2, $3, &$5->common, $1); }
;
XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; }
$$ = NULL;
}
else {
- $$ = CreateXKBFile(param->ctx, $2, $3, $5, $1);
+ $$ = XkbFileCreate(param->ctx, $2, $3, $5, $1);
}
}
;
$$ = NULL;
}
else {
- $$ = CreateXKBFile(param->ctx, $2, $3, $4, $1);
+ $$ = XkbFileCreate(param->ctx, $2, $3, $4, $1);
}
}
;
+++ /dev/null
-/************************************************************
- * 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.
- *
- ********************************************************/
-
-#include "parseutils.h"
-#include "path.h"
-
-ATTR_MALLOC static void *
-malloc_or_die(size_t size)
-{
- void *p = malloc(size);
- if (!p) {
- fprintf(stderr, "Out of memory\n");
- exit(1);
- }
- return p;
-}
-
-ParseCommon *
-AppendStmt(ParseCommon * to, ParseCommon * append)
-{
- ParseCommon *start = to;
-
- if (append == NULL)
- return to;
- while ((to != NULL) && (to->next != NULL))
- {
- to = to->next;
- }
- if (to) {
- to->next = append;
- return start;
- }
- return append;
-}
-
-ExprDef *
-ExprCreate(enum expr_op_type op, enum expr_value_type type)
-{
- ExprDef *expr;
-
- expr = malloc_or_die(sizeof(*expr));
-
- expr->common.type = STMT_EXPR;
- expr->common.next = NULL;
- expr->op = op;
- expr->value_type = type;
- return expr;
-}
-
-ExprDef *
-ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
- ExprDef *child)
-{
- ExprDef *expr;
- expr = malloc_or_die(sizeof(*expr));
-
- expr->common.type = STMT_EXPR;
- expr->common.next = NULL;
- expr->op = op;
- expr->value_type = type;
- expr->value.child = child;
- return expr;
-}
-
-ExprDef *
-ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right)
-{
- ExprDef *expr;
-
- expr = malloc_or_die(sizeof(*expr));
-
- expr->common.type = STMT_EXPR;
- expr->common.next = NULL;
- expr->op = op;
- if (op == EXPR_ASSIGN || left->value_type == EXPR_TYPE_UNKNOWN)
- expr->value_type = right->value_type;
- else if (left->value_type == right->value_type ||
- right->value_type == EXPR_TYPE_UNKNOWN)
- expr->value_type = left->value_type;
- else
- expr->value_type = EXPR_TYPE_UNKNOWN;
- expr->value.binary.left = left;
- expr->value.binary.right = right;
- return expr;
-}
-
-KeycodeDef *
-KeycodeCreate(char keyName[XkbKeyNameLength], unsigned long value)
-{
- KeycodeDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_KEYCODE;
- def->common.next = NULL;
- strncpy(def->name, keyName, XkbKeyNameLength);
- def->value = value;
- return def;
-}
-
-KeyAliasDef *
-KeyAliasCreate(char alias[XkbKeyNameLength], char real[XkbKeyNameLength])
-{
- KeyAliasDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_ALIAS;
- def->common.next = NULL;
- strncpy(def->alias, alias, XkbKeyNameLength);
- strncpy(def->real, real, XkbKeyNameLength);
- return def;
-}
-
-VModDef *
-VModCreate(xkb_atom_t name, ExprDef * value)
-{
- VModDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- 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;
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_VAR;
- def->common.next = NULL;
- def->name = name;
- def->value = value;
- return def;
-}
-
-VarDef *
-BoolVarCreate(xkb_atom_t nameToken, unsigned set)
-{
- ExprDef *name, *value;
-
- name = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN);
- name->value.str = nameToken;
- value = ExprCreate(EXPR_VALUE, EXPR_TYPE_BOOLEAN);
- value->value.uval = set;
- return VarCreate(name, value);
-}
-
-InterpDef *
-InterpCreate(char *sym, ExprDef * match)
-{
- InterpDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_INTERP;
- def->common.next = NULL;
- def->sym = sym;
- def->match = match;
- return def;
-}
-
-KeyTypeDef *
-KeyTypeCreate(xkb_atom_t name, VarDef * body)
-{
- KeyTypeDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_TYPE;
- def->common.next = NULL;
- def->merge = MERGE_DEFAULT;
- def->name = name;
- def->body = body;
- return def;
-}
-
-SymbolsDef *
-SymbolsCreate(char keyName[XkbKeyNameLength], ExprDef *symbols)
-{
- SymbolsDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_SYMBOLS;
- def->common.next = NULL;
- def->merge = MERGE_DEFAULT;
- strncpy(def->keyName, keyName, XkbKeyNameLength);
- def->symbols = symbols;
- return def;
-}
-
-GroupCompatDef *
-GroupCompatCreate(int group, ExprDef * val)
-{
- GroupCompatDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_GROUP_COMPAT;
- def->common.next = NULL;
- def->merge = MERGE_DEFAULT;
- def->group = group;
- def->def = val;
- return def;
-}
-
-ModMapDef *
-ModMapCreate(uint32_t modifier, ExprDef * keys)
-{
- ModMapDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_MODMAP;
- def->common.next = NULL;
- def->merge = MERGE_DEFAULT;
- def->modifier = modifier;
- def->keys = keys;
- return def;
-}
-
-IndicatorMapDef *
-IndicatorMapCreate(xkb_atom_t name, VarDef * body)
-{
- IndicatorMapDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_INDICATOR_MAP;
- def->common.next = NULL;
- def->merge = MERGE_DEFAULT;
- def->name = name;
- def->body = body;
- return def;
-}
-
-IndicatorNameDef *
-IndicatorNameCreate(int ndx, ExprDef * name, bool virtual)
-{
- IndicatorNameDef *def;
-
- def = malloc_or_die(sizeof(*def));
-
- def->common.type = STMT_INDICATOR_NAME;
- def->common.next = NULL;
- def->merge = MERGE_DEFAULT;
- def->ndx = ndx;
- def->name = name;
- def->virtual = virtual;
- return def;
-}
-
-ExprDef *
-ActionCreate(xkb_atom_t name, ExprDef * args)
-{
- ExprDef *act;
-
- act = malloc_or_die(sizeof(*act));
-
- act->common.type = STMT_EXPR;
- act->common.next = NULL;
- act->op = EXPR_ACTION_DECL;
- act->value.action.name = name;
- act->value.action.args = args;
- return act;
-}
-
-ExprDef *
-CreateKeysymList(char *sym)
-{
- ExprDef *def;
-
- def = ExprCreate(EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS);
-
- darray_init(def->value.list.syms);
- darray_init(def->value.list.symsMapIndex);
- darray_init(def->value.list.symsNumEntries);
-
- darray_append(def->value.list.syms, sym);
- darray_append(def->value.list.symsMapIndex, 0);
- darray_append(def->value.list.symsNumEntries, 1);
-
- return def;
-}
-
-ExprDef *
-CreateMultiKeysymList(ExprDef *list)
-{
- size_t nLevels = darray_size(list->value.list.symsMapIndex);
-
- darray_resize(list->value.list.symsMapIndex, 1);
- darray_resize(list->value.list.symsNumEntries, 1);
- darray_item(list->value.list.symsMapIndex, 0) = 0;
- darray_item(list->value.list.symsNumEntries, 0) = nLevels;
-
- return list;
-}
-
-ExprDef *
-AppendKeysymList(ExprDef * list, char *sym)
-{
- size_t nSyms = darray_size(list->value.list.syms);
-
- darray_append(list->value.list.symsMapIndex, nSyms);
- darray_append(list->value.list.symsNumEntries, 1);
- darray_append(list->value.list.syms, sym);
-
- return list;
-}
-
-ExprDef *
-AppendMultiKeysymList(ExprDef * list, ExprDef * append)
-{
- size_t nSyms = darray_size(list->value.list.syms);
- size_t numEntries = darray_size(append->value.list.syms);
-
- darray_append(list->value.list.symsMapIndex, nSyms);
- darray_append(list->value.list.symsNumEntries, numEntries);
- darray_append_items(list->value.list.syms,
- darray_mem(append->value.list.syms, 0),
- numEntries);
-
- darray_resize(append->value.list.syms, 0);
- FreeStmt(&append->common);
-
- return list;
-}
-
-bool
-LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn)
-{
- xkb_keysym_t sym;
-
- if (!str || istreq(str, "any") || istreq(str, "nosymbol")) {
- *sym_rtrn = XKB_KEY_NoSymbol;
- return 1;
- }
-
- if (istreq(str, "none") || istreq(str, "voidsymbol")) {
- *sym_rtrn = XKB_KEY_VoidSymbol;
- return 1;
- }
-
- sym = xkb_keysym_from_name(str);
- if (sym != XKB_KEY_NoSymbol) {
- *sym_rtrn = sym;
- return 1;
- }
-
- return 0;
-}
-
-static void
-FreeInclude(IncludeStmt *incl);
-
-IncludeStmt *
-IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge)
-{
- IncludeStmt *incl, *first;
- char *file, *map, *stmt, *tmp, *extra_data;
- char nextop;
-
- incl = first = NULL;
- file = map = NULL;
- tmp = str;
- stmt = strdup_safe(str);
- while (tmp && *tmp)
- {
- if (!XkbParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data))
- goto err;
-
- if (first == NULL) {
- first = incl = malloc(sizeof(*first));
- } else {
- incl->next_incl = malloc(sizeof(*first));
- incl = incl->next_incl;
- }
-
- if (!incl) {
- log_wsgo(ctx,
- "Allocation failure in IncludeCreate; "
- "Using only part of the include\n");
- 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;
-}
-
-void
-CheckDefaultMap(struct xkb_context *ctx, XkbFile *maps, const char *fileName)
-{
- XkbFile *dflt = NULL, *tmp;
-
- for (tmp = maps; tmp; tmp = (XkbFile *) tmp->common.next) {
- if (!(tmp->flags & XkbLC_Default))
- continue;
- if (!dflt) {
- dflt = tmp;
- continue;
- }
-
- log_lvl(ctx, 3,
- "Multiple default components in %s; "
- "Using %s, ignoring %s\n",
- (fileName ? fileName : "(unknown)"),
- (dflt->name ? dflt->name : "(first)"),
- (tmp->name ? tmp->name : "(subsequent)"));
-
- tmp->flags &= (~XkbLC_Default);
- }
-}
-
-/*
- * All latin-1 alphanumerics, plus parens, slash, minus, underscore and
- * wildcards.
- */
-static const unsigned char componentSpecLegal[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83,
- 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
-};
-
-static void
-EnsureSafeMapName(char *name)
-{
- if (!name)
- return;
-
- while (*name != '\0') {
- if ((componentSpecLegal[(*name) / 8] & (1 << ((*name) % 8))) == 0)
- *name = '_';
- name++;
- }
-}
-
-XkbFile *
-CreateXKBFile(struct xkb_context *ctx, enum xkb_file_type type, char *name,
- ParseCommon *defs, unsigned flags)
-{
- XkbFile *file;
-
- file = calloc(1, sizeof(*file));
- if (!file)
- return NULL;
-
- EnsureSafeMapName(name);
- file->file_type = type;
- file->topName = strdup_safe(name);
- file->name = name;
- file->defs = defs;
- file->id = xkb_context_take_file_id(ctx);
- file->flags = flags;
- return file;
-}
-
-static void
-FreeExpr(ExprDef *expr)
-{
- char **sym;
-
- if (!expr)
- return;
-
- switch (expr->op) {
- case EXPR_ACTION_LIST:
- case EXPR_NEGATE:
- case EXPR_UNARY_PLUS:
- case EXPR_NOT:
- case EXPR_INVERT:
- FreeStmt(&expr->value.child->common);
- break;
-
- case EXPR_DIVIDE:
- case EXPR_ADD:
- case EXPR_SUBTRACT:
- case EXPR_MULTIPLY:
- case EXPR_ASSIGN:
- FreeStmt(&expr->value.binary.left->common);
- FreeStmt(&expr->value.binary.right->common);
- break;
-
- case EXPR_ACTION_DECL:
- FreeStmt(&expr->value.action.args->common);
- break;
-
- case EXPR_ARRAY_REF:
- FreeStmt(&expr->value.array.entry->common);
- break;
-
- case EXPR_KEYSYM_LIST:
- darray_foreach(sym, expr->value.list.syms)
- free(*sym);
- darray_free(expr->value.list.syms);
- darray_free(expr->value.list.symsMapIndex);
- darray_free(expr->value.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;
- YYSTYPE u;
-
- while (stmt)
- {
- next = stmt->next;
- u.any = stmt;
-
- switch (stmt->type) {
- case STMT_INCLUDE:
- FreeInclude((IncludeStmt *) stmt);
- /* stmt is already free'd here. */
- stmt = NULL;
- break;
- case STMT_EXPR:
- FreeExpr(u.expr);
- break;
- case STMT_VAR:
- FreeStmt(&u.var->name->common);
- FreeStmt(&u.var->value->common);
- break;
- case STMT_TYPE:
- FreeStmt(&u.keyType->body->common);
- break;
- case STMT_INTERP:
- free(u.interp->sym);
- FreeStmt(&u.interp->match->common);
- FreeStmt(&u.interp->def->common);
- break;
- case STMT_VMOD:
- FreeStmt(&u.vmod->value->common);
- break;
- case STMT_SYMBOLS:
- FreeStmt(&u.syms->symbols->common);
- break;
- case STMT_MODMAP:
- FreeStmt(&u.modMask->keys->common);
- break;
- case STMT_GROUP_COMPAT:
- FreeStmt(&u.groupCompat->def->common);
- break;
- case STMT_INDICATOR_MAP:
- FreeStmt(&u.ledMap->body->common);
- break;
- case STMT_INDICATOR_NAME:
- FreeStmt(&u.ledName->name->common);
- 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->topName);
- free(file);
- file = next;
- }
-}
-
-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_INDICATOR_MAP] = "indicator map declaration",
- [STMT_INDICATOR_NAME] = "indicator name declaration",
-};
-
-const char *
-StmtTypeToString(enum stmt_type type)
-{
- if (type >= _STMT_NUM_VALUES)
- type = STMT_UNKNOWN;
- return stmt_type_strings[type];
-}
+++ /dev/null
-/************************************************************
- * 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.
- *
- ********************************************************/
-
-#ifndef PARSEUTILS_H
-#define PARSEUTILS_H
-
-#include <stdio.h>
-
-#include "xkbcomp-priv.h"
-
-struct parser_param {
- struct xkb_context *ctx;
- void *scanner;
- XkbFile *rtrn;
-};
-
-#include "parser.h"
-
-struct scanner_extra {
- struct xkb_context *ctx;
- char *scanFile;
- char scanBuf[1024];
- char *s;
-};
-
-extern ParseCommon *
-AppendStmt(ParseCommon *to, ParseCommon *append);
-
-extern ExprDef *
-ExprCreate(enum expr_op_type op, enum expr_value_type type);
-
-extern ExprDef *
-ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
- ExprDef *child);
-
-extern ExprDef *
-ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right);
-
-KeycodeDef *
-KeycodeCreate(char keyName[XkbKeyNameLength], unsigned long value);
-
-extern KeyAliasDef *
-KeyAliasCreate(char keyName[XkbKeyNameLength], char real[XkbKeyNameLength]);
-
-extern VModDef *
-VModCreate(xkb_atom_t name, ExprDef *value);
-
-extern VarDef *
-VarCreate(ExprDef *name, ExprDef *value);
-
-extern VarDef *
-BoolVarCreate(xkb_atom_t nameToken, unsigned set);
-
-extern InterpDef *
-InterpCreate(char *sym, ExprDef *match);
-
-extern KeyTypeDef *
-KeyTypeCreate(xkb_atom_t name, VarDef *body);
-
-extern SymbolsDef *
-SymbolsCreate(char keyName[XkbKeyNameLength], ExprDef *symbols);
-
-extern GroupCompatDef *
-GroupCompatCreate(int group, ExprDef *def);
-
-extern ModMapDef *
-ModMapCreate(uint32_t modifier, ExprDef *keys);
-
-extern IndicatorMapDef *
-IndicatorMapCreate(xkb_atom_t name, VarDef *body);
-
-extern IndicatorNameDef *
-IndicatorNameCreate(int ndx, ExprDef *name, bool virtual);
-
-extern ExprDef *
-ActionCreate(xkb_atom_t name, ExprDef *args);
-
-extern ExprDef *
-CreateMultiKeysymList(ExprDef *list);
-
-extern ExprDef *
-CreateKeysymList(char *sym);
-
-extern ExprDef *
-AppendMultiKeysymList(ExprDef *list, ExprDef *append);
-
-extern ExprDef *
-AppendKeysymList(ExprDef *list, char *sym);
-
-bool
-LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn);
-
-extern IncludeStmt *
-IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge);
-
-extern void
-CheckDefaultMap(struct xkb_context *ctx, XkbFile *maps, const char *fileName);
-
-extern XkbFile *
-CreateXKBFile(struct xkb_context *ctx, enum xkb_file_type type, char *name,
- ParseCommon *defs,
- unsigned flags);
-
-extern bool
-XKBParseFile(struct xkb_context *ctx, FILE *file, const char *file_name,
- XkbFile **out);
-
-extern bool
-XKBParseString(struct xkb_context *context, const char *string,
- const char *file_name,
- XkbFile **out);
-
-extern void
-FreeXKBFile(XkbFile *file);
-
-extern void
-FreeStmt(ParseCommon *stmt);
-
-void
-scanner_error(struct YYLTYPE *loc, void *scanner, const char *msg);
-
-#endif /* PARSEUTILS_H */
+++ /dev/null
-/************************************************************
- * 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.
- *
- ********************************************************/
-
-#include <errno.h>
-#include <limits.h>
-
-#include "path.h"
-#include "parseutils.h"
-
-/**
- * Extract the first token from an include statement.
- * @param str_inout Input statement, modified in-place. Can be passed in
- * repeatedly. If str_inout is NULL, the parsing has completed.
- * @param file_rtrn Set to the include file to be used.
- * @param map_rtrn Set to whatever comes after ), if any.
- * @param nextop_rtrn Set to the next operation in the complete statement.
- * @param extra_data Set to the string between ( and ), if any.
- *
- * @return true if parsing was succcessful, false for an illegal string.
- *
- * Example: "evdev+aliases(qwerty)"
- * str_inout = aliases(qwerty)
- * nextop_retrn = +
- * extra_data = NULL
- * file_rtrn = evdev
- * map_rtrn = NULL
- *
- * 2nd run with "aliases(qwerty)"
- * str_inout = NULL
- * file_rtrn = aliases
- * map_rtrn = qwerty
- * extra_data = NULL
- * nextop_retrn = ""
- *
- */
-bool
-XkbParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn,
- char *nextop_rtrn, char **extra_data)
-{
- char *tmp, *str, *next;
-
- str = *str_inout;
-
- /* search for tokens inside the string */
- next = strpbrk(str, "|+");
- if (next) {
- /* set nextop_rtrn to \0, next to next character */
- *nextop_rtrn = *next;
- *next++ = '\0';
- }
- else {
- *nextop_rtrn = '\0';
- next = NULL;
- }
-
- /* search for :, store result in extra_data */
- tmp = strchr(str, ':');
- if (tmp != NULL) {
- *tmp++ = '\0';
- *extra_data = strdup(tmp);
- }
- else {
- *extra_data = NULL;
- }
-
- tmp = strchr(str, '(');
- if (tmp == NULL) {
- *file_rtrn = strdup(str);
- *map_rtrn = NULL;
- }
- else if (str[0] == '(') {
- free(*extra_data);
- return false;
- }
- else {
- *tmp++ = '\0';
- *file_rtrn = strdup(str);
- str = tmp;
- tmp = strchr(str, ')');
- if ((tmp == NULL) || (tmp[1] != '\0')) {
- free(*file_rtrn);
- free(*extra_data);
- return false;
- }
- *tmp++ = '\0';
- *map_rtrn = strdup(str);
- }
-
- if (*nextop_rtrn == '\0')
- *str_inout = NULL;
- else if ((*nextop_rtrn == '|') || (*nextop_rtrn == '+'))
- *str_inout = next;
- else
- return false;
-
- return true;
-}
-
-/***====================================================================***/
-
-/**
- * Return the xkb directory based on the type.
- */
-const char *
-XkbDirectoryForInclude(enum xkb_file_type type)
-{
- switch (type) {
- case FILE_TYPE_KEYMAP:
- return "keymap";
-
- case FILE_TYPE_KEYCODES:
- return "keycodes";
-
- case FILE_TYPE_TYPES:
- return "types";
-
- case FILE_TYPE_SYMBOLS:
- return "symbols";
-
- case FILE_TYPE_COMPAT:
- return "compat";
-
- case FILE_TYPE_GEOMETRY:
- return "geometry";
-
- case FILE_TYPE_RULES:
- return "rules";
-
- default:
- return "";
- }
-}
-
-/***====================================================================***/
-
-/**
- * Search for the given file name in the include directories.
- *
- * @param ctx the XKB ctx containing the include paths
- * @param type one of FILE_TYPE_TYPES, FILE_TYPE_COMPAT, ..., or
- * FILE_TYPE_KEYMAP or FILE_TYPE_RULES
- * @param pathRtrn is set to the full path of the file if found.
- *
- * @return an FD to the file or NULL. If NULL is returned, the value of
- * pathRtrn is undefined.
- */
-FILE *
-XkbFindFileInPath(struct xkb_context *ctx, const char *name,
- enum xkb_file_type type, char **pathRtrn)
-{
- size_t i;
- int ret;
- FILE *file = NULL;
- char buf[PATH_MAX];
- const char *typeDir;
-
- typeDir = XkbDirectoryForInclude(type);
- for (i = 0; i < xkb_context_num_include_paths(ctx); i++) {
- ret = snprintf(buf, sizeof(buf), "%s/%s/%s",
- xkb_context_include_path_get(ctx, i), typeDir, name);
- if (ret >= (ssize_t) sizeof(buf)) {
- log_err(ctx, "File name (%s/%s/%s) too long\n",
- xkb_context_include_path_get(ctx, i), typeDir, name);
- continue;
- }
- file = fopen(buf, "r");
- if (file == NULL) {
- log_err(ctx, "Couldn't open file (%s/%s/%s): %s\n",
- xkb_context_include_path_get(ctx, i), typeDir, name,
- strerror(errno));
- continue;
- }
- break;
- }
-
- if ((file != NULL) && (pathRtrn != NULL))
- *pathRtrn = strdup(buf);
- return file;
-}
-
-/**
- * Open the file given in the include statement and parse it's content.
- * If the statement defines a specific map to use, this map is returned in
- * file_rtrn. Otherwise, the default map is returned.
- *
- * @param ctx The ctx containing include paths
- * @param stmt The include statement, specifying the file name to look for.
- * @param file_type Type of file (FILE_TYPE_KEYCODES, etc.)
- * @param file_rtrn Returns the key map to be used.
- * @param merge_rtrn Always returns stmt->merge.
- *
- * @return true on success or false otherwise.
- */
-bool
-ProcessIncludeFile(struct xkb_context *ctx,
- IncludeStmt * stmt,
- enum xkb_file_type file_type,
- XkbFile ** file_rtrn, enum merge_mode *merge_rtrn)
-{
- FILE *file;
- XkbFile *rtrn, *mapToUse, *next;
-
- file = XkbFindFileInPath(ctx, stmt->file, file_type, NULL);
- if (file == NULL) {
- log_err(ctx, "Can't find file \"%s\" for %s include\n", stmt->file,
- XkbDirectoryForInclude(file_type));
- return false;
- }
-
- if (!XKBParseFile(ctx, file, stmt->file, &rtrn)) {
- log_err(ctx, "Error interpreting include file \"%s\"\n", stmt->file);
- fclose(file);
- return false;
- }
- fclose(file);
-
- mapToUse = rtrn;
- if (stmt->map != NULL) {
- while (mapToUse)
- {
- next = (XkbFile *) mapToUse->common.next;
- mapToUse->common.next = NULL;
- if (streq(mapToUse->name, stmt->map) &&
- mapToUse->file_type == file_type) {
- FreeXKBFile(next);
- break;
- }
- else {
- FreeXKBFile(mapToUse);
- }
- mapToUse = next;
- }
- if (!mapToUse) {
- log_err(ctx, "No %s named \"%s\" in the include file \"%s\"\n",
- FileTypeText(file_type), stmt->map, stmt->file);
- return false;
- }
- }
- else if (rtrn->common.next) {
- log_lvl(ctx, 5,
- "No map in include statement, but \"%s\" contains several; "
- "Using first defined map, \"%s\"\n",
- stmt->file, rtrn->name);
- }
- if (mapToUse->file_type != file_type) {
- log_err(ctx,
- "Include file wrong type (expected %s, got %s); "
- "Include file \"%s\" ignored\n",
- FileTypeText(file_type), FileTypeText(mapToUse->file_type),
- stmt->file);
- return false;
- }
- /* FIXME: we have to check recursive includes here (or somewhere) */
-
- *file_rtrn = mapToUse;
- *merge_rtrn = stmt->merge;
- return true;
-}
+++ /dev/null
-/************************************************************
- * 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.
- *
- ********************************************************/
-
-#ifndef XKBCOMP_PATH_H
-#define XKBCOMP_PATH_H
-
-#include <stdio.h>
-
-#include "xkbcomp-priv.h"
-
-bool
-XkbParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn,
- char *nextop_rtrn,
- char **extra_data);
-
-const char *
-XkbDirectoryForInclude(enum xkb_file_type type);
-
-FILE *
-XkbFindFileInPath(struct xkb_context *ctx, const char *name,
- enum xkb_file_type type, char **pathRtrn);
-
-#endif /* XKBCOMP_PATH_H */
#include <sys/stat.h>
#include <sys/types.h>
+#include "xkbcomp-priv.h"
#include "rules.h"
-#include "path.h"
+#include "include.h"
static const char *
input_line_get(struct xkb_context *ctx, const char *buf, const char *end,
char *path;
char **include;
- file = XkbFindFileInPath(ctx, rmlvo->rules, FILE_TYPE_RULES, &path);
+ file = FindFileInXkbPath(ctx, rmlvo->rules, FILE_TYPE_RULES, &path);
if (!file) {
log_err(ctx, "Could not find \"%s\" rules in XKB path\n",
rmlvo->rules);
* authorization from the authors.
*/
-#ifndef RULES_H
-#define RULES_H
-
-#include "xkbcomp-priv.h"
+#ifndef XKBCOMP_RULES_H
+#define XKBCOMP_RULES_H
bool
xkb_components_from_rules(struct xkb_context *ctx,
const struct xkb_rule_names *rmlvo,
struct xkb_component_names *out);
-#endif /* RULES_H */
+#endif
********************************************************/
%{
-#include <stdio.h>
-
#include "xkbcomp-priv.h"
-#include "parseutils.h"
+#include "parser-priv.h"
-#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-extern int yyparse(struct parser_param *param);
+struct scanner_extra {
+ struct xkb_context *ctx;
+ char *scanFile;
+ char scanBuf[1024];
+ char *s;
+};
static void
scanner_error_extra(struct YYLTYPE *loc, struct scanner_extra *extra,
scanner_error_extra(loc, extra, msg);
}
+static void
+CheckDefaultMap(struct xkb_context *ctx, XkbFile *maps, const char *fileName)
+{
+ XkbFile *dflt = NULL, *tmp;
+
+ for (tmp = maps; tmp; tmp = (XkbFile *) tmp->common.next) {
+ if (!(tmp->flags & XkbLC_Default))
+ continue;
+
+ if (!dflt) {
+ dflt = tmp;
+ continue;
+ }
+
+ log_lvl(ctx, 3,
+ "Multiple default components in %s; "
+ "Using %s, ignoring %s\n",
+ (fileName ? fileName : "(unknown)"),
+ (dflt->name ? dflt->name : "(first)"),
+ (tmp->name ? tmp->name : "(subsequent)"));
+
+ tmp->flags &= (~XkbLC_Default);
+ }
+}
+
bool
-XKBParseString(struct xkb_context *ctx, const char *string,
+XkbParseString(struct xkb_context *ctx, const char *string,
const char *file_name, XkbFile **out)
{
int ret;
}
bool
-XKBParseFile(struct xkb_context *ctx, FILE *file,
+XkbParseFile(struct xkb_context *ctx, FILE *file,
const char *file_name, XkbFile **out)
{
int ret;
********************************************************/
#include "xkbcomp-priv.h"
-#include "parseutils.h"
+#include "text.h"
+#include "expr.h"
#include "action.h"
#include "vmod.h"
-
-/***====================================================================***/
+#include "keycodes.h"
+#include "include.h"
/* Needed to work with the typechecker. */
typedef darray(xkb_keysym_t) darray_xkb_keysym_t;
MergeIncludedSymbols(&included, &next_incl, merge);
FreeSymbolsInfo(&next_incl);
- FreeXKBFile(rtrn);
+ FreeXkbFile(rtrn);
}
MergeIncludedSymbols(info, &included, merge);
return true;
}
+bool
+LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn)
+{
+ xkb_keysym_t sym;
+
+ if (!str || istreq(str, "any") || istreq(str, "nosymbol")) {
+ *sym_rtrn = XKB_KEY_NoSymbol;
+ return 1;
+ }
+
+ if (istreq(str, "none") || istreq(str, "voidsymbol")) {
+ *sym_rtrn = XKB_KEY_VoidSymbol;
+ return 1;
+ }
+
+ sym = xkb_keysym_from_name(str);
+ if (sym != XKB_KEY_NoSymbol) {
+ *sym_rtrn = sym;
+ return 1;
+ }
+
+ return 0;
+}
+
static bool
AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
ExprDef *value)
--- /dev/null
+/************************************************************
+ * 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.
+ *
+ ********************************************************/
+
+#include "xkbcomp-priv.h"
+#include "text.h"
+#include "vmod.h"
+#include "expr.h"
+#include "include.h"
+
+/*
+ * The xkb_types section
+ * =====================
+ * This section is the second to be processesed, after xkb_keycodes.
+ * However, it is completely independent and could have been the first
+ * to be processed (it does not refer to specific keys as specified in
+ * the xkb_keycodes section).
+ *
+ * This section defines key types, which, given a key and a keyboard
+ * state (i.e. modifier state and group), determine the shift level to
+ * be used in translating the key to keysyms. These types are assigned
+ * to each group in each key, in the xkb_symbols section.
+ *
+ * Key types are called this way because, in a way, they really describe
+ * the "type" of the key (or more correctly, a specific group of the
+ * key). For example, an ordinary keymap will provide a type called
+ * "KEYPAD", which consists of two levels, with the second level being
+ * chosen according to the state of the Num Lock (or Shift) modifiers.
+ * Another example is a type called "ONE_LEVEL", which is usually
+ * assigned to keys such as Escape; these have just one level and are
+ * not affected by the modifier state. Yet more common examples are
+ * "TWO_LEVEL" (with Shift choosing the second level), "ALPHABETIC"
+ * (where Caps Lock may also choose the second level), etc.
+ *
+ * Type definitions
+ * ----------------
+ * Statements of the form:
+ * type "FOUR_LEVEL" { ... }
+ *
+ * The above would create a new type named "FOUR_LEVEL".
+ * The body of the definition may include statements of the following
+ * forms:
+ *
+ * - level_name statements (mandatory for each level in the type):
+ * level_name[Level1] = "Base";
+ *
+ * Gives each level in this type a descriptive name. It isn't used
+ * for any thing.
+ * Note: A level may be specified as Level[1-8] or just a number (can
+ * be more than 8).
+ *
+ * - modifiers statement (mandatory, should be specified only once):
+ * modifiers = Shift+Lock+LevelThree;
+ *
+ * A mask of real and virtual modifiers. These are the only modifiers
+ * being considered when matching the modifier state against the type.
+ * The other modifiers, whether active or not, are masked out in the
+ * calculation.
+ *
+ * - map entry statements (should have at least as many mappings as there
+ * are levels in the type):
+ * map[Shift+LevelThree] = Level4;
+ *
+ * If the active modifiers, masked with the type's modifiers (as stated
+ * above), match (i.e. equal) the modifiers inside the map[] statement,
+ * then the level in the right hand side is chosen. For example, in the
+ * above, if in the current keyboard state the Shift and LevelThree
+ * modifiers are active, while the Lock modifier is not, then the
+ * keysym(s) in the 4th level of the group will be returned to the
+ * user.
+ *
+ * - preserve statements:
+ * map[Shift+Lock+LevelThree] = Level5;
+ * preserve[Shift+Lock+LevelThree] = Lock;
+ *
+ * When a map entry matches the active modifiers and the level it
+ * specified is chosen, then these modifiers are said to be "consumed";
+ * for example, in a simple US keymap where the "g" key is assigned an
+ * ordinary ALPHABETIC key type, if the Lock (Caps Lock) modifier is
+ * active and the key is pressed, then a "G" keysym is produced (as
+ * opposed to lower-case "g"). This is because the type definition has
+ * a map entry like the following:
+ * map[Lock] = Level2;
+ * And as such the Lock modifier is consumed. This information is
+ * relevant for applications which further process the modifiers,
+ * since by then the consumed modifiers have already "done their part"
+ * and should be masked out.
+ *
+ * However, sometimes even if a modifier is actually used to choose
+ * the shift level (as Lock above), it should *not* be reported as
+ * consumed, for various reasons. In this case, a preserve[] statement
+ * can be used to augment the map entry. The modifiers inside the square
+ * brackets should match one of the map[] statements in the type. The
+ * right hand side should consists of modifiers from the left hand
+ * side; these modifiers are then "preserved" and not reported as
+ * consumed.
+ *
+ * Virtual modifier statements
+ * ---------------------------
+ * Statements of the form:
+ * virtual_modifiers LControl;
+ *
+ * Can appear in the xkb_types, xkb_compat, xkb_symbols sections.
+ * TODO
+ */
+
+enum type_field {
+ TYPE_FIELD_MASK = (1 << 0),
+ TYPE_FIELD_MAP = (1 << 1),
+ TYPE_FIELD_PRESERVE = (1 << 2),
+ TYPE_FIELD_LEVEL_NAME = (1 << 3),
+};
+
+typedef struct _KeyTypeInfo {
+ enum type_field defined;
+ unsigned file_id;
+ enum merge_mode merge;
+ struct list entry;
+
+ xkb_atom_t name;
+ xkb_mod_mask_t mods;
+ xkb_level_index_t num_levels;
+ darray(struct xkb_kt_map_entry) entries;
+ darray(xkb_atom_t) level_names;
+} KeyTypeInfo;
+
+typedef struct _KeyTypesInfo {
+ char *name;
+ int errorCount;
+ unsigned file_id;
+ unsigned num_types;
+ struct list types;
+ VModInfo vmods;
+ struct xkb_keymap *keymap;
+} KeyTypesInfo;
+
+/***====================================================================***/
+
+static inline const char *
+MapEntryTxt(KeyTypesInfo *info, struct xkb_kt_map_entry *entry)
+{
+ return VModMaskText(info->keymap, entry->mods.mods);
+}
+
+static inline const char *
+TypeTxt(KeyTypesInfo *info, KeyTypeInfo *type)
+{
+ return xkb_atom_text(info->keymap->ctx, type->name);
+}
+
+static inline const char *
+TypeMaskTxt(KeyTypesInfo *info, KeyTypeInfo *type)
+{
+ return VModMaskText(info->keymap, type->mods);
+}
+
+static inline bool
+ReportTypeShouldBeArray(KeyTypesInfo *info, KeyTypeInfo *type,
+ const char *field)
+{
+ return ReportShouldBeArray(info->keymap, "key type", field,
+ TypeTxt(info, type));
+}
+
+static inline bool
+ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type,
+ const char *field, const char *wanted)
+{
+ return ReportBadType(info->keymap->ctx, "key type", field,
+ TypeTxt(info, type), wanted);
+}
+
+static inline bool
+ReportTypeBadWidth(KeyTypesInfo *info, const char *type, int has, int needs)
+{
+ log_err(info->keymap->ctx,
+ "Key type \"%s\" has %d levels, must have %d; "
+ "Illegal type definition ignored\n",
+ type, has, needs);
+ return false;
+}
+
+/***====================================================================***/
+
+static void
+InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_keymap *keymap,
+ unsigned file_id)
+{
+ info->name = strdup("default");
+ info->errorCount = 0;
+ info->num_types = 0;
+ list_init(&info->types);
+ info->file_id = file_id;
+ InitVModInfo(&info->vmods, keymap);
+ info->keymap = keymap;
+}
+
+static void
+FreeKeyTypeInfo(KeyTypeInfo * type)
+{
+ darray_free(type->entries);
+ darray_free(type->level_names);
+}
+
+static void
+FreeKeyTypesInfo(KeyTypesInfo * info)
+{
+ KeyTypeInfo *type, *next_type;
+ free(info->name);
+ info->name = NULL;
+ list_foreach_safe(type, next_type, &info->types, entry) {
+ FreeKeyTypeInfo(type);
+ free(type);
+ }
+}
+
+static KeyTypeInfo *
+NextKeyType(KeyTypesInfo * info)
+{
+ KeyTypeInfo *type;
+
+ type = calloc(1, sizeof(*type));
+ if (!type)
+ return NULL;
+
+ type->file_id = info->file_id;
+
+ list_append(&type->entry, &info->types);
+ info->num_types++;
+ return type;
+}
+
+static KeyTypeInfo *
+FindMatchingKeyType(KeyTypesInfo *info, xkb_atom_t name)
+{
+ KeyTypeInfo *old;
+
+ list_foreach(old, &info->types, entry)
+ if (old->name == name)
+ return old;
+
+ return NULL;
+}
+
+static bool
+AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new)
+{
+ KeyTypeInfo *old;
+ struct list entry;
+ int verbosity = xkb_get_log_verbosity(info->keymap->ctx);
+
+ old = FindMatchingKeyType(info, new->name);
+ if (old) {
+ if (new->merge == MERGE_REPLACE || new->merge == MERGE_OVERRIDE) {
+ if ((old->file_id == new->file_id && verbosity > 0) ||
+ verbosity > 9) {
+ log_warn(info->keymap->ctx,
+ "Multiple definitions of the %s key type; "
+ "Earlier definition ignored\n",
+ xkb_atom_text(info->keymap->ctx, new->name));
+ }
+
+ entry = old->entry;
+ FreeKeyTypeInfo(old);
+ *old = *new;
+ old->entry = entry;
+ darray_init(new->entries);
+ darray_init(new->level_names);
+ return true;
+ }
+
+ if (old->file_id == new->file_id)
+ log_lvl(info->keymap->ctx, 4,
+ "Multiple definitions of the %s key type; "
+ "Later definition ignored\n",
+ xkb_atom_text(info->keymap->ctx, new->name));
+
+ FreeKeyTypeInfo(new);
+ return true;
+ }
+
+ old = NextKeyType(info);
+ if (!old)
+ return false;
+
+ entry = old->entry;
+ *old = *new;
+ old->entry = entry;
+ darray_init(new->entries);
+ darray_init(new->level_names);
+ return true;
+}
+
+/***====================================================================***/
+
+static void
+MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from,
+ enum merge_mode merge)
+{
+ KeyTypeInfo *type, *next_type;
+
+ if (from->errorCount > 0) {
+ into->errorCount += from->errorCount;
+ return;
+ }
+
+ if (into->name == NULL) {
+ into->name = from->name;
+ from->name = NULL;
+ }
+
+ list_foreach_safe(type, next_type, &from->types, entry) {
+ type->merge = (merge == MERGE_DEFAULT ? type->merge : merge);
+ if (!AddKeyType(into, type))
+ into->errorCount++;
+ }
+}
+
+static void
+HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge);
+
+static bool
+HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *stmt)
+{
+ enum merge_mode merge = MERGE_DEFAULT;
+ XkbFile *rtrn;
+ KeyTypesInfo included, next_incl;
+
+ InitKeyTypesInfo(&included, info->keymap, info->file_id);
+ if (stmt->stmt) {
+ free(included.name);
+ included.name = stmt->stmt;
+ stmt->stmt = NULL;
+ }
+
+ for (; stmt; stmt = stmt->next_incl) {
+ if (!ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_TYPES,
+ &rtrn, &merge)) {
+ info->errorCount += 10;
+ FreeKeyTypesInfo(&included);
+ return false;
+ }
+
+ InitKeyTypesInfo(&next_incl, info->keymap, rtrn->id);
+
+ HandleKeyTypesFile(&next_incl, rtrn, merge);
+
+ MergeIncludedKeyTypes(&included, &next_incl, merge);
+
+ FreeKeyTypesInfo(&next_incl);
+ FreeXkbFile(rtrn);
+ }
+
+ MergeIncludedKeyTypes(info, &included, merge);
+ FreeKeyTypesInfo(&included);
+
+ return (info->errorCount == 0);
+}
+
+/***====================================================================***/
+
+static bool
+SetModifiers(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
+ ExprDef *value)
+{
+ xkb_mod_mask_t mods;
+
+ if (arrayNdx)
+ log_warn(info->keymap->ctx,
+ "The modifiers field of a key type is not an array; "
+ "Illegal array subscript ignored\n");
+
+ /* get modifier mask for current type */
+ if (!ExprResolveVModMask(info->keymap, value, &mods)) {
+ log_err(info->keymap->ctx,
+ "Key type mask field must be a modifier mask; "
+ "Key type definition ignored\n");
+ return false;
+ }
+
+ if (type->defined & TYPE_FIELD_MASK) {
+ log_warn(info->keymap->ctx,
+ "Multiple modifier mask definitions for key type %s; "
+ "Using %s, ignoring %s\n",
+ xkb_atom_text(info->keymap->ctx, type->name),
+ TypeMaskTxt(info, type),
+ VModMaskText(info->keymap, mods));
+ return false;
+ }
+
+ type->mods = mods;
+ return true;
+}
+
+/***====================================================================***/
+
+static struct xkb_kt_map_entry *
+FindMatchingMapEntry(KeyTypeInfo *type, xkb_mod_mask_t mods)
+{
+ struct xkb_kt_map_entry *entry;
+
+ darray_foreach(entry, type->entries)
+ if (entry->mods.mods == mods)
+ return entry;
+
+ return NULL;
+}
+
+/**
+ * Add a new KTMapEntry to the given key type. If an entry with the same mods
+ * already exists, the level is updated (if clobber is TRUE). Otherwise, a new
+ * entry is created.
+ *
+ * @param clobber Overwrite existing entry.
+ * @param report true if a warning is to be printed on.
+ */
+static bool
+AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
+ struct xkb_kt_map_entry *new, bool clobber, bool report)
+{
+ struct xkb_kt_map_entry * old;
+
+ old = FindMatchingMapEntry(type, new->mods.mods);
+ if (old) {
+ if (report && old->level != new->level) {
+ log_warn(info->keymap->ctx,
+ "Multiple map entries for %s in %s; "
+ "Using %d, ignoring %d\n",
+ MapEntryTxt(info, new), TypeTxt(info, type),
+ (clobber ? new->level : old->level) + 1,
+ (clobber ? old->level : new->level) + 1);
+ }
+ else {
+ log_lvl(info->keymap->ctx, 10,
+ "Multiple occurences of map[%s]= %d in %s; Ignored\n",
+ MapEntryTxt(info, new), new->level + 1,
+ TypeTxt(info, type));
+ return true;
+ }
+
+ if (clobber) {
+ if (new->level >= type->num_levels)
+ type->num_levels = new->level + 1;
+ old->level = new->level;
+ }
+
+ return true;
+ }
+
+ if (new->level >= type->num_levels)
+ type->num_levels = new->level + 1;
+
+ darray_append(type->entries, *new);
+ return true;
+}
+
+static bool
+SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
+ ExprDef *value)
+{
+ struct xkb_kt_map_entry entry;
+
+ if (arrayNdx == NULL)
+ return ReportTypeShouldBeArray(info, type, "map entry");
+
+ if (!ExprResolveVModMask(info->keymap, arrayNdx, &entry.mods.mods))
+ return ReportTypeBadType(info, type, "map entry", "modifier mask");
+
+ if (entry.mods.mods & (~type->mods)) {
+ log_lvl(info->keymap->ctx, 1,
+ "Map entry for unused modifiers in %s; "
+ "Using %s instead of %s\n",
+ TypeTxt(info, type),
+ VModMaskText(info->keymap, entry.mods.mods & type->mods),
+ MapEntryTxt(info, &entry));
+ entry.mods.mods &= type->mods;
+ }
+
+ if (!ExprResolveLevel(info->keymap->ctx, value, &entry.level)) {
+ log_err(info->keymap->ctx,
+ "Level specifications in a key type must be integer; "
+ "Ignoring malformed level specification\n");
+ return false;
+ }
+
+ entry.preserve.mods = 0;
+
+ return AddMapEntry(info, type, &entry, true, true);
+}
+
+/***====================================================================***/
+
+static bool
+AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type,
+ xkb_mod_mask_t mods, xkb_mod_mask_t preserve_mods)
+{
+ struct xkb_kt_map_entry *entry;
+ struct xkb_kt_map_entry new;
+
+ darray_foreach(entry, type->entries) {
+ if (entry->mods.mods != mods)
+ continue;
+
+ /* Map exists without previous preserve (or "None"); override. */
+ if (entry->preserve.mods == 0) {
+ entry->preserve.mods = preserve_mods;
+ return true;
+ }
+
+ /* Map exists with same preserve; do nothing. */
+ if (entry->preserve.mods == preserve_mods) {
+ log_lvl(info->keymap->ctx, 10,
+ "Identical definitions for preserve[%s] in %s; "
+ "Ignored\n",
+ VModMaskText(info->keymap, mods),
+ TypeTxt(info, type));
+ return true;
+ }
+
+ /* Map exists with different preserve; latter wins. */
+ log_lvl(info->keymap->ctx, 1,
+ "Multiple definitions for preserve[%s] in %s; "
+ "Using %s, ignoring %s\n",
+ VModMaskText(info->keymap, mods),
+ TypeTxt(info, type),
+ VModMaskText(info->keymap, preserve_mods),
+ VModMaskText(info->keymap, entry->preserve.mods));
+
+ entry->preserve.mods = preserve_mods;
+ return true;
+ }
+
+ /*
+ * Map does not exist, i.e. preserve[] came before map[].
+ * Create a map with the specified mask mapping to Level1. The level
+ * may be overriden later with an explicit map[] statement.
+ */
+ new.level = 0;
+ new.mods.mods = mods;
+ new.preserve.mods = preserve_mods;
+ darray_append(type->entries, new);
+ return true;
+}
+
+static bool
+SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
+ ExprDef *value)
+{
+ xkb_mod_mask_t mods, preserve_mods;
+
+ if (arrayNdx == NULL)
+ return ReportTypeShouldBeArray(info, type, "preserve entry");
+
+ if (!ExprResolveVModMask(info->keymap, arrayNdx, &mods))
+ return ReportTypeBadType(info, type, "preserve entry",
+ "modifier mask");
+
+ if (mods & ~type->mods) {
+ const char *before, *after;
+
+ before = VModMaskText(info->keymap, mods);
+ mods &= type->mods;
+ after = VModMaskText(info->keymap, mods);
+
+ log_lvl(info->keymap->ctx, 1,
+ "Preserve for modifiers not used by the %s type; "
+ "Index %s converted to %s\n",
+ TypeTxt(info, type), before, after);
+ }
+
+ if (!ExprResolveVModMask(info->keymap, value, &preserve_mods)) {
+ log_err(info->keymap->ctx,
+ "Preserve value in a key type is not a modifier mask; "
+ "Ignoring preserve[%s] in type %s\n",
+ VModMaskText(info->keymap, mods),
+ TypeTxt(info, type));
+ return false;
+ }
+
+ if (preserve_mods & ~mods) {
+ const char *before, *after;
+
+ before = VModMaskText(info->keymap, preserve_mods);
+ preserve_mods &= mods;
+ after = VModMaskText(info->keymap, preserve_mods);
+
+ log_lvl(info->keymap->ctx, 1,
+ "Illegal value for preserve[%s] in type %s; "
+ "Converted %s to %s\n",
+ VModMaskText(info->keymap, mods),
+ TypeTxt(info, type), before, after);
+ }
+
+ return AddPreserve(info, type, mods, preserve_mods);
+}
+
+/***====================================================================***/
+
+static bool
+AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type,
+ xkb_level_index_t level, xkb_atom_t name, bool clobber)
+{
+ /* New name. */
+ if (level >= darray_size(type->level_names)) {
+ darray_resize0(type->level_names, level + 1);
+ goto finish;
+ }
+
+ /* Same level, same name. */
+ if (darray_item(type->level_names, level) == name) {
+ log_lvl(info->keymap->ctx, 10,
+ "Duplicate names for level %d of key type %s; Ignored\n",
+ level + 1, TypeTxt(info, type));
+ return true;
+ }
+
+ /* Same level, different name. */
+ if (darray_item(type->level_names, level) != XKB_ATOM_NONE) {
+ const char *old, *new;
+ old = xkb_atom_text(info->keymap->ctx,
+ darray_item(type->level_names, level));
+ new = xkb_atom_text(info->keymap->ctx, name);
+ log_lvl(info->keymap->ctx, 1,
+ "Multiple names for level %d of key type %s; "
+ "Using %s, ignoring %s\n",
+ level + 1, TypeTxt(info, type),
+ (clobber ? new : old), (clobber ? old : new));
+
+ if (!clobber)
+ return true;
+ }
+
+ /* XXX: What about different level, same name? */
+
+finish:
+ darray_item(type->level_names, level) = name;
+ return true;
+}
+
+static bool
+SetLevelName(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
+ ExprDef *value)
+{
+ xkb_level_index_t level;
+ xkb_atom_t level_name;
+ struct xkb_context *ctx = info->keymap->ctx;
+ const char *str;
+
+ if (arrayNdx == NULL)
+ return ReportTypeShouldBeArray(info, type, "level name");
+
+ if (!ExprResolveLevel(ctx, arrayNdx, &level))
+ return ReportTypeBadType(info, type, "level name", "integer");
+
+ if (!ExprResolveString(ctx, value, &str)) {
+ log_err(info->keymap->ctx,
+ "Non-string name for level %d in key type %s; "
+ "Ignoring illegal level name definition\n",
+ level + 1, xkb_atom_text(ctx, type->name));
+ return false;
+ }
+
+ level_name = xkb_atom_intern(ctx, str);
+
+ return AddLevelName(info, type, level, level_name, true);
+}
+
+/***====================================================================***/
+
+/**
+ * Parses the fields in a type "..." { } description.
+ *
+ * @param field The field to parse (e.g. modifiers, map, level_name)
+ */
+static bool
+SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type,
+ const char *field, ExprDef *arrayNdx, ExprDef *value)
+{
+ bool ok = false;
+ enum type_field type_field = 0;
+
+ if (istreq(field, "modifiers")) {
+ type_field = TYPE_FIELD_MASK;
+ ok = SetModifiers(info, type, arrayNdx, value);
+ }
+ else if (istreq(field, "map")) {
+ type_field = TYPE_FIELD_MAP;
+ ok = SetMapEntry(info, type, arrayNdx, value);
+ }
+ else if (istreq(field, "preserve")) {
+ type_field = TYPE_FIELD_PRESERVE;
+ ok = SetPreserve(info, type, arrayNdx, value);
+ }
+ else if (istreq(field, "levelname") || istreq(field, "level_name")) {
+ type_field = TYPE_FIELD_LEVEL_NAME;
+ ok = SetLevelName(info, type, arrayNdx, value);
+ } else {
+ log_err(info->keymap->ctx,
+ "Unknown field %s in key type %s; Definition ignored\n",
+ field, TypeTxt(info, type));
+ }
+
+ type->defined |= type_field;
+ return ok;
+}
+
+static bool
+HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type)
+{
+ bool ok = true;
+ const char *elem, *field;
+ ExprDef *arrayNdx;
+
+ for (; def; def = (VarDef *) def->common.next) {
+ ok = ExprResolveLhs(info->keymap->ctx, def->name, &elem, &field,
+ &arrayNdx);
+ if (!ok)
+ continue;
+
+ if (elem && istreq(elem, "type")) {
+ log_err(info->keymap->ctx,
+ "Support for changing the default type has been removed; "
+ "Statement ignored\n");
+ continue;
+ }
+
+ ok = SetKeyTypeField(info, type, field, arrayNdx, def->value);
+ }
+
+ return ok;
+}
+
+/**
+ * Process a type "XYZ" { } specification in the xkb_types section.
+ *
+ */
+static bool
+HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge)
+{
+ KeyTypeInfo type = {
+ .defined = 0,
+ .file_id = info->file_id,
+ .merge = (def->merge == MERGE_DEFAULT ? merge : def->merge),
+ .name = def->name,
+ .mods = 0,
+ .num_levels = 1,
+ .entries = darray_new(),
+ .level_names = darray_new(),
+ };
+
+ /* Parse the actual content. */
+ if (!HandleKeyTypeBody(info, def->body, &type)) {
+ info->errorCount++;
+ return false;
+ }
+
+ /* Now add the new keytype to the info struct */
+ if (!AddKeyType(info, &type)) {
+ info->errorCount++;
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Process an xkb_types section.
+ *
+ * @param file The parsed xkb_types section.
+ * @param merge Merge Strategy (e.g. MERGE_OVERRIDE)
+ * @param info Pointer to memory where the outcome will be stored.
+ */
+static void
+HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
+{
+ bool ok;
+ ParseCommon *stmt;
+
+ free(info->name);
+ info->name = strdup_safe(file->name);
+
+ for (stmt = file->defs; stmt; stmt = stmt->next) {
+ switch (stmt->type) {
+ case STMT_INCLUDE:
+ ok = HandleIncludeKeyTypes(info, (IncludeStmt *) stmt);
+ break;
+ case STMT_TYPE: /* e.g. type "ONE_LEVEL" */
+ ok = HandleKeyTypeDef(info, (KeyTypeDef *) stmt, merge);
+ break;
+ case STMT_VAR:
+ log_err(info->keymap->ctx,
+ "Support for changing the default type has been removed; "
+ "Statement ignored\n");
+ ok = true;
+ break;
+ case STMT_VMOD: /* virtual_modifiers NumLock, ... */
+ ok = HandleVModDef((VModDef *) stmt, info->keymap, merge,
+ &info->vmods);
+ break;
+ default:
+ log_err(info->keymap->ctx,
+ "Key type files may not include other declarations; "
+ "Ignoring %s\n", StmtTypeToString(stmt->type));
+ ok = false;
+ break;
+ }
+
+ if (!ok)
+ info->errorCount++;
+
+ if (info->errorCount > 10) {
+ log_err(info->keymap->ctx,
+ "Abandoning keytypes file \"%s\"\n", file->topName);
+ break;
+ }
+ }
+}
+
+static bool
+CopyDefToKeyType(KeyTypesInfo *info, KeyTypeInfo *def,
+ struct xkb_key_type *type)
+{
+ type->mods.mods = def->mods;
+ type->num_levels = def->num_levels;
+ type->map = darray_mem(def->entries, 0);
+ type->num_entries = darray_size(def->entries);
+ darray_init(def->entries);
+ type->name = def->name;
+ type->level_names = darray_mem(def->level_names, 0);
+ darray_init(def->level_names);
+
+ return true;
+}
+
+bool
+CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
+ enum merge_mode merge)
+{
+ unsigned int i;
+ unsigned int num_types;
+ KeyTypesInfo info;
+ KeyTypeInfo *def;
+
+ InitKeyTypesInfo(&info, keymap, file->id);
+
+ HandleKeyTypesFile(&info, file, merge);
+
+ if (info.errorCount != 0)
+ goto err_info;
+
+ if (info.name)
+ keymap->types_section_name = strdup(info.name);
+
+ num_types = info.num_types ? info.num_types : 1;
+ keymap->types = calloc(num_types, sizeof(*keymap->types));
+ if (!keymap->types)
+ goto err_info;
+ keymap->num_types = num_types;
+
+ /*
+ * If no types were specified, a default unnamed one-level type is
+ * used for all keys.
+ */
+ if (info.num_types == 0) {
+ KeyTypeInfo dflt = {
+ .name = xkb_atom_intern(keymap->ctx, "default"),
+ .mods = 0,
+ .num_levels = 1,
+ .entries = darray_new(),
+ .level_names = darray_new(),
+ };
+
+ if (!CopyDefToKeyType(&info, &dflt, &keymap->types[0]))
+ goto err_info;
+ } else {
+ i = 0;
+ list_foreach(def, &info.types, entry)
+ if (!CopyDefToKeyType(&info, def, &keymap->types[i++]))
+ goto err_info;
+ }
+
+ FreeKeyTypesInfo(&info);
+ return true;
+
+err_info:
+ FreeKeyTypesInfo(&info);
+ return false;
+}
*
********************************************************/
+#include "xkbcomp-priv.h"
+#include "text.h"
+#include "expr.h"
#include "vmod.h"
void
*
********************************************************/
-#ifndef VMOD_H
-#define VMOD_H 1
-
-#include "xkbcomp-priv.h"
-#include "expr.h"
+#ifndef XKBCOMP_VMOD_H
+#define XKBCOMP_VMOD_H
typedef struct _VModInfo {
xkb_mod_mask_t defined;
xkb_mod_mask_t available;
} VModInfo;
-extern void
+void
InitVModInfo(VModInfo *info, struct xkb_keymap *keymap);
-extern void
+void
ClearVModInfo(VModInfo *info, struct xkb_keymap *keymap);
-extern bool
+bool
HandleVModDef(VModDef *stmt, struct xkb_keymap *keymap,
enum merge_mode mergeMode, VModInfo *info);
ResolveVirtualModifier(ExprDef *def, struct xkb_keymap *keymap,
xkb_mod_index_t *ndx_rtrn, VModInfo *info);
-#endif /* VMOD_H */
+#endif
#ifndef XKBCOMP_PRIV_H
#define XKBCOMP_PRIV_H
-#include "xkbcomp.h"
-#include "text.h"
+#include "xkb-priv.h"
+#include "ast.h"
-extern bool
-ProcessIncludeFile(struct xkb_context *ctx, IncludeStmt *stmt,
- enum xkb_file_type file_type, XkbFile **file_rtrn,
- enum merge_mode *merge_rtrn);
+bool
+XkbParseFile(struct xkb_context *ctx, FILE *file, const char *file_name,
+ XkbFile **out);
-struct xkb_key *
-FindNamedKey(struct xkb_keymap *keymap, unsigned long name,
- bool use_aliases, xkb_keycode_t start_from);
+bool
+XkbParseString(struct xkb_context *context, const char *string,
+ const char *file_name, XkbFile **out);
-extern bool
-FindKeyNameForAlias(struct xkb_keymap *keymap, unsigned long lname,
- unsigned long *real_name);
+void
+FreeXkbFile(XkbFile *file);
-extern bool
+XkbFile *
+XkbFileFromComponents(struct xkb_context *ctx,
+ struct xkb_component_names *kkctgs);
+
+bool
+CompileKeycodes(XkbFile *file, struct xkb_keymap *keymap,
+ enum merge_mode merge);
+
+bool
+CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
+ enum merge_mode merge);
+
+bool
+CompileCompatMap(XkbFile *file, struct xkb_keymap *keymap,
+ enum merge_mode merge);
+
+bool
+CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
+ enum merge_mode merge);
+
+bool
UpdateModifiersFromCompat(struct xkb_keymap *keymap);
+bool
+LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn);
+
const char *
StmtTypeToString(enum stmt_type type);
-static inline unsigned long
-KeyNameToLong(const char name[XkbKeyNameLength])
-{
- return
- (((unsigned long)name[0]) << 24) |
- (((unsigned long)name[1]) << 16) |
- (((unsigned long)name[2]) << 8) |
- (((unsigned long)name[3]) << 0);
-}
-
-static inline void
-LongToKeyName(unsigned long val, char name[XkbKeyNameLength])
-{
- name[0] = ((val >> 24) & 0xff);
- name[1] = ((val >> 16) & 0xff);
- name[2] = ((val >> 8) & 0xff);
- name[3] = ((val >> 0) & 0xff);
-}
-
-static inline const char *
-LongKeyNameText(unsigned long val)
-{
- char buf[XkbKeyNameLength];
- LongToKeyName(val, buf);
- return KeyNameText(buf);
-}
+/***====================================================================***/
static inline bool
ReportNotArray(struct xkb_keymap *keymap, const char *type, const char *field,
return false;
}
-#endif /* XKBCOMP_PRIV_H */
+#endif
*/
#include "xkbcomp-priv.h"
+#include "text.h"
#include "rules.h"
-#include "parseutils.h"
-
-static XkbFile *
-keymap_file_from_names(struct xkb_context *ctx,
- const struct xkb_rule_names *rmlvo)
-{
- struct xkb_component_names kkctgs;
- XkbFile *keycodes, *types, *compat, *symbols;
- IncludeStmt *inc;
-
- if (!xkb_components_from_rules(ctx, rmlvo, &kkctgs)) {
- log_err(ctx,
- "Couldn't look up rules '%s', model '%s', layout '%s', "
- "variant '%s', options '%s'\n",
- rmlvo->rules, rmlvo->model, rmlvo->layout, rmlvo->variant,
- rmlvo->options);
- return NULL;
- }
-
- inc = IncludeCreate(ctx, kkctgs.keycodes, MERGE_DEFAULT);
- keycodes = CreateXKBFile(ctx, FILE_TYPE_KEYCODES, NULL,
- (ParseCommon *) inc, 0);
-
- inc = IncludeCreate(ctx, kkctgs.types, MERGE_DEFAULT);
- types = CreateXKBFile(ctx, FILE_TYPE_TYPES, NULL,
- (ParseCommon *) inc, 0);
- AppendStmt(&keycodes->common, &types->common);
-
- inc = IncludeCreate(ctx, kkctgs.compat, MERGE_DEFAULT);
- compat = CreateXKBFile(ctx, FILE_TYPE_COMPAT, NULL,
- (ParseCommon *) inc, 0);
- AppendStmt(&keycodes->common, &compat->common);
-
- inc = IncludeCreate(ctx, kkctgs.symbols, MERGE_DEFAULT);
- symbols = CreateXKBFile(ctx, FILE_TYPE_SYMBOLS, NULL,
- (ParseCommon *) inc, 0);
- AppendStmt(&keycodes->common, &symbols->common);
-
- free(kkctgs.keycodes);
- free(kkctgs.types);
- free(kkctgs.compat);
- free(kkctgs.symbols);
-
- return CreateXKBFile(ctx, FILE_TYPE_KEYMAP, strdup(""),
- &keycodes->common, 0);
-}
-
-static struct xkb_keymap *
-new_keymap(struct xkb_context *ctx)
-{
- struct xkb_keymap *keymap;
-
- keymap = calloc(1, sizeof(*keymap));
- if (!keymap)
- return NULL;
-
- keymap->refcnt = 1;
- keymap->ctx = xkb_context_ref(ctx);
-
- return keymap;
-}
/**
* Compile the given file and store the output in keymap.
XkbFile *compat = NULL;
XkbFile *symbols = NULL;
- keymap = new_keymap(ctx);
+ keymap = xkb_map_new(ctx);
if (!keymap)
goto err;
const struct xkb_rule_names *rmlvo_in,
enum xkb_map_compile_flags flags)
{
+ bool ok;
+ struct xkb_component_names kccgst;
struct xkb_rule_names rmlvo = *rmlvo_in;
XkbFile *file;
struct xkb_keymap *keymap;
if (isempty(rmlvo.layout))
rmlvo.layout = DEFAULT_XKB_LAYOUT;
- file = keymap_file_from_names(ctx, &rmlvo);
+ ok = xkb_components_from_rules(ctx, &rmlvo, &kccgst);
+ if (!ok) {
+ log_err(ctx,
+ "Couldn't look up rules '%s', model '%s', layout '%s', "
+ "variant '%s', options '%s'\n",
+ rmlvo.rules, rmlvo.model, rmlvo.layout, rmlvo.variant,
+ rmlvo.options);
+ return NULL;
+ }
+
+ file = XkbFileFromComponents(ctx, &kccgst);
+
+ free(kccgst.keycodes);
+ free(kccgst.types);
+ free(kccgst.compat);
+ free(kccgst.symbols);
+
if (!file) {
log_err(ctx,
"Failed to generate parsed XKB file from components\n");
}
keymap = compile_keymap(ctx, file);
- FreeXKBFile(file);
+ FreeXkbFile(file);
return keymap;
}
return NULL;
}
- ok = XKBParseString(ctx, string, "input", &file);
+ ok = XkbParseString(ctx, string, "input", &file);
if (!ok) {
log_err(ctx, "Failed to parse input xkb file\n");
return NULL;
}
keymap = compile_keymap(ctx, file);
- FreeXKBFile(file);
+ FreeXkbFile(file);
return keymap;
}
return NULL;
}
- ok = XKBParseFile(ctx, file, "(unknown file)", &xkb_file);
+ ok = XkbParseFile(ctx, file, "(unknown file)", &xkb_file);
if (!ok) {
log_err(ctx, "Failed to parse input xkb file\n");
return NULL;
}
keymap = compile_keymap(ctx, xkb_file);
- FreeXKBFile(xkb_file);
- return keymap;
-}
-
-XKB_EXPORT struct xkb_keymap *
-xkb_map_ref(struct xkb_keymap *keymap)
-{
- keymap->refcnt++;
+ FreeXkbFile(xkb_file);
return keymap;
}
-
-XKB_EXPORT void
-xkb_map_unref(struct xkb_keymap *keymap)
-{
- unsigned int i;
- struct xkb_key *key;
-
- if (!keymap || --keymap->refcnt > 0)
- return;
-
- for (i = 0; i < keymap->num_types; i++) {
- free(keymap->types[i].map);
- free(keymap->types[i].level_names);
- }
- free(keymap->types);
-
- darray_foreach(key, keymap->keys) {
- free(key->sym_index);
- free(key->num_syms);
- darray_free(key->syms);
- free(key->actions);
- }
- darray_free(keymap->keys);
-
- darray_free(keymap->sym_interpret);
-
- darray_free(keymap->key_aliases);
-
- free(keymap->keycodes_section_name);
- free(keymap->symbols_section_name);
- free(keymap->types_section_name);
- free(keymap->compat_section_name);
-
- xkb_context_unref(keymap->ctx);
-
- free(keymap);
-}
+++ /dev/null
-/************************************************************
- * 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.
- *
- ********************************************************/
-
-#ifndef XKBCOMP_H
-#define XKBCOMP_H 1
-
-#include "xkb-priv.h"
-
-enum stmt_type {
- STMT_UNKNOWN = 0,
- STMT_INCLUDE,
- STMT_KEYCODE,
- STMT_ALIAS,
- STMT_EXPR,
- STMT_VAR,
- STMT_TYPE,
- STMT_INTERP,
- STMT_VMOD,
- STMT_SYMBOLS,
- STMT_MODMAP,
- STMT_GROUP_COMPAT,
- STMT_INDICATOR_MAP,
- STMT_INDICATOR_NAME,
- _STMT_NUM_VALUES
-};
-
-enum expr_value_type {
- EXPR_TYPE_UNKNOWN = 0,
- EXPR_TYPE_BOOLEAN,
- EXPR_TYPE_INT,
- EXPR_TYPE_STRING,
- EXPR_TYPE_ACTION,
- EXPR_TYPE_KEYNAME,
- EXPR_TYPE_SYMBOLS,
-};
-
-enum expr_op_type {
- EXPR_VALUE = 0,
- EXPR_IDENT,
- EXPR_ACTION_DECL,
- EXPR_FIELD_REF,
- EXPR_ARRAY_REF,
- EXPR_KEYSYM_LIST,
- EXPR_ACTION_LIST,
- EXPR_ADD,
- EXPR_SUBTRACT,
- EXPR_MULTIPLY,
- EXPR_DIVIDE,
- EXPR_ASSIGN,
- EXPR_NOT,
- EXPR_NEGATE,
- EXPR_INVERT,
- EXPR_UNARY_PLUS,
-};
-
-enum merge_mode {
- MERGE_DEFAULT,
- MERGE_AUGMENT,
- MERGE_OVERRIDE,
- MERGE_REPLACE,
-};
-
-typedef struct _ParseCommon {
- enum stmt_type type;
- struct _ParseCommon *next;
-} ParseCommon;
-
-typedef struct _IncludeStmt {
- ParseCommon common;
- enum merge_mode merge;
- char *stmt;
- char *file;
- char *map;
- char *modifier;
- struct _IncludeStmt *next_incl;
-} IncludeStmt;
-
-typedef struct _Expr {
- ParseCommon common;
- enum expr_op_type op;
- enum expr_value_type value_type;
- union {
- struct {
- struct _Expr *left;
- struct _Expr *right;
- } binary;
- struct {
- xkb_atom_t element;
- xkb_atom_t field;
- } field;
- struct {
- xkb_atom_t element;
- xkb_atom_t field;
- struct _Expr *entry;
- } array;
- struct {
- xkb_atom_t name;
- struct _Expr *args;
- } action;
- struct {
- darray(char *) syms;
- darray(int) symsMapIndex;
- darray(unsigned int) symsNumEntries;
- } list;
- struct _Expr *child;
- xkb_atom_t str;
- unsigned uval;
- int ival;
- char keyName[XkbKeyNameLength];
- } value;
-} ExprDef;
-
-typedef struct _VarDef {
- ParseCommon common;
- enum merge_mode merge;
- ExprDef *name;
- ExprDef *value;
-} VarDef;
-
-typedef struct _VModDef {
- ParseCommon common;
- enum merge_mode merge;
- xkb_atom_t name;
- ExprDef *value;
-} VModDef;
-
-typedef struct _KeycodeDef {
- ParseCommon common;
- enum merge_mode merge;
- char name[XkbKeyNameLength];
- unsigned long value;
-} KeycodeDef;
-
-typedef struct _KeyAliasDef {
- ParseCommon common;
- enum merge_mode merge;
- char alias[XkbKeyNameLength];
- char real[XkbKeyNameLength];
-} KeyAliasDef;
-
-typedef struct _KeyTypeDef {
- ParseCommon common;
- enum merge_mode merge;
- xkb_atom_t name;
- VarDef *body;
-} KeyTypeDef;
-
-typedef struct _SymbolsDef {
- ParseCommon common;
- enum merge_mode merge;
- char keyName[XkbKeyNameLength];
- ExprDef *symbols;
-} SymbolsDef;
-
-typedef struct _ModMapDef {
- ParseCommon common;
- enum merge_mode merge;
- xkb_atom_t modifier;
- ExprDef *keys;
-} ModMapDef;
-
-typedef struct _GroupCompatDef {
- ParseCommon common;
- enum merge_mode merge;
- int group;
- ExprDef *def;
-} GroupCompatDef;
-
-typedef struct _InterpDef {
- ParseCommon common;
- enum merge_mode merge;
- char *sym;
- ExprDef *match;
- VarDef *def;
-} InterpDef;
-
-typedef struct _IndicatorNameDef {
- ParseCommon common;
- enum merge_mode merge;
- int ndx;
- ExprDef *name;
- bool virtual;
-} IndicatorNameDef;
-
-typedef struct _IndicatorMapDef {
- ParseCommon common;
- enum merge_mode merge;
- xkb_atom_t name;
- VarDef *body;
-} IndicatorMapDef;
-
-typedef struct _XkbFile {
- ParseCommon common;
- enum xkb_file_type file_type;
- char *topName;
- char *name;
- ParseCommon *defs;
- int id;
- unsigned flags;
-} XkbFile;
-
-extern bool
-CompileKeycodes(XkbFile *file, struct xkb_keymap *keymap,
- enum merge_mode merge);
-
-extern bool
-CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
- enum merge_mode merge);
-
-extern bool
-CompileCompatMap(XkbFile *file, struct xkb_keymap *keymap,
- enum merge_mode merge);
-
-extern bool
-CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
- enum merge_mode merge);
-
-#endif /* XKBCOMP_H */
#include <stdio.h>
#include <string.h>
-#include "xkbcommon/xkbcommon.h"
-#include "rules.h"
#include "test.h"
+#include "xkb-priv.h"
+#include "rules.h"
struct test_data {
/* Rules file */