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