printer tree FEATURE using lysc nodes for printing
diff --git a/src/printer_internal.h b/src/printer_internal.h
index e0a04b1..65d2424 100644
--- a/src/printer_internal.h
+++ b/src/printer_internal.h
@@ -114,7 +114,11 @@
 LY_ERR yin_print_parsed_submodule(struct ly_out *out, const struct lysp_submodule *submodp, uint32_t options);
 
 /**
- * @brief YANG Tree Diagram printer of the parsed submodule. Full YANG Tree printer.
+ * @brief Full YANG Tree Diagram printer.
+ *
+ * The module should be compiled and the @ref contextoptions must be set to LY_CTX_SET_PRIV_PARSED.
+ * If not, the printer will use parsed (unresolved) YANG schema tree, which means,
+ * for example, that `grouping` sections will be on the output.
  *
  * @param[in] out Output specification.
  * @param[in] module Main module.
@@ -122,7 +126,7 @@
  * @param[in] line_length Maximum characters to be printed on a line, 0 for unlimited. Only for ::LYS_OUT_TREE printer.
  * @return LY_ERR value, number of the printed bytes is updated in ::ly_out.printed.
  */
-LY_ERR tree_print_parsed_module(struct ly_out *out, const struct lys_module *module, uint32_t options,
+LY_ERR tree_print_module(struct ly_out *out, const struct lys_module *module, uint32_t options,
         size_t line_length);
 
 /**
diff --git a/src/printer_schema.c b/src/printer_schema.c
index 4cb89a0..4b8fed8 100644
--- a/src/printer_schema.c
+++ b/src/printer_schema.c
@@ -68,7 +68,7 @@
             ret = LY_EINVAL;
             break;
         }
-        ret = tree_print_parsed_module(out, module, options, line_length);
+        ret = tree_print_module(out, module, options, line_length);
         break;
     /* TODO not yet implemented
     case LYS_OUT_INFO:
diff --git a/src/printer_tree.c b/src/printer_tree.c
index 37de647..df389cd 100644
--- a/src/printer_tree.c
+++ b/src/printer_tree.c
@@ -42,7 +42,7 @@
  * @subsubsection TRP_trb trb
  * Browse functions contain a general algorithm (Preorder DFS)
  * for traversing the tree. It does not matter what data type
- * the tree contains (\ref lysp_node), because it
+ * the tree contains (\ref lysc_node or \ref lysp_node), because it
  * requires a ready-made getter functions for traversing the tree
  * (\ref trt_fp_all) and transformation function to its own node
  * data type (\ref trt_node). These getter functions are generally
@@ -55,14 +55,17 @@
  * @subsubsection TRP_tro tro
  * Functions that provide an extra wrapper for the libyang library.
  * The Obtain functions are further specialized according to whether
- * they operate on lysp_tree (\ref TRP_trop). If they are general
- * algorithms, then they have the prefix \b tro_. The Obtain functions
- * provide information to \ref TRP_trb functions for printing the
- * Tree diagram.
+ * they operate on lysp_tree (\ref TRP_trop) or lysc_tree
+ * (\ref TRP_troc). If they are general algorithms, then they have the
+ * prefix \b tro_. The Obtain functions provide information to
+ * \ref TRP_trb functions for printing the Tree diagram.
  *
  * @subsubsection TRP_trop trop
  * Functions for Obtaining information from Parsed schema tree.
  *
+ * @subsubsection TRP_troc troc
+ * Functions for Obtaining information from Compiled schema tree.
+ *
  * @subsubsection TRP_trp trp
  * Print functions take care of the printing YANG diagram. They can
  * also split one node into multiple lines if the node does not fit
@@ -76,11 +79,12 @@
  *
  * @subsection TRP_ADJUSTMENTS Adjustments
  * It is assumed that the changes are likely to take place mainly for
- * \ref TRP_tro, \ref TRP_trop functions because they are the only
- * ones dependent on libyang implementation. In special cases, changes
- * will also need to be made to the \ref TRP_trp functions if a special
- * algorithm is needed to print (right now this is prepared for
- * printing list's keys and if-features).
+ * \ref TRP_tro, \ref TRP_trop or \ref TRP_troc functions because
+ * they are the only ones dependent on libyang implementation.
+ * In special cases, changes will also need to be made to the
+ * \ref TRP_trp functions if a special algorithm is needed to print
+ * (right now this is prepared for printing list's keys
+ * and if-features).
  */
 
 #include <assert.h>
@@ -142,6 +146,9 @@
  * cases, it's not that simple, because its entire string is fragmented
  * in memory. For example, for printing list's keys or if-features.
  * However, this depends on how the libyang library is implemented.
+ * This implementation of the printer_tree module goes through
+ * a lysp tree, but if it goes through a lysc tree, these special cases
+ * would be different.
  * Functions must print including spaces or delimiters between names.
  */
 struct trt_fp_print {
@@ -541,7 +548,7 @@
 /**
  * @brief Functions that change the state of the tree_ctx structure.
  *
- * The 'trop' functions are set here, which provide data
+ * The 'trop' or 'troc' functions are set here, which provide data
  * for the 'trp' printing functions and are also called from the
  * 'trb' browsing functions when walking through a tree. These callback
  * functions need to be checked or reformulated if changes to the
@@ -651,7 +658,8 @@
  * the inheritance states will be stored during the recursive calls.
  * So the problem was solved by the second option. Why does
  * the structure contain this data? Because it walks through
- * the lysp tree.
+ * the lysp tree. For walks through the lysc tree is trt_parent_cache
+ * useless.
  *
  * @see TRO_EMPTY_PARENT_CACHE, tro_parent_cache_for_child
  */
@@ -675,13 +683,25 @@
  * @brief Main structure for browsing the libyang tree
  */
 struct trt_tree_ctx {
+    ly_bool lysc_tree;                  /**< The lysc nodes are used for browsing through the tree.
+                                             It is assumed that once set, it does not change.
+                                             If it is true then trt_tree_ctx.pn and
+                                             trt_tree_ctx.tpn are not used.
+                                             If it is false then trt_tree_ctx.cn is not used. */
     trt_actual_section section;         /**< To which section pn points. */
     const struct lys_module *module;    /**< Schema tree structures. */
     const struct lysp_node *pn;         /**< Actual pointer to parsed node. */
     const struct lysp_node *tpn;        /**< Pointer to actual top-node. */
+    const struct lysc_node *cn;         /**< Actual pointer to compiled node. */
 };
 
-/** Getter function for tro_lysp_node_charptr(). */
+/**
+ * @brief Get lysp_node from trt_tree_ctx.cn.
+ */
+#define TRP_TREE_CTX_GET_LYSP_NODE(CN) \
+    ((const struct lysp_node *)CN->priv)
+
+/** Getter function for trop_node_charptr(). */
 typedef const char *(*trt_get_charptr_func)(const struct lysp_node *pn);
 
 /**
@@ -1871,7 +1891,7 @@
 }
 
 /**********************************************************************
- * trop getters
+ * trop and troc getters
  *********************************************************************/
 
 /**
@@ -1973,16 +1993,122 @@
     };
 }
 
+/**
+ * @brief Get nodetype.
+ * @param[in] node is any lysc_node.
+ */
+static uint16_t
+troc_nodetype(const void *node)
+{
+    return ((const struct lysc_node *)node)->nodetype;
+}
+
+/**
+ * @brief Get sibling.
+ * @param[in] node is any lysc_node.
+ */
+static const void *
+troc_next(const void *node)
+{
+    return ((const struct lysc_node *)node)->next;
+}
+
+/**
+ * @brief Get parent.
+ * @param[in] node is any lysc_node.
+ */
+static const void *
+troc_parent(const void *node)
+{
+    return ((const struct lysc_node *)node)->parent;
+}
+
+/**
+ * @brief Try to get child.
+ * @param[in] node is any lysc_node.
+ */
+static const void *
+troc_child(const void *node)
+{
+    return lysc_node_child(node);
+}
+
+/**
+ * @brief Try to get action.
+ * @param[in] node is any lysc_node.
+ */
+static const void *
+troc_actions(const void *node)
+{
+    return lysc_node_actions(node);
+}
+
+/**
+ * @brief Try to get action.
+ * @param[in] node must be of type lysc_node_action.
+ */
+static const void *
+troc_action_input(const void *node)
+{
+    return &((const struct lysc_node_action *)node)->input;
+}
+
+/**
+ * @brief Try to get action.
+ * @param[in] node must be of type lysc_node_action.
+ */
+static const void *
+troc_action_output(const void *node)
+{
+    return &((const struct lysc_node_action *)node)->output;
+}
+
+/**
+ * @brief Try to get action.
+ * @param[in] node is any lysc_node.
+ */
+static const void *
+troc_notifs(const void *node)
+{
+    return lysc_node_notifs(node);
+}
+
+/**
+ * @brief Fill struct tro_getters with \ref TRP_troc getters
+ * which are adapted to lysc nodes.
+ */
+static struct tro_getters
+troc_init_getters()
+{
+    return (struct tro_getters) {
+               .nodetype = troc_nodetype,
+               .next = troc_next,
+               .parent = troc_parent,
+               .child = troc_child,
+               .actions = troc_actions,
+               .action_input = troc_action_input,
+               .action_output = troc_action_output,
+               .notifs = troc_notifs
+    };
+}
+
 /**********************************************************************
  * tro functions
  *********************************************************************/
 
 /**
  * @brief Get next sibling of the current node.
- * @param[in] node points to lysp_node.
+ *
+ * This is a general algorithm that is able to
+ * work with lysp_node or lysc_node.
+ *
+ * @param[in] node points to lysp_node or lysc_node.
+ * @param[in] lysc_tree flag to determine what type the @p node is.
+ * If set to true, then @p points to lysc_node otherwise lysp_node.
+ * This flag should be the same as trt_tree_ctx.lysc_tree.
  */
 static const void *
-tro_next_sibling(const void *node)
+tro_next_sibling(const void *node, ly_bool lysc_tree)
 {
     struct tro_getters get;
     const void *tmp, *parent;
@@ -1990,7 +2116,7 @@
 
     assert(node);
 
-    get = trop_init_getters();
+    get = lysc_tree ? troc_init_getters() : trop_init_getters();
 
     if (get.nodetype(node) & (LYS_RPC | LYS_ACTION)) {
         if ((tmp = get.next(node))) {
@@ -2054,10 +2180,17 @@
 
 /**
  * @brief Get child of the current node.
- * @param[in] node points to lysp_node.
+ *
+ * This is a general algorithm that is able to
+ * work with lysp_node or lysc_node.
+ *
+ * @param[in] node points to lysp_node or lysc_node.
+ * @param[in] lysc_tree flag to determine what type the @p node is.
+ * If set to true, then @p points to lysc_node otherwise lysp_node.
+ * This flag should be the same as trt_tree_ctx.lysc_tree.
  */
 static const void *
-tro_next_child(const void *node)
+tro_next_child(const void *node, ly_bool lysc_tree)
 {
     struct tro_getters get;
     const void *tmp;
@@ -2065,7 +2198,7 @@
 
     assert(node);
 
-    get = trop_init_getters();
+    get = lysc_tree ? troc_init_getters() : trop_init_getters();
 
     if (get.nodetype(node) & (LYS_ACTION | LYS_RPC)) {
         if (get.child(get.action_input(node))) {
@@ -2098,6 +2231,45 @@
 }
 
 /**
+ * @brief Get new trt_parent_cache if we apply the transfer
+ * to the child node in the tree.
+ * @param[in] ca is parent cache for current node.
+ * @param[in] tc contains current tree node.
+ * @return Cache for the current node.
+ */
+static struct trt_parent_cache
+tro_parent_cache_for_child(struct trt_parent_cache ca, const struct trt_tree_ctx *tc)
+{
+    struct trt_parent_cache ret = TRP_EMPTY_PARENT_CACHE;
+
+    if (!tc->lysc_tree) {
+        const struct lysp_node *pn = tc->pn;
+
+        ret.ancestor =
+                pn->nodetype & (LYS_INPUT) ? TRD_ANCESTOR_RPC_INPUT :
+                pn->nodetype & (LYS_OUTPUT) ? TRD_ANCESTOR_RPC_OUTPUT :
+                pn->nodetype & (LYS_NOTIF) ? TRD_ANCESTOR_NOTIF :
+                ca.ancestor;
+
+        ret.lys_status =
+                pn->flags & (LYS_STATUS_CURR | LYS_STATUS_DEPRC | LYS_STATUS_OBSLT) ? pn->flags :
+                ca.lys_status;
+
+        ret.lys_config =
+                ca.ancestor == TRD_ANCESTOR_RPC_INPUT ? 0 : /* because <flags> will be -w */
+                ca.ancestor == TRD_ANCESTOR_RPC_OUTPUT ? LYS_CONFIG_R :
+                pn->flags & (LYS_CONFIG_R | LYS_CONFIG_W) ? pn->flags :
+                ca.lys_config;
+
+        ret.last_list =
+                pn->nodetype & (LYS_LIST) ? (struct lysp_node_list *)pn :
+                ca.last_list;
+    }
+
+    return ret;
+}
+
+/**
  * @brief Transformation of the Schema nodes flags to
  * Tree diagram \<status\>.
  * @param[in] flags is node's flags obtained from the tree.
@@ -2124,6 +2296,127 @@
 }
 
 /**
+ * @brief Print current node's iffeatures.
+ * @param[in] tc is tree context.
+ * @param[in,out] out is output handler.
+ */
+static void
+tro_print_features_names(const struct trt_tree_ctx *tc, struct ly_out *out)
+{
+    const struct lysp_qname *iffs;
+
+    iffs = tc->lysc_tree ?
+            TRP_TREE_CTX_GET_LYSP_NODE(tc->cn)->iffeatures :
+            tc->pn->iffeatures;
+
+    LY_ARRAY_COUNT_TYPE i;
+
+    LY_ARRAY_FOR(iffs, i) {
+        if (i == 0) {
+            ly_print_(out, "%s", iffs[i].str);
+        } else {
+            ly_print_(out, ",%s", iffs[i].str);
+        }
+    }
+
+}
+
+/**
+ * @brief Print current list's keys.
+ *
+ * Well, actually printing keys in the lysp_tree is trivial,
+ * because char* points to all keys. However, special functions have
+ * been reserved for this, because in principle the list of elements
+ * can have more implementations.
+ *
+ * @param[in] tc is tree context.
+ * @param[in,out] out is output handler.
+ */
+static void
+tro_print_keys(const struct trt_tree_ctx *tc, struct ly_out *out)
+{
+    const struct lysp_node_list *list;
+
+    list = tc->lysc_tree ?
+            (const struct lysp_node_list *)TRP_TREE_CTX_GET_LYSP_NODE(tc->cn) :
+            (const struct lysp_node_list *)tc->pn;
+    assert(list->nodetype & LYS_LIST);
+
+    if (trg_charptr_has_data(list->key)) {
+        ly_print_(out, "%s", list->key);
+    }
+}
+
+/**
+ * @brief Get rpcs section if exists.
+ * @param[in,out] tc is tree context.
+ * @return Section representation if it exists. The @p tc is modified
+ * and his pointer points to the first node in rpcs section.
+ * @return Empty section representation otherwise.
+ */
+static struct trt_keyword_stmt
+tro_modi_get_rpcs(struct trt_tree_ctx *tc)
+{
+    assert(tc && tc->module);
+    const void *actions;
+
+    if (tc->lysc_tree) {
+        actions = tc->module->compiled->rpcs;
+        if (actions) {
+            tc->cn = actions;
+        }
+    } else {
+        actions = tc->module->parsed->rpcs;
+        if (actions) {
+            tc->pn = actions;
+            tc->tpn = tc->pn;
+        }
+    }
+
+    if (actions) {
+        tc->section = TRD_SECT_RPCS;
+        return TRP_INIT_KEYWORD_STMT(TRD_KEYWORD_RPC, NULL);
+    } else {
+        return TRP_EMPTY_KEYWORD_STMT;
+    }
+}
+
+/**
+ * @brief Get notification section if exists
+ * @param[in,out] tc is tree context.
+ * @return Section representation if it exists.
+ * The @p tc is modified and his pointer points to the
+ * first node in notification section.
+ * @return Empty section representation otherwise.
+ */
+static struct trt_keyword_stmt
+tro_modi_get_notifications(struct trt_tree_ctx *tc)
+{
+    assert(tc && tc->module);
+    const void *notifs;
+
+    if (tc->lysc_tree) {
+        notifs = tc->module->compiled->notifs;
+        if (notifs) {
+            tc->cn = notifs;
+        }
+    } else {
+        notifs = tc->module->parsed->notifs;
+        if (notifs) {
+            tc->pn = notifs;
+            tc->tpn = tc->pn;
+        }
+    }
+
+    if (notifs) {
+        tc->section = TRD_SECT_NOTIF;
+        return TRP_INIT_KEYWORD_STMT(TRD_KEYWORD_NOTIF, NULL);
+    } else {
+        return TRP_EMPTY_KEYWORD_STMT;
+    }
+}
+
+/**
  * @brief Get next yang-data section if exists.
  *
  * Not implemented.
@@ -2158,41 +2451,6 @@
  *********************************************************************/
 
 /**
- * @brief Get new trt_parent_cache if we apply the transfer
- * to the child node in the tree.
- * @param[in] ca is parent cache for current node.
- * @param[in] tc contains current tree node.
- * @return Cache for the current node.
- */
-static struct trt_parent_cache
-trop_parent_cache_for_child(struct trt_parent_cache ca, const struct lysp_node *pn)
-{
-    struct trt_parent_cache ret;
-
-    ret.ancestor =
-            pn->nodetype & (LYS_INPUT) ? TRD_ANCESTOR_RPC_INPUT :
-            pn->nodetype & (LYS_OUTPUT) ? TRD_ANCESTOR_RPC_OUTPUT :
-            pn->nodetype & (LYS_NOTIF) ? TRD_ANCESTOR_NOTIF :
-            ca.ancestor;
-
-    ret.lys_status =
-            pn->flags & (LYS_STATUS_CURR | LYS_STATUS_DEPRC | LYS_STATUS_OBSLT) ? pn->flags :
-            ca.lys_status;
-
-    ret.lys_config =
-            ca.ancestor == TRD_ANCESTOR_RPC_INPUT ? 0 :     /* because <flags> will be -w */
-            ca.ancestor == TRD_ANCESTOR_RPC_OUTPUT ? LYS_CONFIG_R :
-            pn->flags & (LYS_CONFIG_R | LYS_CONFIG_W) ? pn->flags :
-            ca.lys_config;
-
-    ret.last_list =
-            pn->nodetype & (LYS_LIST) ? (struct lysp_node_list *)pn :
-            ca.last_list;
-
-    return ret;
-}
-
-/**
  * @brief Check if list statement has keys.
  * @param[in] pn is pointer to the list.
  * @return 1 if has keys, otherwise 0.
@@ -2205,7 +2463,7 @@
 
 /**
  * @brief Check if it contains at least one feature.
- * @param[in] iffs is pointer to the if-features.
+ * @param[in] pn is current node.
  * @return 1 if has if-features, otherwise 0.
  */
 static ly_bool
@@ -2485,7 +2743,7 @@
     /* <iffeature> */
     ret.iffeatures = trop_node_has_iffeature(pn);
 
-    ret.last_one = !tro_next_sibling(pn);
+    ret.last_one = !tro_next_sibling(pn, tc->lysc_tree);
 
     return ret;
 }
@@ -2498,7 +2756,7 @@
 static ly_bool
 trop_read_if_sibling_exists(const struct trt_tree_ctx *tc)
 {
-    return tro_next_sibling(tc->pn) != NULL;
+    return tro_next_sibling(tc->pn, tc->lysc_tree) != NULL;
 }
 
 /**********************************************************************
@@ -2545,9 +2803,9 @@
 
     assert(tc && tc->pn);
 
-    if ((tmp = tro_next_child(tc->pn))) {
+    if ((tmp = tro_next_child(tc->pn, tc->lysc_tree))) {
         tc->pn = tmp;
-        return trop_read_node(trop_parent_cache_for_child(ca, tc->pn), tc);
+        return trop_read_node(tro_parent_cache_for_child(ca, tc), tc);
     } else {
         return TRP_EMPTY_NODE;
     }
@@ -2615,7 +2873,7 @@
 
     assert(tc && tc->pn);
 
-    pn = tro_next_sibling(tc->pn);
+    pn = tro_next_sibling(tc->pn, tc->lysc_tree);
     tpn = tc->tpn == tc->pn ? pn : tc->tpn;
 
     /* if next sibling exists */
@@ -2661,53 +2919,6 @@
 }
 
 /**
- * @brief Get rpcs section if exists.
- * @param[in,out] tc is tree context.
- * @return Section representation if it exists. The @p tc is modified
- * and his pointer points to the first node in rpcs section.
- * @return Empty section representation otherwise.
- */
-static struct trt_keyword_stmt
-trop_modi_get_rpcs(struct trt_tree_ctx *tc)
-{
-    assert(tc && tc->module && tc->module->parsed);
-    const struct lysp_node_action *actions = tc->module->parsed->rpcs;
-
-    if (actions) {
-        tc->section = TRD_SECT_RPCS;
-        tc->pn = &actions->node;
-        tc->tpn = tc->pn;
-        return TRP_INIT_KEYWORD_STMT(TRD_KEYWORD_RPC, NULL);
-    } else {
-        return TRP_EMPTY_KEYWORD_STMT;
-    }
-}
-
-/**
- * @brief Get notification section if exists
- * @param[in,out] tc is tree context.
- * @return Section representation if it exists.
- * The @p tc is modified and his pointer points to the
- * first node in notification section.
- * @return Empty section representation otherwise.
- */
-static struct trt_keyword_stmt
-trop_modi_get_notifications(struct trt_tree_ctx *tc)
-{
-    assert(tc && tc->module && tc->module->parsed);
-    const struct lysp_node_notif *notifs = tc->module->parsed->notifs;
-
-    if (notifs) {
-        tc->section = TRD_SECT_NOTIF;
-        tc->pn = &notifs->node;
-        tc->tpn = tc->pn;
-        return TRP_INIT_KEYWORD_STMT(TRD_KEYWORD_NOTIF, NULL);
-    } else {
-        return TRP_EMPTY_KEYWORD_STMT;
-    }
-}
-
-/**
  * @brief Get next (or first) grouping section if exists
  * @param[in,out] tc is tree context. It is modified and his current
  * node is set to the lysp_node_grp.
@@ -2737,55 +2948,217 @@
 }
 
 /**********************************************************************
- * Print Tro getters
+ * Definition of troc reading functions
  *********************************************************************/
 
 /**
- * @brief Print current node's iffeatures.
- * @param[in] tc is tree context.
- * @param[in,out] out is output handler.
+ * @copydoc trop_read_if_sibling_exists
  */
-static void
-trop_print_features_names(const struct trt_tree_ctx *tc, struct ly_out *out)
+static ly_bool
+troc_read_if_sibling_exists(const struct trt_tree_ctx *tc)
 {
-    const struct lysp_qname *iffs = tc->pn->iffeatures;
+    return tro_next_sibling(tc->cn, tc->lysc_tree) != NULL;
+}
 
-    LY_ARRAY_COUNT_TYPE i;
-
-    LY_ARRAY_FOR(iffs, i) {
-        if (i == 0) {
-            ly_print_(out, "%s", iffs[i].str);
-        } else {
-            ly_print_(out, ",%s", iffs[i].str);
-        }
+/**
+ * @brief Resolve \<flags\> of the current node.
+ *
+ * Use this function only if trt_tree_ctx.lysc_tree is true.
+ *
+ * @param[in] nodetype is current lysc_node.nodetype.
+ * @param[in] flags is current lysc_node.flags.
+ * @return The flags type.
+ */
+static trt_flags_type
+troc_resolve_flags(uint16_t nodetype, uint16_t flags)
+{
+    if ((nodetype & LYS_INPUT) || (flags & LYS_IS_INPUT)) {
+        return TRD_FLAGS_TYPE_RPC_INPUT_PARAMS;
+    } else if ((nodetype & LYS_OUTPUT) || (flags & LYS_IS_OUTPUT)) {
+        return TRD_FLAGS_TYPE_RO;
+    } else if (nodetype & LYS_IS_NOTIF) {
+        return TRD_FLAGS_TYPE_RO;
+    } else if (nodetype & LYS_NOTIF) {
+        return TRD_FLAGS_TYPE_NOTIF;
+    } else if (nodetype & LYS_USES) {
+        return TRD_FLAGS_TYPE_USES_OF_GROUPING;
+    } else if (nodetype & (LYS_RPC | LYS_ACTION)) {
+        return TRD_FLAGS_TYPE_RPC;
+    } else {
+        return tro_flags2config(flags);
     }
 }
 
 /**
- * @brief Print current list's keys.
+ * @brief Resolve node type of the current node.
  *
- * Well, actually printing keys in the lysp_tree is trivial,
- * because char* points to all keys. However, special functions have
- * been reserved for this, because in principle the list of elements
- * can have more implementations.
+ * Use this function only if trt_tree_ctx.lysc_tree is true.
  *
- * @param[in] tc is tree context.
- * @param[in,out] out is output handler.
+ * @param[in] nodetype is current lysc_node.nodetype.
+ * @param[in] flags is current lysc_node.flags.
+ */
+static trt_node_type
+troc_resolve_node_type(uint16_t nodetype, uint16_t flags)
+{
+    if (nodetype & (LYS_INPUT | LYS_OUTPUT)) {
+        return TRD_NODE_ELSE;
+    } else if (nodetype & LYS_CASE) {
+        return TRD_NODE_CASE;
+    } else if ((nodetype & LYS_CHOICE) && !(flags & LYS_MAND_TRUE)) {
+        return TRD_NODE_OPTIONAL_CHOICE;
+    } else if (nodetype & LYS_CHOICE) {
+        return TRD_NODE_CHOICE;
+    } else if ((nodetype & LYS_CONTAINER) && (flags & LYS_PRESENCE)) {
+        return TRD_NODE_CONTAINER;
+    } else if ((nodetype & LYS_LIST) && !(flags & LYS_KEYLESS)) {
+        return TRD_NODE_KEYS;
+    } else if (nodetype & (LYS_LIST | LYS_LEAFLIST)) {
+        return TRD_NODE_LISTLEAFLIST;
+    } else if ((nodetype & (LYS_ANYDATA | LYS_ANYXML)) && !(flags & LYS_MAND_TRUE)) {
+        return TRD_NODE_OPTIONAL;
+    } else if ((nodetype & LYS_LEAF) && !(flags & (LYS_MAND_TRUE | LYS_KEY))) {
+        return TRD_NODE_OPTIONAL;
+    } else {
+        return TRD_NODE_ELSE;
+    }
+}
+
+/**
+ * @brief Transformation of current lysc_node to struct trt_node.
+ * @param[in] ca is not used.
+ * @param[in] tc is context of the tree.
+ */
+static struct trt_node
+troc_read_node(struct trt_parent_cache ca, const struct trt_tree_ctx *tc)
+{
+    (void) ca;
+    const struct lysc_node *cn;
+    struct trt_node ret;
+
+    assert(tc && tc->cn);
+
+    cn = tc->cn;
+    ret = TRP_EMPTY_NODE;
+
+    /* <status> */
+    ret.status = tro_flags2status(cn->flags);
+
+    /* TODO: TRD_FLAGS_TYPE_MOUNT_POINT aka "mp" is not supported right now. */
+    /* <flags> */
+    ret.flags = troc_resolve_flags(cn->nodetype, cn->flags);
+
+    /* TODO: TRD_NODE_TOP_LEVEL1 aka '/' is not supported right now. */
+    /* TODO: TRD_NODE_TOP_LEVEL2 aka '@' is not supported right now. */
+    /* set type of the node */
+    ret.name.type = troc_resolve_node_type(cn->nodetype, cn->flags);
+
+    /* TODO: ret.name.module_prefix is not supported right now. */
+    ret.name.module_prefix = NULL;
+
+    /* set node's name */
+    ret.name.str = cn->name;
+
+    /* <type> */
+    ret.type = trop_resolve_type(TRP_TREE_CTX_GET_LYSP_NODE(cn));
+
+    /* <iffeature> */
+    ret.iffeatures = trop_node_has_iffeature(TRP_TREE_CTX_GET_LYSP_NODE(cn));
+
+    ret.last_one = !tro_next_sibling(cn, tc->lysc_tree);
+
+    return ret;
+}
+
+/**********************************************************************
+ * Modify troc getters
+ *********************************************************************/
+
+/**
+ * @copydoc trop_modi_parent()
+ */
+static ly_bool
+troc_modi_parent(struct trt_tree_ctx *tc)
+{
+    assert(tc && tc->cn);
+    /* If no parent exists, stay in actual node. */
+    if (tc->cn->parent) {
+        tc->cn = tc->cn->parent;
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+/**
+ * @copydoc trop_modi_next_sibling()
+ */
+static struct trt_node
+troc_modi_next_sibling(struct trt_parent_cache ca, struct trt_tree_ctx *tc)
+{
+    const struct lysc_node *cn;
+
+    assert(tc && tc->cn);
+
+    cn = tro_next_sibling(tc->cn, tc->lysc_tree);
+
+    /* if next sibling exists */
+    if (cn) {
+        /* update trt_tree_ctx */
+        tc->cn = cn;
+        return troc_read_node(ca, tc);
+    } else {
+        return TRP_EMPTY_NODE;
+    }
+}
+
+/**
+ * @copydoc trop_modi_next_child()
+ */
+static struct trt_node
+troc_modi_next_child(struct trt_parent_cache ca, struct trt_tree_ctx *tc)
+{
+    const struct lysc_node *tmp;
+
+    assert(tc && tc->cn);
+
+    if ((tmp = tro_next_child(tc->cn, tc->lysc_tree))) {
+        tc->cn = tmp;
+        return troc_read_node(ca, tc);
+    } else {
+        return TRP_EMPTY_NODE;
+    }
+}
+
+/**
+ * @copydoc trop_modi_first_sibling()
  */
 static void
-trop_print_keys(const struct trt_tree_ctx *tc, struct ly_out *out)
+troc_modi_first_sibling(struct trt_tree_ctx *tc)
 {
-    const struct lysp_node *pn = tc->pn;
-    const struct lysp_node_list *list;
+    assert(tc && tc->cn);
 
-    if (pn->nodetype != LYS_LIST) {
-        return;
-    }
+    if (troc_modi_parent(tc)) {
+        troc_modi_next_child(TRP_EMPTY_PARENT_CACHE, tc);
+    } else {
+        /* current node is top-node */
+        struct lysc_module *cm = tc->module->compiled;
 
-    list = (const struct lysp_node_list *)pn;
-
-    if (trg_charptr_has_data(list->key)) {
-        ly_print_(out, "%s", list->key);
+        switch (tc->section) {
+        case TRD_SECT_MODULE:
+            tc->cn = cm->data;
+            break;
+        case TRD_SECT_RPCS:
+            tc->cn = (const struct lysc_node *)cm->rpcs;
+            break;
+        case TRD_SECT_NOTIF:
+            tc->cn = (const struct lysc_node *)cm->notifs;
+            break;
+        case TRD_SECT_YANG_DATA:
+            /*TODO: yang-data is not supported now */
+            break;
+        default:
+            assert(0);
+        }
     }
 }
 
@@ -3009,7 +3382,7 @@
         /* print node */
         trb_print_entire_node(max_gap_before_type, wr, ca, pc, tc);
 
-        new_ca = trop_parent_cache_for_child(ca, tc->pn);
+        new_ca = tro_parent_cache_for_child(ca, tc);
         /* go to the actual node's child or stay in actual node */
         node = pc->fp.modify.next_child(ca, tc);
         child_flag = !trp_node_is_empty(node);
@@ -3032,12 +3405,14 @@
 /**
  * @brief Get address of the current node.
  * @param[in] tc contains current node.
- * @return Address of lysp_node, or NULL.
+ * @return Address of lysc_node or lysp_node, or NULL.
  */
 static const void *
 trb_tree_ctx_get_node(struct trt_tree_ctx *tc)
 {
-    return (const void *)tc->pn;
+    return tc->lysc_tree ?
+           (const void *)tc->cn :
+           (const void *)tc->pn;
 }
 
 /**
@@ -3051,7 +3426,11 @@
         return NULL;
     }
 
-    return lysp_node_child(tc->pn);
+    if (tc->lysc_tree) {
+        return lysc_node_child(tc->cn);
+    } else {
+        return lysp_node_child(tc->pn);
+    }
 }
 
 /**
@@ -3061,7 +3440,13 @@
 static void
 trb_tree_ctx_set_child(struct trt_tree_ctx *tc)
 {
-    tc->pn = trb_tree_ctx_get_child(tc);
+    const void *node = trb_tree_ctx_get_child(tc);
+
+    if (tc->lysc_tree) {
+        tc->cn = node;
+    } else {
+        tc->pn = node;
+    }
 }
 
 /**
@@ -3094,7 +3479,7 @@
 
     trb_print_entire_node(max_gap_before_type, wr, ca, pc, tc);
     /* go to the actual node's child */
-    new_ca = trop_parent_cache_for_child(ca, tc->pn);
+    new_ca = tro_parent_cache_for_child(ca, tc);
     node = pc->fp.modify.next_child(ca, tc);
 
     if (!trp_node_is_empty(node)) {
@@ -3133,9 +3518,9 @@
  * @brief Print all parents and their children.
  *
  * This function is suitable for printing top-level nodes that
- * do not have ancestors. Function call trb_print_subtree_nodes()
- * for all top-level siblings. Use this function after 'module' keyword
- * or 'augment' and so.
+ * do not have ancestors. Function call trb_print_subtree_nodes() for all
+ * top-level siblings. Use this function after 'module' keyword or
+ * 'augment' and so.
  *
  * @param[in] wr_t is type of the wrapper.
  * @param[pc] pc contains mainly functions for printing.
@@ -3158,8 +3543,10 @@
     total_parents = trb_get_number_of_siblings(pc->fp.modify, tc);
     max_gap_before_type = trb_try_unified_indent(ca, pc, tc);
 
-    if ((tc->section == TRD_SECT_GROUPING) && (tc->tpn == tc->pn->parent)) {
-        ca.lys_config = 0x0;
+    if (!tc->lysc_tree) {
+        if ((tc->section == TRD_SECT_GROUPING) && (tc->tpn == tc->pn->parent)) {
+            ca.lys_config = 0x0;
+        }
     }
 
     for (uint32_t i = 0; i < total_parents; i++) {
@@ -3188,10 +3575,12 @@
 trm_lysp_tree_ctx(const struct lys_module *module, struct ly_out *out, size_t max_line_length, struct trt_printer_ctx *pc, struct trt_tree_ctx *tc)
 {
     *tc = (struct trt_tree_ctx) {
+        .lysc_tree = 0,
         .section = TRD_SECT_MODULE,
         .module = module,
         .pn = module->parsed->data,
         .tpn = module->parsed->data,
+        .cn = NULL
     };
 
     pc->out = out;
@@ -3202,8 +3591,8 @@
         .next_sibling = trop_modi_next_sibling,
         .next_child = trop_modi_next_child,
         .next_augment = trop_modi_next_augment,
-        .get_rpcs = trop_modi_get_rpcs,
-        .get_notifications = trop_modi_get_notifications,
+        .get_rpcs = tro_modi_get_rpcs,
+        .get_notifications = tro_modi_get_notifications,
         .next_grouping = trop_modi_next_grouping,
         .next_yang_data = tro_modi_next_yang_data
     };
@@ -3215,14 +3604,126 @@
     };
 
     pc->fp.print = (struct trt_fp_print) {
-        .print_features_names = trop_print_features_names,
-        .print_keys = trop_print_keys
+        .print_features_names = tro_print_features_names,
+        .print_keys = tro_print_keys
     };
 
     pc->max_line_length = max_line_length;
 }
 
 /**
+ * @brief Settings if lysc_node are used for browsing through the tree.
+ *
+ * Pointers to current nodes will be set to module data.
+ *
+ * @param[in] module YANG schema tree structure representing
+ * YANG module.
+ * @param[in] out is output handler.
+ * @param[in] max_line_length is the maximum line length limit
+ * that should not be exceeded.
+ * @param[in,out] pc will be adapted to lysc_tree.
+ * @param[in,out] tc will be adapted to lysc_tree.
+ */
+static void
+trm_lysc_tree_ctx(const struct lys_module *module, struct ly_out *out, size_t max_line_length, struct trt_printer_ctx *pc, struct trt_tree_ctx *tc)
+{
+    *tc = (struct trt_tree_ctx) {
+        .lysc_tree = 1,
+        .section = TRD_SECT_MODULE,
+        .module = module,
+        .tpn = NULL,
+        .pn = NULL,
+        .cn = module->compiled->data
+    };
+
+    pc->out = out;
+
+    pc->fp.modify = (struct trt_fp_modify_ctx) {
+        .parent = troc_modi_parent,
+        .first_sibling = troc_modi_first_sibling,
+        .next_sibling = troc_modi_next_sibling,
+        .next_child = troc_modi_next_child,
+        .next_augment = trop_modi_next_augment,
+        .get_rpcs = tro_modi_get_rpcs,
+        .get_notifications = tro_modi_get_notifications,
+        .next_grouping = NULL,
+        .next_yang_data = tro_modi_next_yang_data
+    };
+
+    pc->fp.read = (struct trt_fp_read) {
+        .module_name = tro_read_module_name,
+        .node = troc_read_node,
+        .if_sibling_exists = troc_read_if_sibling_exists
+    };
+
+    pc->fp.print = (struct trt_fp_print) {
+        .print_features_names = tro_print_features_names,
+        .print_keys = tro_print_keys
+    };
+
+    pc->max_line_length = max_line_length;
+}
+
+/**
+ * @brief Reset settings to browsing through the lysc tree.
+ * @param[in,out] pc resets to \ref TRP_troc functions.
+ * @param[in,out] tc resets to lysc browsing.
+ */
+static void
+trm_reset_to_lysc_tree_ctx(struct trt_printer_ctx *pc, struct trt_tree_ctx *tc)
+{
+    trm_lysc_tree_ctx(tc->module, pc->out, pc->max_line_length, pc, tc);
+}
+
+/**
+ * @brief Reset settings to browsing through the lysp tree.
+ * @param[in,out] pc resets to \ref TRP_trop functions.
+ * @param[in,out] tc resets to lysp browsing.
+ */
+static void
+trm_reset_to_lysp_tree_ctx(struct trt_printer_ctx *pc, struct trt_tree_ctx *tc)
+{
+    trm_lysp_tree_ctx(tc->module, pc->out, pc->max_line_length, pc, tc);
+}
+
+/**
+ * @brief If augment's target node is located on the current module.
+ * @param[in] pn is examined augment.
+ * @param[in] pmod is current module.
+ * @return 1 if nodeid refers to the local node, otherwise 0.
+ */
+static ly_bool
+trm_nodeid_target_is_local(const struct lysp_node_augment *pn, const struct lysp_module *pmod)
+{
+    const char *id, *prefix, *name;
+    size_t prefix_len, name_len;
+    const struct lys_module *mod;
+    ly_bool ret = 0;
+
+    if (pn == NULL) {
+        return ret;
+    }
+
+    id = pn->nodeid;
+    if (!id) {
+        return ret;
+    }
+    /* only absolute-schema-nodeid is taken into account */
+    assert(id[0] == '/');
+    ++id;
+
+    ly_parse_nodeid(&id, &prefix, &prefix_len, &name, &name_len);
+    if (prefix) {
+        mod = ly_resolve_prefix(pmod->mod->ctx, prefix, prefix_len, LY_PREF_SCHEMA, pmod);
+        ret = mod->parsed == pmod;
+    } else {
+        ret = 1;
+    }
+
+    return ret;
+}
+
+/**
  * @brief Printing section 'module', 'rpcs' or 'notifications'.
  *
  * First node must be the first child of 'module',
@@ -3295,16 +3796,31 @@
 trm_print_augmentations(struct trt_printer_ctx *pc, struct trt_tree_ctx *tc)
 {
     ly_bool once;
+    ly_bool origin_was_lysc_tree = 0;
 
     if (!pc->fp.modify.next_augment) {
         return;
     }
 
+    if (tc->lysc_tree) {
+        origin_was_lysc_tree = 1;
+        trm_reset_to_lysp_tree_ctx(pc, tc);
+    }
+
     once = 1;
     for (struct trt_keyword_stmt ks = pc->fp.modify.next_augment(tc);
             !(TRP_KEYWORD_STMT_IS_EMPTY(ks));
             ks = pc->fp.modify.next_augment(tc)) {
 
+        if (origin_was_lysc_tree) {
+            /* if lysc tree is used, then only augments targeting
+             * another module are printed
+             */
+            if (trm_nodeid_target_is_local((const struct lysp_node_augment *)tc->tpn, tc->module->parsed)) {
+                continue;
+            }
+        }
+
         if (once) {
             ly_print_(pc->out, "\n");
             ly_print_(pc->out, "\n");
@@ -3315,6 +3831,10 @@
 
         trm_print_section_as_subtree(ks, pc, tc);
     }
+
+    if (origin_was_lysc_tree) {
+        trm_reset_to_lysc_tree_ctx(pc, tc);
+    }
 }
 
 /**
@@ -3426,7 +3946,7 @@
  *********************************************************************/
 
 LY_ERR
-tree_print_parsed_module(struct ly_out *out, const struct lys_module *module, uint32_t UNUSED(options), size_t line_length)
+tree_print_module(struct ly_out *out, const struct lys_module *module, uint32_t UNUSED(options), size_t line_length)
 {
     struct trt_printer_ctx pc;
     struct trt_tree_ctx tc;
@@ -3441,7 +3961,11 @@
     }
 
     line_length = line_length == 0 ? SIZE_MAX : line_length;
-    trm_lysp_tree_ctx(module, new_out, line_length, &pc, &tc);
+    if ((module->ctx->flags & LY_CTX_SET_PRIV_PARSED) && module->compiled) {
+        trm_lysc_tree_ctx(module, new_out, line_length, &pc, &tc);
+    } else {
+        trm_lysp_tree_ctx(module, new_out, line_length, &pc, &tc);
+    }
 
     trm_print_sections(&pc, &tc);
     erc = clb_arg.last_error;