diff UPDATE specific messages for errors in diff

Refs #1771
diff --git a/src/diff.c b/src/diff.c
index 889ad51..6bbba7f 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -35,6 +35,35 @@
 #include "tree_schema.h"
 #include "tree_schema_internal.h"
 
+#define LOGERR_META(ctx, meta_name, node) \
+        { \
+            char *__path = lyd_path(node, LYD_PATH_STD, NULL, 0); \
+            LOGERR(ctx, LY_EINVAL, "Failed to find metadata \"%s\" for node \"%s\".", meta_name, __path); \
+            free(__path); \
+        }
+
+#define LOGERR_NOINST(ctx, node) \
+        { \
+            char *__path = lyd_path(node, LYD_PATH_STD, NULL, 0); \
+            LOGERR(ctx, LY_EINVAL, "Failed to find node \"%s\" instance in data.", __path); \
+            free(__path); \
+        }
+
+#define LOGERR_UNEXPVAL(ctx, node, data_source) \
+        { \
+            char *__path = lyd_path(node, LYD_PATH_STD, NULL, 0); \
+            LOGERR(ctx, LY_EINVAL, "Unexpected value of node \"%s\" in %s.", __path, data_source); \
+            free(__path); \
+        }
+
+#define LOGERR_MERGEOP(ctx, node, src_op, trg_op) \
+        { \
+            char *__path = lyd_path(node, LYD_PATH_STD, NULL, 0); \
+            LOGERR(ctx, LY_EINVAL, "Unable to merge operation \"%s\" with \"%s\" for node \"%s\".", \
+                    lyd_diff_op2str(trg_op), lyd_diff_op2str(src_op), __path); \
+            free(__path); \
+        }
+
 static const char *
 lyd_diff_op2str(enum lyd_diff_op op)
 {
@@ -813,6 +842,7 @@
     struct lyd_meta *meta = NULL;
     const struct lyd_node *diff_parent;
     const char *str;
+    char *path;
 
     for (diff_parent = diff_node; diff_parent; diff_parent = lyd_parent(diff_parent)) {
         LY_LIST_FOR(diff_parent->meta, meta) {
@@ -830,7 +860,13 @@
             break;
         }
     }
-    LY_CHECK_ERR_RET(!meta, LOGINT(LYD_CTX(diff_node)), LY_EINT);
+
+    if (!meta) {
+        path = lyd_path(diff_node, LYD_PATH_STD, NULL, 0);
+        LOGERR(LYD_CTX(diff_node), LY_EINVAL, "Node \"%s\" without an operation.", path);
+        free(path);
+        return LY_EINT;
+    }
 
     return LY_SUCCESS;
 }
@@ -968,7 +1004,7 @@
         if (op == LYD_DIFF_OP_REPLACE) {
             /* find the node (we must have some siblings because the node was only moved) */
             LY_CHECK_RET(lyd_diff_find_match(*first_node, diff_node, 1, dup_inst, &match));
-            LY_CHECK_ERR_RET(!match, LOGINT(ctx), LY_EINT);
+            LY_CHECK_ERR_RET(!match, LOGERR_NOINST(ctx, diff_node), LY_EINVAL);
         } else {
             /* duplicate the node */
             LY_CHECK_RET(lyd_dup_single(diff_node, NULL, LYD_DUP_NO_META, &match));
@@ -983,7 +1019,7 @@
             meta_str = "yang:value";
         }
         meta = lyd_find_meta(diff_node->meta, NULL, meta_str);
-        LY_CHECK_ERR_RET(!meta, LOGINT(ctx), LY_EINT);
+        LY_CHECK_ERR_RET(!meta, LOGERR_META(ctx, meta_str, diff_node), LY_EINVAL);
         str_val = lyd_get_meta_value(meta);
 
         /* insert/move the node */
@@ -1007,7 +1043,7 @@
     case LYD_DIFF_OP_NONE:
         /* find the node */
         LY_CHECK_RET(lyd_diff_find_match(*first_node, diff_node, 1, dup_inst, &match));
-        LY_CHECK_ERR_RET(!match, LOGINT(ctx), LY_EINT);
+        LY_CHECK_ERR_RET(!match, LOGERR_NOINST(ctx, diff_node), LY_EINVAL);
 
         if (match->schema->nodetype & LYD_NODE_TERM) {
             /* special case of only dflt flag change */
@@ -1043,7 +1079,7 @@
     case LYD_DIFF_OP_DELETE:
         /* find the node */
         LY_CHECK_RET(lyd_diff_find_match(*first_node, diff_node, 1, dup_inst, &match));
-        LY_CHECK_ERR_RET(!match, LOGINT(ctx), LY_EINT);
+        LY_CHECK_ERR_RET(!match, LOGERR_NOINST(ctx, diff_node), LY_EINVAL);
 
         /* remove it */
         if ((match == *first_node) && !match->parent) {
@@ -1060,14 +1096,12 @@
 
         /* find the node */
         LY_CHECK_RET(lyd_diff_find_match(*first_node, diff_node, 1, dup_inst, &match));
-        LY_CHECK_ERR_RET(!match, LOGINT(ctx), LY_EINT);
+        LY_CHECK_ERR_RET(!match, LOGERR_NOINST(ctx, diff_node), LY_EINVAL);
 
         /* update the value */
         if (diff_node->schema->nodetype == LYS_LEAF) {
             ret = lyd_change_term(match, lyd_get_value(diff_node));
-            if (ret && (ret != LY_EEXIST)) {
-                LOGINT_RET(ctx);
-            }
+            LY_CHECK_ERR_RET(ret && (ret != LY_EEXIST), LOGERR_UNEXPVAL(ctx, match, "data"), LY_EINVAL);
         } else {
             struct lyd_node_any *any = (struct lyd_node_any *)diff_node;
             LY_CHECK_RET(lyd_any_copy_value(match, &any->value, any->value_type));
@@ -1153,7 +1187,8 @@
         break;
     default:
         /* delete operation is not valid */
-        LOGINT_RET(LYD_CTX(src_diff));
+        LOGERR_MERGEOP(LYD_CTX(diff_match), diff_match, cur_op, LYD_DIFF_OP_NONE);
+        return LY_EINVAL;
     }
 
     return LY_SUCCESS;
@@ -1219,6 +1254,7 @@
     struct lyd_meta *meta;
     const struct lys_module *mod;
     const struct lyd_node_any *any;
+    const struct ly_ctx *ctx = LYD_CTX(diff_match);
 
     /* get "yang" module for the metadata */
     mod = ly_ctx_get_module_latest(LYD_CTX(diff_match), "yang");
@@ -1243,13 +1279,14 @@
 
             lyd_diff_del_meta(diff_match, meta_name);
             meta = lyd_find_meta(src_diff->meta, mod, meta_name);
-            LY_CHECK_ERR_RET(!meta, LOGINT(LYD_CTX(src_diff)), LY_EINT);
+            LY_CHECK_ERR_RET(!meta, LOGERR_META(ctx, meta_name, src_diff), LY_EINVAL);
             LY_CHECK_RET(lyd_dup_meta_single(meta, diff_match, NULL));
             break;
         case LYS_LEAF:
             /* replaced with the exact same value, impossible */
             if (!lyd_compare_single(diff_match, src_diff, 0)) {
-                LOGINT_RET(LYD_CTX(src_diff));
+                LOGERR_UNEXPVAL(ctx, diff_match, "target diff");
+                return LY_EINVAL;
             }
 
             /* modify the node value */
@@ -1260,7 +1297,7 @@
             if (cur_op == LYD_DIFF_OP_REPLACE) {
                 /* compare values whether there is any change at all */
                 meta = lyd_find_meta(diff_match->meta, mod, "orig-value");
-                LY_CHECK_ERR_RET(!meta, LOGINT(LYD_CTX(diff_match)), LY_EINT);
+                LY_CHECK_ERR_RET(!meta, LOGERR_META(ctx, "orig-value", diff_match), LY_EINVAL);
                 str_val = lyd_get_meta_value(meta);
                 ret = lyd_value_compare((struct lyd_node_term *)diff_match, str_val, strlen(str_val));
                 if (!ret) {
@@ -1277,8 +1314,8 @@
         case LYS_ANYXML:
         case LYS_ANYDATA:
             if (!lyd_compare_single(diff_match, src_diff, 0)) {
-                /* replaced with the exact same value, impossible */
-                LOGINT_RET(LYD_CTX(src_diff));
+                LOGERR_UNEXPVAL(ctx, diff_match, "target diff");
+                return LY_EINVAL;
             }
 
             /* modify the node value */
@@ -1306,16 +1343,17 @@
         }
 
         meta = lyd_find_meta(src_diff->meta, mod, orig_meta_name);
-        LY_CHECK_ERR_RET(!meta, LOGINT(LYD_CTX(src_diff)), LY_EINT);
+        LY_CHECK_ERR_RET(!meta, LOGERR_META(ctx, orig_meta_name, src_diff), LY_EINVAL);
         LY_CHECK_RET(lyd_dup_meta_single(meta, diff_match, NULL));
 
         meta = lyd_find_meta(src_diff->meta, mod, meta_name);
-        LY_CHECK_ERR_RET(!meta, LOGINT(LYD_CTX(src_diff)), LY_EINT);
+        LY_CHECK_ERR_RET(!meta, LOGERR_META(ctx, meta_name, src_diff), LY_EINVAL);
         LY_CHECK_RET(lyd_dup_meta_single(meta, diff_match, NULL));
         break;
     default:
         /* delete operation is not valid */
-        LOGINT_RET(LYD_CTX(src_diff));
+        LOGERR_MERGEOP(ctx, diff_match, cur_op, LYD_DIFF_OP_REPLACE);
+        return LY_EINVAL;
     }
 
     return LY_SUCCESS;
@@ -1338,6 +1376,7 @@
     uint32_t trg_flags;
     const char *meta_name, *orig_meta_name;
     struct lyd_meta *meta, *orig_meta;
+    const struct ly_ctx *ctx = LYD_CTX(diff_match);
 
     switch (cur_op) {
     case LYD_DIFF_OP_DELETE:
@@ -1357,8 +1396,9 @@
                 orig_meta_name = "yang:orig-value";
             }
             meta = lyd_find_meta(src_diff->meta, NULL, meta_name);
+            LY_CHECK_ERR_RET(!meta, LOGERR_META(ctx, meta_name, src_diff), LY_EINVAL);
             orig_meta = lyd_find_meta(diff_match->meta, NULL, orig_meta_name);
-            LY_CHECK_ERR_RET(!meta || !orig_meta, LOGINT(LYD_CTX(src_diff)), LY_EINT);
+            LY_CHECK_ERR_RET(!orig_meta, LOGERR_META(ctx, orig_meta_name, diff_match), LY_EINVAL);
 
             /* the (incorrect) assumption made here is that there are no previous diff nodes that would affect
              * the anchors stored in the metadata */
@@ -1421,7 +1461,8 @@
         break;
     default:
         /* create and replace operations are not valid */
-        LOGINT_RET(LYD_CTX(src_diff));
+        LOGERR_MERGEOP(LYD_CTX(src_diff), diff_match, cur_op, LYD_DIFF_OP_CREATE);
+        return LY_EINVAL;
     }
 
     return LY_SUCCESS;
@@ -1441,6 +1482,7 @@
     struct lyd_node *child;
     struct lyd_meta *meta;
     const char *meta_name;
+    const struct ly_ctx *ctx = LYD_CTX(diff_match);
 
     /* we can delete only exact existing nodes */
     LY_CHECK_ERR_RET(lyd_compare_single(diff_match, src_diff, 0), LOGINT(LYD_CTX(src_diff)), LY_EINT);
@@ -1476,14 +1518,15 @@
 
             /* switch value for the original one */
             meta = lyd_find_meta(diff_match->meta, NULL, "yang:orig-value");
-            LY_CHECK_ERR_RET(!meta, LOGINT(LYD_CTX(src_diff)), LY_EINT);
+            LY_CHECK_ERR_RET(!meta, LOGERR_META(ctx, "yang:orig-value", diff_match), LY_EINVAL);
             if (lyd_change_term(diff_match, lyd_get_meta_value(meta))) {
-                LOGINT_RET(LYD_CTX(src_diff));
+                LOGERR_UNEXPVAL(ctx, diff_match, "target diff");
+                return LY_EINVAL;
             }
 
             /* switch default for the original one, then remove the meta */
             meta = lyd_find_meta(diff_match->meta, NULL, "yang:orig-default");
-            LY_CHECK_ERR_RET(!meta, LOGINT(LYD_CTX(src_diff)), LY_EINT);
+            LY_CHECK_ERR_RET(!meta, LOGERR_META(ctx, "yang:orig-default", diff_match), LY_EINVAL);
             diff_match->flags &= ~LYD_DEFAULT;
             if (meta->value.boolean) {
                 diff_match->flags |= LYD_DEFAULT;
@@ -1503,7 +1546,8 @@
         break;
     default:
         /* delete operation is not valid */
-        LOGINT_RET(LYD_CTX(src_diff));
+        LOGERR_MERGEOP(LYD_CTX(diff_match), diff_match, cur_op, LYD_DIFF_OP_DELETE);
+        return LY_EINVAL;
     }
 
     return LY_SUCCESS;
@@ -1767,7 +1811,7 @@
     assert(node->schema->nodetype & (LYS_LEAF | LYS_ANYDATA));
 
     meta = lyd_find_meta(node->meta, mod, "orig-value");
-    LY_CHECK_ERR_RET(!meta, LOGINT(LYD_CTX(node)), LY_EINT);
+    LY_CHECK_ERR_RET(!meta, LOGERR_META(LYD_CTX(node), "orig-value", node), LY_EINVAL);
 
     /* orig-value */
     val1 = lyd_get_meta_value(meta);
@@ -1836,10 +1880,10 @@
     char *val2 = NULL;
 
     meta1 = lyd_find_meta(node->meta, mod, name1);
-    LY_CHECK_ERR_RET(!meta1, LOGINT(LYD_CTX(node)), LY_EINT);
+    LY_CHECK_ERR_RET(!meta1, LOGERR_META(LYD_CTX(node), name1, node), LY_EINVAL);
 
     meta2 = lyd_find_meta(node->meta, mod, name2);
-    LY_CHECK_ERR_RET(!meta2, LOGINT(LYD_CTX(node)), LY_EINT);
+    LY_CHECK_ERR_RET(!meta2, LOGERR_META(LYD_CTX(node), name2, node), LY_EINVAL);
 
     /* value1 */
     val1 = lyd_get_meta_value(meta1);