symbols: rename SymbolsInfo groupNames to group_names
[platform/upstream/libxkbcommon.git] / src / xkbcomp / symbols.c
index 158ccaf..a412495 100644 (file)
@@ -101,14 +101,14 @@ typedef struct _KeyInfo {
 
     unsigned long name; /* the 4 chars of the key name, as long */
 
-    GroupInfo groups[XKB_NUM_GROUPS];
+    darray(GroupInfo) groups;
 
     enum key_repeat repeat;
     xkb_mod_mask_t vmodmap;
     xkb_atom_t dfltType;
 
     enum xkb_range_exceed_type out_of_range_group_action;
-    xkb_group_index_t out_of_range_group_number;
+    xkb_layout_index_t out_of_range_group_number;
 } KeyInfo;
 
 static void
@@ -139,9 +139,10 @@ InitKeyInfo(KeyInfo *keyi, unsigned file_id)
 static void
 ClearKeyInfo(KeyInfo *keyi)
 {
-    xkb_group_index_t i;
-    for (i = 0; i < XKB_NUM_GROUPS; i++)
-        ClearGroupInfo(&keyi->groups[i]);
+    GroupInfo *groupi;
+    darray_foreach(groupi, keyi->groups)
+        ClearGroupInfo(groupi);
+    darray_free(keyi->groups);
 }
 
 /***====================================================================***/
@@ -161,12 +162,12 @@ typedef struct _SymbolsInfo {
     int errorCount;
     unsigned file_id;
     enum merge_mode merge;
-    xkb_group_index_t explicit_group;
+    xkb_layout_index_t explicit_group;
     darray(KeyInfo) keys;
     KeyInfo dflt;
     VModInfo vmods;
     ActionsInfo *actions;
-    xkb_atom_t groupNames[XKB_NUM_GROUPS];
+    xkb_atom_t group_names[XKB_NUM_GROUPS];
     darray(ModMapEntry) modMaps;
 
     struct xkb_keymap *keymap;
@@ -194,11 +195,12 @@ ClearSymbolsInfo(SymbolsInfo * info)
         ClearKeyInfo(keyi);
     darray_free(info->keys);
     darray_free(info->modMaps);
+    ClearKeyInfo(&info->dflt);
 }
 
 static bool
 MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber,
-            bool report, xkb_group_index_t group, unsigned long key_name)
+            bool report, xkb_layout_index_t group, unsigned long key_name)
 {
     xkb_level_index_t i, numLevels;
     enum { INTO = (1 << 0), FROM = (1 << 1) } using;
@@ -393,10 +395,11 @@ UseNewKeyField(enum key_field field, enum key_field old, enum key_field new,
 static bool
 MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from)
 {
-    xkb_group_index_t i;
+    xkb_layout_index_t i;
+    xkb_layout_index_t groups_in_both;
     enum key_field collide = 0;
     bool clobber, report;
-    int verbosity = xkb_get_log_verbosity(info->keymap->ctx);
+    int verbosity = xkb_context_get_log_verbosity(info->keymap->ctx);
 
     if (from->merge == MERGE_REPLACE) {
         ClearKeyInfo(into);
@@ -409,9 +412,18 @@ MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from)
     report = (verbosity > 9 ||
               (into->file_id == from->file_id && verbosity > 0));
 
-    for (i = 0; i < XKB_NUM_GROUPS; i++)
-        MergeGroups(info, &into->groups[i], &from->groups[i], clobber,
-                    report, i, into->name);
+    groups_in_both = MIN(darray_size(into->groups),
+                         darray_size(from->groups));
+    for (i = 0; i < groups_in_both; i++)
+        MergeGroups(info,
+                    &darray_item(into->groups, i),
+                    &darray_item(from->groups, i),
+                    clobber, report, i, into->name);
+    /* If @from has extra groups, just move them to @into. */
+    for (i = groups_in_both; i < darray_size(from->groups); i++) {
+        darray_append(into->groups, darray_item(from->groups, i));
+        InitGroupInfo(&darray_item(from->groups, i));
+    }
 
     if (UseNewKeyField(KEY_FIELD_VMODMAP, into->defined, from->defined,
                        clobber, report, &collide)) {
@@ -546,10 +558,10 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
         from->name = NULL;
     }
     for (i = 0; i < XKB_NUM_GROUPS; i++) {
-        if (from->groupNames[i] != XKB_ATOM_NONE) {
+        if (from->group_names[i] != XKB_ATOM_NONE) {
             if ((merge != MERGE_AUGMENT) ||
-                (into->groupNames[i] == XKB_ATOM_NONE))
-                into->groupNames[i] = from->groupNames[i];
+                (into->group_names[i] == XKB_ATOM_NONE))
+                into->group_names[i] = from->group_names[i];
         }
     }
 
@@ -626,27 +638,34 @@ HandleIncludeSymbols(SymbolsInfo *info, IncludeStmt *stmt)
 
 static bool
 GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
-              unsigned what, xkb_group_index_t *ndx_rtrn)
+              unsigned what, xkb_layout_index_t *ndx_rtrn)
 {
     const char *name = (what == SYMBOLS ? "symbols" : "actions");
 
     if (arrayNdx == NULL) {
-        xkb_group_index_t i;
+        xkb_layout_index_t i;
+        GroupInfo *groupi;
         enum group_field field = (what == SYMBOLS ?
                                   GROUP_FIELD_SYMS : GROUP_FIELD_ACTS);
 
-        for (i = 0; i < XKB_NUM_GROUPS; i++) {
-            if (!(keyi->groups[i].defined & field)) {
+        darray_enumerate(i, groupi, keyi->groups) {
+            if (!(groupi->defined & field)) {
                 *ndx_rtrn = i;
                 return true;
             }
         }
 
-        log_err(info->keymap->ctx,
-                "Too many groups of %s for key %s (max %u); "
-                "Ignoring %s defined for extra groups\n",
-                name, LongKeyNameText(keyi->name), XKB_NUM_GROUPS + 1, name);
-        return false;
+        if (i >= XKB_NUM_GROUPS) {
+            log_err(info->keymap->ctx,
+                    "Too many groups of %s for key %s (max %u); "
+                    "Ignoring %s defined for extra groups\n",
+                    name, LongKeyNameText(keyi->name), XKB_NUM_GROUPS + 1, name);
+            return false;
+        }
+
+        darray_resize0(keyi->groups, darray_size(keyi->groups) + 1);
+        *ndx_rtrn = darray_size(keyi->groups) - 1;
+        return true;
     }
 
     if (!ExprResolveGroup(info->keymap->ctx, arrayNdx, ndx_rtrn)) {
@@ -658,6 +677,9 @@ GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
     }
 
     (*ndx_rtrn)--;
+    if (*ndx_rtrn >= darray_size(keyi->groups))
+        darray_resize0(keyi->groups, *ndx_rtrn + 1);
+
     return true;
 }
 
@@ -689,7 +711,7 @@ static bool
 AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
                 ExprDef *value)
 {
-    xkb_group_index_t ndx;
+    xkb_layout_index_t ndx;
     GroupInfo *groupi;
     unsigned int nSyms;
     xkb_level_index_t nLevels;
@@ -699,7 +721,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
     if (!GetGroupIndex(info, keyi, arrayNdx, SYMBOLS, &ndx))
         return false;
 
-    groupi = &keyi->groups[ndx];
+    groupi = &darray_item(keyi->groups, ndx);
 
     if (value == NULL) {
         groupi->defined |= GROUP_FIELD_SYMS;
@@ -751,7 +773,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
                          LongKeyNameText(keyi->name),
                          ndx + 1,
                          xkb_atom_text(info->keymap->ctx,
-                                       info->groupNames[ndx]),
+                                       info->group_names[ndx]),
                          nSyms);
                 leveli->sym_index = 0;
                 leveli->num_syms = 0;
@@ -779,7 +801,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
                 ExprDef *value)
 {
     unsigned int i;
-    xkb_group_index_t ndx;
+    xkb_layout_index_t ndx;
     GroupInfo *groupi;
     unsigned int nActs;
     ExprDef *act;
@@ -788,7 +810,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
     if (!GetGroupIndex(info, keyi, arrayNdx, ACTIONS, &ndx))
         return false;
 
-    groupi = &keyi->groups[ndx];
+    groupi = &darray_item(keyi->groups, ndx);
 
     if (value == NULL) {
         groupi->defined |= GROUP_FIELD_ACTS;
@@ -854,7 +876,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
     struct xkb_context *ctx = info->keymap->ctx;
 
     if (istreq(field, "type")) {
-        xkb_group_index_t ndx;
+        xkb_layout_index_t ndx;
         xkb_atom_t val;
 
         if (!ExprResolveString(ctx, value, &val))
@@ -875,8 +897,10 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
         }
         else {
             ndx--;
-            keyi->groups[ndx].type = val;
-            keyi->groups[ndx].defined |= GROUP_FIELD_TYPE;
+            if (ndx >= darray_size(keyi->groups))
+                darray_resize0(keyi->groups, ndx + 1);
+            darray_item(keyi->groups, ndx).type = val;
+            darray_item(keyi->groups, ndx).defined |= GROUP_FIELD_TYPE;
         }
     }
     else if (istreq(field, "symbols"))
@@ -980,7 +1004,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
     }
     else if (istreq(field, "groupsredirect") ||
              istreq(field, "redirectgroups")) {
-        xkb_group_index_t grp;
+        xkb_layout_index_t grp;
 
         if (!ExprResolveGroup(ctx, value, &grp)) {
             log_err(info->keymap->ctx,
@@ -1008,7 +1032,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
 static int
 SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value)
 {
-    xkb_group_index_t grp;
+    xkb_layout_index_t grp;
     xkb_atom_t name;
 
     if (!arrayNdx) {
@@ -1032,12 +1056,12 @@ SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value)
         return false;
     }
 
-    info->groupNames[grp - 1 + info->explicit_group] = name;
+    info->group_names[grp - 1 + info->explicit_group] = name;
     return true;
 }
 
 static int
-HandleSymbolsVar(SymbolsInfo *info, VarDef *stmt)
+HandleGlobalVar(SymbolsInfo *info, VarDef *stmt)
 {
     const char *elem, *field;
     ExprDef *arrayNdx;
@@ -1095,7 +1119,9 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
 
     for (; def; def = (VarDef *) def->common.next) {
         if (def->name && def->name->op == EXPR_FIELD_REF) {
-            ok = HandleSymbolsVar(info, def);
+            log_err(info->keymap->ctx,
+                    "Cannot set a global default value from within a key statement; "
+                    "Move statements to the global file scope\n");
             continue;
         }
 
@@ -1121,27 +1147,31 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
 static bool
 SetExplicitGroup(SymbolsInfo *info, KeyInfo *keyi)
 {
-    xkb_group_index_t i;
+    xkb_layout_index_t i;
+    GroupInfo *groupi;
+    bool warn = false;
 
     if (info->explicit_group == 0)
         return true;
 
-    for (i = 1; i < XKB_NUM_GROUPS; i++) {
-        if (keyi->groups[i].defined) {
-            log_warn(info->keymap->ctx,
-                     "For the map %s an explicit group specified, "
-                     "but key %s has more than one group defined; "
-                     "All groups except first one will be ignored\n",
-                     info->name, LongKeyNameText(keyi->name));
-            break;
+    darray_enumerate_from(i, groupi, keyi->groups, 1) {
+        if (groupi->defined) {
+            warn = true;
+            ClearGroupInfo(groupi);
         }
     }
-    if (i < XKB_NUM_GROUPS)
-        for (i = 1; i < XKB_NUM_GROUPS; i++)
-            ClearGroupInfo(&keyi->groups[i]);
 
-    keyi->groups[info->explicit_group] = keyi->groups[0];
-    InitGroupInfo(&keyi->groups[0]);
+    if (warn)
+        log_warn(info->keymap->ctx,
+                 "For the map %s an explicit group specified, "
+                 "but key %s has more than one group defined; "
+                 "All groups except first one will be ignored\n",
+                 info->name, LongKeyNameText(keyi->name));
+
+    darray_resize0(keyi->groups, info->explicit_group + 1);
+    darray_item(keyi->groups, info->explicit_group) =
+        darray_item(keyi->groups, 0);
+    InitGroupInfo(&darray_item(keyi->groups, 0));
     return true;
 }
 
@@ -1149,12 +1179,18 @@ static int
 HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt)
 {
     KeyInfo keyi;
-    xkb_group_index_t i;
+    xkb_layout_index_t i;
 
     keyi = info->dflt;
-    for (i = 0; i < XKB_NUM_GROUPS; i++) {
-        darray_copy(keyi.groups[i].syms, info->dflt.groups[i].syms);
-        darray_copy(keyi.groups[i].levels, info->dflt.groups[i].levels);
+    darray_init(keyi.groups);
+    darray_copy(keyi.groups, info->dflt.groups);
+    for (i = 0; i < darray_size(keyi.groups); i++) {
+        darray_init(darray_item(keyi.groups, i).syms);
+        darray_copy(darray_item(keyi.groups, i).syms,
+                    darray_item(info->dflt.groups, i).syms);
+        darray_init(darray_item(keyi.groups, i).levels);
+        darray_copy(darray_item(keyi.groups, i).levels,
+                    darray_item(info->dflt.groups, i).levels);
     }
     keyi.merge = stmt->merge;
     keyi.name = KeyNameToLong(stmt->keyName);
@@ -1240,7 +1276,7 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
             ok = HandleSymbolsDef(info, (SymbolsDef *) stmt);
             break;
         case STMT_VAR:
-            ok = HandleSymbolsVar(info, (VarDef *) stmt);
+            ok = HandleGlobalVar(info, (VarDef *) stmt);
             break;
         case STMT_VMOD:
             ok = HandleVModDef((VModDef *) stmt, info->keymap, merge,
@@ -1282,7 +1318,7 @@ static struct xkb_key *
 FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym)
 {
     struct xkb_key *key, *ret = NULL;
-    xkb_group_index_t group, min_group = UINT32_MAX;
+    xkb_layout_index_t group, min_group = UINT32_MAX;
     xkb_level_index_t level, min_level = UINT16_MAX;
 
     xkb_foreach_key(key, keymap) {
@@ -1396,85 +1432,14 @@ FindAutomaticType(struct xkb_context *ctx, xkb_level_index_t width,
     return width <= 4;
 }
 
-/**
- * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the
- * groups, and reduce to one group if all groups are identical anyway.
- */
-static void
-PrepareKeyDef(KeyInfo *keyi)
-{
-    xkb_group_index_t i, lastGroup;
-    const GroupInfo *group0;
-    bool identical;
-
-    /* get highest group number */
-    for (i = XKB_NUM_GROUPS - 1; i > 0; i--)
-        if (keyi->groups[i].defined)
-            break;
-    lastGroup = i;
-
-    if (lastGroup == 0)
-        return;
-
-    group0 = &keyi->groups[0];
-
-    /* If there are empty groups between non-empty ones fill them with data */
-    /* from the first group. */
-    /* We can make a wrong assumption here. But leaving gaps is worse. */
-    for (i = lastGroup; i > 0; i--) {
-        GroupInfo *groupi = &keyi->groups[i];
-
-        if (groupi->defined)
-            continue;
-
-        groupi->type = group0->type;
-        darray_copy(groupi->syms, group0->syms);
-        darray_copy(groupi->levels, group0->levels);
-        groupi->defined = group0->defined;
-    }
-
-    /* If all groups are completely identical remove them all */
-    /* exept the first one. */
-    /* XXX: This code needs testing... or removal. */
-    identical = true;
-    for (i = lastGroup; i > 0; i--) {
-        GroupInfo *groupi = &keyi->groups[i];
-
-        if (groupi->type != group0->type) {
-            identical = false;
-            break;
-        }
-        if (!darray_same(groupi->levels, group0->levels) &&
-            (darray_empty(groupi->levels) || darray_empty(group0->levels) ||
-             darray_size(groupi->levels) != darray_size(group0->levels) ||
-             memcmp(darray_mem(groupi->levels, 0),
-                    darray_mem(group0->levels, 0),
-                    darray_size(group0->levels) * sizeof(LevelInfo)))) {
-            identical = false;
-            break;
-        }
-        if (!darray_same(groupi->syms, group0->syms) &&
-            (darray_empty(groupi->syms) || darray_empty(group0->syms) ||
-             darray_size(groupi->syms) != darray_size(group0->syms) ||
-             memcmp(darray_mem(groupi->syms, 0),
-                    darray_mem(group0->syms, 0),
-                    darray_size(group0->syms) * sizeof(xkb_keysym_t)))) {
-            identical = false;
-            break;
-        }
-    }
-
-    if (identical)
-        for (i = lastGroup; i > 0; i--)
-            ClearGroupInfo(&keyi->groups[i]);
-}
-
 static bool
 CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi)
 {
     struct xkb_keymap *keymap = info->keymap;
     struct xkb_key *key;
-    xkb_group_index_t i;
+    GroupInfo *groupi;
+    const GroupInfo *group0;
+    xkb_layout_index_t i;
     bool haveActions;
     unsigned int sizeSyms;
     unsigned int symIndex;
@@ -1491,20 +1456,38 @@ CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi)
         return false;
     }
 
-    /*
-     * Find the range of groups we need. (There shouldn't be any gaps,
-     * see PrepareKeyDef).
-     */
+    /* Find the range of groups we need. */
     key->num_groups = 0;
-    for (i = 0; i < XKB_NUM_GROUPS; i++)
-        if (keyi->groups[i].defined)
+    darray_enumerate(i, groupi, keyi->groups)
+        if (groupi->defined)
             key->num_groups = i + 1;
 
+    if (key->num_groups <= 0)
+        return false; /* WSGO */
+
+    darray_resize(keyi->groups, key->num_groups);
+
+    /*
+     * If there are empty groups between non-empty ones, fill them with data
+     * from the first group.
+     * We can make a wrong assumption here. But leaving gaps is worse.
+     */
+    group0 = &darray_item(keyi->groups, 0);
+    darray_foreach_from(groupi, keyi->groups, 1) {
+        if (groupi->defined)
+            continue;
+
+        groupi->type = group0->type;
+        darray_copy(groupi->syms, group0->syms);
+        darray_copy(groupi->levels, group0->levels);
+        groupi->defined = group0->defined;
+    }
+
     /* See if we need to allocate an actions array. */
     haveActions = false;
-    for (i = 0; i < key->num_groups; i++) {
+    darray_foreach(groupi, keyi->groups) {
         LevelInfo *leveli;
-        darray_foreach(leveli, keyi->groups[i].levels) {
+        darray_foreach(leveli, groupi->levels) {
             if (leveli->act.type != ACTION_TYPE_NONE) {
                 haveActions = true;
                 goto out_of_loops;
@@ -1517,10 +1500,10 @@ out_of_loops:
      * Find and assign the groups' types in the keymap. Also find the
      * key width according to the largest type.
      */
+    key->kt_index = calloc(key->num_groups, sizeof(*key->kt_index));
     key->width = 0;
-    for (i = 0; i < key->num_groups; i++) {
+    darray_enumerate(i, groupi, keyi->groups) {
         struct xkb_key_type *type;
-        GroupInfo *groupi = &keyi->groups[i];
         bool autoType = false;
 
         /* Find the type of the group, if it is missing. */
@@ -1535,7 +1518,7 @@ out_of_loops:
                 log_vrb(info->keymap->ctx, 5,
                         "No automatic type for %d levels; "
                         "Using %s for the %s key\n",
-                        darray_size(groupi->levels),
+                        (int) darray_size(groupi->levels),
                         xkb_atom_text(keymap->ctx, groupi->type),
                         LongKeyNameText(keyi->name));
         }
@@ -1567,7 +1550,7 @@ out_of_loops:
                     xkb_atom_text(keymap->ctx, type->name),
                     type->num_levels,
                     LongKeyNameText(keyi->name),
-                    darray_size(groupi->levels));
+                    (int) darray_size(groupi->levels));
             darray_resize(groupi->levels, type->num_levels);
         }
 
@@ -1584,8 +1567,8 @@ out_of_loops:
 
     /* Find the size of the syms array. */
     sizeSyms = 0;
-    for (i = 0; i < key->num_groups; i++)
-        sizeSyms += darray_size(keyi->groups[i].syms);
+    darray_foreach(groupi, keyi->groups)
+        sizeSyms += darray_size(groupi->syms);
 
     /* Initialize the xkb_key, now that we know the sizes. */
     key->syms = calloc(sizeSyms, sizeof(*key->syms));
@@ -1612,14 +1595,12 @@ out_of_loops:
 
     /* Copy keysyms and actions. */
     symIndex = 0;
-    for (i = 0; i < key->num_groups; i++) {
-        GroupInfo *groupi = &keyi->groups[i];
+    darray_enumerate(i, groupi, keyi->groups) {
         xkb_level_index_t j;
+        LevelInfo *leveli;
 
         /* We rely on calloc having zeroized the arrays up to key->width. */
-        for (j = 0; j < darray_size(groupi->levels); j++) {
-            LevelInfo *leveli = &darray_item(groupi->levels, j);
-
+        darray_enumerate(j, leveli, groupi->levels) {
             if (leveli->act.type != ACTION_TYPE_NONE)
                 key->actions[i * key->width + j] = leveli->act;
 
@@ -1676,22 +1657,20 @@ CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info)
 {
     KeyInfo *keyi;
     ModMapEntry *mm;
-    xkb_group_index_t i;
+    xkb_layout_index_t i;
     struct xkb_key *key;
 
     keymap->symbols_section_name = strdup_safe(info->name);
 
     for (i = 0; i < XKB_NUM_GROUPS; i++)
-        if (info->groupNames[i] != XKB_ATOM_NONE)
-            keymap->group_names[i] = info->groupNames[i];
+        if (info->group_names[i] != XKB_ATOM_NONE)
+            keymap->group_names[i] = info->group_names[i];
 
-    darray_foreach(keyi, info->keys) {
-        PrepareKeyDef(keyi);
+    darray_foreach(keyi, info->keys)
         if (!CopySymbolsDef(info, keyi))
             info->errorCount++;
-    }
 
-    if (xkb_get_log_verbosity(keymap->ctx) > 3) {
+    if (xkb_context_get_log_verbosity(keymap->ctx) > 3) {
         xkb_foreach_key(key, keymap) {
             if (key->name[0] == '\0')
                 continue;