* DEALINGS IN THE SOFTWARE.
*/
+#include "config.h"
+
#include "xkbcomp-priv.h"
#include "text.h"
#include "expr.h"
#include "include.h"
enum si_field {
- SI_FIELD_VIRTUAL_MOD = (1 << 0),
- SI_FIELD_ACTION = (1 << 1),
- SI_FIELD_AUTO_REPEAT = (1 << 2),
+ SI_FIELD_VIRTUAL_MOD = (1 << 0),
+ SI_FIELD_ACTION = (1 << 1),
+ SI_FIELD_AUTO_REPEAT = (1 << 2),
SI_FIELD_LEVEL_ONE_ONLY = (1 << 3),
};
} SymInterpInfo;
enum led_field {
- LED_FIELD_MODS = (1 << 0),
- LED_FIELD_GROUPS = (1 << 1),
- LED_FIELD_CTRLS = (1 << 2),
+ LED_FIELD_MODS = (1 << 0),
+ LED_FIELD_GROUPS = (1 << 1),
+ LED_FIELD_CTRLS = (1 << 2),
};
typedef struct {
SymInterpInfo default_interp;
darray(SymInterpInfo) interps;
LedInfo default_led;
- darray(LedInfo) leds;
+ LedInfo leds[XKB_MAX_LEDS];
+ unsigned int num_leds;
ActionsInfo *actions;
struct xkb_mod_set mods;
ReportSIBadType(CompatInfo *info, SymInterpInfo *si, const char *field,
const char *wanted)
{
- return ReportBadType(info->ctx, "symbol interpretation", field,
+ return ReportBadType(info->ctx, XKB_ERROR_WRONG_FIELD_TYPE,
+ "symbol interpretation", field,
siText(si, info), wanted);
}
ReportLedBadType(CompatInfo *info, LedInfo *ledi, const char *field,
const char *wanted)
{
- return ReportBadType(info->ctx, "indicator map", field,
+ return ReportBadType(info->ctx, XKB_ERROR_WRONG_FIELD_TYPE,
+ "indicator map", field,
xkb_atom_text(info->ctx, ledi->led.name),
wanted);
}
memset(info, 0, sizeof(*info));
info->ctx = ctx;
info->actions = actions;
- CopyModSet(&info->mods, mods);
+ info->mods = *mods;
info->default_interp.merge = MERGE_OVERRIDE;
info->default_interp.interp.virtual_mod = XKB_MOD_INVALID;
info->default_led.merge = MERGE_OVERRIDE;
ClearCompatInfo(CompatInfo *info)
{
free(info->name);
- ClearModSet(&info->mods);
darray_free(info->interps);
- darray_free(info->leds);
}
static SymInterpInfo *
if (new->merge == MERGE_REPLACE) {
if (report)
- log_warn(info->ctx,
+ log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Multiple definitions for \"%s\"; "
"Earlier interpretation ignored\n",
siText(new, info));
}
if (collide) {
- log_warn(info->ctx,
+ log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Multiple interpretations of \"%s\"; "
"Using %s definition for duplicate fields\n",
siText(new, info),
*pred_rtrn = MATCH_EXACTLY;
if (expr->expr.op == EXPR_ACTION_DECL) {
const char *pred_txt = xkb_atom_text(info->ctx, expr->action.name);
- if (!LookupString(symInterpretMatchMaskNames, pred_txt, pred_rtrn)) {
- log_err(info->ctx,
+ if (!LookupString(symInterpretMatchMaskNames, pred_txt, pred_rtrn) ||
+ !expr->action.args || expr->action.args->common.next) {
+ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Illegal modifier predicate \"%s\"; Ignored\n", pred_txt);
return false;
}
static bool
AddLedMap(CompatInfo *info, LedInfo *new, bool same_file)
{
- LedInfo *old;
enum led_field collide;
const int verbosity = xkb_context_get_log_verbosity(info->ctx);
const bool report = (same_file && verbosity > 0) || verbosity > 9;
- darray_foreach(old, info->leds) {
+ for (xkb_led_index_t i = 0; i < info->num_leds; i++) {
+ LedInfo *old = &info->leds[i];
+
if (old->led.name != new->led.name)
continue;
if (new->merge == MERGE_REPLACE) {
if (report)
- log_warn(info->ctx,
+ log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Map for indicator %s redefined; "
"Earlier definition ignored\n",
xkb_atom_text(info->ctx, old->led.name));
}
if (collide) {
- log_warn(info->ctx,
+ log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Map for indicator %s redefined; "
"Using %s definition for duplicate fields\n",
xkb_atom_text(info->ctx, old->led.name),
return true;
}
- darray_append(info->leds, *new);
+ if (info->num_leds >= XKB_MAX_LEDS) {
+ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID,
+ "Too many LEDs defined (maximum %d)\n",
+ XKB_MAX_LEDS);
+ return false;
+ }
+ info->leds[info->num_leds++] = *new;
return true;
}
MergeIncludedCompatMaps(CompatInfo *into, CompatInfo *from,
enum merge_mode merge)
{
- SymInterpInfo *si;
- LedInfo *ledi;
-
if (from->errorCount > 0) {
into->errorCount += from->errorCount;
return;
}
- MoveModSet(&into->mods, &from->mods);
+ into->mods = from->mods;
if (into->name == NULL) {
into->name = from->name;
darray_init(from->interps);
}
else {
+ SymInterpInfo *si;
darray_foreach(si, from->interps) {
si->merge = (merge == MERGE_DEFAULT ? si->merge : merge);
if (!AddInterp(into, si, false))
}
}
- if (darray_empty(into->leds)) {
- into->leds = from->leds;
- darray_init(from->leds);
+ if (into->num_leds == 0) {
+ memcpy(into->leds, from->leds, sizeof(*from->leds) * from->num_leds);
+ into->num_leds = from->num_leds;
+ from->num_leds = 0;
}
else {
- darray_foreach(ledi, from->leds) {
+ for (xkb_led_index_t i = 0; i < from->num_leds; i++) {
+ LedInfo *ledi = &from->leds[i];
ledi->merge = (merge == MERGE_DEFAULT ? ledi->merge : merge);
if (!AddLedMap(into, ledi, false))
into->errorCount++;
{
CompatInfo included;
+ if (!include)
+ return false;
+
InitCompatInfo(&included, info->ctx, info->actions, &info->mods);
included.name = include->stmt;
include->stmt = NULL;
si->defined |= SI_FIELD_AUTO_REPEAT;
}
else if (istreq(field, "locking")) {
- log_dbg(info->ctx,
+ log_dbg(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"The \"locking\" field in symbol interpretation is unsupported; "
"Ignored\n");
}
if (!ExprResolveEnum(info->ctx, value, &val, useModMapValueNames))
return ReportSIBadType(info, si, field, "level specification");
- si->interp.level_one_only = !!val;
+ si->interp.level_one_only = val;
si->defined |= SI_FIELD_LEVEL_ONE_ONLY;
}
else {
ledi->defined |= LED_FIELD_CTRLS;
}
else if (istreq(field, "allowexplicit")) {
- log_dbg(info->ctx,
+ log_dbg(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"The \"allowExplicit\" field in indicator statements is unsupported; "
"Ignored\n");
}
istreq(field, "leddriveskeyboard") ||
istreq(field, "indicatordriveskbd") ||
istreq(field, "indicatordriveskeyboard")) {
- log_dbg(info->ctx,
+ log_dbg(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"The \"%s\" field in indicator statements is unsupported; "
"Ignored\n", field);
}
else if (istreq(field, "index")) {
/* Users should see this, it might cause unexpected behavior. */
- log_err(info->ctx,
+ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"The \"index\" field in indicator statements is unsupported; "
"Ignored\n");
}
else {
- log_err(info->ctx,
+ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Unknown field %s in map for %s indicator; "
"Definition ignored\n",
field, xkb_atom_text(info->ctx, ledi->led.name));
for (; def; def = (VarDef *) def->common.next) {
if (def->name && def->name->expr.op == EXPR_FIELD_REF) {
- log_err(info->ctx,
+ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Cannot set a global default value from within an interpret statement; "
"Move statements to the global file scope\n");
ok = false;
SymInterpInfo si;
if (!ResolveStateAndPredicate(def->match, &pred, &mods, info)) {
- log_err(info->ctx,
+ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Couldn't determine matching modifiers; "
"Symbol interpretation ignored\n");
return false;
}
si = info->default_interp;
- si.merge = merge = (def->merge == MERGE_DEFAULT ? merge : def->merge);
+ si.merge = (def->merge == MERGE_DEFAULT ? merge : def->merge);
si.interp.sym = def->sym;
si.interp.match = pred;
si.interp.mods = mods;
}
if (elem) {
- log_err(info->ctx,
+ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Cannot set defaults for \"%s\" element in indicator map; "
"Assignment to %s.%s ignored\n", elem, elem, field);
ok = false;
ok = HandleInterpDef(info, (InterpDef *) stmt, merge);
break;
case STMT_GROUP_COMPAT:
- log_dbg(info->ctx,
+ log_dbg(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"The \"group\" statement in compat is unsupported; "
"Ignored\n");
ok = true;
ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt, merge);
break;
default:
- log_err(info->ctx,
+ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID,
"Compat files may not include other types; "
"Ignoring %s\n", stmt_type_to_string(stmt->type));
ok = false;
info->errorCount++;
if (info->errorCount > 10) {
- log_err(info->ctx,
- "Abandoning compatibility map \"%s\"\n", file->topName);
+ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID,
+ "Abandoning compatibility map \"%s\"\n", file->name);
break;
}
}
static void
CopyLedMapDefsToKeymap(struct xkb_keymap *keymap, CompatInfo *info)
{
- LedInfo *ledi;
- xkb_led_index_t i;
- struct xkb_led *led;
+ for (xkb_led_index_t idx = 0; idx < info->num_leds; idx++) {
+ LedInfo *ledi = &info->leds[idx];
+ xkb_led_index_t i;
+ struct xkb_led *led;
- darray_foreach(ledi, info->leds) {
/*
* Find the LED with the given name, if it was already declared
* in keycodes.
*/
- darray_enumerate(i, led, keymap->leds)
+ xkb_leds_enumerate(i, led, keymap)
if (led->name == ledi->led.name)
break;
/* Not previously declared; create it with next free index. */
- if (i >= darray_size(keymap->leds)) {
- log_dbg(keymap->ctx,
+ if (i >= keymap->num_leds) {
+ log_dbg(keymap->ctx, XKB_LOG_MESSAGE_NO_ID,
"Indicator name \"%s\" was not declared in the keycodes section; "
"Adding new indicator\n",
xkb_atom_text(keymap->ctx, ledi->led.name));
- darray_enumerate(i, led, keymap->leds)
+ xkb_leds_enumerate(i, led, keymap)
if (led->name == XKB_ATOM_NONE)
break;
- if (i >= darray_size(keymap->leds)) {
+ if (i >= keymap->num_leds) {
/* Not place to put it; ignore. */
if (i >= XKB_MAX_LEDS) {
- log_err(keymap->ctx,
+ log_err(keymap->ctx, XKB_LOG_MESSAGE_NO_ID,
"Too many indicators (maximum is %d); "
"Indicator name \"%s\" ignored\n",
XKB_MAX_LEDS,
xkb_atom_text(keymap->ctx, ledi->led.name));
continue;
}
+
/* Add a new LED. */
- darray_resize(keymap->leds, i + 1);
- led = &darray_item(keymap->leds, i);
+ led = &keymap->leds[keymap->num_leds++];
}
}
keymap->compat_section_name = strdup_safe(info->name);
XkbEscapeMapName(keymap->compat_section_name);
- MoveModSet(&keymap->mods, &info->mods);
+ keymap->mods = info->mods;
if (!darray_empty(info->interps)) {
struct collect collect;
CopyInterps(info, false, MATCH_ANY, &collect);
CopyInterps(info, false, MATCH_ANY_OR_NONE, &collect);
- keymap->num_sym_interprets = darray_size(collect.sym_interprets);
- keymap->sym_interprets = darray_mem(collect.sym_interprets, 0);
+ darray_steal(collect.sym_interprets,
+ &keymap->sym_interprets, &keymap->num_sym_interprets);
}
CopyLedMapDefsToKeymap(keymap, info);