Merge remote-tracking branch 'upstream/libyang2' into libyang2
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index d11c243..8b32c93 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -1,7 +1,7 @@
 /**
  * @file tree_schema_helpers.c
  * @author Radek Krejci <rkrejci@cesnet.cz>
- * @brief Parsing and validation helper functions
+ * @brief Parsing and validation helper functions for schema trees
  *
  * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
  *
@@ -13,18 +13,25 @@
  */
 #include "common.h"
 
+#include <assert.h>
 #include <ctype.h>
-#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <stdint.h>
 #include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
+#include <string.h>
 #include <unistd.h>
 #include <time.h>
 
-#include "libyang.h"
+#include "context.h"
+#include "dict.h"
+#include "extensions.h"
+#include "hash_table.h"
+#include "log.h"
+#include "set.h"
+#include "tree.h"
+#include "tree_schema.h"
 #include "tree_schema_internal.h"
 
 /**
@@ -201,18 +208,18 @@
 }
 
 LY_ERR
-lysp_check_prefix(struct ly_ctx *ctx, uint64_t *line, struct lysp_import *imports, const char *module_prefix, const char **value)
+lysp_check_prefix(struct lys_parser_ctx *ctx, struct lysp_import *imports, const char *module_prefix, const char **value)
 {
     struct lysp_import *i;
 
     if (module_prefix && &module_prefix != value && !strcmp(module_prefix, *value)) {
-        LOGVAL(ctx, LY_VLOG_LINE, line, LYVE_REFERENCE,
+        LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
                "Prefix \"%s\" already used as module prefix.", *value);
         return LY_EEXIST;
     }
     LY_ARRAY_FOR(imports, struct lysp_import, i) {
         if (i->prefix && &i->prefix != value && !strcmp(i->prefix, *value)) {
-            LOGVAL(ctx, LY_VLOG_LINE, line, LYVE_REFERENCE, "Prefix \"%s\" already used to import \"%s\" module.",
+            LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE, "Prefix \"%s\" already used to import \"%s\" module.",
                    *value, i->name);
             return LY_EEXIST;
         }
@@ -244,7 +251,7 @@
 }
 
 LY_ERR
-lysp_check_date(struct ly_parser_ctx *ctx, const char *date, int date_len, const char *stmt)
+lysp_check_date(struct lys_parser_ctx *ctx, const char *date, int date_len, const char *stmt)
 {
     int i;
     struct tm tm, tm_;
@@ -487,7 +494,7 @@
  * @return LY_EEXIST in case of collision, LY_SUCCESS otherwise.
  */
 static LY_ERR
-lysp_check_typedef(struct ly_parser_ctx *ctx, struct lysp_node *node, const struct lysp_tpdf *tpdf,
+lysp_check_typedef(struct lys_parser_ctx *ctx, struct lysp_node *node, const struct lysp_tpdf *tpdf,
                    struct hash_table *tpdfs_global, struct hash_table *tpdfs_scoped)
 {
     struct lysp_node *parent;
@@ -523,7 +530,7 @@
             }
         }
         /* search typedefs in parent's nodes */
-        for (parent = node->parent; parent; parent = node->parent) {
+        for (parent = node->parent; parent; parent = parent->parent) {
             if (lysp_type_match(name, parent)) {
                 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_SYNTAX_YANG,
                        "Invalid name \"%s\" of typedef - name collision with another scoped type.", name);
@@ -562,7 +569,7 @@
 }
 
 LY_ERR
-lysp_check_typedefs(struct ly_parser_ctx *ctx, struct lysp_module *mod)
+lysp_check_typedefs(struct lys_parser_ctx *ctx, struct lysp_module *mod)
 {
     struct hash_table *ids_global;
     struct hash_table *ids_scoped;
@@ -631,7 +638,7 @@
         /* check revision of the parsed model */
         if (!revs || strcmp(info->revision, revs[0].date)) {
             LOGERR(ctx, LY_EINVAL, "Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").", name,
-                   revs[0].date, info->revision);
+                   revs ? revs[0].date : "none", info->revision);
             return LY_EINVAL;
         }
     }
@@ -679,7 +686,7 @@
 }
 
 LY_ERR
-lys_module_localfile(struct ly_ctx *ctx, const char *name, const char *revision, int implement, struct ly_parser_ctx *main_ctx,
+lys_module_localfile(struct ly_ctx *ctx, const char *name, const char *revision, int implement, struct lys_parser_ctx *main_ctx,
                      void **result)
 {
     int fd;
@@ -747,8 +754,18 @@
     if (!*mod) {
         /* try to get the module from the context */
         if (revision) {
+            /* get the specific revision */
             *mod = (struct lys_module*)ly_ctx_get_module(ctx, name, revision);
+        } else if (implement) {
+            /* prefer the implemented module instead of the latest one */
+            *mod = (struct lys_module*)ly_ctx_get_module_implemented(ctx, name);
+            if (!*mod) {
+                /* there is no implemented module in the context, try to get the latest revision module */
+                goto latest_in_the_context;
+            }
         } else {
+            /* get the requested module of the latest revision in the context */
+latest_in_the_context:
             *mod = (struct lys_module*)ly_ctx_get_module_latest(ctx, name);
         }
     }
@@ -836,9 +853,9 @@
 }
 
 LY_ERR
-lysp_load_submodule(struct ly_parser_ctx *ctx, struct lysp_module *mod, struct lysp_include *inc)
+lysp_load_submodule(struct lys_parser_ctx *ctx, struct lysp_module *mod, struct lysp_include *inc)
 {
-    struct lysp_submodule *submod;
+    struct lysp_submodule *submod = NULL;
     const char *submodule_data = NULL;
     LYS_INFORMAT format = LYS_IN_UNKNOWN;
     void (*submodule_data_free)(void *module_data, void *user_data) = NULL;
@@ -939,6 +956,30 @@
 }
 
 const char *
+lys_prefix_find_module(const struct lys_module *mod, const struct lys_module *import)
+{
+    unsigned int u;
+
+    if (import == mod) {
+        return mod->prefix;
+    }
+
+    if (mod->parsed) {
+        LY_ARRAY_FOR(mod->parsed->imports, u) {
+            if (mod->parsed->imports[u].module == import) {
+                return mod->parsed->imports[u].prefix;
+            }
+        }
+    } else {
+        /* we don't have original information about the import's prefix,
+         * so the prefix of the import module itself is returned instead */
+        return import->prefix;
+    }
+
+    return NULL;
+}
+
+const char *
 lys_nodetype2str(uint16_t nodetype)
 {
     switch(nodetype) {
@@ -962,6 +1003,55 @@
         return "RPC/action";
     case LYS_NOTIF:
         return "Notification";
+    case LYS_USES:
+        return "uses";
+    default:
+        return "unknown";
+    }
+}
+
+const char *
+lys_datatype2str(LY_DATA_TYPE basetype)
+{
+    switch(basetype) {
+    case LY_TYPE_BINARY:
+        return "binary";
+    case LY_TYPE_UINT8:
+        return "uint8";
+    case LY_TYPE_UINT16:
+        return "uint16";
+    case LY_TYPE_UINT32:
+        return "uint32";
+    case LY_TYPE_UINT64:
+        return "uint64";
+    case LY_TYPE_STRING:
+        return "string";
+    case LY_TYPE_BITS:
+        return "bits";
+    case LY_TYPE_BOOL:
+        return "boolean";
+    case LY_TYPE_DEC64:
+        return "decimal64";
+    case LY_TYPE_EMPTY:
+        return "empty";
+    case LY_TYPE_ENUM:
+        return "enumeration";
+    case LY_TYPE_IDENT:
+        return "identityref";
+    case LY_TYPE_INST:
+        return "instance-identifier";
+    case LY_TYPE_LEAFREF:
+        return "leafref";
+    case LY_TYPE_UNION:
+        return "union";
+    case LY_TYPE_INT8:
+        return "int8";
+    case LY_TYPE_INT16:
+        return "int16";
+    case LY_TYPE_INT32:
+        return "int32";
+    case LY_TYPE_INT64:
+        return "int64";
     default:
         return "unknown";
     }
@@ -1099,6 +1189,11 @@
 lysp_node_children(const struct lysp_node *node)
 {
     struct lysp_node **children;
+
+    if (!node) {
+        return NULL;
+    }
+
     children = lysp_node_children_p((struct lysp_node*)node);
     if (children) {
         return *children;
@@ -1183,7 +1278,8 @@
             /* LYS_CONFIG_W, but also the default case */
             return &((struct lysc_action*)node)->input.data;
         }
-    /* TODO Notification */
+    case LYS_NOTIF:
+        return &((struct lysc_notif*)node)->data;
     default:
         return NULL;
     }
@@ -1193,6 +1289,11 @@
 lysc_node_children(const struct lysc_node *node, uint16_t flags)
 {
     struct lysc_node **children;
+
+    if (!node) {
+        return NULL;
+    }
+
     children = lysc_node_children_p((struct lysc_node*)node, flags);
     if (children) {
         return *children;
@@ -1407,3 +1508,18 @@
     }
 
 }
+
+unsigned int
+lysp_ext_instance_iter(struct lysp_ext_instance *ext, unsigned int index, LYEXT_SUBSTMT substmt)
+{
+    LY_CHECK_ARG_RET(NULL, ext, LY_EINVAL);
+
+    for (; index < LY_ARRAY_SIZE(ext); index++) {
+        if (ext[index].insubstmt == substmt) {
+            return index;
+        }
+    }
+
+    return LY_ARRAY_SIZE(ext);
+}
+