yanglint FEATURE --yang-library-file for inter-mod
Data file to create an exact YANG schema context is now available
in the interactive mode.
diff --git a/tools/lint/cmd.c b/tools/lint/cmd.c
index 885b689..33734e6 100644
--- a/tools/lint/cmd.c
+++ b/tools/lint/cmd.c
@@ -260,7 +260,7 @@
{"feature", cmd_feature, cmd_feature_help, NULL, "Print all features of module(s) with their state", "haf"},
{"searchpath", cmd_searchpath, cmd_searchpath_help, NULL, "Print/set the search path(s) for schemas", "ch"},
{"extdata", cmd_extdata, cmd_extdata_help, cmd_extdata_free, "Set the specific data required by an extension", "ch"},
- {"clear", cmd_clear, cmd_clear_help, NULL, "Clear the context - remove all the loaded modules", "iyh"},
+ {"clear", cmd_clear, cmd_clear_help, NULL, "Clear the context - remove all the loaded modules", "iyhY:"},
{"verb", cmd_verb, cmd_verb_help, NULL, "Change verbosity", "h"},
#ifndef NDEBUG
{"debug", cmd_debug, cmd_debug_help, NULL, "Display specific debug message groups", "h"},
diff --git a/tools/lint/cmd_clear.c b/tools/lint/cmd_clear.c
index 44b5307..403dc26 100644
--- a/tools/lint/cmd_clear.c
+++ b/tools/lint/cmd_clear.c
@@ -38,11 +38,36 @@
" -y, --yang-library\n"
" Load and implement internal \"ietf-yang-library\" YANG module.\n"
" Note that this module includes definitions of mandatory state\n"
- " data that can result in unexpected data validation errors.\n");
-#if 0
- " If <yang-library-data> path specified, load the modules\n"
- " according to the provided yang library data.\n"
-#endif
+ " data that can result in unexpected data validation errors.\n"
+ " -Y FILE, --yang-library-file=FILE\n"
+ " Parse FILE with \"ietf-yang-library\" data and use them to\n"
+ " create an exact YANG schema context. Searchpaths defined so far\n"
+ " are used, but then deleted.\n");
+}
+
+/**
+ * @brief Convert searchpaths into single string.
+ *
+ * @param[in] ctx Context with searchpaths.
+ * @param[out] searchpaths Collection of paths in the single string. Paths are delimited by colon ":"
+ * (on Windows, used semicolon ";" instead).
+ * @return LY_ERR value.
+ */
+static LY_ERR
+searchpaths_to_str(const struct ly_ctx *ctx, char **searchpaths)
+{
+ uint32_t i;
+ int rc = 0;
+ const char * const *dirs = ly_ctx_get_searchdirs(ctx);
+
+ for (i = 0; dirs[i]; ++i) {
+ rc = searchpath_strcat(searchpaths, dirs[i]);
+ if (!rc) {
+ break;
+ }
+ }
+
+ return rc;
}
void
@@ -52,13 +77,16 @@
char **argv = NULL;
int opt, opt_index;
struct option options[] = {
- {"make-implemented", no_argument, NULL, 'i'},
- {"yang-library", no_argument, NULL, 'y'},
+ {"make-implemented", no_argument, NULL, 'i'},
+ {"yang-library", no_argument, NULL, 'y'},
+ {"yang-library-file", no_argument, NULL, 'Y'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
uint16_t options_ctx = LY_CTX_NO_YANGLIBRARY;
- struct ly_ctx *ctx_new;
+ struct ly_ctx *ctx_new = NULL;
+ char *ylibfile = NULL;
+ char *searchpaths = NULL;
if (parse_cmdline(cmdline, &argc, &argv)) {
goto cleanup;
@@ -77,6 +105,10 @@
case 'y':
options_ctx &= ~LY_CTX_NO_YANGLIBRARY;
break;
+ case 'Y':
+ options_ctx &= ~LY_CTX_NO_YANGLIBRARY;
+ ylibfile = optarg;
+ break;
case 'h':
cmd_clear_help();
goto cleanup;
@@ -86,9 +118,21 @@
}
}
- if (ly_ctx_new(NULL, options_ctx, &ctx_new)) {
- YLMSG_W("Failed to create context.\n");
- goto cleanup;
+ if (ylibfile) {
+ /* Create context according to the provided yang-library data in a file but use already defined searchpaths. */
+ if (searchpaths_to_str(*ctx, &searchpaths)) {
+ YLMSG_E("Storing searchpaths failed.\n");
+ goto cleanup;
+ }
+ if (ly_ctx_new_ylpath(searchpaths, ylibfile, LYD_UNKNOWN, options_ctx, &ctx_new)) {
+ YLMSG_E("Unable to create libyang context with yang-library data.\n");
+ goto cleanup;
+ }
+ } else {
+ if (ly_ctx_new(NULL, options_ctx, &ctx_new)) {
+ YLMSG_W("Failed to create context.\n");
+ goto cleanup;
+ }
}
/* Global variables in commands are also deleted. */
@@ -99,4 +143,5 @@
cleanup:
free_cmdline(argv);
+ free(searchpaths);
}
diff --git a/tools/lint/common.c b/tools/lint/common.c
index f2ff464..96fdb76 100644
--- a/tools/lint/common.c
+++ b/tools/lint/common.c
@@ -954,3 +954,26 @@
*ext_data_free = 1;
return LY_SUCCESS;
}
+
+LY_ERR
+searchpath_strcat(char **searchpaths, const char *path)
+{
+ uint64_t len;
+ char *new;
+
+ if (!(*searchpaths)) {
+ *searchpaths = strdup(path);
+ return LY_SUCCESS;
+ }
+
+ len = strlen(*searchpaths) + strlen(path) + strlen(PATH_SEPARATOR);
+ new = realloc(*searchpaths, sizeof(char) * len + 1);
+ if (!new) {
+ return LY_EMEM;
+ }
+ strcat(new, PATH_SEPARATOR);
+ strcat(new, path);
+ *searchpaths = new;
+
+ return LY_SUCCESS;
+}
diff --git a/tools/lint/common.h b/tools/lint/common.h
index 7e98691..0c7206d 100644
--- a/tools/lint/common.h
+++ b/tools/lint/common.h
@@ -287,4 +287,14 @@
*/
LY_ERR ext_data_clb(const struct lysc_ext_instance *ext, void *user_data, void **ext_data, ly_bool *ext_data_free);
+/**
+ * @brief Concatenation of paths into one string.
+ *
+ * @param[in,out] searchpaths Collection of paths in the single string. Paths are delimited by colon ":"
+ * (on Windows, used semicolon ";" instead).
+ * @param[in] path Path to add.
+ * @return LY_ERR value.
+ */
+LY_ERR searchpath_strcat(char **searchpaths, const char *path);
+
#endif /* COMMON_H_ */
diff --git a/tools/lint/completion.c b/tools/lint/completion.c
index db2704d..3448445 100644
--- a/tools/lint/completion.c
+++ b/tools/lint/completion.c
@@ -414,6 +414,7 @@
{CMD_PRINT, NULL, NULL, get_model_completion},
{CMD_SEARCHPATH, NULL, linenoisePathCompletion, NULL},
{CMD_EXTDATA, NULL, linenoisePathCompletion, NULL},
+ {CMD_CLEAR, "-Y", linenoisePathCompletion, NULL},
{CMD_DATA, "-t", NULL, get_data_type_arg},
{CMD_DATA, "-O", linenoisePathCompletion, NULL},
{CMD_DATA, "-R", linenoisePathCompletion, NULL},
diff --git a/tools/lint/main_ni.c b/tools/lint/main_ni.c
index 2c0ae12..2b016ba 100644
--- a/tools/lint/main_ni.c
+++ b/tools/lint/main_ni.c
@@ -361,29 +361,6 @@
return NULL;
}
-static LY_ERR
-searchpath_strcat(char **searchpaths, const char *path)
-{
- uint64_t len;
- char *new;
-
- if (!(*searchpaths)) {
- *searchpaths = strdup(path);
- return LY_SUCCESS;
- }
-
- len = strlen(*searchpaths) + strlen(path) + strlen(PATH_SEPARATOR);
- new = realloc(*searchpaths, sizeof(char) * len + 1);
- if (!new) {
- return LY_EMEM;
- }
- strcat(new, PATH_SEPARATOR);
- strcat(new, path);
- *searchpaths = new;
-
- return LY_SUCCESS;
-}
-
static int
fill_context_inputs(int argc, char *argv[], struct context *c)
{
diff --git a/tools/lint/tests/interactive/extdata.test b/tools/lint/tests/interactive/extdata.test
index bef06a7..e253d1a 100644
--- a/tools/lint/tests/interactive/extdata.test
+++ b/tools/lint/tests/interactive/extdata.test
@@ -33,6 +33,15 @@
ly_cmd "print -f tree modsm" "--mp root.*--rw lfl/"
}}
+test ext_data_schema_mount_tree_yanglibfile {Print tree output of a model with Schema Mount and --yang-library-file} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -Y $ddir/modsm_ctx_main.xml"
+ ly_cmd "searchpath $mdir"
+ ly_cmd "load modsm"
+ ly_cmd "extdata $ddir/modsm_ctx_ext.xml"
+ ly_cmd "print -f tree modsm" "--mp root.*--rw lfl/.*--rw msa:alf?"
+}}
+
test ext_data_schema_mount_xml {Validating and printing mounted data} {
-setup $ly_setup -cleanup $ly_cleanup -body {
ly_cmd "clear -y"
@@ -42,4 +51,13 @@
ly_cmd "data -f xml -t config $ddir/modsm.xml" "</lfl>"
}}
+test ext_data_schema_mount_xml_yanglibfile {Validating and printing mounted data with --yang-library-file} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -Y $ddir/modsm_ctx_main.xml"
+ ly_cmd "searchpath $mdir"
+ ly_cmd "load modsm"
+ ly_cmd "extdata $ddir/modsm_ctx_ext.xml"
+ ly_cmd "data -f xml -t config $ddir/modsm2.xml" "</lfl>.*</alf>"
+}}
+
cleanupTests