yanglint REFACTOR schema_features in separate file
diff --git a/tools/lint/CMakeLists.txt b/tools/lint/CMakeLists.txt
index 9ff39b2..f333bef 100644
--- a/tools/lint/CMakeLists.txt
+++ b/tools/lint/CMakeLists.txt
@@ -22,6 +22,7 @@
cmd_verb.c
cmd_debug.c
yl_opt.c
+ yl_schema_features.c
common.c
)
if(YANGLINT_INTERACTIVE)
diff --git a/tools/lint/cmd_add.c b/tools/lint/cmd_add.c
index 3b2acd4..6a9af8d 100644
--- a/tools/lint/cmd_add.c
+++ b/tools/lint/cmd_add.c
@@ -28,6 +28,7 @@
#include "common.h"
#include "yl_opt.h"
+#include "yl_schema_features.h"
void
cmd_add_help(void)
diff --git a/tools/lint/cmd_feature.c b/tools/lint/cmd_feature.c
index 09f8a29..d204c90 100644
--- a/tools/lint/cmd_feature.c
+++ b/tools/lint/cmd_feature.c
@@ -25,6 +25,7 @@
#include "common.h"
#include "yl_opt.h"
+#include "yl_schema_features.h"
void
cmd_feature_help(void)
diff --git a/tools/lint/cmd_load.c b/tools/lint/cmd_load.c
index fe56d84..f7457c8 100644
--- a/tools/lint/cmd_load.c
+++ b/tools/lint/cmd_load.c
@@ -28,6 +28,7 @@
#include "common.h"
#include "yl_opt.h"
+#include "yl_schema_features.h"
void
cmd_load_help(void)
diff --git a/tools/lint/common.c b/tools/lint/common.c
index 44dd9b4..bdf96e6 100644
--- a/tools/lint/common.c
+++ b/tools/lint/common.c
@@ -20,7 +20,6 @@
#include <assert.h>
#include <errno.h>
-#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -88,245 +87,6 @@
return 0;
}
-void
-free_features(void *flist)
-{
- struct schema_features *rec = (struct schema_features *)flist;
-
- if (rec) {
- free(rec->mod_name);
- if (rec->features) {
- for (uint32_t u = 0; rec->features[u]; ++u) {
- free(rec->features[u]);
- }
- free(rec->features);
- }
- free(rec);
- }
-}
-
-void
-get_features(const struct ly_set *fset, const char *module, const char ***features)
-{
- /* get features list for this module */
- for (uint32_t u = 0; u < fset->count; ++u) {
- struct schema_features *sf = (struct schema_features *)fset->objs[u];
-
- if (!strcmp(module, sf->mod_name)) {
- /* matched module - explicitly set features */
- *features = (const char **)sf->features;
- sf->applied = 1;
- return;
- }
- }
-
- /* features not set so disable all */
- *features = NULL;
-}
-
-int
-parse_features(const char *fstring, struct ly_set *fset)
-{
- struct schema_features *rec;
- uint32_t count;
- char *p, **fp;
-
- rec = calloc(1, sizeof *rec);
- if (!rec) {
- YLMSG_E("Unable to allocate features information record (%s).\n", strerror(errno));
- return -1;
- }
- if (ly_set_add(fset, rec, 1, NULL)) {
- YLMSG_E("Unable to store features information (%s).\n", strerror(errno));
- free(rec);
- return -1;
- }
-
- /* fill the record */
- p = strchr(fstring, ':');
- if (!p) {
- YLMSG_E("Invalid format of the features specification (%s).\n", fstring);
- return -1;
- }
- rec->mod_name = strndup(fstring, p - fstring);
-
- count = 0;
- while (p) {
- size_t len = 0;
- char *token = p + 1;
-
- p = strchr(token, ',');
- if (!p) {
- /* the last item, if any */
- len = strlen(token);
- } else {
- len = p - token;
- }
-
- if (len) {
- fp = realloc(rec->features, (count + 1) * sizeof *rec->features);
- if (!fp) {
- YLMSG_E("Unable to store features list information (%s).\n", strerror(errno));
- return -1;
- }
- rec->features = fp;
- fp = &rec->features[count++]; /* array item to set */
- (*fp) = strndup(token, len);
- }
- }
-
- /* terminating NULL */
- fp = realloc(rec->features, (count + 1) * sizeof *rec->features);
- if (!fp) {
- YLMSG_E("Unable to store features list information (%s).\n", strerror(errno));
- return -1;
- }
- rec->features = fp;
- rec->features[count++] = NULL;
-
- 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)
-{
- size_t max_len;
- uint32_t j;
- const char *name;
-
- /* header */
- ly_print(out, "%s:\n", mod->name);
-
- /* no features */
- if (!set->count) {
- ly_print(out, "\t(none)\n\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");
- }
-
- ly_print(out, "\n");
-}
-
-int
-generate_features_output(const struct lys_module *mod, const struct ly_set *set, char **features_param)
-{
- 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;
-
- 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, ",");
- }
- }
-
- 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, ly_bool generate_features, char **features_param)
-{
- int ret = 0;
- uint32_t i = 0;
- struct lys_module *mod;
- struct ly_set set = {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 (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;
-}
-
LYS_INFORMAT
get_schema_format(const char *filename)
{
diff --git a/tools/lint/common.h b/tools/lint/common.h
index 0684daa..340cecd 100644
--- a/tools/lint/common.h
+++ b/tools/lint/common.h
@@ -59,82 +59,6 @@
struct cmdline_file;
/**
- * @brief Storage for the list of the features (their names) in a specific YANG module.
- */
-struct schema_features {
- char *mod_name;
- char **features;
- ly_bool applied;
-};
-
-/**
- * @brief Free the schema features list (struct schema_features *)
- * @param[in,out] flist The (struct schema_features *) to free.
- */
-void free_features(void *flist);
-
-/**
- * @brief Get the list of features connected with the specific YANG module.
- *
- * @param[in] fset The set of features information (struct schema_features *).
- * @param[in] module Name of the YANG module which features should be found.
- * @param[out] features Pointer to the list of features being returned.
- */
-void get_features(const struct ly_set *fset, const char *module, const char ***features);
-
-/**
- * @brief Parse features being specified for the specific YANG module.
- *
- * Format of the input @p fstring is as follows: "<module_name>:[<feature>,]*"
- *
- * @param[in] fstring Input string to be parsed.
- * @param[in, out] fset Features information set (of struct schema_features *). The set is being filled.
- */
-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.
- */
-void print_features(struct ly_out *out, const struct lys_module *mod, const struct ly_set *set);
-
-/**
- * @brief Generate a string, which will contain features paramater.
- *
- * @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.
- */
-int generate_features_output(const struct lys_module *mod, const struct ly_set *set, char **features_param);
-
-/**
- * @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.
- */
-int print_all_features(struct ly_out *out, const struct ly_ctx *ctx, ly_bool generate_features, char **features_param);
-
-/**
* @brief Parse path of a schema module file into the directory and module name.
*
* @param[in] path Schema module file path to be parsed.
diff --git a/tools/lint/main_ni.c b/tools/lint/main_ni.c
index b7d821f..71a0639 100644
--- a/tools/lint/main_ni.c
+++ b/tools/lint/main_ni.c
@@ -32,6 +32,7 @@
#include "out.h"
#include "tools/config.h"
#include "yl_opt.h"
+#include "yl_schema_features.h"
static void
version(void)
@@ -274,7 +275,7 @@
{
if (yang_lib_file) {
/* ignore features */
- ly_set_erase(schema_features, free_features);
+ ly_set_erase(schema_features, yl_schema_features_free);
if (ly_ctx_new_ylpath(searchpaths, yang_lib_file, LYD_UNKNOWN, *ctx_options, ctx)) {
YLMSG_E("Unable to modify libyang context with yang-library data.\n");
diff --git a/tools/lint/yl_opt.c b/tools/lint/yl_opt.c
index 20fbf1f..67aff0e 100644
--- a/tools/lint/yl_opt.c
+++ b/tools/lint/yl_opt.c
@@ -23,6 +23,7 @@
#include "common.h"
#include "yl_opt.h"
+#include "yl_schema_features.h"
struct cmdline_file *
fill_cmdline_file(struct ly_set *set, struct ly_in *in, const char *path, LYD_FORMAT format)
@@ -79,7 +80,7 @@
ly_set_erase(&yo->data_xpath, NULL);
/* schema */
- ly_set_erase(&yo->schema_features, free_features);
+ ly_set_erase(&yo->schema_features, yl_schema_features_free);
ly_set_erase(&yo->schema_modules, NULL);
free(yo->features_output);
diff --git a/tools/lint/yl_schema_features.c b/tools/lint/yl_schema_features.c
new file mode 100644
index 0000000..52c75e7
--- /dev/null
+++ b/tools/lint/yl_schema_features.c
@@ -0,0 +1,264 @@
+/**
+ * @file yl_schema_features.c
+ * @author Adam Piecek <piecek@cesnet.cz>
+ * @brief Control features for the schema.
+ *
+ * Copyright (c) 2023 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <stdlib.h> /* calloc */
+#include <string.h> /* strcmp */
+
+#include "compat.h" /* strndup */
+#include "set.h" /* ly_set */
+
+#include "common.h"
+#include "yl_schema_features.h"
+
+void
+yl_schema_features_free(void *flist)
+{
+ struct schema_features *rec = (struct schema_features *)flist;
+
+ if (rec) {
+ free(rec->mod_name);
+ if (rec->features) {
+ for (uint32_t u = 0; rec->features[u]; ++u) {
+ free(rec->features[u]);
+ }
+ free(rec->features);
+ }
+ free(rec);
+ }
+}
+
+void
+get_features(const struct ly_set *fset, const char *module, const char ***features)
+{
+ /* get features list for this module */
+ for (uint32_t u = 0; u < fset->count; ++u) {
+ struct schema_features *sf = (struct schema_features *)fset->objs[u];
+
+ if (!strcmp(module, sf->mod_name)) {
+ /* matched module - explicitly set features */
+ *features = (const char **)sf->features;
+ sf->applied = 1;
+ return;
+ }
+ }
+
+ /* features not set so disable all */
+ *features = NULL;
+}
+
+int
+parse_features(const char *fstring, struct ly_set *fset)
+{
+ struct schema_features *rec;
+ uint32_t count;
+ char *p, **fp;
+
+ rec = calloc(1, sizeof *rec);
+ if (!rec) {
+ YLMSG_E("Unable to allocate features information record (%s).\n", strerror(errno));
+ return -1;
+ }
+ if (ly_set_add(fset, rec, 1, NULL)) {
+ YLMSG_E("Unable to store features information (%s).\n", strerror(errno));
+ free(rec);
+ return -1;
+ }
+
+ /* fill the record */
+ p = strchr(fstring, ':');
+ if (!p) {
+ YLMSG_E("Invalid format of the features specification (%s).\n", fstring);
+ return -1;
+ }
+ rec->mod_name = strndup(fstring, p - fstring);
+
+ count = 0;
+ while (p) {
+ size_t len = 0;
+ char *token = p + 1;
+
+ p = strchr(token, ',');
+ if (!p) {
+ /* the last item, if any */
+ len = strlen(token);
+ } else {
+ len = p - token;
+ }
+
+ if (len) {
+ fp = realloc(rec->features, (count + 1) * sizeof *rec->features);
+ if (!fp) {
+ YLMSG_E("Unable to store features list information (%s).\n", strerror(errno));
+ return -1;
+ }
+ rec->features = fp;
+ fp = &rec->features[count++]; /* array item to set */
+ (*fp) = strndup(token, len);
+ }
+ }
+
+ /* terminating NULL */
+ fp = realloc(rec->features, (count + 1) * sizeof *rec->features);
+ if (!fp) {
+ YLMSG_E("Unable to store features list information (%s).\n", strerror(errno));
+ return -1;
+ }
+ rec->features = fp;
+ rec->features[count++] = NULL;
+
+ 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)
+{
+ size_t max_len;
+ uint32_t j;
+ const char *name;
+
+ /* header */
+ ly_print(out, "%s:\n", mod->name);
+
+ /* no features */
+ if (!set->count) {
+ ly_print(out, "\t(none)\n\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");
+ }
+
+ ly_print(out, "\n");
+}
+
+int
+generate_features_output(const struct lys_module *mod, const struct ly_set *set, char **features_param)
+{
+ 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;
+
+ 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, ",");
+ }
+ }
+
+ 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)
+{
+ int ret = 0;
+ uint32_t i = 0;
+ struct lys_module *mod;
+ struct ly_set set = {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 (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;
+}
diff --git a/tools/lint/yl_schema_features.h b/tools/lint/yl_schema_features.h
new file mode 100644
index 0000000..b697dcc
--- /dev/null
+++ b/tools/lint/yl_schema_features.h
@@ -0,0 +1,102 @@
+/**
+ * @file yl_schema_features.h
+ * @author Adam Piecek <piecek@cesnet.cz>
+ * @brief Control features for the schema.
+ *
+ * Copyright (c) 2023 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#ifndef YL_SCHEMA_FEATURES_H_
+#define YL_SCHEMA_FEATURES_H_
+
+#include <stdint.h>
+
+struct ly_set;
+struct lys_module;
+struct ly_out;
+struct ly_ctx;
+
+/**
+ * @brief Storage for the list of the features (their names) in a specific YANG module.
+ */
+struct schema_features {
+ char *mod_name;
+ char **features;
+ uint8_t applied;
+};
+
+/**
+ * @brief Free the schema features list (struct schema_features *)
+ * @param[in,out] flist The (struct schema_features *) to free.
+ */
+void yl_schema_features_free(void *flist);
+
+/**
+ * @brief Get the list of features connected with the specific YANG module.
+ *
+ * @param[in] fset The set of features information (struct schema_features *).
+ * @param[in] module Name of the YANG module which features should be found.
+ * @param[out] features Pointer to the list of features being returned.
+ */
+void get_features(const struct ly_set *fset, const char *module, const char ***features);
+
+/**
+ * @brief Parse features being specified for the specific YANG module.
+ *
+ * Format of the input @p fstring is as follows: "<module_name>:[<feature>,]*"
+ *
+ * @param[in] fstring Input string to be parsed.
+ * @param[in, out] fset Features information set (of struct schema_features *). The set is being filled.
+ */
+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.
+ */
+void print_features(struct ly_out *out, const struct lys_module *mod, const struct ly_set *set);
+
+/**
+ * @brief Generate a string, which will contain features paramater.
+ *
+ * @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.
+ */
+int generate_features_output(const struct lys_module *mod, const struct ly_set *set, char **features_param);
+
+/**
+ * @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.
+ */
+int print_all_features(struct ly_out *out, const struct ly_ctx *ctx, uint8_t generate_features, char **features_param);
+
+
+#endif /* YL_SCHEMA_FEATURES_H_ */