schema printers FEATURE print compiled schema as YANG (LYS_OUT_YANG_COMPILED)
diff --git a/src/printer_yang.c b/src/printer_yang.c
index b015f3b..9d7921d 100755
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -14,17 +14,26 @@
 
 #include "common.h"
 
+#include <inttypes.h>
+
 #include "printer_internal.h"
 #include "tree_schema.h"
 #include "tree_schema_internal.h"
+#include "xpath.h"
 
 #define LEVEL ctx->level
 #define INDENT (LEVEL)*2,""
 
+enum schema_type {
+    YPR_PARSED,
+    YPR_COMPILED
+};
+
 struct ypr_ctx {
     struct lyout *out;
     unsigned int level;
     const struct lys_module *module;
+    enum schema_type schema;
 };
 
 static void
@@ -138,7 +147,7 @@
 }
 
 static void
-ypr_parsed_stmt(struct ypr_ctx *ctx, struct lysp_stmt *stmt)
+yprp_stmt(struct ypr_ctx *ctx, struct lysp_stmt *stmt)
 {
     struct lysp_stmt *childstmt;
     const char *s, *t;
@@ -170,7 +179,7 @@
     if (stmt->child) {
         LEVEL++;
         LY_LIST_FOR(stmt->child, childstmt) {
-            ypr_parsed_stmt(ctx, childstmt);
+            yprp_stmt(ctx, childstmt);
         }
         LEVEL--;
         ly_print(ctx->out, "%*s}\n", INDENT);
@@ -181,7 +190,7 @@
  * @param[in] count Number of extensions to print, 0 to print them all.
  */
 static void
-ypr_parsed_extension_instances(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
+yprp_extension_instances(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
                                struct lysp_ext_instance *ext, int *flag, unsigned int count)
 {
     unsigned int u;
@@ -205,7 +214,7 @@
             if (ext[u].child) {
                 LEVEL++;
                 LY_LIST_FOR(ext[u].child, stmt) {
-                    ypr_parsed_stmt(ctx, stmt);
+                    yprp_stmt(ctx, stmt);
                 }
                 LEVEL--;
                 ly_print(ctx->out, "%*s}\n", INDENT);
@@ -215,8 +224,34 @@
     }
 }
 
+/**
+ * @param[in] count Number of extensions to print, 0 to print them all.
+ */
 static void
-ypr_parsed_substmt(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index, const char *text, struct lysp_ext_instance *ext)
+yprc_extension_instances(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
+                                 struct lysc_ext_instance *ext, int *flag, unsigned int count)
+{
+    unsigned int u;
+
+    if (!count && ext) {
+        count = LY_ARRAY_SIZE(ext);
+    }
+    LY_ARRAY_FOR(ext, u) {
+        if (!count) {
+            break;
+        }
+        /* TODO compiled extensions */
+        (void) ctx;
+        (void) substmt;
+        (void) substmt_index;
+        (void) flag;
+
+        count--;
+    }
+}
+
+static void
+ypr_substmt(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index, const char *text, void *ext)
 {
     unsigned int u;
     int extflag = 0;
@@ -235,18 +270,21 @@
 
     LEVEL++;
     LY_ARRAY_FOR(ext, u) {
-        if (ext[u].insubstmt != substmt || ext[u].insubstmt_index != substmt_index) {
+        if (((struct lysp_ext_instance*)ext)[u].insubstmt != substmt || ((struct lysp_ext_instance*)ext)[u].insubstmt_index != substmt_index) {
             continue;
         }
-        ypr_parsed_extension_instances(ctx, substmt, substmt_index, &ext[u], &extflag, 1);
+        if (ctx->schema == YPR_PARSED) {
+            yprp_extension_instances(ctx, substmt, substmt_index, &((struct lysp_ext_instance*)ext)[u], &extflag, 1);
+        } else {
+            yprc_extension_instances(ctx, substmt, substmt_index, &((struct lysc_ext_instance*)ext)[u], &extflag, 1);
+        }
     }
     LEVEL--;
     ypr_close(ctx, extflag);
 }
 
 static void
-ypr_parsed_unsigned(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index, struct lysp_ext_instance *exts,
-                    unsigned int attr_value, int *flag)
+ypr_unsigned(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index, void *exts, unsigned int attr_value, int *flag)
 {
     char *str;
 
@@ -255,13 +293,12 @@
         return;
     }
     ypr_open(ctx->out, flag);
-    ypr_parsed_substmt(ctx, substmt, substmt_index, str, exts);
+    ypr_substmt(ctx, substmt, substmt_index, str, exts);
     free(str);
 }
 
 static void
-ypr_parsed_signed(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index, struct lysp_ext_instance *exts,
-                  signed int attr_value, int *flag)
+ypr_signed(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index, void *exts, signed int attr_value, int *flag)
 {
     char *str;
 
@@ -270,19 +307,19 @@
         return;
     }
     ypr_open(ctx->out, flag);
-    ypr_parsed_substmt(ctx, substmt, substmt_index, str, exts);
+    ypr_substmt(ctx, substmt, substmt_index, str, exts);
     free(str);
 }
 
 static void
-ypr_parsed_revision(struct ypr_ctx *ctx, const struct lysp_revision *rev)
+yprp_revision(struct ypr_ctx *ctx, const struct lysp_revision *rev)
 {
     if (rev->dsc || rev->ref || rev->exts) {
         ly_print(ctx->out, "%*srevision %s {\n", INDENT, rev->date);
         LEVEL++;
-        ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, rev->exts, NULL, 0);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, rev->dsc, rev->exts);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, rev->ref, rev->exts);
+        yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, rev->exts, NULL, 0);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, rev->dsc, rev->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, rev->ref, rev->exts);
         LEVEL--;
         ly_print(ctx->out, "%*s}\n", INDENT);
     } else {
@@ -291,25 +328,25 @@
 }
 
 static void
-ypr_parsed_mandatory(struct ypr_ctx *ctx, uint16_t flags, struct lysp_ext_instance *exts, int *flag)
+ypr_mandatory(struct ypr_ctx *ctx, uint16_t flags, void *exts, int *flag)
 {
     if (flags & LYS_MAND_MASK) {
         ypr_open(ctx->out, flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_MANDATORY, 0, (flags & LYS_MAND_TRUE) ? "true" : "false", exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_MANDATORY, 0, (flags & LYS_MAND_TRUE) ? "true" : "false", exts);
     }
 }
 
 static void
-ypr_parsed_config(struct ypr_ctx *ctx, uint16_t flags, struct lysp_ext_instance *exts, int *flag)
+ypr_config(struct ypr_ctx *ctx, uint16_t flags, void *exts, int *flag)
 {
     if (flags & LYS_CONFIG_MASK) {
         ypr_open(ctx->out, flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_CONFIG, 0, (flags & LYS_CONFIG_W) ? "true" : "false", exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_CONFIG, 0, (flags & LYS_CONFIG_W) ? "true" : "false", exts);
     }
 }
 
 static void
-ypr_parsed_status(struct ypr_ctx *ctx, uint16_t flags, struct lysp_ext_instance *exts, int *flag)
+ypr_status(struct ypr_ctx *ctx, uint16_t flags, void *exts, int *flag)
 {
     const char *status = NULL;
 
@@ -323,29 +360,30 @@
         ypr_open(ctx->out, flag);
         status = "obsolete";
     }
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_STATUS, 0, status, exts);
+
+    ypr_substmt(ctx, LYEXT_SUBSTMT_STATUS, 0, status, exts);
 }
 
 static void
-ypr_description(struct ypr_ctx *ctx, const char *dsc, struct lysp_ext_instance *exts, int *flag)
+ypr_description(struct ypr_ctx *ctx, const char *dsc, void *exts, int *flag)
 {
     if (dsc) {
         ypr_open(ctx->out, flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, dsc, exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, dsc, exts);
     }
 }
 
 static void
-ypr_reference(struct ypr_ctx *ctx, const char *ref, struct lysp_ext_instance *exts, int *flag)
+ypr_reference(struct ypr_ctx *ctx, const char *ref, void *exts, int *flag)
 {
     if (ref) {
         ypr_open(ctx->out, flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, ref, exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, ref, exts);
     }
 }
 
 static void
-ypr_parsed_iffeatures(struct ypr_ctx *ctx, const char **iff, struct lysp_ext_instance *exts, int *flag)
+yprp_iffeatures(struct ypr_ctx *ctx, const char **iff, struct lysp_ext_instance *exts, int *flag)
 {
     unsigned int u;
     int extflag;
@@ -362,7 +400,7 @@
             if (exts[u].insubstmt != LYEXT_SUBSTMT_IFFEATURE || exts[u].insubstmt_index != u) {
                 continue;
             }
-            ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_IFFEATURE, u, &exts[u], &extflag, 1);
+            yprp_extension_instances(ctx, LYEXT_SUBSTMT_IFFEATURE, u, &exts[u], &extflag, 1);
         }
         LEVEL--;
         ypr_close(ctx, extflag);
@@ -370,7 +408,77 @@
 }
 
 static void
-ypr_parsed_extension(struct ypr_ctx *ctx, const struct lysp_ext *ext)
+yprc_iffeature(struct ypr_ctx *ctx, struct lysc_iffeature *feat, int *index_e, int *index_f)
+{
+    int brackets_flag = *index_e;
+    uint8_t op;
+
+    op = lysc_iff_getop(feat->expr, *index_e);
+    (*index_e)++;
+
+    switch (op) {
+    case LYS_IFF_F:
+        if (ctx->module == feat->features[*index_f]->module) {
+            ly_print(ctx->out, "%s", feat->features[*index_f]->name);
+        } else {
+            ly_print(ctx->out, "%s:%s", feat->features[*index_f]->module->prefix, feat->features[*index_f]->name);
+        }
+        (*index_f)++;
+        break;
+    case LYS_IFF_NOT:
+        ly_print(ctx->out, "not ");
+        yprc_iffeature(ctx, feat, index_e, index_f);
+        break;
+    case LYS_IFF_AND:
+        if (brackets_flag) {
+            /* AND need brackets only if previous op was not */
+            if (*index_e < 2 || lysc_iff_getop(feat->expr, *index_e - 2) != LYS_IFF_NOT) {
+                brackets_flag = 0;
+            }
+        }
+        /* falls through */
+    case LYS_IFF_OR:
+        if (brackets_flag) {
+            ly_print(ctx->out, "(");
+        }
+        yprc_iffeature(ctx, feat, index_e, index_f);
+        ly_print(ctx->out, " %s ", op == LYS_IFF_OR ? "or" : "and");
+        yprc_iffeature(ctx, feat, index_e, index_f);
+        if (brackets_flag) {
+            ly_print(ctx->out, ")");
+        }
+    }
+}
+
+static void
+yprc_iffeatures(struct ypr_ctx *ctx, struct lysc_iffeature *iff, struct lysc_ext_instance *exts, int *flag)
+{
+    unsigned int u;
+    int extflag;
+
+    LY_ARRAY_FOR(iff, u) {
+        int index_e = 0, index_f = 0;
+
+        ypr_open(ctx->out, flag);
+        extflag = 0;
+
+        yprc_iffeature(ctx, iff, &index_e, &index_f);
+
+        /* extensions */
+        LEVEL++;
+        LY_ARRAY_FOR(exts, u) {
+            if (exts[u].insubstmt != LYEXT_SUBSTMT_IFFEATURE || exts[u].insubstmt_index != u) {
+                continue;
+            }
+            yprc_extension_instances(ctx, LYEXT_SUBSTMT_IFFEATURE, u, &exts[u], &extflag, 1);
+        }
+        LEVEL--;
+        ypr_close(ctx, extflag);
+    }
+}
+
+static void
+yprp_extension(struct ypr_ctx *ctx, const struct lysp_ext *ext)
 {
     int flag = 0, flag2 = 0;
     unsigned int i;
@@ -379,7 +487,7 @@
     LEVEL++;
 
     if (ext->exts) {
-        ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, ext->exts, &flag, 0);
+        yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, ext->exts, &flag, 0);
     }
 
     if (ext->argument) {
@@ -389,19 +497,19 @@
             LEVEL++;
             i = -1;
             while ((i = lysp_ext_instance_iter(ext->exts, i + 1, LYEXT_SUBSTMT_ARGUMENT)) != LY_ARRAY_SIZE(ext->exts)) {
-                ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_ARGUMENT, 0, &ext->exts[i], &flag2, 1);
+                yprp_extension_instances(ctx, LYEXT_SUBSTMT_ARGUMENT, 0, &ext->exts[i], &flag2, 1);
             }
             LEVEL--;
         }
         if ((ext->flags & LYS_YINELEM_MASK) ||
                 (ext->exts && lysp_ext_instance_iter(ext->exts, 0, LYEXT_SUBSTMT_YINELEM) != LY_ARRAY_SIZE(ext->exts))) {
             ypr_open(ctx->out, &flag2);
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_YINELEM, 0, (ext->flags & LYS_YINELEM_TRUE) ? "true" : "false", ext->exts);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_YINELEM, 0, (ext->flags & LYS_YINELEM_TRUE) ? "true" : "false", ext->exts);
         }
         ypr_close(ctx, flag2);
     }
 
-    ypr_parsed_status(ctx, ext->flags, ext->exts, &flag);
+    ypr_status(ctx, ext->flags, ext->exts, &flag);
     ypr_description(ctx, ext->dsc, ext->exts, &flag);
     ypr_reference(ctx, ext->ref, ext->exts, &flag);
 
@@ -410,15 +518,15 @@
 }
 
 static void
-ypr_parsed_feature(struct ypr_ctx *ctx, const struct lysp_feature *feat)
+yprp_feature(struct ypr_ctx *ctx, const struct lysp_feature *feat)
 {
     int flag = 0;
 
     ly_print(ctx->out, "\n%*sfeature %s", INDENT, feat->name);
     LEVEL++;
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, feat->exts, &flag, 0);
-    ypr_parsed_iffeatures(ctx, feat->iffeatures, feat->exts, &flag);
-    ypr_parsed_status(ctx, feat->flags, feat->exts, &flag);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, feat->exts, &flag, 0);
+    yprp_iffeatures(ctx, feat->iffeatures, feat->exts, &flag);
+    ypr_status(ctx, feat->flags, feat->exts, &flag);
     ypr_description(ctx, feat->dsc, feat->exts, &flag);
     ypr_reference(ctx, feat->ref, feat->exts, &flag);
     LEVEL--;
@@ -426,7 +534,23 @@
 }
 
 static void
-ypr_parsed_identity(struct ypr_ctx *ctx, const struct lysp_ident *ident)
+yprc_feature(struct ypr_ctx *ctx, const struct lysc_feature *feat)
+{
+    int flag = 0;
+
+    ly_print(ctx->out, "\n%*sfeature %s", INDENT, feat->name);
+    LEVEL++;
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, feat->exts, &flag, 0);
+    yprc_iffeatures(ctx, feat->iffeatures, feat->exts, &flag);
+    ypr_status(ctx, feat->flags, feat->exts, &flag);
+    ypr_description(ctx, feat->dsc, feat->exts, &flag);
+    ypr_reference(ctx, feat->ref, feat->exts, &flag);
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprp_identity(struct ypr_ctx *ctx, const struct lysp_ident *ident)
 {
     int flag = 0;
     unsigned int u;
@@ -434,15 +558,15 @@
     ly_print(ctx->out, "\n%*sidentity %s", INDENT, ident->name);
     LEVEL++;
 
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, ident->exts, &flag, 0);
-    ypr_parsed_iffeatures(ctx, ident->iffeatures, ident->exts, &flag);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, ident->exts, &flag, 0);
+    yprp_iffeatures(ctx, ident->iffeatures, ident->exts, &flag);
 
     LY_ARRAY_FOR(ident->bases, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_BASE, u, ident->bases[u], ident->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_BASE, u, ident->bases[u], ident->exts);
     }
 
-    ypr_parsed_status(ctx, ident->flags, ident->exts, &flag);
+    ypr_status(ctx, ident->flags, ident->exts, &flag);
     ypr_description(ctx, ident->dsc, ident->exts, &flag);
     ypr_reference(ctx, ident->ref, ident->exts, &flag);
 
@@ -451,7 +575,36 @@
 }
 
 static void
-ypr_parsed_restr(struct ypr_ctx *ctx, const struct lysp_restr *restr, const char *name, int *flag)
+yprc_identity(struct ypr_ctx *ctx, const struct lysc_ident *ident)
+{
+    int flag = 0;
+    unsigned int u;
+
+    ly_print(ctx->out, "\n%*sidentity %s", INDENT, ident->name);
+    LEVEL++;
+
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, ident->exts, &flag, 0);
+    yprc_iffeatures(ctx, ident->iffeatures, ident->exts, &flag);
+
+    LY_ARRAY_FOR(ident->derived, u) {
+        ypr_open(ctx->out, &flag);
+        if (ctx->module != ident->derived[u]->module) {
+            ly_print(ctx->out, "%*sderived %s:%s;\n", INDENT, ident->derived[u]->module->prefix, ident->derived[u]->name);
+        } else {
+            ly_print(ctx->out, "%*sderived %s;\n", INDENT, ident->derived[u]->name);
+        }
+    }
+
+    ypr_status(ctx, ident->flags, ident->exts, &flag);
+    ypr_description(ctx, ident->dsc, ident->exts, &flag);
+    ypr_reference(ctx, ident->ref, ident->exts, &flag);
+
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprp_restr(struct ypr_ctx *ctx, const struct lysp_restr *restr, const char *name, int *flag)
 {
     int inner_flag = 0;
 
@@ -465,34 +618,133 @@
     ly_print(ctx->out, "\"");
 
     LEVEL++;
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, restr->exts, &inner_flag, 0);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, restr->exts, &inner_flag, 0);
     if (restr->arg[0] == 0x15) {
         /* special byte value in pattern's expression: 0x15 - invert-match, 0x06 - match */
         ypr_open(ctx->out, &inner_flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_MODIFIER, 0, "invert-match", restr->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_MODIFIER, 0, "invert-match", restr->exts);
     }
     if (restr->emsg) {
         ypr_open(ctx->out, &inner_flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_ERRMSG, 0, restr->emsg, restr->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ERRMSG, 0, restr->emsg, restr->exts);
     }
     if (restr->eapptag) {
         ypr_open(ctx->out, &inner_flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_ERRTAG, 0, restr->eapptag, restr->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ERRTAG, 0, restr->eapptag, restr->exts);
     }
-    if (restr->dsc != NULL) {
-        ypr_open(ctx->out, &inner_flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, restr->dsc,restr->exts);
-    }
-    if (restr->ref != NULL) {
-        ypr_open(ctx->out, &inner_flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, restr->ref, restr->exts);
-    }
+    ypr_description(ctx, restr->dsc, restr->exts, &inner_flag);
+    ypr_reference(ctx, restr->ref, restr->exts, &inner_flag);
+
     LEVEL--;
     ypr_close(ctx, inner_flag);
 }
 
 static void
-ypr_parsed_when(struct ypr_ctx *ctx, struct lysp_when *when, int *flag)
+yprc_must(struct ypr_ctx *ctx, const struct lysc_must *must, int *flag)
+{
+    int inner_flag = 0;
+
+    ypr_open(ctx->out, flag);
+    ly_print(ctx->out, "%*smust \"", INDENT);
+    ypr_encode(ctx->out, must->cond->expr, -1);
+    ly_print(ctx->out, "\"");
+
+    LEVEL++;
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, must->exts, &inner_flag, 0);
+    if (must->emsg) {
+        ypr_open(ctx->out, &inner_flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ERRMSG, 0, must->emsg, must->exts);
+    }
+    if (must->eapptag) {
+        ypr_open(ctx->out, &inner_flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ERRTAG, 0, must->eapptag, must->exts);
+    }
+    ypr_description(ctx, must->dsc, must->exts, &inner_flag);
+    ypr_reference(ctx, must->ref, must->exts, &inner_flag);
+
+    LEVEL--;
+    ypr_close(ctx, inner_flag);
+}
+
+static void
+yprc_range(struct ypr_ctx *ctx, const struct lysc_range *range, LY_DATA_TYPE basetype, int *flag)
+{
+    int inner_flag = 0;
+    unsigned int u;
+
+    ypr_open(ctx->out, flag);
+    ly_print(ctx->out, "%*s%s \"", (basetype == LY_TYPE_STRING || basetype == LY_TYPE_BINARY)? "length" : "range", INDENT);
+    LY_ARRAY_FOR(range->parts, u) {
+        if (u > 0) {
+            ly_print(ctx->out, " | ");
+        }
+        if (range->parts[u].max_64 == range->parts[u].min_64) {
+            if (basetype <= LY_TYPE_STRING) { /* unsigned values */
+                ly_print(ctx->out, "%"PRIu64, range->parts[u].max_u64);
+            } else { /* signed values */
+                ly_print(ctx->out, "%"PRId64, range->parts[u].max_64);
+            }
+        } else {
+            if (basetype <= LY_TYPE_STRING) { /* unsigned values */
+                ly_print(ctx->out, "%"PRIu64"..%"PRIu64, range->parts[u].min_u64, range->parts[u].max_u64);
+            } else { /* signed values */
+                ly_print(ctx->out, "%"PRId64"..%"PRId64, range->parts[u].min_64, range->parts[u].max_64);
+            }
+        }
+    }
+    ly_print(ctx->out, "\"");
+
+    LEVEL++;
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, range->exts, &inner_flag, 0);
+    if (range->emsg) {
+        ypr_open(ctx->out, &inner_flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ERRMSG, 0, range->emsg, range->exts);
+    }
+    if (range->eapptag) {
+        ypr_open(ctx->out, &inner_flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ERRTAG, 0, range->eapptag, range->exts);
+    }
+    ypr_description(ctx, range->dsc, range->exts, &inner_flag);
+    ypr_reference(ctx, range->ref, range->exts, &inner_flag);
+
+    LEVEL--;
+    ypr_close(ctx, inner_flag);
+}
+
+static void
+yprc_pattern(struct ypr_ctx *ctx, const struct lysc_pattern *pattern, int *flag)
+{
+    int inner_flag = 0;
+
+    ypr_open(ctx->out, flag);
+    ly_print(ctx->out, "%*spattern \"", INDENT);
+    ypr_encode(ctx->out, pattern->orig, -1);
+    ly_print(ctx->out, "\"");
+
+    LEVEL++;
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, pattern->exts, &inner_flag, 0);
+    if (pattern->inverted) {
+        /* special byte value in pattern's expression: 0x15 - invert-match, 0x06 - match */
+        ypr_open(ctx->out, &inner_flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_MODIFIER, 0, "invert-match", pattern->exts);
+    }
+    if (pattern->emsg) {
+        ypr_open(ctx->out, &inner_flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ERRMSG, 0, pattern->emsg, pattern->exts);
+    }
+    if (pattern->eapptag) {
+        ypr_open(ctx->out, &inner_flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ERRTAG, 0, pattern->eapptag, pattern->exts);
+    }
+    ypr_description(ctx, pattern->dsc, pattern->exts, &inner_flag);
+    ypr_reference(ctx, pattern->ref, pattern->exts, &inner_flag);
+
+    LEVEL--;
+    ypr_close(ctx, inner_flag);
+}
+
+static void
+yprp_when(struct ypr_ctx *ctx, struct lysp_when *when, int *flag)
 {
     int inner_flag = 0;
 
@@ -506,7 +758,7 @@
     ly_print(ctx->out, "\"");
 
     LEVEL++;
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, when->exts, &inner_flag, 0);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, when->exts, &inner_flag, 0);
     ypr_description(ctx, when->dsc, when->exts, &inner_flag);
     ypr_reference(ctx, when->ref, when->exts, &inner_flag);
     LEVEL--;
@@ -514,7 +766,29 @@
 }
 
 static void
-ypr_parsed_enum(struct ypr_ctx *ctx, const struct lysp_type_enum *items, LY_DATA_TYPE type, int *flag)
+yprc_when(struct ypr_ctx *ctx, struct lysc_when *when, int *flag)
+{
+    int inner_flag = 0;
+
+    if (!when) {
+        return;
+    }
+    ypr_open(ctx->out, flag);
+
+    ly_print(ctx->out, "%*swhen \"", INDENT);
+    ypr_encode(ctx->out, when->cond->expr, -1);
+    ly_print(ctx->out, "\"");
+
+    LEVEL++;
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, when->exts, &inner_flag, 0);
+    ypr_description(ctx, when->dsc, when->exts, &inner_flag);
+    ypr_reference(ctx, when->ref, when->exts, &inner_flag);
+    LEVEL--;
+    ypr_close(ctx, inner_flag);
+}
+
+static void
+yprp_enum(struct ypr_ctx *ctx, const struct lysp_type_enum *items, LY_DATA_TYPE type, int *flag)
 {
     unsigned int u;
     int inner_flag;
@@ -526,16 +800,16 @@
         ly_print(ctx->out, "\"");
         inner_flag = 0;
         LEVEL++;
-        ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, items[u].exts, &inner_flag, 0);
-        ypr_parsed_iffeatures(ctx, items[u].iffeatures, items[u].exts, &inner_flag);
+        yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, items[u].exts, &inner_flag, 0);
+        yprp_iffeatures(ctx, items[u].iffeatures, items[u].exts, &inner_flag);
         if (items[u].flags & LYS_SET_VALUE) {
             if (type == LY_TYPE_BITS) {
-                ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_POSITION, 0, items[u].exts, items[u].value, &inner_flag);
+                ypr_unsigned(ctx, LYEXT_SUBSTMT_POSITION, 0, items[u].exts, items[u].value, &inner_flag);
             } else { /* LY_TYPE_ENUM */
-                ypr_parsed_signed(ctx, LYEXT_SUBSTMT_VALUE, 0, items[u].exts, items[u].value, &inner_flag);
+                ypr_signed(ctx, LYEXT_SUBSTMT_VALUE, 0, items[u].exts, items[u].value, &inner_flag);
             }
         }
-        ypr_parsed_status(ctx, items[u].flags, items[u].exts, &inner_flag);
+        ypr_status(ctx, items[u].flags, items[u].exts, &inner_flag);
         ypr_description(ctx, items[u].dsc, items[u].exts, &inner_flag);
         ypr_reference(ctx, items[u].ref, items[u].exts, &inner_flag);
         LEVEL--;
@@ -544,7 +818,7 @@
 }
 
 static void
-ypr_parsed_type(struct ypr_ctx *ctx, const struct lysp_type *type)
+yprp_type(struct ypr_ctx *ctx, const struct lysp_type *type)
 {
     unsigned int u;
     int flag = 0;
@@ -552,34 +826,34 @@
     ly_print(ctx->out, "%*stype %s", INDENT, type->name);
     LEVEL++;
 
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, type->exts, &flag, 0);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, type->exts, &flag, 0);
 
-    ypr_parsed_restr(ctx, type->range, "range", &flag);
-    ypr_parsed_restr(ctx, type->length, "length", &flag);
+    yprp_restr(ctx, type->range, "range", &flag);
+    yprp_restr(ctx, type->length, "length", &flag);
     LY_ARRAY_FOR(type->patterns, u) {
-        ypr_parsed_restr(ctx, &type->patterns[u], "pattern", &flag);
+        yprp_restr(ctx, &type->patterns[u], "pattern", &flag);
     }
-    ypr_parsed_enum(ctx, type->bits, LY_TYPE_BITS, &flag);
-    ypr_parsed_enum(ctx, type->enums, LY_TYPE_ENUM, &flag);
+    yprp_enum(ctx, type->bits, LY_TYPE_BITS, &flag);
+    yprp_enum(ctx, type->enums, LY_TYPE_ENUM, &flag);
 
     if (type->path) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_PATH, 0, type->path, type->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_PATH, 0, type->path, type->exts);
     }
     if (type->flags & LYS_SET_REQINST) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_REQINSTANCE, 0, type->require_instance ? "true" : "false", type->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_REQINSTANCE, 0, type->require_instance ? "true" : "false", type->exts);
     }
     if (type->flags & LYS_SET_FRDIGITS) {
-        ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_FRACDIGITS, 0, type->exts, type->fraction_digits, &flag);
+        ypr_unsigned(ctx, LYEXT_SUBSTMT_FRACDIGITS, 0, type->exts, type->fraction_digits, &flag);
     }
     LY_ARRAY_FOR(type->bases, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_BASE, u, type->bases[u], type->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_BASE, u, type->bases[u], type->exts);
     }
     LY_ARRAY_FOR(type->types, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_type(ctx, &type->types[u]);
+        yprp_type(ctx, &type->types[u]);
     }
 
     LEVEL--;
@@ -587,23 +861,141 @@
 }
 
 static void
-ypr_parsed_typedef(struct ypr_ctx *ctx, const struct lysp_tpdf *tpdf)
+yprc_type(struct ypr_ctx *ctx, const struct lysc_type *type)
+{
+    unsigned int u;
+    int flag = 0;
+
+    ly_print(ctx->out, "%*stype %s", INDENT, lys_datatype2str(type->basetype));
+    LEVEL++;
+
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, type->exts, &flag, 0);
+    if (type->dflt) {
+        ypr_open(ctx->out, &flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, type->dflt, type->exts);
+    }
+
+    switch(type->basetype) {
+    case LY_TYPE_BINARY: {
+        struct lysc_type_bin *bin = (struct lysc_type_bin*)type;
+        yprc_range(ctx, bin->length, type->basetype, &flag);
+        break;
+    }
+    case LY_TYPE_UINT8:
+    case LY_TYPE_UINT16:
+    case LY_TYPE_UINT32:
+    case LY_TYPE_UINT64:
+    case LY_TYPE_INT8:
+    case LY_TYPE_INT16:
+    case LY_TYPE_INT32:
+    case LY_TYPE_INT64: {
+        struct lysc_type_num *num = (struct lysc_type_num*)type;
+        yprc_range(ctx, num->range, type->basetype, &flag);
+        break;
+    }
+    case LY_TYPE_STRING: {
+        struct lysc_type_str *str = (struct lysc_type_str*)type;
+        yprc_range(ctx, str->length, type->basetype, &flag);
+        LY_ARRAY_FOR(str->patterns, u) {
+            yprc_pattern(ctx, str->patterns[u], &flag);
+        }
+        break;
+    }
+    case LY_TYPE_BITS:
+    case LY_TYPE_ENUM: {
+        /* bits and enums structures are compatible */
+        struct lysc_type_bits *bits = (struct lysc_type_bits*)type;
+        LY_ARRAY_FOR(bits->bits, u) {
+            struct lysc_type_bitenum_item *item = &bits->bits[u];
+            int inner_flag = 0;
+
+            ypr_open(ctx->out, &flag);
+            ly_print(ctx->out, "%*s%s \"", INDENT, type->basetype == LY_TYPE_BITS ? "bit" : "enum");
+            ypr_encode(ctx->out, item->name, -1);
+            ly_print(ctx->out, "\"");
+            LEVEL++;
+            yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, item->exts, &inner_flag, 0);
+            yprc_iffeatures(ctx, item->iffeatures, item->exts, &inner_flag);
+            if (type->basetype == LY_TYPE_BITS) {
+                ypr_unsigned(ctx, LYEXT_SUBSTMT_POSITION, 0, item->exts, item->position, &inner_flag);
+            } else { /* LY_TYPE_ENUM */
+                ypr_signed(ctx, LYEXT_SUBSTMT_VALUE, 0, item->exts, item->value, &inner_flag);
+            }
+            ypr_status(ctx, item->flags, item->exts, &inner_flag);
+            ypr_description(ctx, item->dsc, item->exts, &inner_flag);
+            ypr_reference(ctx, item->ref, item->exts, &inner_flag);
+            LEVEL--;
+            ypr_close(ctx, inner_flag);
+        }
+        break;
+    }
+    case LY_TYPE_BOOL:
+    case LY_TYPE_EMPTY:
+        /* nothing to do */
+        break;
+    case LY_TYPE_DEC64: {
+        struct lysc_type_dec *dec = (struct lysc_type_dec*)type;
+        ypr_open(ctx->out, &flag);
+        ypr_unsigned(ctx, LYEXT_SUBSTMT_FRACDIGITS, 0, type->exts, dec->fraction_digits, &flag);
+        yprc_range(ctx, dec->range, dec->basetype, &flag);
+        break;
+    }
+    case LY_TYPE_IDENT: {
+        struct lysc_type_identityref *ident = (struct lysc_type_identityref*)type;
+        LY_ARRAY_FOR(ident->bases, u) {
+            ypr_open(ctx->out, &flag);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_BASE, u, ident->bases[u]->name, type->exts);
+        }
+        break;
+    }
+    case LY_TYPE_INST: {
+        struct lysc_type_instanceid *inst = (struct lysc_type_instanceid*)type;
+        ypr_open(ctx->out, &flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_REQINSTANCE, 0, inst->require_instance ? "true" : "false", inst->exts);
+        break;
+    }
+    case LY_TYPE_LEAFREF: {
+        struct lysc_type_leafref *lr = (struct lysc_type_leafref*)type;
+        ypr_open(ctx->out, &flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_PATH, 0, lr->path, lr->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_REQINSTANCE, 0, lr->require_instance ? "true" : "false", lr->exts);
+        yprc_type(ctx, lr->realtype);
+        break;
+    }
+    case LY_TYPE_UNION: {
+        struct lysc_type_union *un = (struct lysc_type_union*)type;
+        LY_ARRAY_FOR(un->types, u) {
+            ypr_open(ctx->out, &flag);
+            yprc_type(ctx, un->types[u]);
+        }
+        break;
+    }
+    default:
+        LOGINT(ctx->module->ctx);
+    }
+
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprp_typedef(struct ypr_ctx *ctx, const struct lysp_tpdf *tpdf)
 {
     ly_print(ctx->out, "\n%*stypedef %s {\n", INDENT, tpdf->name);
     LEVEL++;
 
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, tpdf->exts, NULL, 0);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, tpdf->exts, NULL, 0);
 
-    ypr_parsed_type(ctx, &tpdf->type);
+    yprp_type(ctx, &tpdf->type);
 
     if (tpdf->units) {
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, tpdf->units, tpdf->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, tpdf->units, tpdf->exts);
     }
     if (tpdf->dflt) {
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, tpdf->dflt, tpdf->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, tpdf->dflt, tpdf->exts);
     }
 
-    ypr_parsed_status(ctx, tpdf->flags, tpdf->exts, NULL);
+    ypr_status(ctx, tpdf->flags, tpdf->exts, NULL);
     ypr_description(ctx, tpdf->dsc, tpdf->exts, NULL);
     ypr_reference(ctx, tpdf->ref, tpdf->exts, NULL);
 
@@ -611,11 +1003,12 @@
     ly_print(ctx->out, "%*s}\n", INDENT);
 }
 
-static void ypr_parsed_node(struct ypr_ctx *ctx, const struct lysp_node *node);
-static void ypr_parsed_action(struct ypr_ctx *ctx, const struct lysp_action *action);
+static void yprp_node(struct ypr_ctx *ctx, const struct lysp_node *node);
+static void yprc_node(struct ypr_ctx *ctx, const struct lysc_node *node);
+static void yprp_action(struct ypr_ctx *ctx, const struct lysp_action *action);
 
 static void
-ypr_parsed_grouping(struct ypr_ctx *ctx, const struct lysp_grp *grp)
+yprp_grouping(struct ypr_ctx *ctx, const struct lysp_grp *grp)
 {
     unsigned int u;
     int flag = 0;
@@ -624,26 +1017,26 @@
     ly_print(ctx->out, "\n%*sgrouping %s", INDENT, grp->name);
     LEVEL++;
 
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, grp->exts, &flag, 0);
-    ypr_parsed_status(ctx, grp->flags, grp->exts, &flag);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, grp->exts, &flag, 0);
+    ypr_status(ctx, grp->flags, grp->exts, &flag);
     ypr_description(ctx, grp->dsc, grp->exts, &flag);
     ypr_reference(ctx, grp->ref, grp->exts, &flag);
 
     LY_ARRAY_FOR(grp->typedefs, u) {
-        ypr_parsed_typedef(ctx, &grp->typedefs[u]);
+        yprp_typedef(ctx, &grp->typedefs[u]);
     }
 
     LY_ARRAY_FOR(grp->groupings, u) {
-        ypr_parsed_grouping(ctx, &grp->groupings[u]);
+        yprp_grouping(ctx, &grp->groupings[u]);
     }
 
     LY_LIST_FOR(grp->data, data) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_node(ctx, data);
+        yprp_node(ctx, data);
     }
 
     LY_ARRAY_FOR(grp->actions, u) {
-        ypr_parsed_action(ctx, &grp->actions[u]);
+        yprp_action(ctx, &grp->actions[u]);
     }
 
     LEVEL--;
@@ -651,7 +1044,7 @@
 }
 
 static void
-ypr_parsed_inout(struct ypr_ctx *ctx, const struct lysp_action_inout *inout, int *flag)
+yprp_inout(struct ypr_ctx *ctx, const struct lysp_action_inout *inout, int *flag)
 {
     unsigned int u;
     struct lysp_node *data;
@@ -665,19 +1058,19 @@
     ly_print(ctx->out, "\n%*s%s {\n", INDENT, (inout->nodetype == LYS_INPUT ? "input" : "output"));
     LEVEL++;
 
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, inout->exts, NULL, 0);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, inout->exts, NULL, 0);
     LY_ARRAY_FOR(inout->musts, u) {
-        ypr_parsed_restr(ctx, &inout->musts[u], "must", NULL);
+        yprp_restr(ctx, &inout->musts[u], "must", NULL);
     }
     LY_ARRAY_FOR(inout->typedefs, u) {
-        ypr_parsed_typedef(ctx, &inout->typedefs[u]);
+        yprp_typedef(ctx, &inout->typedefs[u]);
     }
     LY_ARRAY_FOR(inout->groupings, u) {
-        ypr_parsed_grouping(ctx, &inout->groupings[u]);
+        yprp_grouping(ctx, &inout->groupings[u]);
     }
 
     LY_LIST_FOR(inout->data, data) {
-        ypr_parsed_node(ctx, data);
+        yprp_node(ctx, data);
     }
 
     LEVEL--;
@@ -685,7 +1078,35 @@
 }
 
 static void
-ypr_parsed_notification(struct ypr_ctx *ctx, const struct lysp_notif *notif)
+yprc_inout(struct ypr_ctx *ctx, const struct lysc_action *action, const struct lysc_action_inout *inout, int *flag)
+{
+    unsigned int u;
+    struct lysc_node *data;
+
+    if (!inout->data) {
+        /* input/output is empty */
+        return;
+    }
+    ypr_open(ctx->out, flag);
+
+    ly_print(ctx->out, "\n%*s%s {\n", INDENT, (&action->input == inout) ? "input" : "output");
+    LEVEL++;
+
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, (&action->input == inout) ? action->input_exts : action->output_exts, NULL, 0);
+    LY_ARRAY_FOR(inout->musts, u) {
+        yprc_must(ctx, &inout->musts[u], NULL);
+    }
+
+    LY_LIST_FOR(inout->data, data) {
+        yprc_node(ctx, data);
+    }
+
+    LEVEL--;
+    ypr_close(ctx, 1);
+}
+
+static void
+yprp_notification(struct ypr_ctx *ctx, const struct lysp_notif *notif)
 {
     unsigned int u;
     int flag = 0;
@@ -694,29 +1115,29 @@
     ly_print(ctx->out, "%*snotification %s", INDENT, notif->name);
 
     LEVEL++;
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, notif->exts, &flag, 0);
-    ypr_parsed_iffeatures(ctx, notif->iffeatures, notif->exts, &flag);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, notif->exts, &flag, 0);
+    yprp_iffeatures(ctx, notif->iffeatures, notif->exts, &flag);
 
     LY_ARRAY_FOR(notif->musts, u) {
-        ypr_parsed_restr(ctx, &notif->musts[u], "must", &flag);
+        yprp_restr(ctx, &notif->musts[u], "must", &flag);
     }
-    ypr_parsed_status(ctx, notif->flags, notif->exts, &flag);
+    ypr_status(ctx, notif->flags, notif->exts, &flag);
     ypr_description(ctx, notif->dsc, notif->exts, &flag);
     ypr_reference(ctx, notif->ref, notif->exts, &flag);
 
     LY_ARRAY_FOR(notif->typedefs, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_typedef(ctx, &notif->typedefs[u]);
+        yprp_typedef(ctx, &notif->typedefs[u]);
     }
 
     LY_ARRAY_FOR(notif->groupings, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_grouping(ctx, &notif->groupings[u]);
+        yprp_grouping(ctx, &notif->groupings[u]);
     }
 
     LY_LIST_FOR(notif->data, data) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_node(ctx, data);
+        yprp_node(ctx, data);
     }
 
     LEVEL--;
@@ -724,7 +1145,36 @@
 }
 
 static void
-ypr_parsed_action(struct ypr_ctx *ctx, const struct lysp_action *action)
+yprc_notification(struct ypr_ctx *ctx, const struct lysc_notif *notif)
+{
+    unsigned int u;
+    int flag = 0;
+    struct lysc_node *data;
+
+    ly_print(ctx->out, "%*snotification %s", INDENT, notif->name);
+
+    LEVEL++;
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, notif->exts, &flag, 0);
+    yprc_iffeatures(ctx, notif->iffeatures, notif->exts, &flag);
+
+    LY_ARRAY_FOR(notif->musts, u) {
+        yprc_must(ctx, &notif->musts[u], &flag);
+    }
+    ypr_status(ctx, notif->flags, notif->exts, &flag);
+    ypr_description(ctx, notif->dsc, notif->exts, &flag);
+    ypr_reference(ctx, notif->ref, notif->exts, &flag);
+
+    LY_LIST_FOR(notif->data, data) {
+        ypr_open(ctx->out, &flag);
+        yprc_node(ctx, data);
+    }
+
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprp_action(struct ypr_ctx *ctx, const struct lysp_action *action)
 {
     unsigned int u;
     int flag = 0;
@@ -732,96 +1182,143 @@
     ly_print(ctx->out, "%*s%s %s", INDENT, action->parent ? "action" : "rpc", action->name);
 
     LEVEL++;
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, action->exts, &flag, 0);
-    ypr_parsed_iffeatures(ctx, action->iffeatures, action->exts, &flag);
-    ypr_parsed_status(ctx, action->flags, action->exts, &flag);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, action->exts, &flag, 0);
+    yprp_iffeatures(ctx, action->iffeatures, action->exts, &flag);
+    ypr_status(ctx, action->flags, action->exts, &flag);
     ypr_description(ctx, action->dsc, action->exts, &flag);
     ypr_reference(ctx, action->ref, action->exts, &flag);
 
     LY_ARRAY_FOR(action->typedefs, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_typedef(ctx, &action->typedefs[u]);
+        yprp_typedef(ctx, &action->typedefs[u]);
     }
 
     LY_ARRAY_FOR(action->groupings, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_grouping(ctx, &action->groupings[u]);
+        yprp_grouping(ctx, &action->groupings[u]);
     }
 
-    ypr_parsed_inout(ctx, &action->input, &flag);
-    ypr_parsed_inout(ctx, &action->output, &flag);
+    yprp_inout(ctx, &action->input, &flag);
+    yprp_inout(ctx, &action->output, &flag);
 
     LEVEL--;
     ypr_close(ctx, flag);
 }
 
 static void
-ypr_parsed_node_common1(struct ypr_ctx *ctx, const struct lysp_node *node, int *flag)
+yprc_action(struct ypr_ctx *ctx, const struct lysc_action *action)
+{
+    int flag = 0;
+
+    ly_print(ctx->out, "%*s%s %s", INDENT, action->parent ? "action" : "rpc", action->name);
+
+    LEVEL++;
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, action->exts, &flag, 0);
+    yprc_iffeatures(ctx, action->iffeatures, action->exts, &flag);
+    ypr_status(ctx, action->flags, action->exts, &flag);
+    ypr_description(ctx, action->dsc, action->exts, &flag);
+    ypr_reference(ctx, action->ref, action->exts, &flag);
+
+    yprc_inout(ctx, action, &action->input, &flag);
+    yprc_inout(ctx, action, &action->output, &flag);
+
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprp_node_common1(struct ypr_ctx *ctx, const struct lysp_node *node, int *flag)
 {
     ly_print(ctx->out, "\n%*s%s %s%s", INDENT, lys_nodetype2str(node->nodetype), node->name, flag ? "" : " {\n");
     LEVEL++;
 
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, node->exts, flag, 0);
-    ypr_parsed_when(ctx, node->when, flag);
-    ypr_parsed_iffeatures(ctx, node->iffeatures, node->exts, flag);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, node->exts, flag, 0);
+    yprp_when(ctx, node->when, flag);
+    yprp_iffeatures(ctx, node->iffeatures, node->exts, flag);
 }
 
 static void
-ypr_parsed_node_common2(struct ypr_ctx *ctx, const struct lysp_node *node, int *flag)
+yprc_node_common1(struct ypr_ctx *ctx, const struct lysc_node *node, int *flag)
 {
-    ypr_parsed_config(ctx, node->flags, node->exts, flag);
-    if (node->nodetype & (LYS_CHOICE | LYS_LEAF | LYS_ANYDATA)) {
-        ypr_parsed_mandatory(ctx, node->flags, node->exts, flag);
-    }
-    ypr_parsed_status(ctx, node->flags, node->exts, flag);
-    ypr_description(ctx, node->dsc, node->exts, flag);
-    ypr_reference(ctx, node->ref, node->exts, flag);
+    unsigned int u;
 
+    ly_print(ctx->out, "\n%*s%s %s%s", INDENT, lys_nodetype2str(node->nodetype), node->name, flag ? "" : " {\n");
+    LEVEL++;
+
+    yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, node->exts, flag, 0);
+    LY_ARRAY_FOR(node->when, u) {
+        yprc_when(ctx, node->when[u], flag);
+    }
+    yprc_iffeatures(ctx, node->iffeatures, node->exts, flag);
+}
+
+/* macr oto unify the code */
+#define YPR_NODE_COMMON2 \
+    ypr_config(ctx, node->flags, node->exts, flag); \
+    if (node->nodetype & (LYS_CHOICE | LYS_LEAF | LYS_ANYDATA)) { \
+        ypr_mandatory(ctx, node->flags, node->exts, flag); \
+    } \
+    ypr_status(ctx, node->flags, node->exts, flag); \
+    ypr_description(ctx, node->dsc, node->exts, flag); \
+    ypr_reference(ctx, node->ref, node->exts, flag)
+
+static void
+yprp_node_common2(struct ypr_ctx *ctx, const struct lysp_node *node, int *flag)
+{
+    YPR_NODE_COMMON2;
 }
 
 static void
-ypr_parsed_container(struct ypr_ctx *ctx, const struct lysp_node *node)
+yprc_node_common2(struct ypr_ctx *ctx, const struct lysc_node *node, int *flag)
+{
+    YPR_NODE_COMMON2;
+}
+
+#undef YPR_NODE_COMMON2
+
+static void
+yprp_container(struct ypr_ctx *ctx, const struct lysp_node *node)
 {
     unsigned int u;
     int flag = 0;
     struct lysp_node *child;
     struct lysp_node_container *cont = (struct lysp_node_container *)node;
 
-    ypr_parsed_node_common1(ctx, node, &flag);
+    yprp_node_common1(ctx, node, &flag);
 
     LY_ARRAY_FOR(cont->musts, u) {
-        ypr_parsed_restr(ctx, &cont->musts[u], "must", &flag);
+        yprp_restr(ctx, &cont->musts[u], "must", &flag);
     }
     if (cont->presence) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_PRESENCE, 0, cont->presence, cont->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_PRESENCE, 0, cont->presence, cont->exts);
     }
 
-    ypr_parsed_node_common2(ctx, node, &flag);
+    yprp_node_common2(ctx, node, &flag);
 
     LY_ARRAY_FOR(cont->typedefs, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_typedef(ctx, &cont->typedefs[u]);
+        yprp_typedef(ctx, &cont->typedefs[u]);
     }
 
     LY_ARRAY_FOR(cont->groupings, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_grouping(ctx, &cont->groupings[u]);
+        yprp_grouping(ctx, &cont->groupings[u]);
     }
 
     LY_LIST_FOR(cont->child, child) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_node(ctx, child);
+        yprp_node(ctx, child);
     }
 
     LY_ARRAY_FOR(cont->actions, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_action(ctx, &cont->actions[u]);
+        yprp_action(ctx, &cont->actions[u]);
     }
 
     LY_ARRAY_FOR(cont->notifs, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_notification(ctx, &cont->notifs[u]);
+        yprp_notification(ctx, &cont->notifs[u]);
     }
 
     LEVEL--;
@@ -829,24 +1326,100 @@
 }
 
 static void
-ypr_parsed_choice(struct ypr_ctx *ctx, const struct lysp_node *node)
+yprc_container(struct ypr_ctx *ctx, const struct lysc_node *node)
+{
+    unsigned int u;
+    int flag = 0;
+    struct lysc_node *child;
+    struct lysc_node_container *cont = (struct lysc_node_container *)node;
+
+    yprc_node_common1(ctx, node, &flag);
+
+    LY_ARRAY_FOR(cont->musts, u) {
+        yprc_must(ctx, &cont->musts[u], &flag);
+    }
+    if (cont->flags & LYS_PRESENCE) {
+        ypr_open(ctx->out, &flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_PRESENCE, 0, "true", cont->exts);
+    }
+
+    yprc_node_common2(ctx, node, &flag);
+
+    LY_LIST_FOR(cont->child, child) {
+        ypr_open(ctx->out, &flag);
+        yprc_node(ctx, child);
+    }
+
+    LY_ARRAY_FOR(cont->actions, u) {
+        ypr_open(ctx->out, &flag);
+        yprc_action(ctx, &cont->actions[u]);
+    }
+
+    LY_ARRAY_FOR(cont->notifs, u) {
+        ypr_open(ctx->out, &flag);
+        yprc_notification(ctx, &cont->notifs[u]);
+    }
+
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprp_case(struct ypr_ctx *ctx, const struct lysp_node *node)
+{
+    int flag = 0;
+    struct lysp_node *child;
+    struct lysp_node_case *cas = (struct lysp_node_case *)node;
+
+    yprp_node_common1(ctx, node, &flag);
+    yprp_node_common2(ctx, node, &flag);
+
+    LY_LIST_FOR(cas->child, child) {
+        ypr_open(ctx->out, &flag);
+        yprp_node(ctx, child);
+    }
+
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprc_case(struct ypr_ctx *ctx, const struct lysc_node_case *cs)
+{
+    int flag = 0;
+    struct lysc_node *child;
+
+    yprc_node_common1(ctx, (struct lysc_node*)cs, &flag);
+    yprc_node_common2(ctx, (struct lysc_node*)cs, &flag);
+
+    for (child = cs->child; child && child->parent == (struct lysc_node*)cs; child = child->next) {
+        ypr_open(ctx->out, &flag);
+        yprc_node(ctx, child);
+    }
+
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprp_choice(struct ypr_ctx *ctx, const struct lysp_node *node)
 {
     int flag = 0;
     struct lysp_node *child;
     struct lysp_node_choice *choice = (struct lysp_node_choice *)node;
 
-    ypr_parsed_node_common1(ctx, node, &flag);
+    yprp_node_common1(ctx, node, &flag);
 
     if (choice->dflt) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, choice->dflt, choice->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, choice->dflt, choice->exts);
     }
 
-    ypr_parsed_node_common2(ctx, node, &flag);
+    yprp_node_common2(ctx, node, &flag);
 
     LY_LIST_FOR(choice->child, child) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_node(ctx, child);
+        yprp_node(ctx, child);
     }
 
     LEVEL--;
@@ -854,61 +1427,107 @@
 }
 
 static void
-ypr_parsed_leaf(struct ypr_ctx *ctx, const struct lysp_node *node)
+yprc_choice(struct ypr_ctx *ctx, const struct lysc_node *node)
+{
+    int flag = 0;
+    struct lysc_node_case *cs;
+    struct lysc_node_choice *choice = (struct lysc_node_choice *)node;
+
+    yprc_node_common1(ctx, node, &flag);
+
+    if (choice->dflt) {
+        ypr_open(ctx->out, &flag);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, choice->dflt->name, choice->exts);
+    }
+
+    yprc_node_common2(ctx, node, &flag);
+
+    for (cs = choice->cases; cs; cs = (struct lysc_node_case*)cs->next) {
+        ypr_open(ctx->out, &flag);
+        yprc_case(ctx, cs);
+    }
+
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprp_leaf(struct ypr_ctx *ctx, const struct lysp_node *node)
 {
     unsigned int u;
     struct lysp_node_leaf *leaf = (struct lysp_node_leaf *)node;
 
-    ypr_parsed_node_common1(ctx, node, NULL);
+    yprp_node_common1(ctx, node, NULL);
 
-    ypr_parsed_type(ctx, &leaf->type);
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, leaf->units, leaf->exts);
+    yprp_type(ctx, &leaf->type);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, leaf->units, leaf->exts);
     LY_ARRAY_FOR(leaf->musts, u) {
-        ypr_parsed_restr(ctx, &leaf->musts[u], "must", NULL);
+        yprp_restr(ctx, &leaf->musts[u], "must", NULL);
     }
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, leaf->dflt, leaf->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, leaf->dflt, leaf->exts);
 
-    ypr_parsed_node_common2(ctx, node, NULL);
+    yprp_node_common2(ctx, node, NULL);
 
     LEVEL--;
     ly_print(ctx->out, "%*s}\n", INDENT);
 }
 
 static void
-ypr_parsed_leaflist(struct ypr_ctx *ctx, const struct lysp_node *node)
+yprc_leaf(struct ypr_ctx *ctx, const struct lysc_node *node)
+{
+    unsigned int u;
+    struct lysc_node_leaf *leaf = (struct lysc_node_leaf *)node;
+
+    yprc_node_common1(ctx, node, NULL);
+
+    yprc_type(ctx, leaf->type);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, leaf->units, leaf->exts);
+    LY_ARRAY_FOR(leaf->musts, u) {
+        yprc_must(ctx, &leaf->musts[u], NULL);
+    }
+    ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, leaf->dflt, leaf->exts);
+
+    yprc_node_common2(ctx, node, NULL);
+
+    LEVEL--;
+    ly_print(ctx->out, "%*s}\n", INDENT);
+}
+
+static void
+yprp_leaflist(struct ypr_ctx *ctx, const struct lysp_node *node)
 {
     unsigned int u;
     struct lysp_node_leaflist *llist = (struct lysp_node_leaflist *)node;
 
-    ypr_parsed_node_common1(ctx, node, NULL);
+    yprp_node_common1(ctx, node, NULL);
 
-    ypr_parsed_type(ctx, &llist->type);
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, llist->units, llist->exts);
+    yprp_type(ctx, &llist->type);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, llist->units, llist->exts);
     LY_ARRAY_FOR(llist->musts, u) {
-        ypr_parsed_restr(ctx, &llist->musts[u], "must", NULL);
+        yprp_restr(ctx, &llist->musts[u], "must", NULL);
     }
     LY_ARRAY_FOR(llist->dflts, u) {
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, u, llist->dflts[u], llist->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, u, llist->dflts[u], llist->exts);
     }
 
-    ypr_parsed_config(ctx, node->flags, node->exts, NULL);
+    ypr_config(ctx, node->flags, node->exts, NULL);
 
     if (llist->flags & LYS_SET_MIN) {
-        ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, llist->exts, llist->min, NULL);
+        ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, llist->exts, llist->min, NULL);
     }
     if (llist->flags & LYS_SET_MAX) {
         if (llist->max) {
-            ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, llist->exts, llist->max, NULL);
+            ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, llist->exts, llist->max, NULL);
         } else {
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", llist->exts);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", llist->exts);
         }
     }
 
     if (llist->flags & LYS_ORDBY_MASK) {
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_ORDEREDBY, 0, (llist->flags & LYS_ORDBY_USER) ? "user" : "system", llist->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ORDEREDBY, 0, (llist->flags & LYS_ORDBY_USER) ? "user" : "system", llist->exts);
     }
 
-    ypr_parsed_status(ctx, node->flags, node->exts, NULL);
+    ypr_status(ctx, node->flags, node->exts, NULL);
     ypr_description(ctx, node->dsc, node->exts, NULL);
     ypr_reference(ctx, node->ref, node->exts, NULL);
 
@@ -917,71 +1536,107 @@
 }
 
 static void
-ypr_parsed_list(struct ypr_ctx *ctx, const struct lysp_node *node)
+yprc_leaflist(struct ypr_ctx *ctx, const struct lysc_node *node)
+{
+    unsigned int u;
+    struct lysc_node_leaflist *llist = (struct lysc_node_leaflist *)node;
+
+    yprc_node_common1(ctx, node, NULL);
+
+    yprc_type(ctx, llist->type);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, llist->units, llist->exts);
+    LY_ARRAY_FOR(llist->musts, u) {
+        yprc_must(ctx, &llist->musts[u], NULL);
+    }
+    LY_ARRAY_FOR(llist->dflts, u) {
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, u, llist->dflts[u], llist->exts);
+    }
+
+    ypr_config(ctx, node->flags, node->exts, NULL);
+
+    ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, llist->exts, llist->min, NULL);
+    if (llist->max) {
+        ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, llist->exts, llist->max, NULL);
+    } else {
+        ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", llist->exts);
+    }
+
+    ypr_substmt(ctx, LYEXT_SUBSTMT_ORDEREDBY, 0, (llist->flags & LYS_ORDBY_USER) ? "user" : "system", llist->exts);
+
+    ypr_status(ctx, node->flags, node->exts, NULL);
+    ypr_description(ctx, node->dsc, node->exts, NULL);
+    ypr_reference(ctx, node->ref, node->exts, NULL);
+
+    LEVEL--;
+    ly_print(ctx->out, "%*s}\n", INDENT);
+}
+
+static void
+yprp_list(struct ypr_ctx *ctx, const struct lysp_node *node)
 {
     unsigned int u;
     int flag = 0;
     struct lysp_node *child;
     struct lysp_node_list *list = (struct lysp_node_list *)node;
 
-    ypr_parsed_node_common1(ctx, node, &flag);
+    yprp_node_common1(ctx, node, &flag);
 
     LY_ARRAY_FOR(list->musts, u) {
-        ypr_parsed_restr(ctx, &list->musts[u], "must", NULL);
+        yprp_restr(ctx, &list->musts[u], "must", NULL);
     }
     if (list->key) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_KEY, 0, list->key, list->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_KEY, 0, list->key, list->exts);
     }
     LY_ARRAY_FOR(list->uniques, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_UNIQUE, u, list->uniques[u], list->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_UNIQUE, u, list->uniques[u], list->exts);
     }
 
-    ypr_parsed_config(ctx, node->flags, node->exts, NULL);
+    ypr_config(ctx, node->flags, node->exts, NULL);
 
     if (list->flags & LYS_SET_MIN) {
-        ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, list->exts, list->min, NULL);
+        ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, list->exts, list->min, NULL);
     }
     if (list->flags & LYS_SET_MAX) {
         if (list->max) {
-            ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, list->exts, list->max, NULL);
+            ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, list->exts, list->max, NULL);
         } else {
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", list->exts);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", list->exts);
         }
     }
 
     if (list->flags & LYS_ORDBY_MASK) {
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_ORDEREDBY, 0, (list->flags & LYS_ORDBY_USER) ? "user" : "system", list->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_ORDEREDBY, 0, (list->flags & LYS_ORDBY_USER) ? "user" : "system", list->exts);
     }
 
-    ypr_parsed_status(ctx, node->flags, node->exts, NULL);
+    ypr_status(ctx, node->flags, node->exts, NULL);
     ypr_description(ctx, node->dsc, node->exts, NULL);
     ypr_reference(ctx, node->ref, node->exts, NULL);
 
     LY_ARRAY_FOR(list->typedefs, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_typedef(ctx, &list->typedefs[u]);
+        yprp_typedef(ctx, &list->typedefs[u]);
     }
 
     LY_ARRAY_FOR(list->groupings, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_grouping(ctx, &list->groupings[u]);
+        yprp_grouping(ctx, &list->groupings[u]);
     }
 
     LY_LIST_FOR(list->child, child) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_node(ctx, child);
+        yprp_node(ctx, child);
     }
 
     LY_ARRAY_FOR(list->actions, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_action(ctx, &list->actions[u]);
+        yprp_action(ctx, &list->actions[u]);
     }
 
     LY_ARRAY_FOR(list->notifs, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_notification(ctx, &list->notifs[u]);
+        yprp_notification(ctx, &list->notifs[u]);
     }
 
     LEVEL--;
@@ -989,7 +1644,71 @@
 }
 
 static void
-ypr_parsed_refine(struct ypr_ctx *ctx, struct lysp_refine *refine)
+yprc_list(struct ypr_ctx *ctx, const struct lysc_node *node)
+{
+    unsigned int u, v;
+    int flag = 0;
+    struct lysc_node *child;
+    struct lysc_node_list *list = (struct lysc_node_list *)node;
+
+    yprc_node_common1(ctx, node, &flag);
+
+    LY_ARRAY_FOR(list->musts, u) {
+        yprc_must(ctx, &list->musts[u], NULL);
+    }
+    if (list->keys) {
+        ypr_open(ctx->out, &flag);
+        ly_print(ctx->out, "%*skey \"", INDENT);
+        LY_ARRAY_FOR(list->keys, u) {
+            ly_print(ctx->out, "%s%s", u > 0 ? ", " : "", list->keys[u]->name);
+        }
+        ypr_close(ctx, 0);
+    }
+    LY_ARRAY_FOR(list->uniques, u) {
+        ypr_open(ctx->out, &flag);
+        ly_print(ctx->out, "%*sunique \"", INDENT);
+        LY_ARRAY_FOR(list->uniques[u], v) {
+            ly_print(ctx->out, "%s%s", v > 0 ? ", " : "", list->uniques[u][v]->name);
+        }
+        ypr_close(ctx, 0);
+    }
+
+    ypr_config(ctx, node->flags, node->exts, NULL);
+
+    ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, list->exts, list->min, NULL);
+    if (list->max) {
+        ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, list->exts, list->max, NULL);
+    } else {
+        ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", list->exts);
+    }
+
+    ypr_substmt(ctx, LYEXT_SUBSTMT_ORDEREDBY, 0, (list->flags & LYS_ORDBY_USER) ? "user" : "system", list->exts);
+
+    ypr_status(ctx, node->flags, node->exts, NULL);
+    ypr_description(ctx, node->dsc, node->exts, NULL);
+    ypr_reference(ctx, node->ref, node->exts, NULL);
+
+    LY_LIST_FOR(list->child, child) {
+        ypr_open(ctx->out, &flag);
+        yprc_node(ctx, child);
+    }
+
+    LY_ARRAY_FOR(list->actions, u) {
+        ypr_open(ctx->out, &flag);
+        yprc_action(ctx, &list->actions[u]);
+    }
+
+    LY_ARRAY_FOR(list->notifs, u) {
+        ypr_open(ctx->out, &flag);
+        yprc_notification(ctx, &list->notifs[u]);
+    }
+
+    LEVEL--;
+    ypr_close(ctx, flag);
+}
+
+static void
+yprp_refine(struct ypr_ctx *ctx, struct lysp_refine *refine)
 {
     unsigned int u;
     int flag = 0;
@@ -997,37 +1716,37 @@
     ly_print(ctx->out, "%*srefine \"%s\"", INDENT, refine->nodeid);
     LEVEL++;
 
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, refine->exts, &flag, 0);
-    ypr_parsed_iffeatures(ctx, refine->iffeatures, refine->exts, &flag);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, refine->exts, &flag, 0);
+    yprp_iffeatures(ctx, refine->iffeatures, refine->exts, &flag);
 
     LY_ARRAY_FOR(refine->musts, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_restr(ctx, &refine->musts[u], "must", NULL);
+        yprp_restr(ctx, &refine->musts[u], "must", NULL);
     }
 
     if (refine->presence) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_PRESENCE, 0, refine->presence, refine->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_PRESENCE, 0, refine->presence, refine->exts);
     }
 
     LY_ARRAY_FOR(refine->dflts, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, u, refine->dflts[u], refine->exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, u, refine->dflts[u], refine->exts);
     }
 
-    ypr_parsed_config(ctx, refine->flags, refine->exts, &flag);
-    ypr_parsed_mandatory(ctx, refine->flags, refine->exts, &flag);
+    ypr_config(ctx, refine->flags, refine->exts, &flag);
+    ypr_mandatory(ctx, refine->flags, refine->exts, &flag);
 
     if (refine->flags & LYS_SET_MIN) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, refine->exts, refine->min, NULL);
+        ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, refine->exts, refine->min, NULL);
     }
     if (refine->flags & LYS_SET_MAX) {
         ypr_open(ctx->out, &flag);
         if (refine->max) {
-            ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, refine->exts, refine->max, NULL);
+            ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, refine->exts, refine->max, NULL);
         } else {
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", refine->exts);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", refine->exts);
         }
     }
 
@@ -1039,7 +1758,7 @@
 }
 
 static void
-ypr_parsed_augment(struct ypr_ctx *ctx, const struct lysp_augment *aug)
+yprp_augment(struct ypr_ctx *ctx, const struct lysp_augment *aug)
 {
     unsigned int u;
     struct lysp_node *child;
@@ -1047,23 +1766,23 @@
     ly_print(ctx->out, "%*saugment \"%s\" {\n", INDENT, aug->nodeid);
     LEVEL++;
 
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, aug->exts, NULL, 0);
-    ypr_parsed_when(ctx, aug->when, NULL);
-    ypr_parsed_iffeatures(ctx, aug->iffeatures, aug->exts, NULL);
-    ypr_parsed_status(ctx, aug->flags, aug->exts, NULL);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, aug->exts, NULL, 0);
+    yprp_when(ctx, aug->when, NULL);
+    yprp_iffeatures(ctx, aug->iffeatures, aug->exts, NULL);
+    ypr_status(ctx, aug->flags, aug->exts, NULL);
     ypr_description(ctx, aug->dsc, aug->exts, NULL);
     ypr_reference(ctx, aug->ref, aug->exts, NULL);
 
     LY_LIST_FOR(aug->child, child) {
-        ypr_parsed_node(ctx, child);
+        yprp_node(ctx, child);
     }
 
     LY_ARRAY_FOR(aug->actions, u) {
-        ypr_parsed_action(ctx, &aug->actions[u]);
+        yprp_action(ctx, &aug->actions[u]);
     }
 
     LY_ARRAY_FOR(aug->notifs, u) {
-        ypr_parsed_notification(ctx, &aug->notifs[u]);
+        yprp_notification(ctx, &aug->notifs[u]);
     }
 
     LEVEL--;
@@ -1072,23 +1791,23 @@
 
 
 static void
-ypr_parsed_uses(struct ypr_ctx *ctx, const struct lysp_node *node)
+yprp_uses(struct ypr_ctx *ctx, const struct lysp_node *node)
 {
     unsigned int u;
     int flag = 0;
     struct lysp_node_uses *uses = (struct lysp_node_uses *)node;
 
-    ypr_parsed_node_common1(ctx, node, &flag);
-    ypr_parsed_node_common2(ctx, node, &flag);
+    yprp_node_common1(ctx, node, &flag);
+    yprp_node_common2(ctx, node, &flag);
 
     LY_ARRAY_FOR(uses->refines, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_refine(ctx, &uses->refines[u]);
+        yprp_refine(ctx, &uses->refines[u]);
     }
 
     LY_ARRAY_FOR(uses->augments, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_augment(ctx, &uses->augments[u]);
+        yprp_augment(ctx, &uses->augments[u]);
     }
 
     LEVEL--;
@@ -1096,72 +1815,73 @@
 }
 
 static void
-ypr_parsed_anydata(struct ypr_ctx *ctx, const struct lysp_node *node)
+yprp_anydata(struct ypr_ctx *ctx, const struct lysp_node *node)
 {
     unsigned int u;
     int flag = 0;
     struct lysp_node_anydata *any = (struct lysp_node_anydata *)node;
 
-    ypr_parsed_node_common1(ctx, node, &flag);
+    yprp_node_common1(ctx, node, &flag);
 
     LY_ARRAY_FOR(any->musts, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_restr(ctx, &any->musts[u], "must", NULL);
+        yprp_restr(ctx, &any->musts[u], "must", NULL);
     }
 
-    ypr_parsed_node_common2(ctx, node, &flag);
+    yprp_node_common2(ctx, node, &flag);
 
     LEVEL--;
     ypr_close(ctx, flag);
 }
 
 static void
-ypr_parsed_case(struct ypr_ctx *ctx, const struct lysp_node *node)
+yprc_anydata(struct ypr_ctx *ctx, const struct lysc_node *node)
 {
+    unsigned int u;
     int flag = 0;
-    struct lysp_node *child;
-    struct lysp_node_case *cas = (struct lysp_node_case *)node;
+    struct lysc_node_anydata *any = (struct lysc_node_anydata *)node;
 
-    ypr_parsed_node_common1(ctx, node, &flag);
-    ypr_parsed_node_common2(ctx, node, &flag);
+    yprc_node_common1(ctx, node, &flag);
 
-    LY_LIST_FOR(cas->child, child) {
+    LY_ARRAY_FOR(any->musts, u) {
         ypr_open(ctx->out, &flag);
-        ypr_parsed_node(ctx, child);
+        yprc_must(ctx, &any->musts[u], NULL);
     }
 
+    yprc_node_common2(ctx, node, &flag);
+
     LEVEL--;
     ypr_close(ctx, flag);
 }
 
 static void
-ypr_parsed_node(struct ypr_ctx *ctx, const struct lysp_node *node)
+yprp_node(struct ypr_ctx *ctx, const struct lysp_node *node)
 {
     switch (node->nodetype) {
     case LYS_CONTAINER:
-        ypr_parsed_container(ctx, node);
+        yprp_container(ctx, node);
         break;
     case LYS_CHOICE:
-        ypr_parsed_choice(ctx, node);
+        yprp_choice(ctx, node);
         break;
     case LYS_LEAF:
-        ypr_parsed_leaf(ctx, node);
+        yprp_leaf(ctx, node);
         break;
     case LYS_LEAFLIST:
-        ypr_parsed_leaflist(ctx, node);
+        yprp_leaflist(ctx, node);
         break;
     case LYS_LIST:
-        ypr_parsed_list(ctx, node);
+        yprp_list(ctx, node);
         break;
     case LYS_USES:
-        ypr_parsed_uses(ctx, node);
+        yprp_uses(ctx, node);
         break;
     case LYS_ANYXML:
     case LYS_ANYDATA:
-        ypr_parsed_anydata(ctx, node);
+        yprp_anydata(ctx, node);
         break;
     case LYS_CASE:
-        ypr_parsed_case(ctx, node);
+        yprp_case(ctx, node);
         break;
     default:
         break;
@@ -1169,7 +1889,35 @@
 }
 
 static void
-ypr_parsed_deviation(struct ypr_ctx *ctx, const struct lysp_deviation *deviation)
+yprc_node(struct ypr_ctx *ctx, const struct lysc_node *node)
+{
+    switch (node->nodetype) {
+    case LYS_CONTAINER:
+        yprc_container(ctx, node);
+        break;
+    case LYS_CHOICE:
+        yprc_choice(ctx, node);
+        break;
+    case LYS_LEAF:
+        yprc_leaf(ctx, node);
+        break;
+    case LYS_LEAFLIST:
+        yprc_leaflist(ctx, node);
+        break;
+    case LYS_LIST:
+        yprc_list(ctx, node);
+        break;
+    case LYS_ANYXML:
+    case LYS_ANYDATA:
+        yprc_anydata(ctx, node);
+        break;
+    default:
+        break;
+    }
+}
+
+static void
+yprp_deviation(struct ypr_ctx *ctx, const struct lysp_deviation *deviation)
 {
     unsigned int u, v;
     struct lysp_deviate_add *add;
@@ -1179,7 +1927,7 @@
     ly_print(ctx->out, "%*sdeviation \"%s\" {\n", INDENT, deviation->nodeid);
     LEVEL++;
 
-    ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, deviation->exts, NULL, 0);
+    yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, deviation->exts, NULL, 0);
     ypr_description(ctx, deviation->dsc, deviation->exts, NULL);
     ypr_reference(ctx, deviation->ref, deviation->exts, NULL);
 
@@ -1190,7 +1938,7 @@
                 ly_print(ctx->out, "not-supported {\n");
                 LEVEL++;
 
-                ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, deviation->deviates[u].exts, NULL, 0);
+                yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, deviation->deviates[u].exts, NULL, 0);
             } else {
                 ly_print(ctx->out, "not-supported;\n");
                 continue;
@@ -1200,27 +1948,27 @@
             ly_print(ctx->out, "add {\n");
             LEVEL++;
 
-            ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, add->exts, NULL, 0);
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, add->units, add->exts);
+            yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, add->exts, NULL, 0);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, add->units, add->exts);
             LY_ARRAY_FOR(add->musts, v) {
-                ypr_parsed_restr(ctx, &add->musts[v], "must", NULL);
+                yprp_restr(ctx, &add->musts[v], "must", NULL);
             }
             LY_ARRAY_FOR(add->uniques, v) {
-                ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_UNIQUE, v, add->uniques[v], add->exts);
+                ypr_substmt(ctx, LYEXT_SUBSTMT_UNIQUE, v, add->uniques[v], add->exts);
             }
             LY_ARRAY_FOR(add->dflts, v) {
-                ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, v, add->dflts[v], add->exts);
+                ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, v, add->dflts[v], add->exts);
             }
-            ypr_parsed_config(ctx, add->flags, add->exts, NULL);
-            ypr_parsed_mandatory(ctx, add->flags, add->exts, NULL);
+            ypr_config(ctx, add->flags, add->exts, NULL);
+            ypr_mandatory(ctx, add->flags, add->exts, NULL);
             if (add->flags & LYS_SET_MIN) {
-                ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, add->exts, add->min, NULL);
+                ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, add->exts, add->min, NULL);
             }
             if (add->flags & LYS_SET_MAX) {
                 if (add->max) {
-                    ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, add->exts, add->max, NULL);
+                    ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, add->exts, add->max, NULL);
                 } else {
-                    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", add->exts);
+                    ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", add->exts);
                 }
             }
         } else if (deviation->deviates[u].mod == LYS_DEV_REPLACE) {
@@ -1228,22 +1976,22 @@
             ly_print(ctx->out, "replace {\n");
             LEVEL++;
 
-            ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, rpl->exts, NULL, 0);
+            yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, rpl->exts, NULL, 0);
             if (rpl->type) {
-                ypr_parsed_type(ctx, rpl->type);
+                yprp_type(ctx, rpl->type);
             }
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, rpl->units, rpl->exts);
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, rpl->dflt, rpl->exts);
-            ypr_parsed_config(ctx, rpl->flags, rpl->exts, NULL);
-            ypr_parsed_mandatory(ctx, rpl->flags, rpl->exts, NULL);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, rpl->units, rpl->exts);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, rpl->dflt, rpl->exts);
+            ypr_config(ctx, rpl->flags, rpl->exts, NULL);
+            ypr_mandatory(ctx, rpl->flags, rpl->exts, NULL);
             if (rpl->flags & LYS_SET_MIN) {
-                ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, rpl->exts, rpl->min, NULL);
+                ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, rpl->exts, rpl->min, NULL);
             }
             if (rpl->flags & LYS_SET_MAX) {
                 if (rpl->max) {
-                    ypr_parsed_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, rpl->exts, rpl->max, NULL);
+                    ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, rpl->exts, rpl->max, NULL);
                 } else {
-                    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", rpl->exts);
+                    ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", rpl->exts);
                 }
             }
         } else if (deviation->deviates[u].mod == LYS_DEV_DELETE) {
@@ -1251,16 +1999,16 @@
             ly_print(ctx->out, "delete {\n");
             LEVEL++;
 
-            ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, del->exts, NULL, 0);
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, del->units, del->exts);
+            yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, del->exts, NULL, 0);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, del->units, del->exts);
             LY_ARRAY_FOR(del->musts, v) {
-                ypr_parsed_restr(ctx, &del->musts[v], "must", NULL);
+                yprp_restr(ctx, &del->musts[v], "must", NULL);
             }
             LY_ARRAY_FOR(del->uniques, v) {
-                ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_UNIQUE, v, del->uniques[v], del->exts);
+                ypr_substmt(ctx, LYEXT_SUBSTMT_UNIQUE, v, del->uniques[v], del->exts);
             }
             LY_ARRAY_FOR(del->dflts, v) {
-                ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, v, del->dflts[v], del->exts);
+                ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, v, del->dflts[v], del->exts);
             }
         }
 
@@ -1272,37 +2020,82 @@
     ypr_close(ctx, 1);
 }
 
+/**
+ * @brief Minimal print of a schema.
+ *
+ * To print
+ * a) compiled schema when it is not compiled or
+ * b) parsed when the parsed form was already removed
+ */
+static LY_ERR
+ypr_missing_format(struct ypr_ctx *ctx, const struct lys_module *module)
+{
+    /* module-header-stmts */
+    if (module->version) {
+        if (module->version) {
+            ypr_substmt(ctx, LYEXT_SUBSTMT_VERSION, 0, module->version == LYS_VERSION_1_1 ? "1.1" : "1", NULL);
+        }
+    }
+    ypr_substmt(ctx, LYEXT_SUBSTMT_NAMESPACE, 0, module->ns, NULL);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, module->prefix, NULL);
+
+    /* meta-stmts */
+    if (module->org || module->contact || module->dsc || module->ref) {
+        ly_print(ctx->out, "\n");
+    }
+    ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, NULL);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, NULL);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, module->dsc, NULL);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, module->ref, NULL);
+
+    /* revision-stmts */
+    if (module->revision) {
+        ly_print(ctx->out, "\n%*srevision %s;\n", INDENT, module->revision);
+    }
+
+    LEVEL--;
+    ly_print(ctx->out, "%*s}\n", INDENT);
+    ly_print_flush(ctx->out);
+
+    return LY_SUCCESS;
+}
+
 LY_ERR
 yang_print_parsed(struct lyout *out, const struct lys_module *module)
 {
     unsigned int u;
     struct lysp_node *data;
     struct lysp_module *modp = module->parsed;
-    struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = module}, *ctx = &ctx_;
+    struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = module, .schema = YPR_PARSED}, *ctx = &ctx_;
 
     ly_print(ctx->out, "%*smodule %s {\n", INDENT, module->name);
     LEVEL++;
 
+    if (!modp) {
+        ly_print(ctx->out, "%*s/* PARSED INFORMATION ARE NOT FULLY PRESENT */\n", INDENT);
+        return ypr_missing_format(ctx, module);
+    }
+
     /* module-header-stmts */
     if (module->version) {
         if (module->version) {
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_VERSION, 0, module->version == LYS_VERSION_1_1 ? "1.1" : "1", modp->exts);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_VERSION, 0, module->version == LYS_VERSION_1_1 ? "1.1" : "1", modp->exts);
         }
     }
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_NAMESPACE, 0, module->ns, modp->exts);
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, module->prefix, modp->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_NAMESPACE, 0, module->ns, modp->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, module->prefix, modp->exts);
 
     /* linkage-stmts */
     LY_ARRAY_FOR(modp->imports, u) {
         ly_print(out, "\n%*simport %s {\n", INDENT, modp->imports[u].module->name);
         LEVEL++;
-        ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modp->imports[u].exts, NULL, 0);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, modp->imports[u].prefix, modp->imports[u].exts);
+        yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modp->imports[u].exts, NULL, 0);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, modp->imports[u].prefix, modp->imports[u].exts);
         if (modp->imports[u].rev[0]) {
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_REVISIONDATE, 0, modp->imports[u].rev, modp->imports[u].exts);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_REVISIONDATE, 0, modp->imports[u].rev, modp->imports[u].exts);
         }
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, modp->imports[u].dsc, modp->imports[u].exts);
-        ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, modp->imports[u].ref, modp->imports[u].exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, modp->imports[u].dsc, modp->imports[u].exts);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, modp->imports[u].ref, modp->imports[u].exts);
         LEVEL--;
         ly_print(out, "%*s}\n", INDENT);
     }
@@ -1310,12 +2103,12 @@
         if (modp->includes[u].rev[0] || modp->includes[u].dsc || modp->includes[u].ref || modp->includes[u].exts) {
             ly_print(out, "\n%*sinclude %s {\n", INDENT, modp->includes[u].submodule->name);
             LEVEL++;
-            ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modp->includes[u].exts, NULL, 0);
+            yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modp->includes[u].exts, NULL, 0);
             if (modp->includes[u].rev[0]) {
-                ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_REVISIONDATE, 0, modp->includes[u].rev, modp->includes[u].exts);
+                ypr_substmt(ctx, LYEXT_SUBSTMT_REVISIONDATE, 0, modp->includes[u].rev, modp->includes[u].exts);
             }
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, modp->includes[u].dsc, modp->includes[u].exts);
-            ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, modp->includes[u].ref, modp->includes[u].exts);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, modp->includes[u].dsc, modp->includes[u].exts);
+            ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, modp->includes[u].ref, modp->includes[u].exts);
             LEVEL--;
             ly_print(out, "%*s}\n", INDENT);
         } else {
@@ -1327,62 +2120,62 @@
     if (module->org || module->contact || module->dsc || module->ref) {
         ly_print(out, "\n");
     }
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, modp->exts);
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, modp->exts);
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, module->dsc, modp->exts);
-    ypr_parsed_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, module->ref, modp->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, modp->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, modp->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, module->dsc, modp->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, module->ref, modp->exts);
 
     /* revision-stmts */
     if (modp->revs) {
         ly_print(out, "\n");
     }
     LY_ARRAY_FOR(modp->revs, u) {
-        ypr_parsed_revision(ctx, &modp->revs[u]);
+        yprp_revision(ctx, &modp->revs[u]);
     }
     /* body-stmts */
     LY_ARRAY_FOR(modp->extensions, u) {
         ly_print(out, "\n");
-        ypr_parsed_extension(ctx, &modp->extensions[u]);
+        yprp_extension(ctx, &modp->extensions[u]);
     }
     if (modp->exts) {
         ly_print(out, "\n");
-        ypr_parsed_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, module->parsed->exts, NULL, 0);
+        yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, module->parsed->exts, NULL, 0);
     }
 
     LY_ARRAY_FOR(modp->features, u) {
-        ypr_parsed_feature(ctx, &modp->features[u]);
+        yprp_feature(ctx, &modp->features[u]);
     }
 
     LY_ARRAY_FOR(modp->identities, u) {
-        ypr_parsed_identity(ctx, &modp->identities[u]);
+        yprp_identity(ctx, &modp->identities[u]);
     }
 
     LY_ARRAY_FOR(modp->typedefs, u) {
-        ypr_parsed_typedef(ctx, &modp->typedefs[u]);
+        yprp_typedef(ctx, &modp->typedefs[u]);
     }
 
     LY_ARRAY_FOR(modp->groupings, u) {
-        ypr_parsed_grouping(ctx, &modp->groupings[u]);
+        yprp_grouping(ctx, &modp->groupings[u]);
     }
 
     LY_LIST_FOR(modp->data, data) {
-        ypr_parsed_node(ctx, data);
+        yprp_node(ctx, data);
     }
 
     LY_ARRAY_FOR(modp->augments, u) {
-        ypr_parsed_augment(ctx, &modp->augments[u]);
+        yprp_augment(ctx, &modp->augments[u]);
     }
 
     LY_ARRAY_FOR(modp->rpcs, u) {
-        ypr_parsed_action(ctx, &modp->rpcs[u]);
+        yprp_action(ctx, &modp->rpcs[u]);
     }
 
     LY_ARRAY_FOR(modp->notifs, u) {
-        ypr_parsed_notification(ctx, &modp->notifs[u]);
+        yprp_notification(ctx, &modp->notifs[u]);
     }
 
     LY_ARRAY_FOR(modp->deviations, u) {
-        ypr_parsed_deviation(ctx, &modp->deviations[u]);
+        yprp_deviation(ctx, &modp->deviations[u]);
     }
 
     LEVEL--;
@@ -1395,8 +2188,84 @@
 LY_ERR
 yang_print_compiled(struct lyout *out, const struct lys_module *module)
 {
-    (void) out;
-    (void) module;
+    unsigned int u;
+    struct lysc_node *data;
+    struct lysc_module *modc = module->compiled;
+    struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = module}, *ctx = &ctx_;
+
+    ly_print(ctx->out, "%*smodule %s {\n", INDENT, module->name);
+    LEVEL++;
+
+    if (!modc) {
+        ly_print(ctx->out, "%*s/* COMPILED INFORMATION ARE NOT PRESENT */\n", INDENT);
+        return ypr_missing_format(ctx, module);
+    }
+
+    /* module-header-stmts */
+    if (module->version) {
+        if (module->version) {
+            ypr_substmt(ctx, LYEXT_SUBSTMT_VERSION, 0, module->version == LYS_VERSION_1_1 ? "1.1" : "1", modc->exts);
+        }
+    }
+    ypr_substmt(ctx, LYEXT_SUBSTMT_NAMESPACE, 0, module->ns, modc->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, module->prefix, modc->exts);
+
+    /* linkage-stmts */
+    LY_ARRAY_FOR(modc->imports, u) {
+        ly_print(out, "\n%*simport %s {\n", INDENT, modc->imports[u].module->name);
+        LEVEL++;
+        yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modc->imports[u].exts, NULL, 0);
+        ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, modc->imports[u].prefix, modc->imports[u].exts);
+        if (modc->imports[u].module->revision) {
+            ypr_substmt(ctx, LYEXT_SUBSTMT_REVISIONDATE, 0, modc->imports[u].module->revision, modc->imports[u].exts);
+        }
+        LEVEL--;
+        ly_print(out, "%*s}\n", INDENT);
+    }
+
+    /* meta-stmts */
+    if (module->org || module->contact || module->dsc || module->ref) {
+        ly_print(out, "\n");
+    }
+    ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, modc->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, modc->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, module->dsc, modc->exts);
+    ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, module->ref, modc->exts);
+
+    /* revision-stmts */
+    if (module->revision) {
+        ly_print(ctx->out, "\n%*srevision %s;\n", INDENT, module->revision);
+    }
+
+    /* body-stmts */
+    if (modc->exts) {
+        ly_print(out, "\n");
+        yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, module->compiled->exts, NULL, 0);
+    }
+
+    LY_ARRAY_FOR(modc->features, u) {
+        yprc_feature(ctx, &modc->features[u]);
+    }
+
+    LY_ARRAY_FOR(modc->identities, u) {
+        yprc_identity(ctx, &modc->identities[u]);
+    }
+
+    LY_LIST_FOR(modc->data, data) {
+        yprc_node(ctx, data);
+    }
+
+    LY_ARRAY_FOR(modc->rpcs, u) {
+        yprc_action(ctx, &modc->rpcs[u]);
+    }
+
+    LY_ARRAY_FOR(modc->notifs, u) {
+        yprc_notification(ctx, &modc->notifs[u]);
+    }
+
+    LEVEL--;
+    ly_print(out, "%*s}\n", INDENT);
+    ly_print_flush(out);
 
     return LY_SUCCESS;
 }
diff --git a/src/tree_schema.c b/src/tree_schema.c
index e190763..316f3a3 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -217,8 +217,8 @@
     return feature->flags & LYS_FENABLED ? 1 : 0;
 }
 
-static uint8_t
-iff_getop(uint8_t *list, int pos)
+uint8_t
+lysc_iff_getop(uint8_t *list, int pos)
 {
     uint8_t *item;
     uint8_t mask = 3, result;
@@ -236,7 +236,7 @@
     uint8_t op;
     int a, b;
 
-    op = iff_getop(iff->expr, *index_e);
+    op = lysc_iff_getop(iff->expr, *index_e);
     (*index_e)++;
 
     switch (op) {
@@ -662,7 +662,7 @@
 
     if (!mod->implemented) {
         /* pre-compile features of the module */
-        LY_CHECK_GOTO(lys_feature_precompile(ctx, mod->parsed->features, &mod->off_features), error);
+        LY_CHECK_GOTO(lys_feature_precompile(ctx, mod, mod->parsed->features, &mod->off_features), error);
     }
 
     /* decide the latest revision */
@@ -708,7 +708,7 @@
         }
         if (!mod->implemented) {
             /* pre-compile features of the module */
-            LY_CHECK_GOTO(lys_feature_precompile(ctx, inc->submodule->features, &mod->off_features), error);
+            LY_CHECK_GOTO(lys_feature_precompile(ctx, mod, inc->submodule->features, &mod->off_features), error);
         }
     }
     mod->parsed->parsing = 0;
diff --git a/src/tree_schema.h b/src/tree_schema.h
index f99368a..6539294 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -133,7 +133,7 @@
 typedef enum {
     LYS_IN_UNKNOWN = 0,  /**< unknown format, used as return value in case of error */
     LYS_IN_YANG = 1,     /**< YANG schema input format */
-    LYS_IN_YIN = 2       /**< YIN schema input format */
+    LYS_IN_YIN = 3       /**< YIN schema input format */
 } LYS_INFORMAT;
 
 /**
@@ -142,8 +142,8 @@
 typedef enum {
     LYS_OUT_UNKNOWN = 0, /**< unknown format, used as return value in case of error */
     LYS_OUT_YANG = 1,    /**< YANG schema output format */
-    LYS_OUT_YIN = 2,     /**< YIN schema output format */
-    LYS_OUT_YANG_COMPILED, /**< YANG schema output format of the compiled schema tree */
+    LYS_OUT_YIN = 3,     /**< YIN schema output format */
+    LYS_OUT_YANG_COMPILED = 2, /**< YANG schema output format of the compiled schema tree */
 
     LYS_OUT_TREE,        /**< Tree schema output format, for more information see the [printers](@ref howtoschemasprinters) page */
     LYS_OUT_INFO,        /**< Info schema output format, for more information see the [printers](@ref howtoschemasprinters) page */
@@ -259,10 +259,10 @@
 struct lysp_ext_instance {
     const char *name;                /**< extension identifier, including possible prefix */
     const char *argument;            /**< optional value of the extension's argument */
+    struct lysp_stmt *child;         /**< list of the extension's substatements (linked list) */
     LYEXT_SUBSTMT insubstmt;         /**< value identifying placement of the extension instance */
     uint32_t insubstmt_index;        /**< in case the instance is in a substatement, this identifies
                                           the index of that substatement */
-    struct lysp_stmt *child;         /**< list of the extension's substatements (linked list) */
 };
 
 /**
@@ -557,39 +557,40 @@
  *     2 - choice       7 - case              12 - feature
  *     3 - leaf         8 - notification      13 - identity
  *     4 - leaflist     9 - rpc               14 - extension
- *     5 - list        10 - input
+ *     5 - list        10 - input             15 - bitenum
  *
- *                                             1 1 1 1 1
- *     bit name              1 2 3 4 5 6 7 8 9 0 1 2 3 4
- *     ---------------------+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *       1 LYS_CONFIG_W     |x|x|x|x|x|x|x| | | | | | | |
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *       2 LYS_CONFIG_R     |x|x|x|x|x|x|x| | | | | | | |
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *       3 LYS_STATUS_CURR  |x|x|x|x|x|x|x|x|x| | |x|x|x|
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *       4 LYS_STATUS_DEPRC |x|x|x|x|x|x|x|x|x| | |x|x|x|
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *       5 LYS_STATUS_OBSLT |x|x|x|x|x|x|x|x|x| | |x|x|x|
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *       6 LYS_MAND_TRUE    |x|x|x|x|x|x| | | | | | | | |
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *       7 LYS_ORDBY_USER   | | | |x|x| | | | | | | | | |
- *         LYS_MAND_FALSE   | |x|x| | |x| | | | | | | | |
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *       8 LYS_ORDBY_SYSTEM | | | |x|x| | | | | | | | | |
- *         LYS_PRESENCE     |x| | | | | | | | | | | | | |
- *         LYS_UNIQUE       | | |x| | | | | | | | | | | |
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *       9 LYS_KEY          | | |x| | | | | | | | | | | |
- *         LYS_FENABLED     | | | | | | | | | | | |x| | |
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *      10 LYS_SET_DFLT     | | |x|x| | |x| | | | | | | |
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *      11 LYS_SET_UNITS    | | |x|x| | | | | | | | | | |
- *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *      11 LYS_SET_CONFIG   |x|x|x|x|x|x|x| | |x|x| | | |
- *     ---------------------+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *                                             1 1 1 1 1 1
+ *     bit name              1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ *     ---------------------+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *       1 LYS_CONFIG_W     |x|x|x|x|x|x|x| | | | | | | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *       2 LYS_CONFIG_R     |x|x|x|x|x|x|x| | | | | | | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *       3 LYS_STATUS_CURR  |x|x|x|x|x|x|x|x|x| | |x|x|x| |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *       4 LYS_STATUS_DEPRC |x|x|x|x|x|x|x|x|x| | |x|x|x| |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *       5 LYS_STATUS_OBSLT |x|x|x|x|x|x|x|x|x| | |x|x|x| |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *       6 LYS_MAND_TRUE    |x|x|x|x|x|x| | | | | | | | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *       7 LYS_ORDBY_USER   | | | |x|x| | | | | | | | | | |
+ *         LYS_MAND_FALSE   | |x|x| | |x| | | | | | | | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *       8 LYS_ORDBY_SYSTEM | | | |x|x| | | | | | | | | | |
+ *         LYS_PRESENCE     |x| | | | | | | | | | | | | | |
+ *         LYS_UNIQUE       | | |x| | | | | | | | | | | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *       9 LYS_KEY          | | |x| | | | | | | | | | | | |
+ *         LYS_FENABLED     | | | | | | | | | | | |x| | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      10 LYS_SET_DFLT     | | |x|x| | |x| | | | | | | | |
+ *         LYS_ISENUM       | | | | | | | | | | | | | | |x|
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      11 LYS_SET_UNITS    | | |x|x| | | | | | | | | | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      11 LYS_SET_CONFIG   |x|x|x|x|x|x|x| | |x|x| | | | |
+ *     ---------------------+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
  */
 
@@ -651,6 +652,8 @@
 #define LYS_SINGLEQUOTED 0x100       /**< flag for single-quoted argument of an extension instance's substatement */
 #define LYS_DOUBLEQUOTED 0x200       /**< flag for double-quoted argument of an extension instance's substatement */
 
+#define LYS_ISENUM       0x200       /**< flag to simply distinguish type in struct lysc_type_bitenum_item */
+
 #define LYS_FLAGS_COMPILED_MASK 0xff /**< mask for flags that maps to the compiled structures */
 /** @} */
 
@@ -1011,6 +1014,7 @@
     const char *name;                /**< identity name (mandatory), including possible prefix */
     const char *dsc;                 /**< description */
     const char *ref;                 /**< reference */
+    struct lys_module *module;       /**< module structure */
     struct lysc_ident **derived;     /**< list of (pointers to the) derived identities ([sized array](@ref sizedarrays)) */
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
     struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
@@ -1024,6 +1028,7 @@
     const char *name;                /**< feature name (mandatory) */
     const char *dsc;                 /**< description */
     const char *ref;                 /**< reference */
+    struct lys_module *module;       /**< module structure */
     struct lysc_feature **depfeatures;/**< list of pointers to other features depending on this one ([sized array](@ref sizedarrays)) */
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
     struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
@@ -1055,13 +1060,13 @@
 
 struct lysc_range {
     struct lysc_range_part {
-        union {                      /**< min boundary TODO decimal */
-            int64_t min_64;          /**< for int8, int16, int32 and int64 */
-            uint64_t min_u64;        /**< for uint8, uint16, uint32 and uint64 */
+        union {                      /**< min boundary */
+            int64_t min_64;          /**< for int8, int16, int32, int64 and decimal64 */
+            uint64_t min_u64;        /**< for uint8, uint16, uint32, uint64, string and binary */
         };
-        union {                      /**< max boundary TODO decimal */
-            int64_t max_64;          /**< for int8, int16, int32 and int64 */
-            uint64_t max_u64;        /**< for uint8, uint16, uint32 and uint64 */
+        union {                      /**< max boundary */
+            int64_t max_64;          /**< for int8, int16, int32, int64 and decimal64 */
+            uint64_t max_u64;        /**< for uint8, uint16, uint32, uint64, string and binary */
         };
     } *parts;                        /**< compiled range expression ([sized array](@ref sizedarrays)) */
     const char *dsc;                 /**< description */
@@ -1072,6 +1077,7 @@
 };
 
 struct lysc_pattern {
+    const char *orig;                /**< original, not compiled, regular expression */
     pcre *expr;                      /**< compiled regular expression */
     pcre_extra *expr_extra;          /**< additional information to speed up matching */
     const char *dsc;                 /**< description */
@@ -1126,19 +1132,34 @@
     struct lysc_pattern **patterns;  /**< Optional list of pointers to pattern limitations ([sized array](@ref sizedarrays)) */
 };
 
+struct lysc_type_bitenum_item {
+    const char *name;            /**< enumeration identifier */
+    const char *dsc;             /**< description */
+    const char *ref;             /**< reference */
+    struct lysc_ext_instance *exts;    /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+    union {
+        int32_t value;           /**< integer value associated with the enumeration */
+        uint32_t position;       /**< non-negative integer value associated with the bit */
+    };
+    uint16_t flags;              /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_ and LYS_SET_VALUE
+                                          values are allowed */
+};
+
 struct lysc_type_enum {
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
     const char *dflt;                /**< type's default value if any */
     LY_DATA_TYPE basetype;           /**< Base type of the type */
     uint32_t refcount;               /**< reference counter for type sharing */
-    struct lysc_type_enum_item {
-        const char *name;            /**< enumeration identifier */
-        const char *dsc;             /**< description */
-        const char *ref;             /**< reference */
-        struct lysc_ext_instance *exts;    /**< list of the extension instances ([sized array](@ref sizedarrays)) */
-        struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-        int32_t value;               /**< integer value associated with the enumeration */
-    } *enums;                        /**< enumerations list ([sized array](@ref sizedarrays)), mandatory (at least 1 item) */
+    struct lysc_type_bitenum_item *enums; /**< enumerations list ([sized array](@ref sizedarrays)), mandatory (at least 1 item) */
+};
+
+struct lysc_type_bits {
+    struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    const char *dflt;                /**< type's default value if any */
+    LY_DATA_TYPE basetype;           /**< Base type of the type */
+    uint32_t refcount;               /**< reference counter for type sharing */
+    struct lysc_type_bitenum_item *bits; /**< bits list ([sized array](@ref sizedarrays)), mandatory (at least 1 item) */
 };
 
 struct lysc_type_leafref {
@@ -1169,21 +1190,6 @@
     uint8_t require_instance;        /**< require-instance flag */
 };
 
-struct lysc_type_bits {
-    struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
-    const char *dflt;                /**< type's default value if any */
-    LY_DATA_TYPE basetype;           /**< Base type of the type */
-    uint32_t refcount;               /**< reference counter for type sharing */
-    struct lysc_type_bits_item {
-        const char *name;            /**< bit identifier */
-        const char *dsc;             /**< description */
-        const char *ref;             /**< reference */
-        struct lysc_ext_instance *exts;    /**< list of the extension instances ([sized array](@ref sizedarrays)) */
-        struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
-        uint32_t position;           /**< non-negative integer value associated with the bit */
-    } *bits;                         /**< bits list ([sized array](@ref sizedarrays)), mandatory (at least 1 item) */
-};
-
 struct lysc_type_union {
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
     const char *dflt;                /**< type's default value if any */
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 40c1419..a9bf7de 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -640,6 +640,7 @@
     DUP_STRING(ctx->ctx, ident_p->name, ident->name);
     DUP_STRING(ctx->ctx, ident_p->dsc, ident->dsc);
     DUP_STRING(ctx->ctx, ident_p->ref, ident->ref);
+    ident->module = ctx->mod;
     COMPILE_ARRAY_GOTO(ctx, ident_p->iffeatures, ident->iffeatures, options, u, lys_compile_iffeature, ret, done);
     /* backlings (derived) can be added no sooner than when all the identities in the current module are present */
     COMPILE_ARRAY_GOTO(ctx, ident_p->exts, ident->exts, options, u, lys_compile_ext, ret, done);
@@ -810,7 +811,7 @@
 }
 
 LY_ERR
-lys_feature_precompile(struct ly_ctx *ctx, struct lysp_feature *features_p, struct lysc_feature **features)
+lys_feature_precompile(struct ly_ctx *ctx, struct lys_module *module, struct lysp_feature *features_p, struct lysc_feature **features)
 {
     unsigned int offset = 0, u;
     struct lysc_ctx context = {0};
@@ -833,6 +834,7 @@
         DUP_STRING(ctx, features_p[u].dsc, (*features)[offset + u].dsc);
         DUP_STRING(ctx, features_p[u].ref, (*features)[offset + u].ref);
         (*features)[offset + u].flags = features_p[u].flags;
+        (*features)[offset + u].module = module;
     }
 
     return LY_SUCCESS;
@@ -1745,6 +1747,7 @@
         if (patterns_p[u].arg[0] == 0x15) {
             (*pattern)->inverted = 1;
         }
+        DUP_STRING(ctx->ctx, &patterns_p[u].arg[1], (*pattern)->orig);
         DUP_STRING(ctx->ctx, patterns_p[u].eapptag, (*pattern)->eapptag);
         DUP_STRING(ctx->ctx, patterns_p[u].emsg, (*pattern)->emsg);
         DUP_STRING(ctx->ctx, patterns_p[u].dsc, (*pattern)->dsc);
@@ -1802,13 +1805,13 @@
  */
 static LY_ERR
 lys_compile_type_enums(struct lysc_ctx *ctx, struct lysp_type_enum *enums_p, LY_DATA_TYPE basetype, int options,
-                       struct lysc_type_enum_item *base_enums, struct lysc_type_enum_item **enums)
+                       struct lysc_type_bitenum_item *base_enums, struct lysc_type_bitenum_item **enums)
 {
     LY_ERR ret = LY_SUCCESS;
     unsigned int u, v, match;
     int32_t value = 0;
     uint32_t position = 0;
-    struct lysc_type_enum_item *e, storage;
+    struct lysc_type_bitenum_item *e, storage;
 
     if (base_enums && ctx->mod_def->version < 2) {
         LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "%s type can be subtyped only in YANG 1.1 modules.",
@@ -1821,6 +1824,7 @@
         DUP_STRING(ctx->ctx, enums_p[u].name, e->name);
         DUP_STRING(ctx->ctx, enums_p[u].ref, e->dsc);
         DUP_STRING(ctx->ctx, enums_p[u].ref, e->ref);
+        e->flags = enums_p[u].flags & LYS_FLAGS_COMPILED_MASK;
         if (base_enums) {
             /* check the enum/bit presence in the base type - the set of enums/bits in the derived type must be a subset */
             LY_ARRAY_FOR(base_enums, v) {
@@ -1838,6 +1842,7 @@
         }
 
         if (basetype == LY_TYPE_ENUM) {
+            e->flags |= LYS_ISENUM;
             if (enums_p[u].flags & LYS_SET_VALUE) {
                 e->value = (int32_t)enums_p[u].value;
                 if (!u || e->value >= value) {
@@ -2479,8 +2484,8 @@
         bits = (struct lysc_type_bits*)(*type);
         if (type_p->bits) {
             ret = lys_compile_type_enums(ctx, type_p->bits, basetype, options,
-                                         base ? (struct lysc_type_enum_item*)((struct lysc_type_bits*)base)->bits : NULL,
-                                         (struct lysc_type_enum_item**)&bits->bits);
+                                         base ? (struct lysc_type_bitenum_item*)((struct lysc_type_bits*)base)->bits : NULL,
+                                         (struct lysc_type_bitenum_item**)&bits->bits);
             LY_CHECK_RET(ret);
         }
 
@@ -5751,7 +5756,7 @@
         /* features are compiled directly into the compiled module structure,
          * but it must be done in two steps to allow forward references (via if-feature) between the features themselves.
          * The features compilation is finished in the main module (lys_compile()). */
-        ret = lys_feature_precompile(ctx->ctx, submod->features,
+        ret = lys_feature_precompile(ctx->ctx, ctx->mod, submod->features,
                                      mainmod->mod->off_features ? &mainmod->mod->off_features : &mainmod->features);
         LY_CHECK_GOTO(ret, error);
     }
@@ -5809,7 +5814,7 @@
     } else {
         /* features are compiled directly into the compiled module structure,
          * but it must be done in two steps to allow forward references (via if-feature) between the features themselves */
-        ret = lys_feature_precompile(ctx.ctx, sp->features, &mod_c->features);
+        ret = lys_feature_precompile(ctx.ctx, ctx.mod, sp->features, &mod_c->features);
         LY_CHECK_GOTO(ret, error);
     }
     /* finish feature compilation, not only for the main module, but also for the submodules.
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 1c94ae7..9e5563c 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -547,6 +547,7 @@
     }
     pcre_free((*pattern)->expr);
     pcre_free_study((*pattern)->expr_extra);
+    FREE_STRING(ctx, (*pattern)->orig);
     FREE_STRING(ctx, (*pattern)->eapptag);
     FREE_STRING(ctx, (*pattern)->emsg);
     FREE_STRING(ctx, (*pattern)->dsc);
@@ -556,7 +557,7 @@
 }
 
 static void
-lysc_enum_item_free(struct ly_ctx *ctx, struct lysc_type_enum_item *item)
+lysc_enum_item_free(struct ly_ctx *ctx, struct lysc_type_bitenum_item *item)
 {
     FREE_STRING(ctx, item->name);
     FREE_STRING(ctx, item->dsc);
@@ -581,7 +582,7 @@
         FREE_MEMBER(ctx, ((struct lysc_type_bin*)type)->length, lysc_range_free);
         break;
     case LY_TYPE_BITS:
-        FREE_ARRAY(ctx, (struct lysc_type_enum_item*)((struct lysc_type_bits*)type)->bits, lysc_enum_item_free);
+        FREE_ARRAY(ctx, (struct lysc_type_bitenum_item*)((struct lysc_type_bits*)type)->bits, lysc_enum_item_free);
         break;
     case LY_TYPE_DEC64:
         FREE_MEMBER(ctx, ((struct lysc_type_dec*)type)->range, lysc_range_free);
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index 1ff0161..ada61c7 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -949,6 +949,30 @@
 }
 
 const char *
+lys_prefix_find_module(const struct lys_module *mod, const struct lys_module *import)
+{
+    unsigned int u;
+
+    if (import == mod) {
+        return mod->prefix;
+    }
+
+    if (mod->parsed) {
+        LY_ARRAY_FOR(mod->parsed->imports, u) {
+            if (mod->parsed->imports[u].module == import) {
+                return mod->parsed->imports[u].prefix;
+            }
+        }
+    } else {
+        /* we don't have original information about the import's prefix,
+         * so the prefix of the import module itself is returned instead */
+        return import->prefix;
+    }
+
+    return NULL;
+}
+
+const char *
 lys_nodetype2str(uint16_t nodetype)
 {
     switch(nodetype) {
@@ -979,6 +1003,53 @@
     }
 }
 
+const char *
+lys_datatype2str(LY_DATA_TYPE basetype)
+{
+    switch(basetype) {
+    case LY_TYPE_BINARY:
+        return "binary";
+    case LY_TYPE_UINT8:
+        return "uint8";
+    case LY_TYPE_UINT16:
+        return "uint16";
+    case LY_TYPE_UINT32:
+        return "uint32";
+    case LY_TYPE_UINT64:
+        return "uint64";
+    case LY_TYPE_STRING:
+        return "string";
+    case LY_TYPE_BITS:
+        return "bits";
+    case LY_TYPE_BOOL:
+        return "boolean";
+    case LY_TYPE_DEC64:
+        return "decimal64";
+    case LY_TYPE_EMPTY:
+        return "empty";
+    case LY_TYPE_ENUM:
+        return "enumeration";
+    case LY_TYPE_IDENT:
+        return "identityref";
+    case LY_TYPE_INST:
+        return "instance-identifier";
+    case LY_TYPE_LEAFREF:
+        return "leafref";
+    case LY_TYPE_UNION:
+        return "union";
+    case LY_TYPE_INT8:
+        return "int8";
+    case LY_TYPE_INT16:
+        return "int16";
+    case LY_TYPE_INT32:
+        return "int32";
+    case LY_TYPE_INT64:
+        return "int64";
+    default:
+        return "unknown";
+    }
+}
+
 API const struct lysp_tpdf *
 lysp_node_typedefs(const struct lysp_node *node)
 {
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index e15f7cd..c694d46 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -330,6 +330,8 @@
 /**
  * @brief Find the module referenced by prefix in the provided mod.
  *
+ * Reverse function to lys_prefix_find_module().
+ *
  * @param[in] mod Schema module where the prefix was used.
  * @param[in] prefix Prefix used to reference a module.
  * @param[in] len Length of the prefix since it is not necessary NULL-terminated.
@@ -338,6 +340,20 @@
 struct lys_module *lys_module_find_prefix(const struct lys_module *mod, const char *prefix, size_t len);
 
 /**
+ * @brief Find the prefix used to referenced the import module in the provided mod.
+ *
+ * Reverse function to lys_module_find_prefix().
+ *
+ * Note that original prefixes are present only in the parsed schema. In case it is not available
+ * (only compiled schema available), the own prefix of the import module is returned instead.
+ *
+ * @param[in] mod Schema module where the import module was used.
+ * @param[in] import Module referenced in mod.
+ * @return Prefix of the import module.
+ */
+const char *lys_prefix_find_module(const struct lys_module *mod, const struct lys_module *import);
+
+/**
  * @brief Stringify schema nodetype.
  * @param[in] nodetype Nodetype to stringify.
  * @return Constant string with the name of the node's type.
@@ -345,6 +361,13 @@
 const char *lys_nodetype2str(uint16_t nodetype);
 
 /**
+ * @brief Stringify YANG built-in type.
+ * @param[in] basetype Built-in tyep ID to stringify.
+ * @return Constant string with the name of the built-in type.
+ */
+const char *lys_datatype2str(LY_DATA_TYPE basetype);
+
+/**
  * @brief Parse YANG module from a string.
  *
  * The modules are added into the context and the latest_revision flag is updated.
@@ -493,13 +516,22 @@
  * if-feature structures.
  *
  * @param[in] ctx libyang context.
+ * @param[in] module Module of the features.
  * @param[in] features_p Array if the parsed features definitions to precompile.
  * @param[in,out] features Pointer to the storage of the (pre)compiled features array where the new features are
  * supposed to be added. The storage is supposed to be initiated to NULL when the first parsed features are going
  * to be processed.
  * @return LY_ERR value.
  */
-LY_ERR lys_feature_precompile(struct ly_ctx *ctx, struct lysp_feature *features_p, struct lysc_feature **features);
+LY_ERR lys_feature_precompile(struct ly_ctx *ctx, struct lys_module *module, struct lysp_feature *features_p, struct lysc_feature **features);
+
+/**
+ * @brief Get the @ref ifftokens from the given position in the 2bits array
+ * (libyang format of the if-feature expression).
+ * @param[in] list The 2bits array with the compiled if-feature expression.
+ * @param[in] pos Position (0-based) to specify from which position get the operator.
+ */
+uint8_t lysc_iff_getop(uint8_t *list, int pos);
 
 /**
  * @brief Macro to free [sized array](@ref sizedarrays) of items using the provided free function. The ARRAY itself is also freed,
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index 6c43df5..da5ea4c 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -1287,9 +1287,11 @@
     assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
     assert_string_equal("errortag", ((struct lysc_type_str*)type)->patterns[0]->eapptag);
     assert_string_equal("error", ((struct lysc_type_str*)type)->patterns[0]->emsg);
+    assert_string_equal(".*", ((struct lysc_type_str*)type)->patterns[0]->orig);
     assert_int_equal(0, ((struct lysc_type_str*)type)->patterns[0]->inverted);
     assert_null(((struct lysc_type_str*)type)->patterns[1]->eapptag);
     assert_null(((struct lysc_type_str*)type)->patterns[1]->emsg);
+    assert_string_equal("[0-9].*[0-9]", ((struct lysc_type_str*)type)->patterns[1]->orig);
     assert_int_equal(1, ((struct lysc_type_str*)type)->patterns[1]->inverted);
 
     assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;typedef mytype {type string {pattern '[0-9]*';}}"
@@ -1300,7 +1302,9 @@
     assert_int_equal(1, type->refcount);
     assert_non_null(((struct lysc_type_str*)type)->patterns);
     assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+    assert_string_equal("[0-9]*", ((struct lysc_type_str*)type)->patterns[0]->orig);
     assert_int_equal(3, ((struct lysc_type_str*)type)->patterns[0]->refcount);
+    assert_string_equal("[0-4]*", ((struct lysc_type_str*)type)->patterns[1]->orig);
     assert_int_equal(1, ((struct lysc_type_str*)type)->patterns[1]->refcount);
 
     assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c;typedef mytype {type string {pattern '[0-9]*';}}"
@@ -1311,6 +1315,7 @@
     assert_int_equal(1, type->refcount);
     assert_non_null(((struct lysc_type_str*)type)->patterns);
     assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+    assert_string_equal("[0-9]*", ((struct lysc_type_str*)type)->patterns[0]->orig);
     assert_int_equal(2, ((struct lysc_type_str*)type)->patterns[0]->refcount);
 
     /* test substitutions */
@@ -1320,6 +1325,7 @@
     assert_non_null(type);
     assert_non_null(((struct lysc_type_str*)type)->patterns);
     assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+    assert_string_equal("^\\p{IsLatinExtended-A}$", ((struct lysc_type_str*)type)->patterns[0]->orig);
     /* TODO check some data "^ř$" */
 
     *state = NULL;
diff --git a/tools/lint/commands.c b/tools/lint/commands.c
index 0e7913a..bb6bf1b 100644
--- a/tools/lint/commands.c
+++ b/tools/lint/commands.c
@@ -346,13 +346,14 @@
 int
 cmd_print(const char *arg)
 {
-    int c, argc, option_index, ret = 1, tree_ll = 0, tree_opts = 0;
+    int c, argc, option_index, ret = 1, tree_ll = 0, tree_opts = 0, compiled = 0;
     char **argv = NULL, *ptr, *model_name, *revision;
     const char *out_path = NULL;
     const struct lys_module *module;
     LYS_OUTFORMAT format = LYS_OUT_TREE;
     FILE *output = stdout;
     static struct option long_options[] = {
+        {"compiled", no_argument, 0, 'c'},
         {"help", no_argument, 0, 'h'},
         {"format", required_argument, 0, 'f'},
         {"output", required_argument, 0, 'o'},
@@ -386,12 +387,15 @@
     optind = 0;
     while (1) {
         option_index = 0;
-        c = getopt_long(argc, argv, "hf:go:guP:L:", long_options, &option_index);
+        c = getopt_long(argc, argv, "chf:go:guP:L:", long_options, &option_index);
         if (c == -1) {
             break;
         }
 
         switch (c) {
+        case 'c':
+            compiled = 1;
+            break;
         case 'h':
             cmd_print_help();
             ret = 0;
@@ -453,6 +457,11 @@
         goto cleanup;
     }
 
+    /* compiled format */
+    if (compiled) {
+        format++;
+    }
+
     /* tree fromat with or without gropings */
     if ((tree_opts || tree_ll) && format != LYS_OUT_TREE) {
         fprintf(stderr, "--tree options take effect only in case of the tree output format.\n");
diff --git a/tools/lint/main_ni.c b/tools/lint/main_ni.c
index 892d242..220ef33 100644
--- a/tools/lint/main_ni.c
+++ b/tools/lint/main_ni.c
@@ -254,7 +254,7 @@
 main_ni(int argc, char* argv[])
 {
     int ret = EXIT_FAILURE;
-    int opt, opt_index = 0, i, featsize = 0;
+    int opt, opt_index = 0, i, featsize = 0, compiled = 0;
     struct option options[] = {
 #if 0
         {"auto",             no_argument,       NULL, 'a'},
@@ -269,6 +269,7 @@
         {"tree-path",        required_argument, NULL, 'P'},
         {"tree-line-length", required_argument, NULL, 'L'},
 #endif
+        {"compiled",         no_argument,       NULL, 'c'},
         {"help",             no_argument,       NULL, 'h'},
 #if 0
         {"tree-help",        no_argument,       NULL, 'H'},
@@ -330,9 +331,9 @@
 
     opterr = 0;
 #ifndef NDEBUG
-    while ((opt = getopt_long(argc, argv, "ad:f:F:gunP:L:hHiDlmo:p:r:O:st:vVG:y:", options, &opt_index)) != -1)
+    while ((opt = getopt_long(argc, argv, "acd:f:F:gunP:L:hHiDlmo:p:r:O:st:vVG:y:", options, &opt_index)) != -1)
 #else
-    while ((opt = getopt_long(argc, argv, "ad:f:F:gunP:L:hHiDlmo:p:r:O:st:vVy:", options, &opt_index)) != -1)
+    while ((opt = getopt_long(argc, argv, "acd:f:F:gunP:L:hHiDlmo:p:r:O:st:vVy:", options, &opt_index)) != -1)
 #endif
     {
         switch (opt) {
@@ -356,6 +357,9 @@
             }
             break;
 #endif
+        case 'c':
+            compiled = 1;
+            break;
         case 'f':
             if (!strcasecmp(optarg, "yang")) {
                 outformat_s = LYS_OUT_YANG;
@@ -603,6 +607,13 @@
         fprintf(stderr, "yanglint error: missing <file> to process\n");
         goto cleanup;
     }
+    if (compiled) {
+        if (!outformat_s) {
+            fprintf(stderr, "yanglint warning: --compiled option takes effect only in case of printing schemas.\n");
+        } else {
+            outformat_s++;
+        }
+    }
     if (outformat_s && outformat_s != LYS_OUT_TREE && (optind + 1) < argc) {
         /* we have multiple schemas to be printed as YIN or YANG */
         fprintf(stderr, "yanglint error: too many schemas to convert and store.\n");