xpath RFEACTOR expr_dup LY_ERR return (#1206)

diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 720351a..d7f0872 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -2521,9 +2521,8 @@
  */
 static LY_ERR
 lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_node_p, uint16_t context_flags,
-        struct lysp_module *context_mod, const char *context_name, struct lysp_type *type_p,
-        struct lys_module *module, LY_DATA_TYPE basetype, const char *tpdfname, struct lysc_type *base,
-        struct lysc_type **type)
+        struct lysp_module *context_mod, const char *context_name, struct lysp_type *type_p, struct lys_module *module,
+        LY_DATA_TYPE basetype, const char *tpdfname, struct lysc_type *base, struct lysc_type **type)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lysc_type_bin *bin;
@@ -2545,14 +2544,9 @@
             LY_CHECK_RET(lys_compile_type_range(ctx, type_p->length, basetype, 1, 0,
                                                 base ? ((struct lysc_type_bin *)base)->length : NULL, &bin->length));
             if (!tpdfname) {
-                COMPILE_EXTS_GOTO(ctx, type_p->length->exts, bin->length->exts, bin->length, LYEXT_PAR_LENGTH, ret, done);
+                COMPILE_EXTS_GOTO(ctx, type_p->length->exts, bin->length->exts, bin->length, LYEXT_PAR_LENGTH, ret, cleanup);
             }
         }
-
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_bin));
-        }
         break;
     case LY_TYPE_BITS:
         /* RFC 7950 9.7 - bits */
@@ -2569,16 +2563,9 @@
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "bit", "bits type ", tpdfname);
             } else {
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "bit", "bits type", "");
-                free(*type);
-                *type = NULL;
             }
             return LY_EVALID;
         }
-
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_bits));
-        }
         break;
     case LY_TYPE_DEC64:
         dec = (struct lysc_type_dec *)(*type);
@@ -2590,8 +2577,6 @@
                     LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "fraction-digits", "decimal64 type ", tpdfname);
                 } else {
                     LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "fraction-digits", "decimal64 type", "");
-                    free(*type);
-                    *type = NULL;
                 }
                 return LY_EVALID;
             }
@@ -2606,8 +2591,6 @@
                 } else {
                     LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
                            "Invalid fraction-digits substatement for type not directly derived from decimal64 built-in type.");
-                    free(*type);
-                    *type = NULL;
                 }
                 return LY_EVALID;
             }
@@ -2619,14 +2602,9 @@
             LY_CHECK_RET(lys_compile_type_range(ctx, type_p->range, basetype, 0, dec->fraction_digits,
                                                 base ? ((struct lysc_type_dec *)base)->range : NULL, &dec->range));
             if (!tpdfname) {
-                COMPILE_EXTS_GOTO(ctx, type_p->range->exts, dec->range->exts, dec->range, LYEXT_PAR_RANGE, ret, done);
+                COMPILE_EXTS_GOTO(ctx, type_p->range->exts, dec->range->exts, dec->range, LYEXT_PAR_RANGE, ret, cleanup);
             }
         }
-
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_dec));
-        }
         break;
     case LY_TYPE_STRING:
         str = (struct lysc_type_str *)(*type);
@@ -2636,7 +2614,7 @@
             LY_CHECK_RET(lys_compile_type_range(ctx, type_p->length, basetype, 1, 0,
                                                 base ? ((struct lysc_type_str *)base)->length : NULL, &str->length));
             if (!tpdfname) {
-                COMPILE_EXTS_GOTO(ctx, type_p->length->exts, str->length->exts, str->length, LYEXT_PAR_LENGTH, ret, done);
+                COMPILE_EXTS_GOTO(ctx, type_p->length->exts, str->length->exts, str->length, LYEXT_PAR_LENGTH, ret, cleanup);
             }
         } else if (base && ((struct lysc_type_str *)base)->length) {
             str->length = lysc_range_dup(ctx->ctx, ((struct lysc_type_str *)base)->length);
@@ -2649,11 +2627,6 @@
         } else if (base && ((struct lysc_type_str *)base)->patterns) {
             str->patterns = lysc_patterns_dup(ctx->ctx, ((struct lysc_type_str *)base)->patterns);
         }
-
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_str));
-        }
         break;
     case LY_TYPE_ENUM:
         enumeration = (struct lysc_type_enum *)(*type);
@@ -2670,16 +2643,9 @@
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "enum", "enumeration type ", tpdfname);
             } else {
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "enum", "enumeration type", "");
-                free(*type);
-                *type = NULL;
             }
             return LY_EVALID;
         }
-
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_enum));
-        }
         break;
     case LY_TYPE_INT8:
     case LY_TYPE_UINT8:
@@ -2696,14 +2662,9 @@
             LY_CHECK_RET(lys_compile_type_range(ctx, type_p->range, basetype, 0, 0,
                                                 base ? ((struct lysc_type_num *)base)->range : NULL, &num->range));
             if (!tpdfname) {
-                COMPILE_EXTS_GOTO(ctx, type_p->range->exts, num->range->exts, num->range, LYEXT_PAR_RANGE, ret, done);
+                COMPILE_EXTS_GOTO(ctx, type_p->range->exts, num->range->exts, num->range, LYEXT_PAR_RANGE, ret, cleanup);
             }
         }
-
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_num));
-        }
         break;
     case LY_TYPE_IDENT:
         idref = (struct lysc_type_identityref *)(*type);
@@ -2719,8 +2680,6 @@
                 } else {
                     LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
                            "Invalid base substatement for the type not directly derived from identityref built-in type.");
-                    free(*type);
-                    *type = NULL;
                 }
                 return LY_EVALID;
             }
@@ -2733,16 +2692,9 @@
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "base", "identityref type ", tpdfname);
             } else {
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "base", "identityref type", "");
-                free(*type);
-                *type = NULL;
             }
             return LY_EVALID;
         }
-
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_identityref));
-        }
         break;
     case LY_TYPE_LEAFREF:
         lref = (struct lysc_type_leafref *)*type;
@@ -2756,8 +2708,6 @@
                 } else {
                     LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
                            "Leafref type can be restricted by require-instance statement only in YANG 1.1 modules.");
-                    free(*type);
-                    *type = NULL;
                 }
                 return LY_EVALID;
             }
@@ -2770,24 +2720,18 @@
             lref->require_instance = 1;
         }
         if (type_p->path) {
-            lref->path = lyxp_expr_dup(ctx->ctx, type_p->path);
+            LY_CHECK_RET(lyxp_expr_dup(ctx->ctx, type_p->path, &lref->path));
             lref->path_context = module;
         } else if (base) {
-            lref->path = lyxp_expr_dup(ctx->ctx, ((struct lysc_type_leafref *)base)->path);
+            LY_CHECK_RET(lyxp_expr_dup(ctx->ctx, ((struct lysc_type_leafref *)base)->path, &lref->path));
             lref->path_context = ((struct lysc_type_leafref *)base)->path_context;
         } else if (tpdfname) {
             LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "path", "leafref type ", tpdfname);
             return LY_EVALID;
         } else {
             LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "path", "leafref type", "");
-            free(*type);
-            *type = NULL;
             return LY_EVALID;
         }
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_leafref));
-        }
         break;
     case LY_TYPE_INST:
         /* RFC 7950 9.9.3 - require-instance */
@@ -2797,11 +2741,6 @@
             /* default is true */
             ((struct lysc_type_instanceid *)(*type))->require_instance = 1;
         }
-
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_instanceid));
-        }
         break;
     case LY_TYPE_UNION:
         un = (struct lysc_type_union *)(*type);
@@ -2817,8 +2756,6 @@
                 } else {
                     LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
                            "Invalid type substatement for the type not directly derived from union built-in type.");
-                    free(*type);
-                    *type = NULL;
                 }
                 return LY_EVALID;
             }
@@ -2842,7 +2779,7 @@
                             lref = (struct lysc_type_leafref *)un->types[u + additional];
 
                             lref->basetype = LY_TYPE_LEAFREF;
-                            lref->path = lyxp_expr_dup(ctx->ctx, ((struct lysc_type_leafref *)un_aux->types[v])->path);
+                            LY_CHECK_RET(lyxp_expr_dup(ctx->ctx, ((struct lysc_type_leafref *)un_aux->types[v])->path, &lref->path));
                             lref->refcount = 1;
                             lref->require_instance = ((struct lysc_type_leafref *)un_aux->types[v])->require_instance;
                             lref->path_context = ((struct lysc_type_leafref *)un_aux->types[v])->path_context;
@@ -2872,24 +2809,74 @@
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "type", "union type ", tpdfname);
             } else {
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "type", "union type", "");
-                free(*type);
-                *type = NULL;
             }
             return LY_EVALID;
         }
-
-        if (tpdfname) {
-            type_p->compiled = *type;
-            *type = calloc(1, sizeof(struct lysc_type_union));
-        }
         break;
     case LY_TYPE_BOOL:
     case LY_TYPE_EMPTY:
     case LY_TYPE_UNKNOWN: /* just to complete switch */
         break;
     }
+
+    if (tpdfname) {
+        switch (basetype) {
+        case LY_TYPE_BINARY:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_bin));
+            break;
+        case LY_TYPE_BITS:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_bits));
+            break;
+        case LY_TYPE_DEC64:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_dec));
+            break;
+        case LY_TYPE_STRING:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_str));
+            break;
+        case LY_TYPE_ENUM:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_enum));
+            break;
+        case LY_TYPE_INT8:
+        case LY_TYPE_UINT8:
+        case LY_TYPE_INT16:
+        case LY_TYPE_UINT16:
+        case LY_TYPE_INT32:
+        case LY_TYPE_UINT32:
+        case LY_TYPE_INT64:
+        case LY_TYPE_UINT64:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_num));
+            break;
+        case LY_TYPE_IDENT:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_identityref));
+            break;
+        case LY_TYPE_LEAFREF:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_leafref));
+            break;
+        case LY_TYPE_INST:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_instanceid));
+            break;
+        case LY_TYPE_UNION:
+            type_p->compiled = *type;
+            *type = calloc(1, sizeof(struct lysc_type_union));
+            break;
+        case LY_TYPE_BOOL:
+        case LY_TYPE_EMPTY:
+        case LY_TYPE_UNKNOWN: /* just to complete switch */
+            break;
+        }
+    }
     LY_CHECK_ERR_RET(!(*type), LOGMEM(ctx->ctx), LY_EMEM);
-done:
+
+cleanup:
     return ret;
 }
 
diff --git a/src/xpath.c b/src/xpath.c
index 4691984..0648706 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -2949,29 +2949,30 @@
     return ret;
 }
 
-struct lyxp_expr *
-lyxp_expr_dup(const struct ly_ctx *ctx, const struct lyxp_expr *exp)
+LY_ERR
+lyxp_expr_dup(const struct ly_ctx *ctx, const struct lyxp_expr *exp, struct lyxp_expr **dup_p)
 {
-    struct lyxp_expr *dup;
+    LY_ERR ret = LY_SUCCESS;
+    struct lyxp_expr *dup = NULL;
     uint32_t i, j;
 
     dup = calloc(1, sizeof *dup);
-    LY_CHECK_ERR_GOTO(!dup, LOGMEM(ctx), error);
+    LY_CHECK_ERR_GOTO(!dup, LOGMEM(ctx); ret = LY_EMEM, cleanup);
 
     dup->tokens = malloc(exp->used * sizeof *dup->tokens);
-    LY_CHECK_ERR_GOTO(!dup->tokens, LOGMEM(ctx), error);
+    LY_CHECK_ERR_GOTO(!dup->tokens, LOGMEM(ctx); ret = LY_EMEM, cleanup);
     memcpy(dup->tokens, exp->tokens, exp->used * sizeof *dup->tokens);
 
     dup->tok_pos = malloc(exp->used * sizeof *dup->tok_pos);
-    LY_CHECK_ERR_GOTO(!dup->tok_pos, LOGMEM(ctx), error);
+    LY_CHECK_ERR_GOTO(!dup->tok_pos, LOGMEM(ctx); ret = LY_EMEM, cleanup);
     memcpy(dup->tok_pos, exp->tok_pos, exp->used * sizeof *dup->tok_pos);
 
     dup->tok_len = malloc(exp->used * sizeof *dup->tok_len);
-    LY_CHECK_ERR_GOTO(!dup->tok_len, LOGMEM(ctx), error);
+    LY_CHECK_ERR_GOTO(!dup->tok_len, LOGMEM(ctx); ret = LY_EMEM, cleanup);
     memcpy(dup->tok_len, exp->tok_len, exp->used * sizeof *dup->tok_len);
 
     dup->repeat = malloc(exp->used * sizeof *dup->repeat);
-    LY_CHECK_ERR_GOTO(!dup->repeat, LOGMEM(ctx), error);
+    LY_CHECK_ERR_GOTO(!dup->repeat, LOGMEM(ctx); ret = LY_EMEM, cleanup);
     for (i = 0; i < exp->used; ++i) {
         if (!exp->repeat[i]) {
             dup->repeat[i] = NULL;
@@ -2981,7 +2982,7 @@
             ++j;
 
             dup->repeat[i] = malloc(j * sizeof **dup->repeat);
-            LY_CHECK_ERR_GOTO(!dup->repeat[i], LOGMEM(ctx), error);
+            LY_CHECK_ERR_GOTO(!dup->repeat[i], LOGMEM(ctx); ret = LY_EMEM, cleanup);
             memcpy(dup->repeat[i], exp->repeat[i], j * sizeof **dup->repeat);
             dup->repeat[i][j - 1] = 0;
         }
@@ -2989,13 +2990,15 @@
 
     dup->used = exp->used;
     dup->size = exp->used;
-    LY_CHECK_GOTO(lydict_insert(ctx, exp->expr, 0, &dup->expr), error);
+    LY_CHECK_GOTO(ret = lydict_insert(ctx, exp->expr, 0, &dup->expr), cleanup);
 
-    return dup;
-
-error:
-    lyxp_expr_free(ctx, dup);
-    return NULL;
+cleanup:
+    if (ret) {
+        lyxp_expr_free(ctx, dup);
+    } else {
+        *dup_p = dup;
+    }
+    return ret;
 }
 
 /*
diff --git a/src/xpath.h b/src/xpath.h
index 20498cd..099f810 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -390,9 +390,10 @@
  *
  * @param[in] ctx Context with a dictionary.
  * @param[in] exp Parsed expression.
- * @return Duplicated structure, NULL on error.
+ * @param[out] dup Duplicated structure.
+ * @return LY_ERR value.
  */
-struct lyxp_expr *lyxp_expr_dup(const struct ly_ctx *ctx, const struct lyxp_expr *exp);
+LY_ERR lyxp_expr_dup(const struct ly_ctx *ctx, const struct lyxp_expr *exp, struct lyxp_expr **dup);
 
 /**
  * @brief Look at the next token and check its kind.