yanglint REFACTOR printing features simplified
diff --git a/tools/lint/cmd.c b/tools/lint/cmd.c
index a162f6e..344900d 100644
--- a/tools/lint/cmd.c
+++ b/tools/lint/cmd.c
@@ -77,7 +77,7 @@
         "List all the loaded modules", "f:h"
     },
     {
-        "feature", cmd_feature_opt, cmd_feature_dep, cmd_feature_exec, cmd_feature_print_fparam, cmd_feature_help, NULL,
+        "feature", cmd_feature_opt, cmd_feature_dep, cmd_feature_exec, cmd_feature_fin, cmd_feature_help, NULL,
         "Print all features of module(s) with their state", "haf"
     },
     {
diff --git a/tools/lint/cmd.h b/tools/lint/cmd.h
index 047c580..bd2f2f2 100644
--- a/tools/lint/cmd.h
+++ b/tools/lint/cmd.h
@@ -223,13 +223,13 @@
 int cmd_feature_exec(struct ly_ctx **ctx, struct yl_opt *yo, const char *posv);
 
 /**
- * @brief Generate features for the command 'add'.
+ * @brief Printing of features ends.
  *
- * @param[in,out] ctx context for libyang.
- * @param[in,out] yo context for yanglint. All necessary parameters should already be set.
+ * @param[in] ctx context for libyang. Not used.
+ * @param[in] yo context for yanglint.
  * @return 0 on success.
  */
-int cmd_feature_print_fparam(struct ly_ctx *ctx, struct yl_opt *yo);
+int cmd_feature_fin(struct ly_ctx *ctx, struct yl_opt *yo);
 void cmd_feature_help(void);
 
 /* cmd_load.c */
diff --git a/tools/lint/cmd_feature.c b/tools/lint/cmd_feature.c
index 4214ce3..5c8bd82 100644
--- a/tools/lint/cmd_feature.c
+++ b/tools/lint/cmd_feature.c
@@ -99,62 +99,33 @@
 int
 cmd_feature_exec(struct ly_ctx **ctx, struct yl_opt *yo, const char *posv)
 {
-    int rc = 0;
-    struct ly_set set = {0};
     const struct lys_module *mod;
 
     if (yo->feature_print_all) {
-        if (print_all_features(yo->out, *ctx, yo->feature_param_format, &yo->features_output)) {
-            YLMSG_E("Printing all features failed.\n");
-            rc = 1;
-            goto cleanup;
-        }
-        if (yo->feature_param_format) {
-            printf("%s\n", yo->features_output);
-        }
-        goto cleanup;
+        print_all_features(yo->out, *ctx, yo->feature_param_format);
+        return 0;
     }
 
     mod = ly_ctx_get_module_latest(*ctx, posv);
     if (!mod) {
         YLMSG_E("Module \"%s\" not found.\n", posv);
-        rc = 1;
-        goto cleanup;
-    }
-
-    /* collect features of the module */
-    if (collect_features(mod, &set)) {
-        rc = 1;
-        goto cleanup;
+        return 1;
     }
 
     if (yo->feature_param_format) {
-        if (generate_features_output(mod, &set, &yo->features_output)) {
-            rc = 1;
-            goto cleanup;
-        }
-        /* don't print features and their state of each module if generating features parameter */
-        goto cleanup;
+        print_feature_param(yo->out, mod);
+    } else {
+        print_features(yo->out, mod);
     }
 
-    if (yo->interactive) {
-        print_features(yo->out, mod, &set);
-    }
-
-cleanup:
-    ly_set_erase(&set, NULL);
-
-    return rc;
+    return 0;
 }
 
 int
-cmd_feature_print_fparam(struct ly_ctx *ctx, struct yl_opt *yo)
+cmd_feature_fin(struct ly_ctx *ctx, struct yl_opt *yo)
 {
     (void) ctx;
 
-    if (!yo->feature_print_all && yo->feature_param_format) {
-        printf("%s\n", yo->features_output);
-    }
-
+    ly_print(yo->out, "\n");
     return 0;
 }
diff --git a/tools/lint/main_ni.c b/tools/lint/main_ni.c
index fee2b81..6f04623 100644
--- a/tools/lint/main_ni.c
+++ b/tools/lint/main_ni.c
@@ -751,9 +751,7 @@
                 goto cleanup;
             }
         }
-        if ((ret = cmd_feature_print_fparam(ctx, &yo))) {
-            goto cleanup;
-        }
+        cmd_feature_fin(ctx, &yo);
     } else if (yo.schema_out_format && yo.schema_node_path) {
         if ((ret = cmd_print_exec(&ctx, &yo, NULL))) {
             goto cleanup;
diff --git a/tools/lint/yl_opt.c b/tools/lint/yl_opt.c
index 67aff0e..1a6add0 100644
--- a/tools/lint/yl_opt.c
+++ b/tools/lint/yl_opt.c
@@ -82,7 +82,6 @@
     /* schema */
     ly_set_erase(&yo->schema_features, yl_schema_features_free);
     ly_set_erase(&yo->schema_modules, NULL);
-    free(yo->features_output);
 
     /* context */
     free(yo->searchpaths);
diff --git a/tools/lint/yl_opt.h b/tools/lint/yl_opt.h
index a517148..d66ae4d 100644
--- a/tools/lint/yl_opt.h
+++ b/tools/lint/yl_opt.h
@@ -106,7 +106,6 @@
     LYS_OUTFORMAT schema_out_format;
     ly_bool feature_param_format;
     ly_bool feature_print_all;
-    char *features_output;
 
     /*
      * data
diff --git a/tools/lint/yl_schema_features.c b/tools/lint/yl_schema_features.c
index 0caac17..b452496 100644
--- a/tools/lint/yl_schema_features.c
+++ b/tools/lint/yl_schema_features.c
@@ -123,142 +123,84 @@
     return 0;
 }
 
-int
-collect_features(const struct lys_module *mod, struct ly_set *set)
-{
-    struct lysp_feature *f = NULL;
-    uint32_t idx = 0;
-
-    while ((f = lysp_feature_next(f, mod->parsed, &idx))) {
-        if (ly_set_add(set, (void *)f->name, 1, NULL)) {
-            YLMSG_E("Memory allocation failed.\n");
-            ly_set_erase(set, NULL);
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
 void
-print_features(struct ly_out *out, const struct lys_module *mod, const struct ly_set *set)
+print_features(struct ly_out *out, const struct lys_module *mod)
 {
-    size_t max_len;
-    uint32_t j;
-    const char *name;
+    struct lysp_feature *f;
+    uint32_t idx;
+    size_t max_len, len;
 
-    /* header */
     ly_print(out, "%s:\n", mod->name);
 
-    /* no features */
-    if (!set->count) {
-        ly_print(out, "\t(none)\n\n");
+    /* get max len, so the statuses of all the features will be aligned */
+    max_len = 0, idx = 0, f = NULL;
+    while ((f = lysp_feature_next(f, mod->parsed, &idx))) {
+        len = strlen(f->name);
+        max_len = (max_len > len) ? max_len : len;
+    }
+    if (!max_len) {
+        ly_print(out, "\t(none)\n");
         return;
     }
 
-    /* get max len, so the statuses of all the features will be aligned */
-    max_len = 0;
-    for (j = 0; j < set->count; ++j) {
-        name = set->objs[j];
-        if (strlen(name) > max_len) {
-            max_len = strlen(name);
-        }
-    }
-
     /* print features */
-    for (j = 0; j < set->count; ++j) {
-        name = set->objs[j];
-        ly_print(out, "\t%-*s (%s)\n", (int)max_len, name, lys_feature_value(mod, name) ? "off" : "on");
+    idx = 0, f = NULL;
+    while ((f = lysp_feature_next(f, mod->parsed, &idx))) {
+        ly_print(out, "\t%-*s (%s)\n", (int)max_len, f->name, lys_feature_value(mod, f->name) ? "off" : "on");
     }
-
-    ly_print(out, "\n");
 }
 
-int
-generate_features_output(const struct lys_module *mod, const struct ly_set *set, char **features_param)
+void
+print_feature_param(struct ly_out *out, const struct lys_module *mod)
 {
-    uint32_t j;
-    /*
-     * features_len - length of all the features in the current module
-     * added_len - length of a string to be added, = features_len + extra necessary length
-     * param_len - length of the parameter before appending new string
-    */
-    size_t features_len, added_len, param_len;
-    char *tmp;
+    struct lysp_feature *f = NULL;
+    uint32_t idx = 0;
+    uint8_t first = 1;
 
-    features_len = 0;
-    for (j = 0; j < set->count; j++) {
-        features_len += strlen(set->objs[j]);
-    }
-
-    if (j == 0) {
-        /* no features */
-        added_len = strlen("-F ") + strlen(mod->name) + strlen(":");
-    } else {
-        /* j = comma count, -1 because of trailing comma */
-        added_len = strlen("-F ") + strlen(mod->name) + strlen(":") + features_len + j - 1;
-    }
-
-    /* to avoid strlen(NULL) if this is the first call */
-    param_len = 0;
-    if (*features_param) {
-        param_len = strlen(*features_param);
-    }
-
-    /* +1 because of white space at the beginning */
-    tmp = realloc(*features_param, param_len + added_len + 1 + 1);
-    if (!tmp) {
-        goto error;
-    } else {
-        *features_param = tmp;
-    }
-    sprintf(*features_param + param_len, " -F %s:", mod->name);
-
-    for (j = 0; j < set->count; j++) {
-        strcat(*features_param, set->objs[j]);
-        /* no trailing comma */
-        if (j != (set->count - 1)) {
-            strcat(*features_param, ",");
+    ly_print(out, " -F %s:", mod->name);
+    while ((f = lysp_feature_next(f, mod->parsed, &idx))) {
+        if (first) {
+            ly_print(out, "%s", f->name);
+            first = 0;
+        } else {
+            ly_print(out, ",%s", f->name);
         }
     }
-
-    return 0;
-
-error:
-    YLMSG_E("Memory allocation failed (%s:%d, %s).\n", __FILE__, __LINE__, strerror(errno));
-    return 1;
 }
 
-int
-print_all_features(struct ly_out *out, const struct ly_ctx *ctx, uint8_t generate_features, char **features_param)
+void
+print_all_features(struct ly_out *out, const struct ly_ctx *ctx, uint8_t feature_param)
 {
-    int ret = 0;
-    uint32_t i = 0;
+    uint32_t i;
     struct lys_module *mod;
-    struct ly_set set = {0};
+    uint8_t first;
 
+    /* Print features for all implemented modules. */
+    first = 1;
+    i = 0;
     while ((mod = ly_ctx_get_module_iter(ctx, &i)) != NULL) {
-        /* only care about implemented modules */
         if (!mod->implemented) {
             continue;
         }
-
-        /* always erase the set, so the previous module's features don't carry over to the next module's features */
-        ly_set_erase(&set, NULL);
-
-        if (collect_features(mod, &set)) {
-            ret = 1;
-            goto cleanup;
+        if (first) {
+            print_features(out, mod);
+            first = 0;
+        } else {
+            ly_print(out, "\n");
+            print_features(out, mod);
         }
-
-        if (generate_features && generate_features_output(mod, &set, features_param)) {
-            ret = 1;
-            goto cleanup;
-        }
-        print_features(out, mod, &set);
     }
 
-cleanup:
-    ly_set_erase(&set, NULL);
-    return ret;
+    if (!feature_param) {
+        return;
+    }
+    ly_print(out, "\n");
+
+    /* Print features for all implemented modules in 'feature-param' format. */
+    i = 0;
+    while ((mod = ly_ctx_get_module_iter(ctx, &i)) != NULL) {
+        if (mod->implemented) {
+            print_feature_param(out, mod);
+        }
+    }
 }
diff --git a/tools/lint/yl_schema_features.h b/tools/lint/yl_schema_features.h
index 7c96ba8..7bfe9fd 100644
--- a/tools/lint/yl_schema_features.h
+++ b/tools/lint/yl_schema_features.h
@@ -57,46 +57,28 @@
 int parse_features(const char *fstring, struct ly_set *fset);
 
 /**
- * @brief Collect all features of a module.
- *
- * @param[in] mod Module to be searched for features.
- * @param[out] set Set in which the features will be stored.
- * @return 0 on success.
- * @return 1 on error.
- */
-int collect_features(const struct lys_module *mod, struct ly_set *set);
-
-/**
  * @brief Print all features of a single module.
  *
  * @param[in] out The output handler for printing.
- * @param[in] mod Module which contains the features.
- * @param[in] set Set which holds the features.
+ * @param[in] mod Module which can contains the features.
  */
-void print_features(struct ly_out *out, const struct lys_module *mod, const struct ly_set *set);
+void print_features(struct ly_out *out, const struct lys_module *mod);
 
 /**
- * @brief Generate a string, which will contain features paramater.
+ * @brief Print all features in the 'feature-param' format.
  *
- * @param[in] mod Module, for which the string will be generated.
- * @param[in] set Set containing the features.
- * @param[out] features_param String which will contain the output.
- * @return 0 on success.
- * @return 1 on error.
+ * @param[in] out The output handler for printing.
+ * @param[in] mod Module which can contains the features.
  */
-int generate_features_output(const struct lys_module *mod, const struct ly_set *set, char **features_param);
+void print_feature_param(struct ly_out *out, const struct lys_module *mod);
 
 /**
  * @brief Print all features of all implemented modules.
  *
  * @param[in] out The output handler for printing.
  * @param[in] ctx Libyang context.
- * @param[in] generate_features Flag expressing whether to generate features parameter.
- * @param[out] features_param String, which will contain the output if the above flag is set.
- * @return 0 on success.
- * @return 1 on error.
+ * @param[in] feature_param Flag expressing whether to print features parameter.
  */
-int print_all_features(struct ly_out *out, const struct ly_ctx *ctx, uint8_t generate_features, char **features_param);
-
+void print_all_features(struct ly_out *out, const struct ly_ctx *ctx, uint8_t feature_param);
 
 #endif /* YL_SCHEMA_FEATURES_H_ */