dump: a few more tweaks to match xkbcomp output
[platform/upstream/libxkbcommon.git] / src / xkbcomp / rules.c
index ce211f9..5cd4e31 100644 (file)
 #include "rules.h"
 #include "path.h"
 
-#define DFLT_LINE_SIZE 128
-
-struct input_line {
-    size_t size;
-    size_t offset;
-    char buf[DFLT_LINE_SIZE];
-    char *line;
-};
-
-static void
-input_line_init(struct input_line *line)
-{
-    line->size = DFLT_LINE_SIZE;
-    line->offset = 0;
-    line->line = line->buf;
-}
-
-static void
-input_line_deinit(struct input_line *line)
-{
-    if (line->line != line->buf)
-        free(line->line);
-    line->offset = 0;
-    line->size = DFLT_LINE_SIZE;
-    line->line = line->buf;
-}
-
-static int
-input_line_add_char(struct input_line *line, int ch)
-{
-    if (line->offset >= line->size) {
-        if (line->line == line->buf) {
-            line->line = malloc(line->size * 2);
-            memcpy(line->line, line->buf, line->size);
-        }
-        else {
-            line->line = realloc(line->line, line->size * 2);
-        }
-
-        line->size *= 2;
-    }
-
-    line->line[line->offset++] = ch;
-    return ch;
-}
-
 static bool
-input_line_get(FILE *file, struct input_line *line)
+input_line_get(FILE *file, darray_char *line)
 {
     int ch;
     bool end_of_file = false;
@@ -85,7 +39,7 @@ input_line_get(FILE *file, struct input_line *line)
     bool slash_pending;
     bool in_comment;
 
-    while (!end_of_file && line->offset == 0) {
+    while (!end_of_file && darray_empty(*line)) {
         space_pending = slash_pending = in_comment = false;
 
         while ((ch = getc(file)) != '\n' && ch != EOF) {
@@ -118,11 +72,11 @@ input_line_get(FILE *file, struct input_line *line)
 
             if (slash_pending) {
                 if (space_pending) {
-                    input_line_add_char(line, ' ');
+                    darray_append(*line, ' ');
                     space_pending = false;
                 }
 
-                input_line_add_char(line, '/');
+                darray_append(*line, '/');
                 slash_pending = false;
             }
 
@@ -133,27 +87,27 @@ input_line_get(FILE *file, struct input_line *line)
                 if (ch == EOF)
                     break;
 
-                if (ch != '\n' && line->offset > 0)
+                if (ch != '\n' && !darray_empty(*line))
                     space_pending = true;
 
                 ungetc(ch, file);
             }
             else {
                 if (space_pending) {
-                    input_line_add_char(line, ' ');
+                    darray_append(*line, ' ');
                     space_pending = false;
                 }
 
                 if (ch == '!') {
-                    if (line->offset != 0) {
+                    if (!darray_empty(*line)) {
                         WARN("The '!' is legal only at start of line\n");
                         ACTION("Line containing '!' ignored\n");
-                        line->offset = 0;
+                        darray_resize(*line, 0);
                         break;
                     }
                 }
 
-                input_line_add_char(line, ch);
+                darray_append(*line, ch);
             }
         }
 
@@ -161,10 +115,10 @@ input_line_get(FILE *file, struct input_line *line)
             end_of_file = true;
     }
 
-    if (line->offset == 0 && end_of_file)
+    if (darray_empty(*line) && end_of_file)
         return false;
 
-    input_line_add_char(line, '\0');
+    darray_append(*line, '\0');
     return true;
 }
 
@@ -186,11 +140,10 @@ enum {
     TYPES,
     COMPAT,
     GEOMETRY,
-    KEYMAP,
 
 #define COMPONENT_MASK \
     ((1 << KEYCODES) | (1 << SYMBOLS) | (1 << TYPES) | (1 << COMPAT) | \
-     (1 << GEOMETRY) | (1 << KEYMAP))
+     (1 << GEOMETRY))
 
     MAX_WORDS
 };
@@ -206,14 +159,6 @@ static const char *cname[] = {
     [TYPES] = "types",
     [COMPAT] = "compat",
     [GEOMETRY] = "geometry",
-    [KEYMAP] = "keymap",
-};
-
-struct var_defs {
-    const char *model;
-    const char *layout;
-    const char *variant;
-    const char *options;
 };
 
 struct multi_defs {
@@ -239,12 +184,6 @@ struct var_desc {
     char *desc;
 };
 
-struct describe_vars {
-    size_t sz_desc;
-    size_t num_desc;
-    struct var_desc *desc;
-};
-
 struct group {
     int number;
     char *name;
@@ -274,23 +213,12 @@ struct rule {
     char *symbols;
     char *types;
     char *compat;
-    char *keymap;
     unsigned flags;
 };
 
 struct rules {
-    struct describe_vars models;
-    struct describe_vars layouts;
-    struct describe_vars variants;
-    struct describe_vars options;
-
-    size_t sz_rules;
-    size_t num_rules;
-    struct rule *rules;
-
-    size_t sz_groups;
-    size_t num_groups;
-    struct group *groups;
+    darray(struct rule) rules;
+    darray(struct group) groups;
 };
 
 /***====================================================================***/
@@ -329,10 +257,10 @@ get_index(char *str, int *ndx)
  * mapping->map[3] = {.word = SYMBOLS, .index = 0}
  */
 static void
-match_mapping_line(struct input_line *line, struct mapping *mapping)
+match_mapping_line(darray_char *line, struct mapping *mapping)
 {
     char *tok;
-    char *str = &line->line[1];
+    char *str = darray_mem(*line, 1);
     unsigned present = 0, layout_ndx_present = 0, variant_ndx_present = 0;
     int i, tmp;
     size_t len;
@@ -422,14 +350,6 @@ match_mapping_line(struct input_line *line, struct mapping *mapping)
         return;
     }
 
-    if (((present & COMPONENT_MASK) & (1 << KEYMAP)) &&
-        ((present & COMPONENT_MASK) != (1 << KEYMAP))) {
-        WARN("Keymap cannot appear with other components\n");
-        ACTION("Illegal mapping ignored\n");
-        mapping->num_maps = 0;
-        return;
-    }
-
     mapping->number++;
 }
 
@@ -438,10 +358,10 @@ match_mapping_line(struct input_line *line, struct mapping *mapping)
  * ! $pcmodels = pc101 pc102 pc104 pc105
  */
 static bool
-match_group_line(struct input_line *line, struct group *group)
+match_group_line(darray_char *line, struct group *group)
 {
     int i;
-    char *name = strchr(line->line, '$');
+    char *name = strchr(darray_mem(*line, 0), '$');
     char *words = strchr(name, ' ');
 
     if (!words)
@@ -475,7 +395,7 @@ match_group_line(struct input_line *line, struct group *group)
 
 /* Match lines following a mapping (see match_mapping_line comment). */
 static bool
-match_rule_line(struct input_line *line, struct mapping *mapping,
+match_rule_line(darray_char *line, struct mapping *mapping,
                 struct rule *rule)
 {
     char *str, *tok;
@@ -490,7 +410,7 @@ match_rule_line(struct input_line *line, struct mapping *mapping,
         return false;
     }
 
-    str = line->line;
+    str = darray_mem(*line, 0);
 
     for (nread = 0; (tok = strtok_r(str, " ", &strtok_buf)) != NULL; nread++) {
         str = NULL;
@@ -512,7 +432,7 @@ match_rule_line(struct input_line *line, struct mapping *mapping,
     }
 
     if (nread < mapping->num_maps) {
-        WARN("Too few words on a line: %s\n", line->line);
+        WARN("Too few words on a line: %s\n", darray_mem(*line, 0));
         ACTION("line ignored\n");
         return false;
     }
@@ -536,7 +456,6 @@ match_rule_line(struct input_line *line, struct mapping *mapping,
     rule->symbols = uDupString(names[SYMBOLS]);
     rule->types = uDupString(names[TYPES]);
     rule->compat = uDupString(names[COMPAT]);
-    rule->keymap = uDupString(names[KEYMAP]);
 
     rule->layout_num = rule->variant_num = 0;
     for (i = 0; i < nread; i++) {
@@ -552,13 +471,14 @@ match_rule_line(struct input_line *line, struct mapping *mapping,
 }
 
 static bool
-match_line(struct input_line *line, struct mapping *mapping,
+match_line(darray_char *line, struct mapping *mapping,
            struct rule *rule, struct group *group)
 {
-    if (line->line[0] != '!')
+    if (darray_item(*line, 0) != '!')
         return match_rule_line(line, mapping, rule);
 
-    if (line->line[1] == '$' || (line->line[1] == ' ' && line->line[2] == '$'))
+    if (darray_item(*line, 1) == '$' ||
+        (darray_item(*line, 1) == ' ' && darray_item(*line, 2) == '$'))
         return match_group_line(line, group);
 
     match_mapping_line(line, mapping);
@@ -580,10 +500,10 @@ squeeze_spaces(char *p1)
 }
 
 /*
- * Expand the layout and variant of a var_defs and remove extraneous spaces.
- * If there's one layout/variant, it is kept in .layout[0]/.variant[0], else
- * is kept in [1], [2] and so on, and [0] remains empty.
- * For example, this var_defs:
+ * Expand the layout and variant of the rule_names and remove extraneous
+ * spaces. If there's one layout/variant, it is kept in
+ * .layout[0]/.variant[0], else is kept in [1], [2] and so on, and [0]
+ * remains empty. For example, this rule_names:
  *      .model  = "pc105",
  *      .layout = "us,il,ru,ca"
  *      .variant = ",,,multix"
@@ -595,31 +515,31 @@ squeeze_spaces(char *p1)
  *      .options = "grp:alts_toggle,ctrl:nocaps,compose:rwin"
  */
 static bool
-make_multi_defs(struct multi_defs *mdefs, struct var_defs *defs)
+make_multi_defs(struct multi_defs *mdefs, const struct xkb_rule_names *mlvo)
 {
     char *p;
     int i;
 
     memset(mdefs, 0, sizeof(*mdefs));
 
-    if (defs->model) {
-        mdefs->model = defs->model;
+    if (mlvo->model) {
+        mdefs->model = mlvo->model;
     }
 
-    if (defs->options) {
-        mdefs->options = strdup(defs->options);
+    if (mlvo->options) {
+        mdefs->options = strdup(mlvo->options);
         if (mdefs->options == NULL)
             return false;
 
         squeeze_spaces(mdefs->options);
     }
 
-    if (defs->layout) {
-        if (!strchr(defs->layout, ',')) {
-            mdefs->layout[0] = defs->layout;
+    if (mlvo->layout) {
+        if (!strchr(mlvo->layout, ',')) {
+            mdefs->layout[0] = mlvo->layout;
         }
         else {
-            p = strdup(defs->layout);
+            p = strdup(mlvo->layout);
             if (p == NULL)
                 return false;
 
@@ -641,12 +561,12 @@ make_multi_defs(struct multi_defs *mdefs, struct var_defs *defs)
         }
     }
 
-    if (defs->variant) {
-        if (!strchr(defs->variant, ',')) {
-            mdefs->variant[0] = defs->variant;
+    if (mlvo->variant) {
+        if (!strchr(mlvo->variant, ',')) {
+            mdefs->variant[0] = mlvo->variant;
         }
         else {
-            p = strdup(defs->variant);
+            p = strdup(mlvo->variant);
             if (p == NULL)
                 return false;
 
@@ -720,7 +640,6 @@ apply_rule(struct rule *rule, struct xkb_component_names *kccgst)
     apply(rule->symbols, &kccgst->symbols);
     apply(rule->types, &kccgst->types);
     apply(rule->compat, &kccgst->compat);
-    apply(rule->keymap, &kccgst->keymap);
 }
 
 /*
@@ -737,15 +656,17 @@ match_group_member(struct rules *rules, const char *group_name,
 {
    int i;
    const char *word;
-   struct group *group;
+   struct group *iter, *group = NULL;
 
-   for (i = 0; i < rules->num_groups; i++)
-       if (strcmp(rules->groups[i].name, group_name) == 0)
+   darray_foreach(iter, rules->groups) {
+       if (strcmp(iter->name, group_name) == 0) {
+           group = iter;
            break;
+       }
+   }
 
-   if (i == rules->num_groups)
+   if (!group)
        return false;
-   group = &rules->groups[i];
 
    word = group->words;
    for (i = 0; i < group->number; i++, word += strlen(word) + 1)
@@ -759,19 +680,16 @@ match_group_member(struct rules *rules, const char *group_name,
 static bool
 match_one_of(const char *haystack, const char *needle, char sep)
 {
-    const char *s = strstr(haystack, needle);
+    const char *s = haystack;
+    const size_t len = strlen(needle);
 
-    if (s == NULL)
-        return false;
-
-    if (s != haystack && *s != sep)
-        return false;
-
-    s += strlen(needle);
-    if (*s != '\0' && *s != sep)
-        return false;
+    do {
+        if (strncmp(s, needle, len) == 0 && (s[len] == '\0' || s[len] == sep))
+            return true;
+        s = strchr(s, sep);
+    } while (s++);
 
-    return true;
+    return false;
 }
 
 static int
@@ -806,8 +724,7 @@ apply_rule_if_matches(struct rules *rules, struct rule *rule,
     }
 
     if (rule->layout) {
-        if (mdefs->layout[rule->layout_num] == NULL ||
-            *mdefs->layout[rule->layout_num] == '\0')
+        if (mdefs->layout[rule->layout_num] == NULL)
             return 0;
 
         if (strcmp(rule->layout, "*") == 0) {
@@ -825,8 +742,7 @@ apply_rule_if_matches(struct rules *rules, struct rule *rule,
     }
 
     if (rule->variant) {
-        if (mdefs->variant[rule->variant_num] == NULL ||
-            *mdefs->variant[rule->variant_num] == '\0')
+        if (mdefs->variant[rule->variant_num] == NULL)
             return 0;
 
         if (strcmp(rule->variant, "*") == 0) {
@@ -855,33 +771,30 @@ apply_rule_if_matches(struct rules *rules, struct rule *rule,
 static void
 clear_partial_matches(struct rules *rules)
 {
-    int i;
+    struct rule *rule;
 
-    for (i = 0; i < rules->num_rules; i++)
-        rules->rules[i].flags &= ~RULE_FLAG_PENDING_MATCH;
+    darray_foreach(rule, rules->rules)
+        rule->flags &= ~RULE_FLAG_PENDING_MATCH;
 }
 
 static void
 apply_partial_matches(struct rules *rules, struct xkb_component_names *kccgst)
 {
-    int i;
+    struct rule *rule;
 
-    for (i = 0; i < rules->num_rules; i++)
-        if (rules->rules[i].flags & RULE_FLAG_PENDING_MATCH)
-            apply_rule(&rules->rules[i], kccgst);
+    darray_foreach(rule, rules->rules)
+        if (rule->flags & RULE_FLAG_PENDING_MATCH)
+            apply_rule(rule, kccgst);
 }
 
 static void
 apply_matching_rules(struct rules *rules, struct multi_defs *mdefs,
                      struct xkb_component_names *kccgst, unsigned int flags)
 {
-    int i;
     int skip = -1;
     struct rule *rule;
 
-    for (i = 0; i < rules->num_rules; i++) {
-        rule = &rules->rules[i];
-
+    darray_foreach(rule, rules->rules) {
         if ((rule->flags & flags) != flags)
             continue;
 
@@ -1021,12 +934,12 @@ substitute_vars(char *name, struct multi_defs *mdefs)
 /***====================================================================***/
 
 static bool
-get_components(struct rules *rules, struct var_defs *defs,
+get_components(struct rules *rules, const struct xkb_rule_names *mlvo,
                struct xkb_component_names *kccgst)
 {
     struct multi_defs mdefs;
 
-    make_multi_defs(&mdefs, defs);
+    make_multi_defs(&mdefs, mlvo);
 
     clear_partial_matches(rules);
 
@@ -1043,123 +956,61 @@ get_components(struct rules *rules, struct var_defs *defs,
     kccgst->symbols = substitute_vars(kccgst->symbols, &mdefs);
     kccgst->types = substitute_vars(kccgst->types, &mdefs);
     kccgst->compat = substitute_vars(kccgst->compat, &mdefs);
-    kccgst->keymap = substitute_vars(kccgst->keymap, &mdefs);
 
     free_multi_defs(&mdefs);
 
-    return (kccgst->keycodes && kccgst->symbols && kccgst->types &&
-            kccgst->compat) || kccgst->keymap;
-}
-
-static struct rule *
-XkbcRF_AddRule(struct rules *rules)
-{
-    if (rules->sz_rules<1) {
-       rules->sz_rules= 16;
-       rules->num_rules= 0;
-       rules->rules = calloc(rules->sz_rules, sizeof(*rules->rules));
-    }
-    else if (rules->num_rules>=rules->sz_rules) {
-       rules->sz_rules*= 2;
-        rules->rules = realloc(rules->rules,
-                               rules->sz_rules * sizeof(*rules->rules));
-    }
-    if (!rules->rules) {
-       rules->sz_rules= rules->num_rules= 0;
-       return NULL;
-    }
-    memset(&rules->rules[rules->num_rules], 0, sizeof(*rules->rules));
-    return &rules->rules[rules->num_rules++];
-}
-
-static struct group *
-XkbcRF_AddGroup(struct rules *rules)
-{
-    if (rules->sz_groups<1) {
-       rules->sz_groups= 16;
-       rules->num_groups= 0;
-        rules->groups = calloc(rules->sz_groups, sizeof(*rules->groups));
-    }
-    else if (rules->num_groups >= rules->sz_groups) {
-       rules->sz_groups *= 2;
-        rules->groups = realloc(rules->groups,
-                                rules->sz_groups * sizeof(*rules->groups));
-    }
-    if (!rules->groups) {
-       rules->sz_groups= rules->num_groups= 0;
-       return NULL;
-    }
-
-    memset(&rules->groups[rules->num_groups], 0, sizeof(*rules->groups));
-    return &rules->groups[rules->num_groups++];
+    return
+        kccgst->keycodes && kccgst->symbols && kccgst->types && kccgst->compat;
 }
 
 static struct rules *
-XkbcRF_LoadRules(FILE *file)
+load_rules(FILE *file)
 {
-    struct input_line line;
+    darray_char line;
     struct mapping mapping;
-    struct rule trule, *rule;
-    struct group tgroup, *group;
+    struct rule trule;
+    struct group tgroup;
     struct rules *rules;
 
     rules = calloc(1, sizeof(*rules));
     if (!rules)
         return NULL;
+    darray_init(rules->rules);
+    darray_growalloc(rules->rules, 16);
 
     memset(&mapping, 0, sizeof(mapping));
     memset(&tgroup, 0, sizeof(tgroup));
-    input_line_init(&line);
+    darray_init(line);
+    darray_growalloc(line, 128);
 
     while (input_line_get(file, &line)) {
         if (match_line(&line, &mapping, &trule, &tgroup)) {
             if (tgroup.number) {
-               if ((group= XkbcRF_AddGroup(rules))!=NULL) {
-                   *group= tgroup;
-                   memset(&tgroup, 0, sizeof(tgroup));
-               }
-           } else {
-               if ((rule= XkbcRF_AddRule(rules))!=NULL) {
-                   *rule= trule;
-                   memset(&trule, 0, sizeof(trule));
-               }
-           }
-       }
-       line.offset = 0;
-    }
-    input_line_deinit(&line);
-    return rules;
-}
-
-static void
-XkbRF_ClearVarDescriptions(struct describe_vars *var)
-{
-    int i;
+                darray_append(rules->groups, tgroup);
+                memset(&tgroup, 0, sizeof(tgroup));
+            } else {
+                darray_append(rules->rules, trule);
+                memset(&trule, 0, sizeof(trule));
+            }
+        }
 
-    for (i=0;i<var->num_desc;i++) {
-       free(var->desc[i].name);
-       free(var->desc[i].desc);
-       var->desc[i].name= var->desc[i].desc= NULL;
+        darray_resize(line, 0);
     }
-    free(var->desc);
-    var->desc= NULL;
+
+    darray_free(line);
+    return rules;
 }
 
 static void
-XkbcRF_Free(struct rules *rules)
+free_rules(struct rules *rules)
 {
-    int i;
     struct rule *rule;
     struct group *group;
 
     if (!rules)
-       return;
-    XkbRF_ClearVarDescriptions(&rules->models);
-    XkbRF_ClearVarDescriptions(&rules->layouts);
-    XkbRF_ClearVarDescriptions(&rules->variants);
-    XkbRF_ClearVarDescriptions(&rules->options);
+        return;
 
-    for (i=0, rule = rules->rules; i < rules->num_rules && rules; i++, rule++) {
+    darray_foreach(rule, rules->rules) {
         free(rule->model);
         free(rule->layout);
         free(rule->variant);
@@ -1168,15 +1019,14 @@ XkbcRF_Free(struct rules *rules)
         free(rule->symbols);
         free(rule->types);
         free(rule->compat);
-        free(rule->keymap);
     }
-    free(rules->rules);
+    darray_free(rules->rules);
 
-    for (i=0, group = rules->groups; i < rules->num_groups && group; i++, group++) {
+    darray_foreach(group, rules->groups) {
         free(group->name);
         free(group->words);
     }
-    free(rules->groups);
+    darray_free(rules->groups);
 
     free(rules);
 }
@@ -1186,20 +1036,13 @@ xkb_components_from_rules(struct xkb_context *ctx,
                           const struct xkb_rule_names *rmlvo)
 {
     int i;
-    FILE *rulesFile;
-    char *rulesPath;
-    struct rules *loaded;
-    struct xkb_component_names *names = NULL;
-    struct var_defs defs = {
-        .model = rmlvo->model,
-        .layout = rmlvo->layout,
-        .variant = rmlvo->variant,
-        .options = rmlvo->options,
-    };
-
-    rulesFile = XkbFindFileInPath(ctx, rmlvo->rules, XkmRulesFile,
-                                  &rulesPath);
-    if (!rulesFile) {
+    FILE *file;
+    char *path;
+    struct rules *rules;
+    struct xkb_component_names *kccgst = NULL;
+
+    file = XkbFindFileInPath(ctx, rmlvo->rules, FILE_TYPE_RULES, &path);
+    if (!file) {
         ERROR("could not find \"%s\" rules in XKB path\n", rmlvo->rules);
         ERROR("%d include paths searched:\n",
               xkb_context_num_include_paths(ctx));
@@ -1208,33 +1051,33 @@ xkb_components_from_rules(struct xkb_context *ctx,
         return NULL;
     }
 
-    loaded = XkbcRF_LoadRules(rulesFile);
-    if (!loaded) {
-        ERROR("failed to load XKB rules \"%s\"\n", rulesPath);
-        goto unwind_file;
+    rules = load_rules(file);
+    if (!rules) {
+        ERROR("failed to load XKB rules \"%s\"\n", path);
+        goto err;
     }
 
-    names = calloc(1, sizeof(*names));
-    if (!names) {
+    kccgst = calloc(1, sizeof(*kccgst));
+    if (!kccgst) {
         ERROR("failed to allocate XKB components\n");
-        goto unwind_file;
+        goto err;
     }
 
-    if (!get_components(loaded, &defs, names)) {
-        free(names->keymap);
-        free(names->keycodes);
-        free(names->types);
-        free(names->compat);
-        free(names->symbols);
-        free(names);
-        names = NULL;
-        ERROR("no components returned from XKB rules \"%s\"\n", rulesPath);
+    if (!get_components(rules, rmlvo, kccgst)) {
+        free(kccgst->keycodes);
+        free(kccgst->types);
+        free(kccgst->compat);
+        free(kccgst->symbols);
+        free(kccgst);
+        kccgst = NULL;
+        ERROR("no components returned from XKB rules \"%s\"\n", path);
+        goto err;
     }
 
-unwind_file:
-    XkbcRF_Free(loaded);
-    if (rulesFile)
-        fclose(rulesFile);
-    free(rulesPath);
-    return names;
+err:
+    free_rules(rules);
+    if (file)
+        fclose(file);
+    free(path);
+    return kccgst;
 }