CHANGE ietf-yang-library model updated from a draft in LC
diff --git a/src/context.c b/src/context.c
index b48b71a..46d54e4 100644
--- a/src/context.c
+++ b/src/context.c
@@ -41,8 +41,8 @@
 #define IETF_INET_TYPES_PATH "../models/ietf-inet-types@2013-07-15.h"
 #define IETF_YANG_TYPES_PATH "../models/ietf-yang-types@2013-07-15.h"
 #define IETF_DATASTORES "../models/ietf-datastores@2017-08-17.h"
-#define IETF_YANG_LIB_PATH "../models/ietf-yang-library@2017-08-17.h"
-#define IETF_YANG_LIB_REV "2017-08-17"
+#define IETF_YANG_LIB_PATH "../models/ietf-yang-library@2018-01-17.h"
+#define IETF_YANG_LIB_REV "2018-01-17"
 
 #include IETF_YANG_METADATA_PATH
 #include YANG_PATH
@@ -65,7 +65,7 @@
     {"ietf-yang-types", "2013-07-15", (const char*)ietf_yang_types_2013_07_15_yin, 0, LYS_IN_YIN},
     /* ietf-datastores and ietf-yang-library must be right here at the end of the list! */
     {"ietf-datastores", "2017-08-17", (const char*)ietf_datastores_2017_08_17_yin, 0, LYS_IN_YIN},
-    {"ietf-yang-library", IETF_YANG_LIB_REV, (const char*)ietf_yang_library_2017_08_17_yin, 1, LYS_IN_YIN}
+    {"ietf-yang-library", IETF_YANG_LIB_REV, (const char*)ietf_yang_library_2018_01_17_yin, 1, LYS_IN_YIN}
 };
 
 API unsigned int
@@ -151,34 +151,19 @@
     return NULL;
 }
 
-static struct ly_ctx *
-ly_ctx_new_yl_common(const char *search_dir, const char *input, LYD_FORMAT format, int options,
-                     struct lyd_node* (*parser_func)(struct ly_ctx*, const char*, LYD_FORMAT, int,...))
+static int
+ly_ctx_new_yl_legacy(struct ly_ctx *ctx, struct lyd_node *yltree)
 {
     unsigned int i, u;
     struct lyd_node *module, *node;
+    struct ly_set *set;
     const char *name, *revision;
     struct ly_set features = {0, 0, {NULL}};
     const struct lys_module *mod;
-    struct lyd_node *yltree = NULL;
-    struct ly_ctx *ctx = NULL;
-    struct ly_set *set = NULL;
 
-    /* create empty (with internal modules including ietf-yang-library) context */
-    ctx = ly_ctx_new(search_dir, options);
-    if (!ctx) {
-        goto error;
-    }
-
-    /* parse yang library data tree */
-    yltree = parser_func(ctx, input, format, LYD_OPT_DATA, NULL);
-    if (!yltree) {
-        goto error;
-    }
-
-    set = lyd_find_path(yltree, "/ietf-yang-library:yang-library/modules/module");
+    set = lyd_find_path(yltree, "/ietf-yang-library:yang-library/modules-state/module");
     if (!set) {
-        goto error;
+        return 1;
     }
 
     /* process the data tree */
@@ -209,7 +194,8 @@
         mod = ly_ctx_load_module(ctx, name, revision);
         if (!mod) {
             LOGERR(LY_EINVAL, "Unable to load module specified by yang library data.");
-            goto error;
+            ly_set_free(set);
+            return 1;
         }
 
         /* set features */
@@ -218,6 +204,79 @@
         }
     }
 
+    ly_set_free(set);
+    return 0;
+}
+
+static struct ly_ctx *
+ly_ctx_new_yl_common(const char *search_dir, const char *input, LYD_FORMAT format, int options,
+                     struct lyd_node* (*parser_func)(struct ly_ctx*, const char*, LYD_FORMAT, int,...))
+{
+    unsigned int i, u;
+    struct lyd_node *module, *node;
+    const char *name, *revision;
+    struct ly_set features = {0, 0, {NULL}};
+    const struct lys_module *mod;
+    struct lyd_node *yltree = NULL;
+    struct ly_ctx *ctx = NULL;
+    struct ly_set *set = NULL;
+
+    /* create empty (with internal modules including ietf-yang-library) context */
+    ctx = ly_ctx_new(search_dir, options);
+    if (!ctx) {
+        goto error;
+    }
+
+    /* parse yang library data tree */
+    yltree = parser_func(ctx, input, format, LYD_OPT_DATA, NULL);
+    if (!yltree) {
+        goto error;
+    }
+
+    set = lyd_find_path(yltree, "/ietf-yang-library:yang-library/module-set[1]/module");
+    if (!set) {
+        goto error;
+    }
+
+    if (set->number == 0) {
+        /* perhaps a legacy data tree? */
+        if (ly_ctx_new_yl_legacy(ctx, yltree)) {
+            goto error;
+        }
+    } else {
+        /* process the data tree */
+        for (i = 0; i < set->number; ++i) {
+            module = set->set.d[i];
+
+            /* initiate */
+            name = NULL;
+            revision = NULL;
+            ly_set_clean(&features);
+
+            LY_TREE_FOR(module->child, node) {
+                if (!strcmp(node->schema->name, "name")) {
+                    name = ((struct lyd_node_leaf_list*)node)->value_str;
+                } else if (!strcmp(node->schema->name, "revision")) {
+                    revision = ((struct lyd_node_leaf_list*)node)->value_str;
+                } else if (!strcmp(node->schema->name, "feature")) {
+                    ly_set_add(&features, node->child, LY_SET_OPT_USEASLIST);
+                }
+            }
+
+            /* use the gathered data to load the module */
+            mod = ly_ctx_load_module(ctx, name, revision);
+            if (!mod) {
+                LOGERR(LY_EINVAL, "Unable to load module specified by yang library data.");
+                goto error;
+            }
+
+            /* set features */
+            for (u = 0; u < features.number; u++) {
+                lys_features_enable(mod, ((struct lyd_node_leaf_list*)features.set.d[u])->value_str);
+            }
+        }
+    }
+
     if (0) {
         /* skip context destroy in case of success */
 error:
@@ -1402,9 +1461,10 @@
 }
 
 static int
-ylib_feature(struct lyd_node *parent, struct lys_module *cur_mod)
+ylib_feature(struct lyd_node *parent, struct lys_module *cur_mod, int bis)
 {
     int i, j;
+    struct lyd_node *list;
 
     /* module features */
     for (i = 0; i < cur_mod->features_size; ++i) {
@@ -1412,7 +1472,11 @@
             continue;
         }
 
-        if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->features[i].name)) {
+        if (bis) {
+            if (!(list = lyd_new(parent, NULL, "feature")) || !lyd_new_leaf(list, NULL, "name", cur_mod->features[i].name)) {
+                return EXIT_FAILURE;
+            }
+        } else if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->features[i].name)) {
             return EXIT_FAILURE;
         }
     }
@@ -1424,7 +1488,12 @@
                 continue;
             }
 
-            if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->inc[i].submodule->features[j].name)) {
+            if (bis) {
+                if (!(list = lyd_new(parent, NULL, "feature"))
+                        || !lyd_new_leaf(list, NULL, "name", cur_mod->inc[i].submodule->features[j].name)) {
+                    return EXIT_FAILURE;
+                }
+            } else if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->inc[i].submodule->features[j].name)) {
                 return EXIT_FAILURE;
             }
         }
@@ -1434,7 +1503,7 @@
 }
 
 static int
-ylib_deviation(struct lyd_node *parent, struct lys_module *cur_mod)
+ylib_deviation(struct lyd_node *parent, struct lys_module *cur_mod, int bis)
 {
     uint32_t i = 0, j;
     const struct lys_module *mod;
@@ -1455,11 +1524,17 @@
                         return EXIT_FAILURE;
                     }
 
-                    if (!lyd_new_leaf(cont, NULL, "name", mod->name)) {
-                        return EXIT_FAILURE;
-                    }
-                    if (!lyd_new_leaf(cont, NULL, "revision", (mod->rev_size ? mod->rev[0].date : ""))) {
-                        return EXIT_FAILURE;
+                    if (bis) {
+                        if (!lyd_new_leaf(cont, NULL, "module", mod->name)) {
+                            return EXIT_FAILURE;
+                        }
+                    } else {
+                        if (!lyd_new_leaf(cont, NULL, "name", mod->name)) {
+                            return EXIT_FAILURE;
+                        }
+                        if (!lyd_new_leaf(cont, NULL, "revision", (mod->rev_size ? mod->rev[0].date : ""))) {
+                            return EXIT_FAILURE;
+                        }
                     }
 
                     break;
@@ -1472,7 +1547,7 @@
 }
 
 static int
-ylib_submodules(struct lyd_node *parent, struct lys_module *cur_mod)
+ylib_submodules(struct lyd_node *parent, struct lys_module *cur_mod, int bis)
 {
     int i;
     char *str;
@@ -1487,15 +1562,16 @@
         if (!lyd_new_leaf(item, NULL, "name", cur_mod->inc[i].submodule->name)) {
             return EXIT_FAILURE;
         }
-        if (!lyd_new_leaf(item, NULL, "revision", (cur_mod->inc[i].submodule->rev_size ?
-                          cur_mod->inc[i].submodule->rev[0].date : ""))) {
+        if ((!bis || cur_mod->inc[i].submodule->rev_size)
+                && !lyd_new_leaf(item, NULL, "revision",
+                    (cur_mod->inc[i].submodule->rev_size ? cur_mod->inc[i].submodule->rev[0].date : ""))) {
             return EXIT_FAILURE;
         }
         if (cur_mod->inc[i].submodule->filepath) {
             if (asprintf(&str, "file://%s", cur_mod->inc[i].submodule->filepath) == -1) {
                 LOGMEM;
                 return EXIT_FAILURE;
-            } else if (!lyd_new_leaf(item, NULL, "schema", str)) {
+            } else if (!lyd_new_leaf(item, NULL, bis ? "location" : "schema", str)) {
                 free(str);
                 return EXIT_FAILURE;
             }
@@ -1513,7 +1589,7 @@
     char id[8];
     char *str;
     const struct lys_module *mod;
-    struct lyd_node *root, *root_bis = NULL, *cont = NULL, *cont_bis = NULL;
+    struct lyd_node *root, *root_bis = NULL, *cont = NULL, *set_bis = NULL;
 
     if (!ctx) {
         ly_errno = LY_EINVAL;
@@ -1525,7 +1601,7 @@
         LOGERR(LY_EINVAL, "ietf-yang-library is not implemented.");
         return NULL;
     }
-    if (mod->rev && !strcmp(mod->rev[0].date, "2016-06-21")) {
+    if (mod->rev && !strcmp(mod->rev[0].date, "2016-04-09")) {
         bis = 0;
     } else if (mod->rev && !strcmp(mod->rev[0].date, IETF_YANG_LIB_REV)) {
         bis = 1;
@@ -1540,8 +1616,16 @@
     }
 
     if (bis) {
-        root_bis = lyd_new(NULL, mod, "yang-library");
-        if (!root_bis || !lyd_new(root_bis, mod, "modules") || !lyd_new(root_bis, mod, "module-sets")) {
+        if (!(root_bis = lyd_new(NULL, mod, "yang-library")) || !(set_bis = lyd_new(root_bis, NULL, "module-set"))) {
+            goto error;
+        }
+
+        if (!lyd_new_leaf(set_bis, NULL, "name", "complete")) {
+            goto error;
+        }
+
+        sprintf(id, "%u", ctx->models.module_set_id);
+        if (!lyd_new_leaf(set_bis, NULL, "checksum", id)) {
             goto error;
         }
     }
@@ -1552,36 +1636,19 @@
             continue;
         }
 
-        cont = lyd_new(root, mod, "module");
+        /*
+         * deprecated legacy
+         */
+        cont = lyd_new(root, NULL, "module");
         if (!cont) {
             goto error;
         }
-        if (bis) {
-            if (!(cont_bis = lyd_new(root_bis->child, mod, "module"))) {
-                goto error;
-            }
-
-            /* id is present only in yang-library container */
-            sprintf(id, "%d", i);
-            if (!lyd_new_leaf(cont_bis, mod, "id", id)) {
-                goto error;
-            }
-        }
-
         /* name */
-        if (!lyd_new_leaf(cont, mod, "name", ctx->models.list[i]->name)) {
-            goto error;
-        }
-        if (bis && !lyd_new_leaf(cont_bis, mod, "name", ctx->models.list[i]->name)) {
+        if (!lyd_new_leaf(cont, NULL, "name", ctx->models.list[i]->name)) {
             goto error;
         }
         /* revision */
-        if (!lyd_new_leaf(cont, mod, "revision", (ctx->models.list[i]->rev_size ?
-                              ctx->models.list[i]->rev[0].date : ""))) {
-            goto error;
-        }
-        if (bis && !lyd_new_leaf(cont_bis, mod, "revision", (ctx->models.list[i]->rev_size ?
-                                 ctx->models.list[i]->rev[0].date : ""))) {
+        if (!lyd_new_leaf(cont, NULL, "revision", (ctx->models.list[i]->rev_size ? ctx->models.list[i]->rev[0].date : ""))) {
             goto error;
         }
         /* schema */
@@ -1590,77 +1657,93 @@
                 LOGMEM;
                 goto error;
             }
-            if (!lyd_new_leaf(cont, mod, "schema", str)) {
-                free(str);
-                goto error;
-            }
-            if (bis && !lyd_new_leaf(cont_bis, mod, "schema", str)) {
+            if (!lyd_new_leaf(cont, NULL, "schema", str)) {
                 free(str);
                 goto error;
             }
             free(str);
         }
         /* namespace */
-        if (!lyd_new_leaf(cont, mod, "namespace", ctx->models.list[i]->ns)) {
-            goto error;
-        }
-        if (bis && !lyd_new_leaf(cont_bis, mod, "namespace", ctx->models.list[i]->ns)) {
+        if (!lyd_new_leaf(cont, NULL, "namespace", ctx->models.list[i]->ns)) {
             goto error;
         }
         /* feature leaf-list */
-        if (ylib_feature(cont, ctx->models.list[i])) {
-            goto error;
-        }
-        if (bis && ylib_feature(cont_bis, ctx->models.list[i])) {
+        if (ylib_feature(cont, ctx->models.list[i], 0)) {
             goto error;
         }
         /* deviation list */
-        if (ylib_deviation(cont, ctx->models.list[i])) {
-            goto error;
-        }
-        if (bis && ylib_deviation(cont_bis, ctx->models.list[i])) {
+        if (ylib_deviation(cont, ctx->models.list[i], 0)) {
             goto error;
         }
         /* conformance-type */
-        if (!lyd_new_leaf(cont, mod, "conformance-type",
-                          ctx->models.list[i]->implemented ? "implement" : "import")) {
-            goto error;
-        }
-        if (bis && !lyd_new_leaf(cont_bis, mod, "conformance-type",
-                                 ctx->models.list[i]->implemented ? "implement" : "import")) {
+        if (!lyd_new_leaf(cont, NULL, "conformance-type", ctx->models.list[i]->implemented ? "implement" : "import")) {
             goto error;
         }
         /* submodule list */
-        if (ylib_submodules(cont, ctx->models.list[i])) {
+        if (ylib_submodules(cont, ctx->models.list[i], 0)) {
             goto error;
         }
-        if (bis && ylib_submodules(cont_bis, ctx->models.list[i])) {
-            goto error;
-        }
-    }
 
-    if (bis) {
-        /* module-sets - libyang currently has just one module set with all modules */
-        if (!(cont_bis = lyd_new(root_bis->child->next, mod, "module-set"))) {
-            goto error;
-        }
-        if (!lyd_new_leaf(cont_bis, mod, "id", "complete")) {
-            goto error;
-        }
-        /* refer all modules */
-        for (i = 0; i < ctx->models.used; ++i) {
-            sprintf(id, "%d", i);
-            if (!lyd_new_leaf(cont_bis, mod, "module", id)) {
+        /*
+         * current revision
+         */
+        if (bis) {
+            if (ctx->models.list[i]->implemented) {
+                if (!(cont = lyd_new(set_bis, NULL, "module"))) {
+                    goto error;
+                }
+            } else {
+                if (!(cont = lyd_new(set_bis, NULL, "import-only-module"))) {
+                    goto error;
+                }
+            }
+            /* name */
+            if (!lyd_new_leaf(cont, NULL, "name", ctx->models.list[i]->name)) {
                 goto error;
             }
+            /* revision */
+            if ((!ctx->models.list[i]->implemented || ctx->models.list[i]->rev_size)
+                    && !lyd_new_leaf(cont, NULL, "revision", ctx->models.list[i]->rev[0].date)) {
+                goto error;
+            }
+            /* namespace */
+            if (!lyd_new_leaf(cont, NULL, "namespace", ctx->models.list[i]->ns)) {
+                goto error;
+            }
+            /* location */
+            if (ctx->models.list[i]->filepath) {
+                if (asprintf(&str, "file://%s", ctx->models.list[i]->filepath) == -1) {
+                    LOGMEM;
+                    goto error;
+                }
+                if (!lyd_new_leaf(cont, NULL, "location", str)) {
+                    free(str);
+                    goto error;
+                }
+                free(str);
+            }
+            /* submodule list */
+            if (ylib_submodules(cont, ctx->models.list[i], 1)) {
+                goto error;
+            }
+            if (ctx->models.list[i]->implemented) {
+                /* feature list */
+                if (ylib_feature(cont, ctx->models.list[i], 1)) {
+                    goto error;
+                }
+                /* deviation */
+                if (ylib_deviation(cont, ctx->models.list[i], 1)) {
+                    goto error;
+                }
+            }
         }
     }
 
     sprintf(id, "%u", ctx->models.module_set_id);
-    if (!lyd_new_leaf(root, mod, "module-set-id", id)) {
+    if (!lyd_new_leaf(root, NULL, "module-set-id", id)) {
         goto error;
     }
-    if (bis && !lyd_new_leaf(root_bis, mod, "checksum", id)) {
+    if (bis && !lyd_new_leaf(root_bis, NULL, "checksum", id)) {
         goto error;
     }
 
diff --git a/src/libyang.h.in b/src/libyang.h.in
index 36899c3..0d6a959 100644
--- a/src/libyang.h.in
+++ b/src/libyang.h.in
@@ -1060,7 +1060,7 @@
                                         causes that function ly_ctx_info() does not work (returns NULL) until
                                         the ietf-yang-library module is loaded manually. While any revision
                                         of this schema can be loaded with this option, note that the only
-                                        revisions implemented by ly_ctx_info() are 2016-06-21 and 2017-08-17.
+                                        revisions implemented by ly_ctx_info() are 2016-04-09 and 2018-01-17.
                                         This option cannot be used with ly_ctx_new_yl*() functions. */
 
 /**@} contextoptions */
@@ -1096,6 +1096,10 @@
  * ly_ctx_new() by loading modules specified in the ietf-yang-library form into the context
  * being created.
  *
+ * The preferred tree model revision is 2018-01-17. However, only the first module-set is processed
+ * and loaded into the context. If there are no matching nodes from this tree, the legacy tree
+ * (originally from model revision 2016-04-09) is processed.
+ *
  * Note, that the modules are loaded the same way as in case of ly_ctx_load_module(), so the schema
  * paths in the yang-library data are ignored and the modules are loaded from the context's search
  * locations. On the other hand, YANG features of the modules are set as specified in the yang-library
@@ -1120,6 +1124,10 @@
  * ly_ctx_new() by loading modules specified in the ietf-yang-library form into the context
  * being created.
  *
+ * The preferred tree model revision is 2018-01-17. However, only the first module-set is processed
+ * and loaded into the context. If there are no matching nodes from this tree, the legacy tree
+ * (originally from model revision 2016-04-09) is processed.
+ *
  * Note, that the modules are loaded the same way as in case of ly_ctx_load_module(), so the schema
  * paths in the yang-library data are ignored and the modules are loaded from the context's search
  * locations. On the other hand, YANG features of the modules are set as specified in the yang-library