plugins CHANGE redesign lists of internal extension/type plugins

Prepare the lists of plugins for support of external plugins. Instead of
a statically allocated array, change the API to functions encapsulating
accessing and manipulation with the lists and plugins inside.

So far the lists still contain only the internal plugins, loading
external plugins will be added in a separated commit.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 61fce57..d367f5f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -133,6 +133,7 @@
     src/printer_yang.c
     src/printer_yin.c
     src/printer_tree.c
+    src/plugins.c
     src/plugins_types.c
     src/plugins_types_binary.c
     src/plugins_types_bits.c
@@ -162,6 +163,10 @@
     src/in.h
     src/parser_data.h
     src/parser_schema.h
+    src/plugins.h
+    src/plugins_exts.h
+    src/plugins_exts_compile.h
+    src/plugins_exts_print.h
     src/plugins_types.h
     src/out.h
     src/printer_data.h
diff --git a/src/context.c b/src/context.c
index 801d636..e8d0eb3 100644
--- a/src/context.c
+++ b/src/context.c
@@ -35,6 +35,7 @@
 #include "hash_table.h"
 #include "in.h"
 #include "parser_data.h"
+#include "plugins_internal.h"
 #include "plugins_types.h"
 #include "schema_compile.h"
 #include "set.h"
@@ -226,10 +227,8 @@
     /* dictionary */
     lydict_init(&ctx->dict);
 
-#if 0 /* TODO when plugins implemented */
     /* plugins */
-    ly_load_plugins();
-#endif
+    LY_CHECK_ERR_RET(lyplg_init(), LOGINT(NULL), LY_EINT);
 
     /* initialize thread-specific keys */
     while ((pthread_key_create(&ctx->errlist_key, ly_err_free)) == EAGAIN) {}
@@ -914,10 +913,8 @@
     /* dictionary */
     lydict_clean(&ctx->dict);
 
-#if 0 /* TODO when plugins implemented */
     /* plugins - will be removed only if this is the last context */
-    ly_clean_plugins();
-#endif
+    lyplg_clean();
 
     free(ctx);
 }
diff --git a/src/plugins.c b/src/plugins.c
new file mode 100644
index 0000000..fa243c8
--- /dev/null
+++ b/src/plugins.c
@@ -0,0 +1,232 @@
+/**
+ * @file plugins.c
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief Manipulate with the type and extension plugins.
+ *
+ * Copyright (c) 2021 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#include "plugins.h"
+#include "plugins_internal.h"
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <string.h>
+
+#include "common.h"
+#include "plugins_exts.h"
+#include "plugins_types.h"
+
+/*
+ * internal type plugins records
+ */
+extern const struct lyplg_type_record plugins_binary[];
+extern const struct lyplg_type_record plugins_bits[];
+extern const struct lyplg_type_record plugins_boolean[];
+extern const struct lyplg_type_record plugins_decimal64[];
+extern const struct lyplg_type_record plugins_empty[];
+extern const struct lyplg_type_record plugins_enumeration[];
+extern const struct lyplg_type_record plugins_identityref[];
+extern const struct lyplg_type_record plugins_instanceid[];
+extern const struct lyplg_type_record plugins_integer[];
+extern const struct lyplg_type_record plugins_leafref[];
+extern const struct lyplg_type_record plugins_string[];
+extern const struct lyplg_type_record plugins_union[];
+
+/*
+ * internal extension plugins records
+ */
+extern struct lyplg_ext_record plugins_metadata[];
+extern struct lyplg_ext_record plugins_nacm[];
+extern struct lyplg_ext_record plugins_yangdata[];
+
+static pthread_mutex_t plugins_guard = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * @brief Counter for currently present contexts able to refer to the loaded plugins.
+ *
+ * Plugins are shared among all the created contexts. They are loaded with the creation of the very first context and
+ * unloaded with the destroy of the last context. Therefore, to reload the list of plugins, all the contexts must be
+ * destroyed and with the creation of a first new context after that, the plugins will be reloaded.
+ */
+static uint32_t context_refcount = 0;
+
+/**
+ * @brief Record describing an implemented extension.
+ *
+ * Matches ::lyplg_ext_record and ::lyplg_type_record
+ */
+struct lyplg_record {
+    const char *module;          /**< name of the module where the extension/type is defined */
+    const char *revision;        /**< optional module revision - if not specified, the plugin applies to any revision,
+                                      which is not an optimal approach due to a possible future revisions of the module.
+                                      Instead, there should be defined multiple items in the plugins list, each with the
+                                      different revision, but all with the same pointer to the plugin functions. The
+                                      only valid use case for the NULL revision is the case the module has no revision. */
+    const char *name;            /**< name of the extension/typedef */
+    int8_t plugin[];             /**< specific plugin type's data - ::lyplg_ext or ::lyplg_type */
+};
+
+static struct ly_set plugins_types = {0};
+static struct ly_set plugins_extensions = {0};
+
+/**
+ * @brief Iterate over list of loaded plugins of the given @p type.
+ *
+ * @param[in] type Type of the plugins to iterate.
+ * @param[in,out] index The iterator - set to 0 for the first call.
+ * @return The plugin records, NULL if no more record is available.
+ */
+static struct lyplg_record *
+plugins_iter(enum LYPLG type, uint32_t *index)
+{
+    struct ly_set *plugins;
+
+    assert(index);
+
+    if (type == LYPLG_EXTENSION) {
+        plugins = &plugins_extensions;
+    } else {
+        plugins = &plugins_types;
+    }
+
+    if (*index == plugins->count) {
+        return NULL;
+    }
+
+    *index += 1;
+    return plugins->objs[*index - 1];
+}
+
+void *
+lyplg_find(enum LYPLG type, const char *module, const char *revision, const char *name)
+{
+    uint32_t i = 0;
+    struct lyplg_record *item;
+
+    assert(module);
+    assert(name);
+
+    while ((item = plugins_iter(type, &i)) != NULL) {
+        if (!strcmp(item->module, module) && !strcmp(item->name, name)) {
+            if (item->revision && revision && strcmp(item->revision, revision)) {
+                continue;
+            } else if (!revision && item->revision) {
+                continue;
+            }
+
+            return &item->plugin;
+        }
+    }
+
+    return NULL;
+}
+
+/**
+ * @brief Insert the provided extension plugin records into the internal set of extension plugins for use by libyang.
+ *
+ * @param[in] recs An array of plugin records provided by the plugin implementation. The array must be terminated by a zeroed
+ * record.
+ * @return LY_SUCCESS in case of success
+ * @return LY_EINVAL for invalid information in @p recs.
+ * @return LY_EMEM in case of memory allocation failure.
+ */
+static LY_ERR
+plugins_insert(enum LYPLG type, const void *recs)
+{
+    if (!recs) {
+        return LY_SUCCESS;
+    }
+
+    if (type == LYPLG_EXTENSION) {
+        const struct lyplg_ext_record *rec = (const struct lyplg_ext_record *)recs;
+
+        for (uint32_t i = 0; rec[i].name; i++) {
+            LY_CHECK_RET(ly_set_add(&plugins_extensions, (void *)&rec[i], 0, NULL));
+        }
+    } else { /* LY_PLUGIN_TYPE */
+        const struct lyplg_type_record *rec = (const struct lyplg_type_record *)recs;
+
+        for (uint32_t i = 0; rec[i].name; i++) {
+            LY_CHECK_RET(ly_set_add(&plugins_types, (void *)&rec[i], 0, NULL));
+        }
+    }
+
+    return LY_SUCCESS;
+}
+
+static void
+lyplg_clean_(void)
+{
+    if (--context_refcount) {
+        /* there is still some other context, do not remove the plugins */
+        return;
+    }
+
+    ly_set_erase(&plugins_types, NULL);
+    ly_set_erase(&plugins_extensions, NULL);
+}
+
+void
+lyplg_clean(void)
+{
+    pthread_mutex_lock(&plugins_guard);
+    lyplg_clean_();
+    pthread_mutex_unlock(&plugins_guard);
+}
+
+LY_ERR
+lyplg_init(void)
+{
+    LY_ERR ret;
+
+    pthread_mutex_lock(&plugins_guard);
+    /* let only the first context to initiate plugins, but let others wait for finishing the initiation */
+    if (context_refcount++) {
+        /* already initiated */
+        pthread_mutex_unlock(&plugins_guard);
+        return LY_SUCCESS;
+    }
+
+    /* internal types */
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_binary), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_bits), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_boolean), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_decimal64), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_empty), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_enumeration), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_identityref), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_instanceid), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_integer), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_leafref), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_string), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_union), error);
+
+    /* internal extensions */
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_metadata), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_nacm), error);
+    LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_yangdata), error);
+
+    /* initiation done, wake-up possibly waiting threads creating another contexts */
+    pthread_mutex_unlock(&plugins_guard);
+
+    return LY_SUCCESS;
+
+error:
+    /* initiation was not successful - cleanup (and let others to try) */
+    lyplg_clean_();
+    pthread_mutex_unlock(&plugins_guard);
+
+    if (ret == LY_EINVAL) {
+        /* all the plugins here are internal, invalid record actually means an internal libyang error */
+        ret = LY_EINT;
+    }
+    return ret;
+}
diff --git a/src/plugins.h b/src/plugins.h
new file mode 100644
index 0000000..7baa00f
--- /dev/null
+++ b/src/plugins.h
@@ -0,0 +1,44 @@
+/**
+ * @file plugins.h
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief Plugins manipulation.
+ *
+ * Copyright (c) 2021 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#ifndef LY_PLUGINS_H_
+#define LY_PLUGINS_H_
+
+#include "log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup plugins Plugins
+ * @{
+ *
+ */
+
+/**
+ * @brief Identifiers of the plugin type.
+ */
+enum LYPLG {
+    LYPLG_TYPE,      /**< Specific type (typedef) */
+    LYPLG_EXTENSION  /**< YANG extension */
+};
+
+/** @} plugins */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LY_PLUGINS_H_ */
diff --git a/src/plugins_exts.c b/src/plugins_exts.c
index 92344cd..1cac204 100644
--- a/src/plugins_exts.c
+++ b/src/plugins_exts.c
@@ -25,40 +25,10 @@
 
 /* internal libyang headers - do not make them accessible to the extension plugins in plugins_exts_*.c */
 #include "common.h"
-#include "plugins_exts_internal.h"
+#include "plugins_internal.h"
 #include "printer_internal.h"
 #include "schema_compile.h"
 
-/**
- * @brief list of all extension plugins implemented internally
- */
-struct lyplg_ext_record lyext_plugins_internal[] = {
-    {"ietf-netconf-acm", "2012-02-22", "default-deny-write", &nacm_plugin},
-    {"ietf-netconf-acm", "2018-02-14", "default-deny-write", &nacm_plugin},
-    {"ietf-netconf-acm", "2012-02-22", "default-deny-all", &nacm_plugin},
-    {"ietf-netconf-acm", "2018-02-14", "default-deny-all", &nacm_plugin},
-    {"ietf-yang-metadata", "2016-08-05", "annotation", &metadata_plugin},
-    {"ietf-restconf", "2017-01-26", "yang-data", &yangdata_plugin},
-    {NULL, NULL, NULL, NULL} /* terminating item */
-};
-
-/* TODO support for external extension plugins */
-
-struct lyplg_ext *
-lyext_get_plugin(struct lysc_ext *ext)
-{
-    for (uint8_t u = 0; lyext_plugins_internal[u].module; ++u) {
-        if (!strcmp(ext->name, lyext_plugins_internal[u].name) &&
-                !strcmp(ext->module->name, lyext_plugins_internal[u].module) &&
-                (!lyext_plugins_internal[u].revision || !strcmp(ext->module->revision, lyext_plugins_internal[u].revision))) {
-            /* we have the match */
-            return lyext_plugins_internal[u].plugin;
-        }
-    }
-
-    return NULL;
-}
-
 API struct ly_ctx *
 lysc_ctx_get_ctx(const struct lysc_ctx *ctx)
 {
diff --git a/src/plugins_exts.h b/src/plugins_exts.h
index 16bbe0c..6ebe123 100644
--- a/src/plugins_exts.h
+++ b/src/plugins_exts.h
@@ -16,6 +16,7 @@
 #define LY_PLUGINS_EXTS_H_
 
 #include "log.h"
+#include "plugins.h"
 #include "tree_edit.h"
 #include "tree_schema.h"
 
@@ -169,6 +170,20 @@
     lyext_clb_free free;                /**< Free the extension instance specific data created by ::lyplg_ext.compile callback */
 };
 
+struct lyplg_ext_record {
+    /* plugin identification */
+    const char *module;          /**< name of the module where the extension is defined */
+    const char *revision;        /**< optional module revision - if not specified, the plugin applies to any revision,
+                                      which is not an optimal approach due to a possible future revisions of the module.
+                                      Instead, there should be defined multiple items in the plugins list, each with the
+                                      different revision, but all with the same pointer to the plugin functions. The
+                                      only valid use case for the NULL revision is the case the module has no revision. */
+    const char *name;            /**< name of the extension */
+
+    /* runtime data */
+    struct lyplg_ext plugin;     /**< data to utilize plugin implementation */
+};
+
 /**
  * @brief Provide a log message from an extension plugin.
  *
diff --git a/src/plugins_exts_internal.h b/src/plugins_exts_internal.h
deleted file mode 100644
index 75bc3f1..0000000
--- a/src/plugins_exts_internal.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * @file plugins_exts_internal.h
- * @author Radek Krejci <rkrejci@cesnet.cz>
- * @brief internal functions to support extension plugins.
- *
- * Copyright (c) 2019 CESNET, z.s.p.o.
- *
- * This source code is licensed under BSD 3-Clause License (the "License").
- * You may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/BSD-3-Clause
- */
-
-#ifndef LY_PLUGINS_EXTS_INTERNAL_H_
-#define LY_PLUGINS_EXTS_INTERNAL_H_
-
-#include "plugins_exts.h"
-#include "tree_schema.h"
-
-#include "plugins_exts_metadata.h"
-
-/**
- * @brief Record describing an implemented extension.
- */
-struct lyplg_ext_record {
-    const char *module;          /**< name of the module where the extension is defined */
-    const char *revision;        /**< optional module revision - if not specified, the plugin applies to any revision,
-                                      which is not an optimal approach due to a possible future revisions of the module.
-                                      Instead, there should be defined multiple items in the plugins list, each with the
-                                      different revision, but all with the same pointer to the plugin extension. The
-                                      only valid use case for the NULL revision is the case the module has no revision. */
-    const char *name;            /**< name of the extension */
-    struct lyplg_ext *plugin;    /**< plugin for the extension */
-};
-
-/**
- * @brief List of internally implemented extension plugins.
- */
-extern struct lyplg_ext_record lyext_plugins_internal[];
-
-/**
- * @brief Index of Metadata's annotation extension plugin in lyext_plugins_internal
- */
-#define LYEXT_PLUGIN_INTERNAL_ANNOTATION 4
-
-/**
- * @brief Index of yang-data extension plugin in lyext_plugins_internal
- */
-#define LYEXT_PLUGIN_INTERNAL_YANGDATA 5
-
-/**
- * @brief Find the extension plugin for the specified extension instance.
- *
- * @param[in] mod YANG module where the
- */
-struct lyplg_ext *lyext_get_plugin(struct lysc_ext *ext);
-
-#endif /* LY_PLUGINS_EXTS_INTERNAL_H_ */
diff --git a/src/plugins_exts_metadata.c b/src/plugins_exts_metadata.c
index 12b99e8..807122b 100644
--- a/src/plugins_exts_metadata.c
+++ b/src/plugins_exts_metadata.c
@@ -45,7 +45,7 @@
  *
  * Implementation of lyext_clb_compile callback set as lyext_plugin::compile.
  */
-LY_ERR
+static LY_ERR
 annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext)
 {
     LY_ERR ret;
@@ -128,7 +128,7 @@
  *
  * Implementation of lyext_clb_schema_printer set as ::lyext_plugin::sprinter
  */
-LY_ERR
+static LY_ERR
 annotation_schema_printer(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
 {
     lysc_print_extension_instance(ctx, ext, flag);
@@ -141,7 +141,7 @@
  *
  * Implementation of lyext_clb_free callback set as ::lyext_plugin::free.
  */
-void
+static void
 annotation_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
 {
     if (!ext->substmts) {
@@ -153,12 +153,19 @@
 }
 
 /**
- * @brief Plugin for the Metadata's annotation extension
+ * @brief Plugin descriptions for the Metadata's annotation extension
  */
-struct lyplg_ext metadata_plugin = {
-    .id = "libyang 2 - metadata, version 1",
-    .compile = &annotation_compile,
-    .validate = NULL,
-    .sprinter = &annotation_schema_printer,
-    .free = annotation_free
+const struct lyplg_ext_record plugins_metadata[] = {
+    {
+        .module = "ietf-yang-metadata",
+        .revision = "2016-08-05",
+        .name = "annotation",
+
+        .plugin.id = "libyang 2 - metadata, version 1",
+        .plugin.compile = &annotation_compile,
+        .plugin.validate = NULL,
+        .plugin.sprinter = &annotation_schema_printer,
+        .plugin.free = annotation_free
+    },
+    {0}     /* terminating zeroed record */
 };
diff --git a/src/plugins_exts_metadata.h b/src/plugins_exts_metadata.h
index bc78d91..0b0683d 100644
--- a/src/plugins_exts_metadata.h
+++ b/src/plugins_exts_metadata.h
@@ -26,6 +26,8 @@
 #define ANNOTATION_SUBSTMT_DSC     4 /**< index for the LY_STMT_DSC substatement in annotation's ::lysc_ext_instance.substmts */
 #define ANNOTATION_SUBSTMT_REF     5 /**< index for the LY_STMT_REF substatement in annotation's ::lysc_ext_instance.substmts */
 
+#define LYEXT_PLUGIN_INTERNAL_ANNOTATION "ietf-yang-metadata", "2016-08-05", "annotation"
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/plugins_exts_nacm.c b/src/plugins_exts_nacm.c
index 0dab1c2..5002e6f 100644
--- a/src/plugins_exts_nacm.c
+++ b/src/plugins_exts_nacm.c
@@ -82,7 +82,7 @@
  *
  * Implementation of lyext_clb_compile callback set as lyext_plugin::compile.
  */
-LY_ERR
+static LY_ERR
 nacm_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext)
 {
     LY_ERR ret;
@@ -126,9 +126,9 @@
 
     /* check for duplication */
     LY_ARRAY_FOR(parent->exts, u) {
-        if ((&parent->exts[u] != c_ext) && (parent->exts[u].def->plugin == c_ext->def->plugin)) {
+        if ((&parent->exts[u] != c_ext) && (parent->exts[u].def->plugin->compile == c_ext->def->plugin->compile)) {
             /* duplication of a NACM extension on a single node
-             * We check plugin since we want to catch even the situation that there is default-deny-all
+             * We check for all NACM plugins since we want to catch even the situation that there is default-deny-all
              * AND default-deny-write */
             if (parent->exts[u].def == c_ext->def) {
                 lyext_log(c_ext, LY_LLERR, LY_EVALID, lysc_ctx_get_path(cctx),
@@ -150,12 +150,49 @@
 }
 
 /**
- * @brief Plugin for the NACM's default-deny-write and default-deny-all extensions
+ * @brief Plugin descriptions for the NACM's default-deny-write and default-deny-all extensions
  */
-struct lyplg_ext nacm_plugin = {
-    .id = "libyang 2 - NACM, version 1",
-    .compile = &nacm_compile,
-    .validate = NULL,
-    .sprinter = NULL,
-    .free = NULL
+const struct lyplg_ext_record plugins_nacm[] = {
+    {
+        .module = "ietf-netconf-acm",
+        .revision = "2012-02-22",
+        .name = "default-deny-write",
+
+        .plugin.id = "libyang 2 - NACM, version 1",
+        .plugin.compile = &nacm_compile,
+        .plugin.validate = NULL,
+        .plugin.sprinter = NULL,
+        .plugin.free = NULL
+    }, {
+        .module = "ietf-netconf-acm",
+        .revision = "2018-02-14",
+        .name = "default-deny-write",
+
+        .plugin.id = "libyang 2 - NACM, version 1",
+        .plugin.compile = &nacm_compile,
+        .plugin.validate = NULL,
+        .plugin.sprinter = NULL,
+        .plugin.free = NULL
+    }, {
+        .module = "ietf-netconf-acm",
+        .revision = "2012-02-22",
+        .name = "default-deny-all",
+
+        .plugin.id = "libyang 2 - NACM, version 1",
+        .plugin.compile = &nacm_compile,
+        .plugin.validate = NULL,
+        .plugin.sprinter = NULL,
+        .plugin.free = NULL
+    }, {
+        .module = "ietf-netconf-acm",
+        .revision = "2018-02-14",
+        .name = "default-deny-all",
+
+        .plugin.id = "libyang 2 - NACM, version 1",
+        .plugin.compile = &nacm_compile,
+        .plugin.validate = NULL,
+        .plugin.sprinter = NULL,
+        .plugin.free = NULL
+    },
+    {0} /* terminating zeroed item */
 };
diff --git a/src/plugins_exts_yangdata.c b/src/plugins_exts_yangdata.c
index f06fd64..890266d 100644
--- a/src/plugins_exts_yangdata.c
+++ b/src/plugins_exts_yangdata.c
@@ -30,7 +30,7 @@
  *
  * Implementation of ::lyext_clb_free callback set as lyext_plugin::free.
  */
-void
+static void
 yangdata_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
 {
     lysc_extension_instance_substatements_free(ctx, ext->substmts);
@@ -41,7 +41,7 @@
  *
  * Implementation of lyext_clb_compile callback set as lyext_plugin::compile.
  */
-LY_ERR
+static LY_ERR
 yangdata_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext)
 {
     LY_ERR ret;
@@ -156,7 +156,7 @@
  *
  * Implementation of ::lyext_clb_schema_printer set as ::lyext_plugin::sprinter
  */
-LY_ERR
+static LY_ERR
 yangdata_schema_printer(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
 {
     lysc_print_extension_instance(ctx, ext, flag);
@@ -164,12 +164,19 @@
 }
 
 /**
- * @brief Plugin for the yang-data extension
+ * @brief Plugin descriptions for the yang-data extension
  */
-struct lyplg_ext yangdata_plugin = {
-    .id = "libyang 2 - yang-data, version 1",
-    .compile = &yangdata_compile,
-    .validate = NULL,
-    .sprinter = &yangdata_schema_printer,
-    .free = yangdata_free
+const struct lyplg_ext_record plugins_yangdata[] = {
+    {
+        .module = "ietf-restconf",
+        .revision = "2017-01-26",
+        .name = "yang-data",
+
+        .plugin.id = "libyang 2 - yang-data, version 1",
+        .plugin.compile = &yangdata_compile,
+        .plugin.validate = NULL,
+        .plugin.sprinter = &yangdata_schema_printer,
+        .plugin.free = yangdata_free
+    },
+    {0}     /* terminating zeroed record */
 };
diff --git a/src/plugins_internal.h b/src/plugins_internal.h
index 7fc5530..dd10823 100644
--- a/src/plugins_internal.h
+++ b/src/plugins_internal.h
@@ -15,6 +15,12 @@
 #ifndef LY_PLUGINS_INTERNAL_H_
 #define LY_PLUGINS_INTERNAL_H_
 
+#include <stdint.h>
+
+#include "plugins.h"
+#include "plugins_exts.h"
+#include "tree_schema.h"
+
 #define LY_TYPE_UNKNOWN_STR "unknown"               /**< text representation of ::LY_TYPE_UNKNOWN */
 #define LY_TYPE_BINARY_STR "binary"                 /**< text representation of ::LY_TYPE_BINARY */
 #define LY_TYPE_UINT8_STR "8bit unsigned integer"   /**< text representation of ::LY_TYPE_UINT8 */
@@ -36,4 +42,34 @@
 #define LY_TYPE_INT32_STR "32bit integer"           /**< text representation of ::LY_TYPE_INT32 */
 #define LY_TYPE_INT64_STR "64bit integer"           /**< text representation of ::LY_TYPE_INT64 */
 
+/**
+ * @brief Initiate libyang plugins.
+ *
+ * Covers both the types and extensions plugins.
+ *
+ * @return LY_SUCCESS in case of success
+ * @return LY_EINT in case of internal error
+ * @return LY_EMEM in case of memory allocation failure.
+ */
+LY_ERR lyplg_init(void);
+
+/**
+ * @brief Remove (unload) all the plugins currently available.
+ */
+void lyplg_clean(void);
+
+/**
+ * @brief Find the plugin matching the provided attributes.
+ *
+ * @param[in] type Type of the plugin to find (type or extension)
+ * @param[in] module Name of the module where the type/extension is defined. Must not be NULL, in case of plugins for
+ * built-in types, the module is "".
+ * @param[in] revision The revision of the module for which the plugin is implemented. NULL is not a wildcard, it matches
+ * only the plugins with NULL revision specified.
+ * @param[in] name Name of the type/extension which the plugin implements.
+ * @return NULL if the plugin matching the restrictions is not present.
+ * @return Pointer to the matching ::ly_type_plugin or ::lyext_plugin according to the plugin's @p type.
+ */
+void *lyplg_find(enum LYPLG type, const char *module, const char *revision, const char *name);
+
 #endif /* LY_PLUGINS_INTERNAL_H_ */
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 8e58a0c..49d9490 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -824,157 +824,3 @@
     lyxp_set_free_content(&set);
     return ret;
 }
-
-/* plugins_types_binary.c */
-extern LY_ERR ly_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-
-/* plugins_types_integer.c */
-extern LY_ERR ly_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-extern LY_ERR ly_type_store_uint(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-
-/* plugins_types_string.c */
-extern LY_ERR ly_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-
-/* plugins_types_bits.c */
-extern LY_ERR ly_type_store_bits(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-extern LY_ERR ly_type_dup_bits(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup);
-extern void ly_type_free_bits(const struct ly_ctx *ctx, struct lyd_value *value);
-
-/* plugins_types_boolean.c */
-extern LY_ERR ly_type_store_boolean(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-
-/* plugins_types_decimal64.c */
-extern LY_ERR ly_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-
-/* plugins_types_empty.c */
-extern LY_ERR ly_type_store_empty(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-extern LY_ERR ly_type_compare_empty(const struct lyd_value *val1, const struct lyd_value *val2);
-
-/* plugins_types_enumeration.c */
-extern LY_ERR ly_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-
-/* plugins_types_identityref.c */
-extern LY_ERR ly_type_store_identityref(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-extern LY_ERR ly_type_compare_identityref(const struct lyd_value *val1, const struct lyd_value *val2);
-extern const char *ly_type_print_identityref(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data,
-        ly_bool *dynamic);
-
-/* plugins_types_instanceid.c */
-extern LY_ERR ly_type_store_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-extern LY_ERR ly_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err);
-extern LY_ERR ly_type_compare_instanceid(const struct lyd_value *val1, const struct lyd_value *val2);
-extern const char *ly_type_print_instanceid(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data,
-        ly_bool *dynamic);
-extern LY_ERR ly_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup);
-extern void ly_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value);
-
-/* plugins_types_leafref.c */
-extern LY_ERR ly_type_store_leafref(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-extern LY_ERR ly_type_validate_leafref(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err);
-extern LY_ERR ly_type_compare_leafref(const struct lyd_value *val1, const struct lyd_value *val2);
-extern const char *ly_type_print_leafref(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data,
-        ly_bool *dynamic);
-extern LY_ERR ly_type_dup_leafref(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup);
-extern void ly_type_free_leafref(const struct ly_ctx *ctx, struct lyd_value *value);
-
-/* plugins_types_union.c */
-extern LY_ERR ly_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const char *value, size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
-extern LY_ERR ly_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type,
-        const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err);
-extern LY_ERR ly_type_compare_union(const struct lyd_value *val1, const struct lyd_value *val2);
-extern const char *ly_type_print_union(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data,
-        ly_bool *dynamic);
-extern LY_ERR ly_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup);
-extern void ly_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value);
-
-/**
- * @brief Set of type plugins for YANG built-in types
- */
-struct lyplg_type ly_builtin_type_plugins[LY_DATA_TYPE_COUNT] = {
-    {0}, /* LY_TYPE_UNKNOWN */
-    {.type = LY_TYPE_BINARY, .store = ly_type_store_binary, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - binary, version 1"},
-    {.type = LY_TYPE_UINT8, .store = ly_type_store_uint, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - unsigned integer, version 1"},
-    {.type = LY_TYPE_UINT16, .store = ly_type_store_uint, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - unsigned integer, version 1"},
-    {.type = LY_TYPE_UINT32, .store = ly_type_store_uint, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - unsigned integer, version 1"},
-    {.type = LY_TYPE_UINT64, .store = ly_type_store_uint, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - unsigned integer, version 1"},
-    {.type = LY_TYPE_STRING, .store = ly_type_store_string, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - string, version 1"},
-    {.type = LY_TYPE_BITS, .store = ly_type_store_bits, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_bits, .free = ly_type_free_bits,
-        .id = "libyang 2 - bits, version 1"},
-    {.type = LY_TYPE_BOOL, .store = ly_type_store_boolean, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - boolean, version 1"},
-    {.type = LY_TYPE_DEC64, .store = ly_type_store_decimal64, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - decimal64, version 1"},
-    {.type = LY_TYPE_EMPTY, .store = ly_type_store_empty, .validate = NULL, .compare = ly_type_compare_empty,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - empty, version 1"},
-    {.type = LY_TYPE_ENUM, .store = ly_type_store_enum, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - enumeration, version 1"},
-    {.type = LY_TYPE_IDENT, .store = ly_type_store_identityref, .validate = NULL, .compare = ly_type_compare_identityref,
-        .print = ly_type_print_identityref, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - identityref, version 1"},
-    {.type = LY_TYPE_INST, .store = ly_type_store_instanceid, .validate = ly_type_validate_instanceid,
-        .compare = ly_type_compare_instanceid, .print = ly_type_print_instanceid, .duplicate = ly_type_dup_instanceid,
-        .free = ly_type_free_instanceid, .id = "libyang 2 - instance-identifier, version 1"},
-    {.type = LY_TYPE_LEAFREF, .store = ly_type_store_leafref, .validate = ly_type_validate_leafref,
-        .compare = ly_type_compare_leafref, .print = ly_type_print_leafref, .duplicate = ly_type_dup_leafref,
-        .free = ly_type_free_leafref, .id = "libyang 2 - leafref, version 1"},
-    {.type = LY_TYPE_UNION, .store = ly_type_store_union, .validate = ly_type_validate_union,
-        .compare = ly_type_compare_union, .print = ly_type_print_union, .duplicate = ly_type_dup_union,
-        .free = ly_type_free_union, .id = "libyang 2 - union,version 1"},
-    {.type = LY_TYPE_INT8, .store = ly_type_store_int, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - integer, version 1"},
-    {.type = LY_TYPE_INT16, .store = ly_type_store_int, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - integer, version 1"},
-    {.type = LY_TYPE_INT32, .store = ly_type_store_int, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - integer, version 1"},
-    {.type = LY_TYPE_INT64, .store = ly_type_store_int, .validate = NULL, .compare = ly_type_compare_simple,
-        .print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
-        .id = "libyang 2 - integer, version 1"},
-};
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 5a5f06d..5c10500 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -19,6 +19,7 @@
 #include <stdint.h>
 
 #include "log.h"
+#include "plugins.h"
 #include "tree.h"
 
 #include "tree_edit.h"
@@ -371,7 +372,7 @@
  * functionality.
  */
 struct lyplg_type {
-    LY_DATA_TYPE type;               /**< implemented type, use LY_TYPE_UNKNOWN for derived data types */
+    LY_DATA_TYPE type;               /**< implemented type, use ::LY_TYPE_UNKNOWN for derived data types */
     ly_type_store_clb store;         /**< store and canonize the value in the type-specific way */
     ly_type_validate_clb validate;   /**< optional, validate the value in the type-specific way in data */
     ly_type_compare_clb compare;     /**< comparison callback to compare 2 values of the same type */
@@ -381,12 +382,19 @@
     const char *id;                  /**< Plugin identification (mainly for distinguish incompatible versions when used by external tools) */
 };
 
-/**
- * @brief List of type plugins for built-in types.
- *
- * TODO hide behind some plugin getter
- */
-extern struct lyplg_type ly_builtin_type_plugins[LY_DATA_TYPE_COUNT];
+struct lyplg_type_record {
+    /* plugin identification */
+    const char *module;          /**< name of the module where the type is defined (top-level typedef) */
+    const char *revision;        /**< optional module revision - if not specified, the plugin applies to any revision,
+                                      which is not an optimal approach due to a possible future revisions of the module.
+                                      Instead, there should be defined multiple items in the plugins list, each with the
+                                      different revision, but all with the same pointer to the plugin functions. The
+                                      only valid use case for the NULL revision is the case the module has no revision. */
+    const char *name;            /**< name of the typedef */
+
+    /* runtime data */
+    struct lyplg_type plugin; /**< data to utilize plugin implementation */
+};
 
 /**
  * @brief Generic simple comparison callback checking the canonical value.
diff --git a/src/plugins_types_binary.c b/src/plugins_types_binary.c
index c5cb593..3740cc9 100644
--- a/src/plugins_types_binary.c
+++ b/src/plugins_types_binary.c
@@ -26,6 +26,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API LY_ERR
 ly_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
@@ -123,3 +124,21 @@
     }
     return ret;
 }
+
+const struct lyplg_type_record plugins_binary[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_BINARY_STR,
+
+        .plugin.id = "libyang 2 - binary, version 1",
+        .plugin.type = LY_TYPE_BINARY,
+        .plugin.store = ly_type_store_binary,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple,
+    },
+    {0}
+};
diff --git a/src/plugins_types_bits.c b/src/plugins_types_bits.c
index 1cf1445..85a5f1b 100644
--- a/src/plugins_types_bits.c
+++ b/src/plugins_types_bits.c
@@ -28,6 +28,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API LY_ERR
 ly_type_store_bits(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
@@ -220,3 +221,21 @@
     lydict_remove(ctx, value->canonical);
     value->canonical = NULL;
 }
+
+const struct lyplg_type_record plugins_bits[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_BITS_STR,
+
+        .plugin.id = "libyang 2 - bits, version 1",
+        .plugin.type = LY_TYPE_BITS,
+        .plugin.store = ly_type_store_bits,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_bits,
+        .plugin.free = ly_type_free_bits
+    },
+    {0}
+};
diff --git a/src/plugins_types_boolean.c b/src/plugins_types_boolean.c
index db2148c..5153e1b 100644
--- a/src/plugins_types_boolean.c
+++ b/src/plugins_types_boolean.c
@@ -26,6 +26,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API LY_ERR
 ly_type_store_boolean(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
@@ -68,3 +69,21 @@
     }
     return ret;
 }
+
+const struct lyplg_type_record plugins_boolean[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_BOOL_STR,
+
+        .plugin.id = "libyang 2 - boolean, version 1",
+        .plugin.type = LY_TYPE_BOOL,
+        .plugin.store = ly_type_store_boolean,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    },
+    {0}
+};
diff --git a/src/plugins_types_decimal64.c b/src/plugins_types_decimal64.c
index d4044e8..fb78483 100644
--- a/src/plugins_types_decimal64.c
+++ b/src/plugins_types_decimal64.c
@@ -27,6 +27,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API LY_ERR
 ly_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
@@ -96,3 +97,21 @@
     }
     return ret;
 }
+
+const struct lyplg_type_record plugins_decimal64[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_DEC64_STR,
+
+        .plugin.id = "libyang 2 - decimal64, version 1",
+        .plugin.type = LY_TYPE_DEC64,
+        .plugin.store = ly_type_store_decimal64,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    },
+    {0}
+};
diff --git a/src/plugins_types_empty.c b/src/plugins_types_empty.c
index 4da1e88..07482cc 100644
--- a/src/plugins_types_empty.c
+++ b/src/plugins_types_empty.c
@@ -25,6 +25,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API LY_ERR
 ly_type_store_empty(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
@@ -73,3 +74,21 @@
     /* empty has just one value, so empty data must be always the same */
     return LY_SUCCESS;
 }
+
+const struct lyplg_type_record plugins_empty[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_EMPTY_STR,
+
+        .plugin.id = "libyang 2 - empty, version 1",
+        .plugin.type = LY_TYPE_EMPTY,
+        .plugin.store = ly_type_store_empty,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_empty,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    },
+    {0}
+};
diff --git a/src/plugins_types_enumeration.c b/src/plugins_types_enumeration.c
index 15b21e1..eb56210 100644
--- a/src/plugins_types_enumeration.c
+++ b/src/plugins_types_enumeration.c
@@ -25,6 +25,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API LY_ERR
 ly_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
@@ -74,3 +75,21 @@
 
     return ret;
 }
+
+const struct lyplg_type_record plugins_enumeration[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_ENUM_STR,
+
+        .plugin.id = "libyang 2 - enumeration, version 1",
+        .plugin.type = LY_TYPE_ENUM,
+        .plugin.store = ly_type_store_enum,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    },
+    {0}
+};
diff --git a/src/plugins_types_identityref.c b/src/plugins_types_identityref.c
index 3535c07..95a7731 100644
--- a/src/plugins_types_identityref.c
+++ b/src/plugins_types_identityref.c
@@ -27,6 +27,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API const char *
 ly_type_print_identityref(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data, ly_bool *dynamic)
@@ -172,3 +173,21 @@
     }
     return LY_ENOT;
 }
+
+const struct lyplg_type_record plugins_identityref[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_IDENT_STR,
+
+        .plugin.id = "libyang 2 - identityref, version 1",
+        .plugin.type = LY_TYPE_IDENT,
+        .plugin.store = ly_type_store_identityref,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_identityref,
+        .plugin.print = ly_type_print_identityref,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    },
+    {0}
+};
diff --git a/src/plugins_types_instanceid.c b/src/plugins_types_instanceid.c
index 7bebe34..baacd19 100644
--- a/src/plugins_types_instanceid.c
+++ b/src/plugins_types_instanceid.c
@@ -28,8 +28,8 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
-
 #include "path.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API const char *
 ly_type_print_instanceid(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data, ly_bool *dynamic)
@@ -289,3 +289,21 @@
     value->target = NULL;
     ly_type_free_simple(ctx, value);
 }
+
+const struct lyplg_type_record plugins_instanceid[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_INST_STR,
+
+        .plugin.id = "libyang 2 - instance-identifier, version 1",
+        .plugin.type = LY_TYPE_INST,
+        .plugin.store = ly_type_store_instanceid,
+        .plugin.validate = ly_type_validate_instanceid,
+        .plugin.compare = ly_type_compare_instanceid,
+        .plugin.print = ly_type_print_instanceid,
+        .plugin.duplicate = ly_type_dup_instanceid,
+        .plugin.free = ly_type_free_instanceid
+    },
+    {0}
+};
diff --git a/src/plugins_types_integer.c b/src/plugins_types_integer.c
index f0e5383..4e9b919 100644
--- a/src/plugins_types_integer.c
+++ b/src/plugins_types_integer.c
@@ -26,6 +26,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API LY_ERR
 ly_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
@@ -139,3 +140,112 @@
     }
     return ret;
 }
+
+const struct lyplg_type_record plugins_integer[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_UINT8_STR,
+
+        .plugin.id = "libyang 2 - integers, version 1",
+        .plugin.type = LY_TYPE_UINT8,
+        .plugin.store = ly_type_store_uint,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    }, {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_UINT16_STR,
+
+        .plugin.id = "libyang 2 - integers, version 1",
+        .plugin.type = LY_TYPE_UINT16,
+        .plugin.store = ly_type_store_uint,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    }, {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_UINT32_STR,
+
+        .plugin.id = "libyang 2 - integers, version 1",
+        .plugin.type = LY_TYPE_UINT32,
+        .plugin.store = ly_type_store_uint,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    }, {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_UINT64_STR,
+
+        .plugin.id = "libyang 2 - integers, version 1",
+        .plugin.type = LY_TYPE_UINT64,
+        .plugin.store = ly_type_store_uint,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    }, {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_INT8_STR,
+
+        .plugin.id = "libyang 2 - integers, version 1",
+        .plugin.type = LY_TYPE_INT8,
+        .plugin.store = ly_type_store_int,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    }, {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_INT16_STR,
+
+        .plugin.id = "libyang 2 - integers, version 1",
+        .plugin.type = LY_TYPE_INT16,
+        .plugin.store = ly_type_store_int,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    }, {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_INT32_STR,
+
+        .plugin.id = "libyang 2 - integers, version 1",
+        .plugin.type = LY_TYPE_INT32,
+        .plugin.store = ly_type_store_int,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    }, {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_INT64_STR,
+
+        .plugin.id = "libyang 2 - integers, version 1",
+        .plugin.type = LY_TYPE_INT64,
+        .plugin.store = ly_type_store_int,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    },
+    {0}
+};
diff --git a/src/plugins_types_leafref.c b/src/plugins_types_leafref.c
index 34c7523..507b128 100644
--- a/src/plugins_types_leafref.c
+++ b/src/plugins_types_leafref.c
@@ -26,6 +26,9 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
+
+const struct lyplg_type_record plugins_leafref[];
 
 API LY_ERR
 ly_type_store_leafref(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
@@ -101,8 +104,26 @@
 API void
 ly_type_free_leafref(const struct ly_ctx *ctx, struct lyd_value *value)
 {
-    if (value->realtype->plugin != &ly_builtin_type_plugins[LY_TYPE_LEAFREF]) {
+    if (value->realtype->plugin != &plugins_leafref[0].plugin) {
         /* leafref's realtype is again leafref only in case of incomplete store */
         value->realtype->plugin->free(ctx, value);
     }
 }
+
+const struct lyplg_type_record plugins_leafref[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_LEAFREF_STR,
+
+        .plugin.id = "libyang 2 - leafref, version 1",
+        .plugin.type = LY_TYPE_LEAFREF,
+        .plugin.store = ly_type_store_leafref,
+        .plugin.validate = ly_type_validate_leafref,
+        .plugin.compare = ly_type_compare_leafref,
+        .plugin.print = ly_type_print_leafref,
+        .plugin.duplicate = ly_type_dup_leafref,
+        .plugin.free = ly_type_free_leafref
+    },
+    {0}
+};
diff --git a/src/plugins_types_string.c b/src/plugins_types_string.c
index af08545..c78e0e5 100644
--- a/src/plugins_types_string.c
+++ b/src/plugins_types_string.c
@@ -25,6 +25,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 API LY_ERR
 ly_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
@@ -72,3 +73,21 @@
 
     return ret;
 }
+
+const struct lyplg_type_record plugins_string[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_STRING_STR,
+
+        .plugin.id = "libyang 2 - string, version 1",
+        .plugin.type = LY_TYPE_STRING,
+        .plugin.store = ly_type_store_string,
+        .plugin.validate = NULL,
+        .plugin.compare = ly_type_compare_simple,
+        .plugin.print = ly_type_print_simple,
+        .plugin.duplicate = ly_type_dup_simple,
+        .plugin.free = ly_type_free_simple
+    },
+    {0}
+};
diff --git a/src/plugins_types_union.c b/src/plugins_types_union.c
index 17a0fcc..7f5c7f1 100644
--- a/src/plugins_types_union.c
+++ b/src/plugins_types_union.c
@@ -26,6 +26,7 @@
 /* additional internal headers for some useful simple macros */
 #include "common.h"
 #include "compat.h"
+#include "plugins_internal.h" /* LY_TYPE_*_STR */
 
 static LY_ERR
 ly_type_union_store_type(const struct ly_ctx *ctx, struct lysc_type **types, struct lyd_value_subvalue *subvalue,
@@ -229,3 +230,21 @@
         value->subvalue = NULL;
     }
 }
+
+const struct lyplg_type_record plugins_union[] = {
+    {
+        .module = "",
+        .revision = NULL,
+        .name = LY_TYPE_UNION_STR,
+
+        .plugin.id = "libyang 2 - union,version 1",
+        .plugin.type = LY_TYPE_UNION,
+        .plugin.store = ly_type_store_union,
+        .plugin.validate = ly_type_validate_union,
+        .plugin.compare = ly_type_compare_union,
+        .plugin.print = ly_type_print_union,
+        .plugin.duplicate = ly_type_dup_union,
+        .plugin.free = ly_type_free_union
+    },
+    {0}
+};
diff --git a/src/schema_compile.c b/src/schema_compile.c
index 0877fea..3588a7d 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -33,7 +33,7 @@
 #include "path.h"
 #include "plugins_exts.h"
 #include "plugins_exts_compile.h"
-#include "plugins_exts_internal.h"
+#include "plugins_internal.h"
 #include "plugins_types.h"
 #include "schema_compile_amend.h"
 #include "schema_compile_node.h"
@@ -76,7 +76,8 @@
         lysc_update_path(ctx, NULL, NULL);
 
         /* find extension definition plugin */
-        ext_p->compiled->plugin = lyext_get_plugin(ext_p->compiled);
+        ext_p->compiled->plugin = lyplg_find(LYPLG_EXTENSION, ext_p->compiled->module->name,
+                ext_p->compiled->module->revision, ext_p->compiled->name);
     }
 
     *ext = lysc_ext_dup(ext_p->compiled);
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index 5bd4acd..24187ad 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -1938,7 +1938,7 @@
 
         (*type)->basetype = basetype;
         /* TODO user type plugins */
-        (*type)->plugin = &ly_builtin_type_plugins[basetype];
+        (*type)->plugin = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[basetype]);
         prev_type = *type;
         ret = lys_compile_type_(ctx, tctx->node, tctx->tpdf->flags, tctx->tpdf->name,
                 &((struct lysp_tpdf *)tctx->tpdf)->type, basetype, tctx->tpdf->name, base, type);
@@ -1953,7 +1953,7 @@
         /* get restrictions from the node itself */
         (*type)->basetype = basetype;
         /* TODO user type plugins */
-        (*type)->plugin = &ly_builtin_type_plugins[basetype];
+        (*type)->plugin = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[basetype]);
         ++(*type)->refcount;
         ret = lys_compile_type_(ctx, context_pnode, context_flags, context_name, type_p, basetype, NULL, base, type);
         LY_CHECK_GOTO(ret, cleanup);
diff --git a/src/tree_data.c b/src/tree_data.c
index c4e3013..3d4fe56 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -38,8 +38,8 @@
 #include "parser_internal.h"
 #include "path.h"
 #include "plugins_exts.h"
-#include "plugins_exts_internal.h"
 #include "plugins_exts_metadata.h"
+#include "plugins_internal.h"
 #include "plugins_types.h"
 #include "set.h"
 #include "tree.h"
@@ -2645,7 +2645,7 @@
     LOG_LOCSET(parent ? parent->schema : NULL, parent, NULL, NULL);
 
     LY_ARRAY_FOR(mod->compiled->exts, u) {
-        if ((mod->compiled->exts[u].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin) &&
+        if ((mod->compiled->exts[u].def->plugin == lyplg_find(LYPLG_EXTENSION, LYEXT_PLUGIN_INTERNAL_ANNOTATION)) &&
                 !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
             /* we have the annotation definition */
             ant = &mod->compiled->exts[u];
diff --git a/tests/utests/types/bits.c b/tests/utests/types/bits.c
index 2436f36..7b871e7 100644
--- a/tests/utests/types/bits.c
+++ b/tests/utests/types/bits.c
@@ -755,7 +755,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value value = {0};
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_BITS]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_BITS]);
     struct lysc_type *lysc_type;
     struct lysc_type lysc_type_test;
     LY_ERR ly_ret;
@@ -850,7 +850,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value values[10];
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_BITS]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_BITS]);
     struct lysc_type *lysc_type;
     LY_ERR ly_ret;
     const char *schema;
@@ -940,7 +940,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value values[10];
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_BITS]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_BITS]);
     struct lysc_type *lysc_type;
     LY_ERR ly_ret;
     const char *schema;
@@ -982,7 +982,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value values[10];
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_BITS]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_BITS]);
     struct lysc_type *lysc_type;
     const char *schema;
     LY_ERR ly_ret;
diff --git a/tests/utests/types/int8.c b/tests/utests/types/int8.c
index 254888f..a76a784 100644
--- a/tests/utests/types/int8.c
+++ b/tests/utests/types/int8.c
@@ -22,6 +22,7 @@
 /* LOCAL INCLUDE HEADERS */
 #include "libyang.h"
 #include "path.h"
+#include "plugins_internal.h"
 
 #define LYD_TREE_CREATE(INPUT, MODEL) \
     CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, MODEL)
@@ -1379,7 +1380,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value value = {0};
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_INT8]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_INT8]);
     struct lysc_type *lysc_type;
     LY_ERR ly_ret;
     char *alloc;
@@ -1393,7 +1394,7 @@
 
     /* check proper type */
     assert_int_equal(LY_TYPE_INT8, type->type);
-    assert_string_equal("libyang 2 - integer, version 1", type->id);
+    assert_string_equal("libyang 2 - integers, version 1", type->id);
 
     /* check store
      * options = LY_TYPE_STORE_IMPLEMENT | LY_TYPE_STORE_DYNAMIC
@@ -1514,7 +1515,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value values[10];
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_INT8]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_INT8]);
     struct lysc_type *lysc_type;
     LY_ERR ly_ret;
     const char *schema;
@@ -1602,7 +1603,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value values[10];
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_INT8]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_INT8]);
     struct lysc_type *lysc_type;
     LY_ERR ly_ret;
     const char *schema;
@@ -1642,7 +1643,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value values[10];
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_INT8]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_INT8]);
     struct lysc_type *lysc_type[2];
     const char *schema;
     LY_ERR ly_ret;
diff --git a/tests/utests/types/string.c b/tests/utests/types/string.c
index c838e1f..f771e39 100644
--- a/tests/utests/types/string.c
+++ b/tests/utests/types/string.c
@@ -21,6 +21,7 @@
 /* LOCAL INCLUDE HEADERS */
 #include "libyang.h"
 #include "path.h"
+#include "plugins_internal.h"
 
 #define MODULE_CREATE_YIN(MOD_NAME, NODES) \
     "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
@@ -1040,7 +1041,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value value = {0};
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_STRING]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_STRING]);
     struct lysc_type *lysc_type;
     char *alloc_text;
     unsigned int alloc_text_size;
@@ -1149,7 +1150,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value values[10];
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_STRING]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_STRING]);
     struct lysc_type *lysc_type;
     LY_ERR ly_ret;
     const char *schema;
@@ -1230,7 +1231,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value values[10];
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_STRING]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_STRING]);
     struct lysc_type *lysc_type;
     LY_ERR ly_ret;
 
@@ -1269,7 +1270,7 @@
     struct ly_err_item *err = NULL;
     const struct lys_module *mod;
     struct lyd_value values[10];
-    struct lyplg_type *type = &(ly_builtin_type_plugins[LY_TYPE_STRING]);
+    struct lyplg_type *type = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[LY_TYPE_STRING]);
     struct lysc_type *lysc_type[2];
     const char *schema;
     LY_ERR ly_ret;
diff --git a/tests/utests/utests.h b/tests/utests/utests.h
index d43506d..c3bfb73 100644
--- a/tests/utests/utests.h
+++ b/tests/utests/utests.h
@@ -27,6 +27,7 @@
 #include <string.h>
 
 #include "libyang.h"
+#include "plugins_internal.h"
 #include "plugins_types.h"
 #include "tests/config.h"
 #include "tree_schema_internal.h"
@@ -217,7 +218,7 @@
     assert_non_null(NODE); \
     assert_int_equal((NODE)->basetype, TYPE); \
     CHECK_ARRAY((NODE)->exts, EXTS); \
-    assert_ptr_equal((NODE)->plugin, &(ly_builtin_type_plugins[TYPE]))
+    assert_ptr_equal((NODE)->plugin, lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[TYPE]))
 
 /* @brief check compileted numeric type
  * @param[in] NODE pointer to lysc_type_num value