libyang REFACTOR use freeing context

Fixes compiled extension memory leaks.
Refactoring included.
diff --git a/src/schema_compile.c b/src/schema_compile.c
index f4aae9e..c02e628 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -44,6 +44,7 @@
 #include "tree.h"
 #include "tree_data.h"
 #include "tree_schema.h"
+#include "tree_schema_free.h"
 #include "tree_schema_internal.h"
 #include "xpath.h"
 
@@ -55,39 +56,30 @@
 {
     LY_ERR ret = LY_SUCCESS;
 
-    if (ext_p->compiled && (ext_p->compiled->refcount == 1)) {
-        /* context recompilation - all the extension instances were previously freed (the last link to the compiled extension
-         * remains from the parsed extension definition) and now we are recompiling them again, to have the up-to-date
-         * extension definition, we have to recompile it as well now */
-        lysc_extension_free(ctx->ctx, &ext_p->compiled);
-    }
-
     if (!ext_p->compiled) {
         lysc_update_path(ctx, NULL, "{extension}");
         lysc_update_path(ctx, NULL, ext_p->name);
 
         /* compile the extension definition */
-        ext_p->compiled = calloc(1, sizeof **ext);
-        ext_p->compiled->refcount = 2;
-        DUP_STRING_GOTO(ctx->ctx, ext_p->name, ext_p->compiled->name, ret, done);
-        DUP_STRING_GOTO(ctx->ctx, ext_p->argname, ext_p->compiled->argname, ret, done);
-        ext_p->compiled->module = (struct lys_module *)ext_mod;
-        COMPILE_EXTS_GOTO(ctx, ext_p->exts, ext_p->compiled->exts, *ext, ret, done);
+        *ext = ext_p->compiled = calloc(1, sizeof **ext);
+        (*ext)->refcount = 1;
+        DUP_STRING_GOTO(ctx->ctx, ext_p->name, (*ext)->name, ret, done);
+        DUP_STRING_GOTO(ctx->ctx, ext_p->argname, (*ext)->argname, ret, done);
+        (*ext)->module = (struct lys_module *)ext_mod;
+
+        /* compile nested extensions */
+        COMPILE_EXTS_GOTO(ctx, ext_p->exts, (*ext)->exts, *ext, ret, done);
 
         lysc_update_path(ctx, NULL, NULL);
         lysc_update_path(ctx, NULL, NULL);
 
         /* find extension definition plugin */
-        ext_p->compiled->plugin = lyplg_find(LYPLG_EXTENSION, ext_p->compiled->module->name,
-                ext_p->compiled->module->revision, ext_p->compiled->name);
-
-        /* refcount 2 already */
-        *ext = ext_p->compiled;
-    } else {
-        /* increase refcount */
-        *ext = lysc_ext_dup(ext_p->compiled);
+        (*ext)->plugin = lyplg_find(LYPLG_EXTENSION, (*ext)->module->name,
+                (*ext)->module->revision, (*ext)->name);
     }
 
+    *ext = ext_p->compiled;
+
 done:
     if (ret) {
         lysc_update_path(ctx, NULL, NULL);
@@ -126,7 +118,7 @@
         }
         ret = ext->def->plugin->compile(ctx, ext_p, ext);
         if (ret == LY_ENOT) {
-            lysc_ext_instance_free(ctx->ctx, ext);
+            lysc_ext_instance_free(&ctx->free_ctx, ext);
         }
         if (ext->argument) {
             lysc_update_path(ctx, NULL, NULL);
@@ -137,7 +129,6 @@
 cleanup:
     lysc_update_path(ctx, NULL, NULL);
     lysc_update_path(ctx, NULL, NULL);
-
     return ret;
 }
 
@@ -286,19 +277,19 @@
         const struct lysp_ident *identities_p, struct lysc_ident **identities)
 {
     LY_ARRAY_COUNT_TYPE u;
-    struct lysc_ctx context = {0};
+    struct lysc_ctx cctx;
     struct lysc_ident *ident;
     LY_ERR ret = LY_SUCCESS;
 
     assert(ctx_sc || ctx);
 
     if (!ctx_sc) {
-        context.ctx = ctx;
-        context.cur_mod = parsed_mod ? parsed_mod->mod : NULL;
-        context.pmod = parsed_mod;
-        context.path_len = 1;
-        context.path[0] = '/';
-        ctx_sc = &context;
+        if (parsed_mod) {
+            LYSC_CTX_INIT_PMOD(cctx, parsed_mod);
+        } else {
+            LYSC_CTX_INIT_CTX(cctx, ctx);
+        }
+        ctx_sc = &cctx;
     }
 
     if (!identities_p) {
@@ -657,7 +648,7 @@
                     LY_CHECK_GOTO(rc = lysp_stmt_parse(ctx, stmt, &parsed, NULL), cleanup);
                     r = lys_compile_type(ctx, NULL, flags ? *flags : 0, ext_p->name, parsed, (struct lysc_type **)compiled,
                             (units && !*units) ? units : NULL, NULL);
-                    lysp_type_free(ctx->ctx, parsed);
+                    lysp_type_free(&ctx->free_ctx, parsed);
                     free(parsed);
                     LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
                     break;
@@ -1033,7 +1024,7 @@
  * @param[in] items Sized array of bits/enums.
  */
 static void
-lys_compile_unres_disabled_bitenum_remove(struct ly_ctx *ctx, struct lysc_type_bitenum_item *items)
+lys_compile_unres_disabled_bitenum_remove(struct lysf_ctx *ctx, struct lysc_type_bitenum_item *items)
 {
     LY_ARRAY_COUNT_TYPE u = 0, last_u;
 
@@ -1082,7 +1073,7 @@
         if ((t[u]->basetype == LY_TYPE_BITS) || (t[u]->basetype == LY_TYPE_ENUM)) {
             /* remove all disabled items */
             ent = (struct lysc_type_enum *)(t[u]);
-            lys_compile_unres_disabled_bitenum_remove(ctx->ctx, ent->enums);
+            lys_compile_unres_disabled_bitenum_remove(&ctx->free_ctx, ent->enums);
 
             if (!LY_ARRAY_COUNT(ent->enums)) {
                 LOGVAL(ctx->ctx, LYVE_SEMANTICS, "%s type of node \"%s\" without any (or all disabled) valid values.",
@@ -1384,22 +1375,16 @@
     struct lysc_node *node;
     struct lysc_type *typeiter;
     struct lysc_type_leafref *lref;
-    struct lysc_ctx cctx;
-    struct lys_depset_unres *ds_unres;
+    struct lysc_ctx cctx = {0};
+    struct lys_depset_unres *ds_unres = &unres->ds_unres;
     struct ly_path *path;
     LY_ARRAY_COUNT_TYPE v;
     struct lysc_unres_leafref *l;
+    struct lysc_unres_must *m;
+    struct lysc_unres_dflt *r;
     uint32_t i, processed_leafrefs = 0;
 
-    ds_unres = &unres->ds_unres;
-
-    /* fake compile context */
 resolve_all:
-    memset(&cctx, 0, sizeof cctx);
-    cctx.ctx = ctx;
-    cctx.path_len = 1;
-    cctx.path[0] = '/';
-
     /* for leafref, we need 2 rounds - first detects circular chain by storing the first referred type (which
      * can be also leafref, in case it is already resolved, go through the chain and check that it does not
      * point to the starting leafref type). The second round stores the first non-leafref type for later data validation.
@@ -1408,8 +1393,7 @@
         /* remember index, it can change before we get to free this item */
         i = ds_unres->disabled_leafrefs.count - 1;
         l = ds_unres->disabled_leafrefs.objs[i];
-        cctx.cur_mod = l->node->module;
-        cctx.pmod = l->node->module->parsed;
+        LYSC_CTX_INIT_PMOD(cctx, l->node->module->parsed);
 
         LOG_LOCSET(l->node, NULL, NULL, NULL);
         v = 0;
@@ -1417,24 +1401,22 @@
             ret = lys_compile_unres_leafref(&cctx, l->node, lref, l->local_mod, unres);
         }
         LOG_LOCBACK(1, 0, 0, 0);
-        LY_CHECK_RET(ret);
+        LY_CHECK_GOTO(ret, cleanup);
 
         ly_set_rm_index(&ds_unres->disabled_leafrefs, i, free);
     }
 
     for (i = processed_leafrefs; i < ds_unres->leafrefs.count; ++i) {
         l = ds_unres->leafrefs.objs[i];
-        cctx.cur_mod = l->node->module;
-        cctx.pmod = l->node->module->parsed;
-        LOG_LOCSET(l->node, NULL, NULL, NULL);
+        LYSC_CTX_INIT_PMOD(cctx, l->node->module->parsed);
 
+        LOG_LOCSET(l->node, NULL, NULL, NULL);
         v = 0;
         while ((ret == LY_SUCCESS) && (lref = lys_type_leafref_next(l->node, &v))) {
             ret = lys_compile_unres_leafref(&cctx, l->node, lref, l->local_mod, unres);
         }
-
         LOG_LOCBACK(1, 0, 0, 0);
-        LY_CHECK_RET(ret);
+        LY_CHECK_GOTO(ret, cleanup);
     }
     for (i = processed_leafrefs; i < ds_unres->leafrefs.count; ++i) {
         l = ds_unres->leafrefs.objs[i];
@@ -1446,7 +1428,7 @@
                     typeiter->basetype == LY_TYPE_LEAFREF;
                     typeiter = ((struct lysc_type_leafref *)typeiter)->realtype) {}
 
-            lysc_type_free(ctx, lref->realtype);
+            lysc_type_free(&cctx.free_ctx, lref->realtype);
             lref->realtype = typeiter;
             ++lref->realtype->refcount;
         }
@@ -1461,13 +1443,12 @@
     while (ds_unres->whens.count) {
         i = ds_unres->whens.count - 1;
         node = ds_unres->whens.objs[i];
-        cctx.cur_mod = node->module;
-        cctx.pmod = node->module->parsed;
+        LYSC_CTX_INIT_PMOD(cctx, node->module->parsed);
 
         LOG_LOCSET(node, NULL, NULL, NULL);
         ret = lys_compile_unres_when(&cctx, node, unres);
         LOG_LOCBACK(1, 0, 0, 0);
-        LY_CHECK_RET(ret);
+        LY_CHECK_GOTO(ret, cleanup);
 
         ly_set_rm_index(&ds_unres->whens, i, NULL);
     }
@@ -1475,15 +1456,13 @@
     /* check must */
     while (ds_unres->musts.count) {
         i = ds_unres->musts.count - 1;
-        struct lysc_unres_must *m = ds_unres->musts.objs[i];
-
-        cctx.cur_mod = m->node->module;
-        cctx.pmod = m->node->module->parsed;
+        m = ds_unres->musts.objs[i];
+        LYSC_CTX_INIT_PMOD(cctx, m->node->module->parsed);
 
         LOG_LOCSET(m->node, NULL, NULL, NULL);
         ret = lys_compile_unres_must(&cctx, m->node, m->local_mods, unres);
         LOG_LOCBACK(1, 0, 0, 0);
-        LY_CHECK_RET(ret);
+        LY_CHECK_GOTO(ret, cleanup);
 
         lysc_unres_must_free(m);
         ly_set_rm_index(&ds_unres->musts, i, NULL);
@@ -1493,13 +1472,12 @@
     while (ds_unres->disabled_bitenums.count) {
         i = ds_unres->disabled_bitenums.count - 1;
         node = ds_unres->disabled_bitenums.objs[i];
-        cctx.cur_mod = node->module;
-        cctx.pmod = node->module->parsed;
+        LYSC_CTX_INIT_PMOD(cctx, node->module->parsed);
 
         LOG_LOCSET(node, NULL, NULL, NULL);
         ret = lys_compile_unres_disabled_bitenum(&cctx, (struct lysc_node_leaf *)node);
         LOG_LOCBACK(1, 0, 0, 0);
-        LY_CHECK_RET(ret);
+        LY_CHECK_GOTO(ret, cleanup);
 
         ly_set_rm_index(&ds_unres->disabled_bitenums, i, NULL);
     }
@@ -1507,10 +1485,8 @@
     /* finish incomplete default values compilation */
     while (ds_unres->dflts.count) {
         i = ds_unres->dflts.count - 1;
-        struct lysc_unres_dflt *r = ds_unres->dflts.objs[i];
-
-        cctx.cur_mod = r->leaf->module;
-        cctx.pmod = r->leaf->module->parsed;
+        r = ds_unres->dflts.objs[i];
+        LYSC_CTX_INIT_PMOD(cctx, r->leaf->module->parsed);
 
         LOG_LOCSET(&r->leaf->node, NULL, NULL, NULL);
         if (r->leaf->nodetype == LYS_LEAF) {
@@ -1519,7 +1495,7 @@
             ret = lys_compile_unres_llist_dflts(&cctx, r->llist, r->dflt, r->dflts, unres);
         }
         LOG_LOCBACK(1, 0, 0, 0);
-        LY_CHECK_RET(ret);
+        LY_CHECK_GOTO(ret, cleanup);
 
         lysc_unres_dflt_free(ctx, r);
         ly_set_rm_index(&ds_unres->dflts, i, NULL);
@@ -1538,17 +1514,18 @@
             LOG_LOCSET(node, NULL, NULL, NULL);
             LOGVAL(ctx, LYVE_REFERENCE, "Key \"%s\" is disabled.", node->name);
             LOG_LOCBACK(1, 0, 0, 0);
-            return LY_EVALID;
+            ret = LY_EVALID;
+            goto cleanup;
         }
+        LYSC_CTX_INIT_PMOD(cctx, node->module->parsed);
 
-        lysc_node_free(ctx, node, 1);
+        lysc_node_free(&cctx.free_ctx, node, 1);
     }
 
     /* also check if the leafref target has not been disabled */
     for (i = 0; i < ds_unres->leafrefs.count; ++i) {
         l = ds_unres->leafrefs.objs[i];
-        cctx.cur_mod = l->node->module;
-        cctx.pmod = l->node->module->parsed;
+        LYSC_CTX_INIT_PMOD(cctx, l->node->module->parsed);
 
         v = 0;
         while ((lref = lys_type_leafref_next(l->node, &v))) {
@@ -1563,12 +1540,15 @@
                 LOGVAL(ctx, LYVE_REFERENCE, "Target of leafref \"%s\" cannot be referenced because it is disabled.",
                         l->node->name);
                 LOG_LOCBACK(1, 0, 0, 0);
-                return LY_EVALID;
+                ret = LY_EVALID;
+                goto cleanup;
             }
         }
     }
 
-    return LY_SUCCESS;
+cleanup:
+    lysf_ctx_erase(&cctx.free_ctx);
+    return ret;
 }
 
 /**
@@ -1609,6 +1589,7 @@
 lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob_unres *unres)
 {
     LY_ERR ret = LY_SUCCESS;
+    struct lysf_ctx fctx = {.ctx = ctx};
     struct lys_module *mod;
     uint32_t i;
 
@@ -1621,7 +1602,7 @@
         assert(mod->implemented);
 
         /* free the compiled module, if any */
-        lysc_module_free(mod->compiled);
+        lysc_module_free(&fctx, mod->compiled);
         mod->compiled = NULL;
 
         /* (re)compile the module */
@@ -1647,6 +1628,7 @@
 
 cleanup:
     lys_compile_unres_depset_erase(ctx, unres);
+    lysf_ctx_erase(&fctx);
     return ret;
 }
 
@@ -1782,7 +1764,7 @@
 LY_ERR
 lys_compile(struct lys_module *mod, struct lys_depset_unres *unres)
 {
-    struct lysc_ctx ctx = {0};
+    struct lysc_ctx ctx;
     struct lysc_module *mod_c = NULL;
     struct lysp_module *sp;
     struct lysp_submodule *submod;
@@ -1796,12 +1778,7 @@
     assert(mod->implemented && mod->to_compile);
 
     sp = mod->parsed;
-
-    ctx.ctx = mod->ctx;
-    ctx.cur_mod = mod;
-    ctx.pmod = sp;
-    ctx.path_len = 1;
-    ctx.path[0] = '/';
+    LYSC_CTX_INIT_PMOD(ctx, sp);
     ctx.unres = unres;
 
     ++mod->ctx->change_count;
@@ -1898,7 +1875,7 @@
     LOG_LOCBACK(0, 0, 1, 0);
     lys_compile_unres_mod_erase(&ctx, ret);
     if (ret) {
-        lysc_module_free(mod_c);
+        lysc_module_free(&ctx.free_ctx, mod_c);
         mod->compiled = NULL;
     }
     return ret;
@@ -1908,7 +1885,7 @@
 lys_compile_identities(struct lys_module *mod)
 {
     LY_ERR rc = LY_SUCCESS;
-    struct lysc_ctx ctx = {0};
+    struct lysc_ctx ctx;
     struct lysp_submodule *submod;
     LY_ARRAY_COUNT_TYPE u;
 
@@ -1922,11 +1899,7 @@
     }
 
     /* prepare context */
-    ctx.ctx = mod->ctx;
-    ctx.cur_mod = mod;
-    ctx.pmod = mod->parsed;
-    ctx.path_len = 1;
-    ctx.path[0] = '/';
+    LYSC_CTX_INIT_PMOD(ctx, mod->parsed);
 
     if (mod->parsed->identities) {
         rc = lys_compile_identities_derived(&ctx, mod->parsed->identities, &mod->identities);