extensions CHANGE CHANGE cleanup API of the schema printer for extension plugins

Be more clear by what API of the compiled schema printer is available for the
extension plugins. While the printer context is needed, we want to keep its
members hidden to be able to make future changes. Therefore, there is only a
(possibly extensible in a future) set of getters to access the context's members
to be read and updated by the plugins' printer callbacks.

The patch also explicitely states the common compatible members of the
different schema printers.
diff --git a/src/plugins_exts.c b/src/plugins_exts.c
index ded7c5e..11ada75 100644
--- a/src/plugins_exts.c
+++ b/src/plugins_exts.c
@@ -24,6 +24,7 @@
 
 /* internal libyang headers - do not make them accessible to the extension plugins in plugins_exts_*.c */
 #include "common.h"
+#include "printer_internal.h"
 #include "schema_compile.h"
 
 /**
@@ -73,3 +74,21 @@
 {
     return ctx->path;
 }
+
+API struct ly_out **
+lys_ypr_ctx_get_out(const struct lyspr_ctx *ctx)
+{
+    return &((struct lyspr_ctx *)ctx)->out;
+}
+
+API uint32_t *
+lys_ypr_ctx_get_options(const struct lyspr_ctx *ctx)
+{
+    return &((struct lyspr_ctx *)ctx)->options;
+}
+
+API uint16_t *
+lys_ypr_ctx_get_level(const struct lyspr_ctx *ctx)
+{
+    return &((struct lyspr_ctx *)ctx)->level;
+}
diff --git a/src/plugins_exts.h b/src/plugins_exts.h
index ebeead8..77950d3 100644
--- a/src/plugins_exts.h
+++ b/src/plugins_exts.h
@@ -20,6 +20,7 @@
 #include "tree_schema.h"
 
 #include "plugins_exts_compile.h"
+#include "plugins_exts_print.h"
 
 struct ly_ctx;
 struct lyd_node;
@@ -71,41 +72,6 @@
 };
 
 /**
- * @brief Types of the YANG printers
- */
-enum lys_ypr_schema_type {
-    LYS_YPR_PARSED,   /**< YANG printer of the parsed schema */
-    LYS_YPR_COMPILED  /**< YANG printer of the compiled schema */
-};
-
-/**
- * @brief Compiled YANG printer context for use in ::lyext_clb_schema_printer callback implementation.
- *
- * The structure provides basic information how the compiled schema is supposed to be printed and where. In the most simple
- * case, the provided context is just passed into ::lysc_print_extension_instance() function which handles printing the
- * extension's substatements in the standard way.
- */
-struct lys_ypr_ctx {
-    struct ly_out *out;              /**< output specification */
-    uint16_t level;                  /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
-    uint32_t options;                /**< Schema output options (see @ref schemaprinterflags). */
-    const struct lys_module *module; /**< schema to print */
-    enum lys_ypr_schema_type schema; /**< type of the schema to print */
-};
-
-/**
- * @brief Print substatements of an extension instance
- *
- * Generic function to access YANG printer functions from the extension plugins (::lyext_clb_schema_printer).
- *
- * @param[in] ctx YANG printer context to provide output handler and other information for printing.
- * @param[in] ext The compiled extension instance to access the extensions and substatements data.
- * @param[in, out] flag Flag to be shared with the caller regarding the opening brackets - 0 if the '{' not yet printed,
- * 1 otherwise.
- */
-void lysc_print_extension_instance(struct lys_ypr_ctx *ctx, const struct lysc_ext_instance *ext, ly_bool *flag);
-
-/**
  * @brief Free the extension instance's data compiled with ::lys_compile_extension_instance().
  *
  * @param[in] libyang context
@@ -187,7 +153,7 @@
  *
  * @return LY_SUCCESS when everything was fine, other LY_ERR values in case of failure
  */
-typedef LY_ERR (*lyext_clb_schema_printer)(struct lys_ypr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag);
+typedef LY_ERR (*lyext_clb_schema_printer)(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag);
 
 /**
  * @brief Extension plugin implementing various aspects of a YANG extension
diff --git a/src/plugins_exts_compile.h b/src/plugins_exts_compile.h
index 42e21fd..260d1d5 100644
--- a/src/plugins_exts_compile.h
+++ b/src/plugins_exts_compile.h
@@ -76,7 +76,7 @@
 /**
  * @brief YANG schema compilation context getter for compilation options.
  * @param[in] ctx YANG schema compilation context.
- * @return pointer to the compilation context to allow modifying the options with @ref scflags values.
+ * @return pointer to the compilation options to allow modifying them with @ref scflags values.
  */
 uint32_t *lysc_ctx_get_options(const struct lysc_ctx *ctx);
 
diff --git a/src/plugins_exts_metadata.c b/src/plugins_exts_metadata.c
index f4ab6f8..4b8527e 100644
--- a/src/plugins_exts_metadata.c
+++ b/src/plugins_exts_metadata.c
@@ -125,7 +125,7 @@
  * Implementation of lyext_clb_schema_printer set as ::lyext_plugin::sprinter
  */
 LY_ERR
-annotation_schema_printer(struct lys_ypr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
+annotation_schema_printer(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
 {
     lysc_print_extension_instance(ctx, ext, flag);
 
diff --git a/src/plugins_exts_print.h b/src/plugins_exts_print.h
new file mode 100644
index 0000000..380c180
--- /dev/null
+++ b/src/plugins_exts_print.h
@@ -0,0 +1,81 @@
+/**
+ * @file plugins_exts_print.h
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief libyang support for YANG extensions implementation - schema print related items.
+ *
+ * Copyright (c) 2015 - 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_EXTS_PRINT_H_
+#define LY_PLUGINS_EXTS_PRINT_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup extensions YANG Extensions
+ *
+ * @{
+ */
+
+/**
+ * @brief YANG printer context for use in ::lyext_clb_schema_printer callback implementation.
+ *
+ * The structure provides basic information how the compiled schema is supposed to be printed and where. In the most simple
+ * case, the provided context is just passed into ::lysc_print_extension_instance() function which handles printing the
+ * extension's substatements in the standard way.
+ *
+ * To access various items from the context, use some of the following lys_ypr_ctx_get_* getters.
+ */
+struct lyspr_ctx;
+
+/**
+ * @brief YANG printer context getter for output handler.
+ * @param[in] ctx YANG printer context.
+ * @return Output handler where the data are being printed. Note that the address of the handler pointer in the context is
+ * returned to allow to modify the handler.
+ */
+struct ly_out **lys_ypr_ctx_get_out(const struct lyspr_ctx *ctx);
+
+/**
+ * @brief YANG printer context getter for printer options.
+ * @param[in] ctx YANG printer context.
+ * @return pointer to the printer options to allow modifying them with @ref schemaprinterflags values.
+ */
+uint32_t *lys_ypr_ctx_get_options(const struct lyspr_ctx *ctx);
+
+/**
+ * @brief YANG printer context getter for printer indentation level.
+ * @param[in] ctx YANG printer context.
+ * @return pointer to the printer's indentation level to allow modifying its value.
+ */
+uint16_t *lys_ypr_ctx_get_level(const struct lyspr_ctx *ctx);
+
+/**
+ * @brief Print substatements of an extension instance
+ *
+ * Generic function to access YANG printer functions from the extension plugins (::lyext_clb_schema_printer).
+ *
+ * @param[in] ctx YANG printer context to provide output handler and other information for printing.
+ * @param[in] ext The compiled extension instance to access the extensions and substatements data.
+ * @param[in, out] flag Flag to be shared with the caller regarding the opening brackets - 0 if the '{' not yet printed,
+ * 1 otherwise.
+ */
+void lysc_print_extension_instance(struct lyspr_ctx *ctx, const struct lysc_ext_instance *ext, ly_bool *flag);
+
+/** @} extensions */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LY_PLUGINS_EXTS_PRINT_H_ */
diff --git a/src/plugins_exts_yangdata.c b/src/plugins_exts_yangdata.c
index f398cac..180de16 100644
--- a/src/plugins_exts_yangdata.c
+++ b/src/plugins_exts_yangdata.c
@@ -157,7 +157,7 @@
  * Implementation of ::lyext_clb_schema_printer set as ::lyext_plugin::sprinter
  */
 LY_ERR
-yangdata_schema_printer(struct lys_ypr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
+yangdata_schema_printer(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
 {
     lysc_print_extension_instance(ctx, ext, flag);
     return LY_SUCCESS;
diff --git a/src/printer_internal.h b/src/printer_internal.h
index 838ca54..e0a04b1 100644
--- a/src/printer_internal.h
+++ b/src/printer_internal.h
@@ -23,6 +23,18 @@
 struct lysp_submodule;
 
 /**
+ * @brief Generic YANG schema printer context
+ *
+ * Note that the YANG extensions API provides getter to the members for the extension plugins.
+ */
+struct lyspr_ctx {
+    struct ly_out *out;              /**< output specification */
+    uint16_t level;                  /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
+    uint32_t options;                /**< Schema output options (see @ref schemaprinterflags). */
+    const struct lys_module *module; /**< schema to print */
+};
+
+/**
  * @brief YANG printer of the parsed module. Full YANG printer.
  *
  * @param[in] out Output specification.
diff --git a/src/printer_yang.c b/src/printer_yang.c
index c5700b4..e168396 100644
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -26,8 +26,8 @@
 #include "log.h"
 #include "out.h"
 #include "out_internal.h"
-#include "plugins_exts.h"
 #include "plugins_exts_internal.h"
+#include "plugins_exts_print.h"
 #include "plugins_types.h"
 #include "printer_internal.h"
 #include "printer_schema.h"
@@ -38,6 +38,34 @@
 #include "xpath.h"
 
 /**
+ * @brief Types of the YANG printers
+ */
+enum lys_ypr_schema_type {
+    LYS_YPR_PARSED,   /**< YANG printer of the parsed schema */
+    LYS_YPR_COMPILED  /**< YANG printer of the compiled schema */
+};
+
+/**
+ * @brief Compiled YANG printer context
+ *
+ * Note that the YANG extensions API provides getter to the members for the extension plugins.
+ */
+struct lys_ypr_ctx {
+    union {
+        struct {
+            struct ly_out *out;              /**< output specification */
+            uint16_t level;                  /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
+            uint32_t options;                /**< Schema output options (see @ref schemaprinterflags). */
+            const struct lys_module *module; /**< schema to print */
+        };
+        struct lyspr_ctx printer_ctx;
+    };
+
+    /* YANG printer specific members */
+    enum lys_ypr_schema_type schema; /**< type of the schema to print */
+};
+
+/**
  * @brief Print the given text as content of a double quoted YANG string,
  * including encoding characters that have special meanings. The quotation marks
  * are not printed.
@@ -2320,7 +2348,7 @@
         yprc_extension_instances(ctx, LY_STMT_EXTENSION_INSTANCE, 0, ext[u].exts, &inner_flag, 0);
 
         if (ext[u].def->plugin->sprinter) {
-            ext[u].def->plugin->sprinter(ctx, &ext[u], &inner_flag);
+            ext[u].def->plugin->sprinter(&ctx->printer_ctx, &ext[u], &inner_flag);
         }
 
         LEVEL--;
@@ -2329,8 +2357,9 @@
 }
 
 void
-lysc_print_extension_instance(struct lys_ypr_ctx *ctx, const struct lysc_ext_instance *ext, ly_bool *flag)
+lysc_print_extension_instance(struct lyspr_ctx *ctx_generic, const struct lysc_ext_instance *ext, ly_bool *flag)
 {
+    struct lys_ypr_ctx *ctx = (struct lys_ypr_ctx *)ctx_generic;
     LY_ARRAY_COUNT_TYPE u, v;
 
     LY_ARRAY_FOR(ext->substmts, u) {
diff --git a/src/printer_yin.c b/src/printer_yin.c
index 5ccea30..93fd271 100644
--- a/src/printer_yin.c
+++ b/src/printer_yin.c
@@ -34,10 +34,17 @@
  * @brief YIN printer context.
  */
 struct lys_ypr_ctx {
-    struct ly_out *out;              /**< output specification */
-    uint16_t level;                  /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
-    uint32_t options;                /**< Schema output options (see @ref schemaprinterflags). */
-    const struct lys_module *module; /**< schema to print */
+    union {
+        struct {
+            struct ly_out *out;              /**< output specification */
+            uint16_t level;                  /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
+            uint32_t options;                /**< Schema output options (see @ref schemaprinterflags). */
+            const struct lys_module *module; /**< schema to print */
+        };
+        struct lyspr_ctx printer_ctx;
+    };
+
+    /* YIN printer specific members */
 };
 
 static void yprp_extension_instances(struct lys_ypr_ctx *ctx, enum ly_stmt substmt, uint8_t substmt_index,