yin printer FEATURE printer implemented
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bb51fb1..a1be678 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,6 +60,7 @@
 	src/printer.c
 	src/xpath.c
 	src/printer_yang.c
+	src/printer_yin.c
 	src/printer_xml.c
 	src/printer_tree.c
 	src/printer_info.c
diff --git a/src/libyang.h b/src/libyang.h
index c533492..33d6ab8 100644
--- a/src/libyang.h
+++ b/src/libyang.h
@@ -276,8 +276,6 @@
  *   Alternative XML-based format to YANG. The details can be found in
  *   [RFC 6020](http://tools.ietf.org/html/rfc6020#section-11).
  *
- *   \todo YIN output is not yet implemented
- *
  * - Tree
  *
  *   Simple tree structure of the module.
diff --git a/src/printer.c b/src/printer.c
index 0243a20..f18d692 100644
--- a/src/printer.c
+++ b/src/printer.c
@@ -142,8 +142,7 @@
 {
     switch (format) {
     case LYS_OUT_YIN:
-        LOGERR(LY_EINVAL, "YIN output format not supported yet.");
-        return EXIT_FAILURE;
+        return yin_print_model(out, module);
     case LYS_OUT_YANG:
         return yang_print_model(out, module);
     case LYS_OUT_TREE:
diff --git a/src/printer.h b/src/printer.h
index 8a66e05..aa3710b 100644
--- a/src/printer.h
+++ b/src/printer.h
@@ -57,6 +57,7 @@
 int ly_write(struct lyout *out, const char *buf, size_t count);
 
 int yang_print_model(struct lyout *out, const struct lys_module *module);
+int yin_print_model(struct lyout *out, const struct lys_module *module);
 int tree_print_model(struct lyout *out, const struct lys_module *module);
 int info_print_model(struct lyout *out, const struct lys_module *module, const char *target_node);
 
diff --git a/src/printer_yin.c b/src/printer_yin.c
new file mode 100644
index 0000000..3b97285
--- /dev/null
+++ b/src/printer_yin.c
@@ -0,0 +1,1375 @@
+/**
+ * @file printer_yin.c
+ * @author Michal Vasko <mvasko@cesnet.cz>
+ * @brief YIN printer for libyang data model structure
+ *
+ * Copyright (c) 2016 CESNET, z.s.p.o.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of the Company nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+#include "printer.h"
+#include "tree_schema.h"
+#include "xml_internal.h"
+
+#define INDENT ""
+#define LEVEL (level*2)
+
+static void yin_print_snode(struct lyout *out, int level, const struct lys_node *node, int mask);
+
+static void
+yin_print_open(struct lyout *out, const char *elem_name, const char *attr_name, const char *attr_value, int level,
+               int close)
+{
+    ly_print(out, "%*s<%s %s=\"%s\"%s>\n", LEVEL, INDENT, elem_name, attr_name, attr_value, (close ? "/" : ""));
+}
+
+static void
+yin_print_close(struct lyout *out, const char *elem_name, int level)
+{
+    ly_print(out, "%*s</%s>\n", LEVEL, INDENT, elem_name);
+}
+
+static void
+yin_print_unsigned(struct lyout *out, const char *elem_name, const char *attr_name, unsigned int attr_value, int level)
+{
+    ly_print(out, "%*s<%s %s=\"%u\"/>\n", LEVEL, INDENT, elem_name, attr_name, attr_value);
+}
+
+static void
+yin_print_text(struct lyout *out, int level, const char *elem_name, const char *text)
+{
+    ly_print(out, "%*s<%s>\n", LEVEL, INDENT, elem_name);
+
+    level++;
+    ly_print(out, "%*s<text>", LEVEL, INDENT);
+    lyxml_dump_text(out, text);
+    ly_print(out, "</text>\n");
+    level--;
+
+    ly_print(out, "%*s</%s>\n", LEVEL, INDENT, elem_name);
+}
+
+static void
+yin_print_restr_sub(struct lyout *out, const struct lys_restr *restr, int level)
+{
+    if (restr->dsc) {
+        yin_print_text(out, level, "description", restr->dsc);
+    }
+    if (restr->ref) {
+        yin_print_text(out, level, "reference", restr->ref);
+    }
+    if (restr->eapptag) {
+        yin_print_open(out, "error-app-tag", "value", restr->eapptag, level, 1);
+    }
+    if (restr->emsg) {
+        ly_print(out, "%*s<error-message>\n", LEVEL, INDENT);
+
+        level++;
+        ly_print(out, "%*s<value>", LEVEL, INDENT, restr->emsg);
+        lyxml_dump_text(out, restr->emsg);
+        ly_print(out, "</value>\n");
+        level--;
+
+        yin_print_close(out, "error-message", level);
+    }
+}
+
+static void
+yin_print_restr(struct lyout *out, const char *elem_name, const struct lys_restr *restr, int level)
+{
+    int close;
+
+    close = (restr->dsc || restr->ref || restr->eapptag || restr->emsg ? 0 : 1);
+
+    yin_print_open(out, elem_name, "value", restr->expr, level, close);
+    if (!close) {
+        yin_print_restr_sub(out, restr, level);
+
+        yin_print_close(out, elem_name, level);
+    }
+}
+
+static int
+yin_has_nacmext(const struct lys_node *node)
+{
+    if (node->nacm && (!node->parent || node->parent->nacm != node->nacm)) {
+        return 1;
+    }
+    return 0;
+}
+
+static void
+yin_print_nacmext(struct lyout *out, int level, const struct lys_node *node, const struct lys_module *module)
+{
+    int i, j;
+    const char *prefix = NULL;
+
+    if (node->nacm && (!node->parent || node->parent->nacm != node->nacm)) {
+        /* locate ietf-netconf-acm module in imports */
+        if (!strcmp(module->name, "ietf-netconf-acm")) {
+            prefix = module->prefix;
+        } else {
+            /* search in imports */
+            for (i = 0; i < module->imp_size; i++) {
+                if (!strcmp(module->imp[i].module->name, "ietf-netconf-acm")) {
+                    prefix = module->imp[i].prefix;
+                    break;
+                }
+            }
+            /* and in imports of includes */
+            if (!prefix) {
+                for (j = 0; j < module->inc_size; j++) {
+                    for (i = 0; i < module->inc[j].submodule->imp_size; i++) {
+                        if (!strcmp(module->inc[j].submodule->imp[i].module->name, "ietf-netconf-acm")) {
+                            prefix = module->inc[j].submodule->imp[i].prefix;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        if ((node->nacm & LYS_NACM_DENYW) && (!node->parent || !(node->parent->nacm & LYS_NACM_DENYW))) {
+            ly_print(out, "%*s<%s:default-deny-write/>\n", LEVEL, INDENT, prefix);
+        }
+        if ((node->nacm & LYS_NACM_DENYA) && (!node->parent || !(node->parent->nacm & LYS_NACM_DENYA))) {
+            ly_print(out, "%*s<%s:default-deny-all/>\n", LEVEL, INDENT, prefix);
+        }
+    }
+}
+
+static int
+yin_has_snode_common(const struct lys_node *node)
+{
+    if ((node->flags & LYS_STATUS_MASK) || node->dsc || node->ref) {
+        return 1;
+    }
+    return 0;
+}
+
+/*
+ * Covers:
+ * description, reference, status
+ */
+static void
+yin_print_snode_common(struct lyout *out, int level, const struct lys_node *node)
+{
+    if (node->flags & LYS_STATUS_CURR) {
+        yin_print_open(out, "status", "value", "current", level, 1);
+    } else if (node->flags & LYS_STATUS_DEPRC) {
+        yin_print_open(out, "status", "value", "deprecated", level, 1);
+    } else if (node->flags & LYS_STATUS_OBSLT) {
+        yin_print_open(out, "status", "value", "obsolete", level, 1);
+    }
+
+    if (node->dsc) {
+        yin_print_text(out, level, "description", node->dsc);
+    }
+    if (node->ref) {
+        yin_print_text(out, level, "reference", node->ref);
+    }
+}
+
+static int
+yin_has_snode_common2(const struct lys_node *node)
+{
+    if ((node->parent && (node->parent->flags & LYS_CONFIG_MASK) != (node->flags & LYS_CONFIG_MASK))
+            || (!node->parent && (node->flags & LYS_CONFIG_R)) || (node->flags & LYS_MAND_MASK)) {
+        return 1;
+    }
+    return yin_has_snode_common(node);
+}
+
+/*
+ * Covers:
+ * config, mandatory
+ * description, reference, status
+ */
+static void
+yin_print_snode_common2(struct lyout *out, int level, const struct lys_node *node)
+{
+    if (node->parent) {
+        if ((node->parent->flags & LYS_CONFIG_MASK) != (node->flags & LYS_CONFIG_MASK)) {
+            /* print config when it differs from the parent ... */
+            if (node->flags & LYS_CONFIG_W) {
+                yin_print_open(out, "config", "value", "true", level, 1);
+            } else if (node->flags & LYS_CONFIG_R) {
+                yin_print_open(out, "config", "value", "false", level, 1);
+            }
+        }
+    } else if (node->flags & LYS_CONFIG_R) {
+        /* ... or is a top-level state node */
+        yin_print_open(out, "config", "value", "false", level, 1);
+    }
+
+    if (node->flags & LYS_MAND_TRUE) {
+        yin_print_open(out, "mandatory", "value", "true", level, 1);
+    } else if (node->flags & LYS_MAND_FALSE) {
+        yin_print_open(out, "mandatory", "value", "false", level, 1);
+    }
+
+    yin_print_snode_common(out, level, node);
+}
+
+static void
+yin_print_iffeature(struct lyout *out, int level, const struct lys_module *module, const struct lys_feature *feat)
+{
+    const struct lys_module *mod;
+
+    ly_print(out, "%*s<if-feature name=\"", LEVEL, INDENT);
+    mod = (feat->module->type ? ((struct lys_submodule *)feat->module)->belongsto : feat->module);
+    if (module != mod) {
+        ly_print(out, "%s:", transform_module_name2import_prefix(module, mod->name));
+    }
+    ly_print(out, "%s\"/>\n", feat->name);
+}
+
+static void
+yin_print_feature(struct lyout *out, int level, const struct lys_feature *feat)
+{
+    int i, close;
+
+    close = (yin_has_snode_common((struct lys_node *)feat) || feat->features_size ? 0 : 1);
+
+    yin_print_open(out, "feature", "name", feat->name, level, close);
+
+    if (!close) {
+        level++;
+        yin_print_snode_common(out, level, (struct lys_node *)feat);
+        for (i = 0; i < feat->features_size; ++i) {
+            yin_print_iffeature(out, level, feat->module, feat->features[i]);
+        }
+        level--;
+
+        yin_print_close(out, "feature", level);
+    }
+}
+
+static void
+yin_print_when(struct lyout *out, int level, const struct lys_module *module, const struct lys_when *when)
+{
+    int close;
+    const char *str;
+
+    close = (when->dsc || when->ref ? 0 : 1);
+
+    str = transform_json2schema(module, when->cond);
+    if (!str) {
+        ly_print(out, "(!error!)");
+        return;
+    }
+
+    ly_print(out, "%*s<when condition=\"", LEVEL, INDENT);
+    lyxml_dump_text(out, str);
+    ly_print(out, "\"%s>\n", (close ? "/" : ""));
+
+    lydict_remove(module->ctx, str);
+
+    if (!close) {
+        level++;
+        if (when->dsc) {
+            yin_print_text(out, level, "description", when->dsc);
+        }
+        if (when->ref) {
+            yin_print_text(out, level, "reference", when->ref);
+        }
+        level--;
+
+        yin_print_close(out, "when", level);
+    }
+}
+
+static void
+yin_print_type(struct lyout *out, int level, const struct lys_module *module, const struct lys_type *type)
+{
+    int i, close;
+    const char *str;
+    struct lys_module *mod;
+
+    switch (type->base) {
+    case LY_TYPE_BINARY:
+        close = 1;
+        if (type->info.binary.length) {
+            close = 0;
+        }
+        break;
+    case LY_TYPE_DEC64:
+    case LY_TYPE_ENUM:
+    case LY_TYPE_IDENT:
+    case LY_TYPE_BITS:
+    case LY_TYPE_UNION:
+    case LY_TYPE_LEAFREF:
+        close = 0;
+        break;
+    case LY_TYPE_INST:
+        close = 1;
+        if (type->info.inst.req) {
+            close = 0;
+        }
+        break;
+    case LY_TYPE_INT8:
+    case LY_TYPE_INT16:
+    case LY_TYPE_INT32:
+    case LY_TYPE_INT64:
+    case LY_TYPE_UINT8:
+    case LY_TYPE_UINT16:
+    case LY_TYPE_UINT32:
+    case LY_TYPE_UINT64:
+        close = 1;
+        if (type->info.num.range) {
+            close = 0;
+        }
+        break;
+    case LY_TYPE_STRING:
+        close = 1;
+        if (type->info.str.length || type->info.str.pat_count) {
+            close = 0;
+        }
+        break;
+    default:
+        close = 1;
+        break;
+    }
+
+    if (type->module_name) {
+        ly_print(out, "%*s<type name=\"%s:%s\"%s>\n", LEVEL, INDENT,
+                 transform_module_name2import_prefix(module, type->module_name), type->der->name, (close ? "/" : ""));
+    } else {
+        yin_print_open(out, "type", "name", type->der->name, level, close);
+    }
+
+    if (!close) {
+        level++;
+        switch (type->base) {
+        case LY_TYPE_BINARY:
+            if (type->info.binary.length) {
+                yin_print_restr(out, "length", type->info.binary.length, level);
+            }
+            break;
+        case LY_TYPE_BITS:
+            for (i = 0; i < type->info.bits.count; ++i) {
+                yin_print_open(out, "bit", "name", type->info.bits.bit[i].name, level, 0);
+
+                level++;
+                yin_print_snode_common(out, level, (struct lys_node *)&type->info.bits.bit[i]);
+                yin_print_unsigned(out, "position", "value", type->info.bits.bit[i].pos, level);
+                level--;
+
+                yin_print_close(out, "bit", level);
+            }
+            break;
+        case LY_TYPE_DEC64:
+            yin_print_unsigned(out, "fraction-digits", "value", type->info.dec64.dig, level);
+            if (type->info.dec64.range) {
+                yin_print_restr(out, "range", type->info.dec64.range, level);
+            }
+            break;
+        case LY_TYPE_ENUM:
+            for (i = 0; i < type->info.enums.count; i++) {
+                yin_print_open(out, "enum", "name", type->info.enums.enm[i].name, level, 0);
+
+                level++;
+                yin_print_snode_common(out, level, (struct lys_node *)&type->info.enums.enm[i]);
+                ly_print(out, "%*s<value value=\"%d\"/>\n", LEVEL, INDENT, type->info.enums.enm[i].value);
+                level--;
+
+                yin_print_close(out, "enum", level);
+            }
+            break;
+        case LY_TYPE_IDENT:
+            mod = type->info.ident.ref->module->type ?
+                            ((struct lys_submodule *)type->info.ident.ref->module)->belongsto :
+                            type->info.ident.ref->module;
+            if (module == mod) {
+                ly_print(out, "%*s<base name=\"%s\"/>\n", LEVEL, INDENT, type->info.ident.ref->name);
+            } else {
+                ly_print(out, "%*s<base name=\"%s:%s\"/>\n", LEVEL, INDENT,
+                         transform_module_name2import_prefix(module, mod->name), type->info.ident.ref->name);
+            }
+            break;
+        case LY_TYPE_INST:
+            if (type->info.inst.req == 1) {
+                yin_print_open(out, "require-instance", "value", "true", level, 1);
+            } else if (type->info.inst.req == -1) {
+                yin_print_open(out, "require-instance", "value", "false", level, 1);
+            }
+            break;
+        case LY_TYPE_INT8:
+        case LY_TYPE_INT16:
+        case LY_TYPE_INT32:
+        case LY_TYPE_INT64:
+        case LY_TYPE_UINT8:
+        case LY_TYPE_UINT16:
+        case LY_TYPE_UINT32:
+        case LY_TYPE_UINT64:
+            if (type->info.num.range) {
+                yin_print_restr(out, "range", type->info.num.range, level);
+            }
+            break;
+        case LY_TYPE_LEAFREF:
+            str = transform_json2schema(module, type->info.lref.path);
+            yin_print_open(out, "path", "value", str, level, 1);
+            lydict_remove(module->ctx, str);
+            break;
+        case LY_TYPE_STRING:
+            if (type->info.str.length) {
+                yin_print_restr(out, "length", type->info.str.length, level);
+            }
+            for (i = 0; i < type->info.str.pat_count; i++) {
+                yin_print_restr(out, "pattern", &type->info.str.patterns[i], level);
+            }
+            break;
+        case LY_TYPE_UNION:
+            for (i = 0; i < type->info.uni.count; ++i) {
+                yin_print_type(out, level, module, &type->info.uni.types[i]);
+            }
+            break;
+        default:
+            /* other types do not have substatements */
+            break;
+        }
+        level--;
+
+        yin_print_close(out, "type", level);
+    }
+}
+
+static void
+yin_print_must(struct lyout *out, int level, const struct lys_module *module, const struct lys_restr *must)
+{
+    const char *str;
+    int close;
+
+    close = (must->dsc || must->ref || must->eapptag || must->emsg ? 0 : 1);
+
+    str = transform_json2schema(module, must->expr);
+    if (!str) {
+        ly_print(out, "(!error!)");
+        return;
+    }
+
+    ly_print(out, "%*s<must condition=\"", LEVEL, INDENT);
+    lyxml_dump_text(out, str);
+    ly_print(out, "\"%s>\n", (close ? "/" : ""));
+
+    lydict_remove(module->ctx, str);
+
+    if (!close) {
+        yin_print_restr_sub(out, must, level + 1);
+        yin_print_close(out, "must", level);
+    }
+}
+
+static void
+yin_print_unique(struct lyout *out, int level, const struct lys_unique *uniq)
+{
+    int i;
+
+    ly_print(out, "%*s<unique tag=\"", LEVEL, INDENT);
+    for (i = 0; i < uniq->expr_size; i++) {
+        ly_print(out, "%s%s", uniq->expr[i], i + 1 < uniq->expr_size ? " " : "");
+    }
+    ly_print(out, "\"/>\n");
+}
+
+static void
+yin_print_refine(struct lyout *out, int level, const struct lys_module *module, const struct lys_refine *refine)
+{
+    int i;
+    const char *str;
+
+    str = transform_json2xml(module, refine->target_name, NULL, NULL, NULL);
+    ly_print(out, "refine", "target-node", str, level, 0);
+    lydict_remove(module->ctx, str);
+
+    level++;
+    if (refine->flags & LYS_CONFIG_W) {
+        yin_print_open(out, "config", "value", "true", level, 1);
+    } else if (refine->flags & LYS_CONFIG_R) {
+        yin_print_open(out, "config", "value", "false", level, 1);
+    }
+
+    if (refine->flags & LYS_MAND_TRUE) {
+        yin_print_open(out, "mandatory", "value", "true", level, 1);
+    } else if (refine->flags & LYS_MAND_FALSE) {
+        yin_print_open(out, "mandatory", "value", "false", level, 1);
+    }
+
+    yin_print_snode_common(out, level, (struct lys_node *)refine);
+
+    for (i = 0; i < refine->must_size; ++i) {
+        yin_print_must(out, level, module, &refine->must[i]);
+    }
+
+    if (refine->target_type & (LYS_LEAF | LYS_CHOICE)) {
+        if (refine->mod.dflt) {
+            yin_print_open(out, "default", "value", refine->mod.dflt, level, 1);
+        }
+    } else if (refine->target_type == LYS_CONTAINER) {
+        if (refine->mod.presence) {
+            yin_print_open(out, "presence", "value", refine->mod.presence, level, 1);
+        }
+    } else if (refine->target_type & (LYS_LIST | LYS_LEAFLIST)) {
+        if (refine->mod.list.min > 0) {
+            yin_print_unsigned(out, "min-elements", "value", refine->mod.list.min, level);
+        }
+        if (refine->mod.list.max > 0) {
+            yin_print_unsigned(out, "max-elements", "value", refine->mod.list.max, level);
+        }
+    }
+    level--;
+
+    yin_print_close(out, "refine", level);
+}
+
+static void
+yin_print_deviation(struct lyout *out, int level, const struct lys_module *module,
+                    const struct lys_deviation *deviation)
+{
+    int i, j;
+    const char *str;
+
+    str = transform_json2xml(module, deviation->target_name, NULL, NULL, NULL);
+    yin_print_open(out, "deviation", "target-node", str, level, 0);
+    lydict_remove(module->ctx, str);
+
+    level++;
+    if (deviation->dsc) {
+        yin_print_text(out, level, "description", deviation->dsc);
+    }
+    if (deviation->ref) {
+        yin_print_text(out, level, "reference", deviation->ref);
+    }
+
+    for (i = 0; i < deviation->deviate_size; ++i) {
+        ly_print(out, "%*s<deviate value=", LEVEL, INDENT);
+        if (deviation->deviate[i].mod == LY_DEVIATE_NO) {
+            ly_print(out, "\"not-supported\">\n");
+        } else if (deviation->deviate[i].mod == LY_DEVIATE_ADD) {
+            ly_print(out, "\"add\">\n");
+        } else if (deviation->deviate[i].mod == LY_DEVIATE_RPL) {
+            ly_print(out, "\"replace\">\n");
+        } else if (deviation->deviate[i].mod == LY_DEVIATE_DEL) {
+            ly_print(out, "\"delete\">\n");
+        }
+
+        level++;
+        if (deviation->deviate[i].flags & LYS_CONFIG_W) {
+            yin_print_open(out, "config", "value", "true", level, 1);
+        } else if (deviation->deviate[i].flags & LYS_CONFIG_R) {
+            yin_print_open(out, "config", "value", "false", level, 1);
+        }
+
+        if (deviation->deviate[i].flags & LYS_MAND_TRUE) {
+            yin_print_open(out, "mandatory", "value", "true", level, 1);
+        } else if (deviation->deviate[i].flags & LYS_MAND_FALSE) {
+            yin_print_open(out, "mandatory", "value", "false", level, 1);
+        }
+
+        if (deviation->deviate[i].dflt) {
+            yin_print_open(out, "default", "value", deviation->deviate[i].dflt, level, 1);
+        }
+
+        if (deviation->deviate[i].min) {
+            yin_print_unsigned(out, "min-elements", "value", deviation->deviate[i].min, level);
+        }
+        if (deviation->deviate[i].max) {
+            yin_print_unsigned(out, "max-elements", "value", deviation->deviate[i].max, level);
+        }
+
+        for (j = 0; j < deviation->deviate[i].must_size; ++j) {
+            yin_print_must(out, level, module, &deviation->deviate[i].must[j]);
+        }
+
+        for (j = 0; j < deviation->deviate[i].unique_size; ++j) {
+            yin_print_unique(out, level, &deviation->deviate[i].unique[j]);
+        }
+
+        if (deviation->deviate[i].type) {
+            yin_print_type(out, level, module, deviation->deviate[i].type);
+        }
+
+        if (deviation->deviate[i].units) {
+            yin_print_open(out, "units", "name", deviation->deviate[i].units, level, 1);
+        }
+        level--;
+
+        yin_print_close(out, "deviate", level);
+    }
+    level--;
+
+    yin_print_close(out, "deviation", level);
+}
+
+static void
+yin_print_augment(struct lyout *out, int level, const struct lys_module *module,
+                  const struct lys_node_augment *augment)
+{
+    int i;
+    struct lys_node *sub;
+    const char *str;
+
+    str = transform_json2xml(module, augment->target_name, NULL, NULL, NULL);
+    yin_print_open(out, "augment", "target-node", str, level, 0);
+    lydict_remove(module->ctx, str);
+
+    level++;
+    yin_print_nacmext(out, level, (struct lys_node *)augment, module);
+    yin_print_snode_common(out, level, (struct lys_node *)augment);
+
+    for (i = 0; i < augment->features_size; i++) {
+        yin_print_iffeature(out, level, module, augment->features[i]);
+    }
+
+    if (augment->when) {
+        yin_print_when(out, level, module, augment->when);
+    }
+
+    LY_TREE_FOR(augment->child, sub) {
+        yin_print_snode(out, level, sub,
+                        LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
+                        LYS_USES | LYS_ANYXML | LYS_CASE);
+    }
+    level--;
+
+    yin_print_close(out, "augment", level);
+}
+
+static void
+yin_print_typedef(struct lyout *out, int level, const struct lys_module *module, const struct lys_tpdf *tpdf)
+{
+    yin_print_open(out, "typedef", "name", tpdf->name, level, 0);
+
+    level++;
+    yin_print_snode_common(out, level, (struct lys_node *)tpdf);
+    yin_print_type(out, level, module, &tpdf->type);
+    if (tpdf->units) {
+        yin_print_open(out, "units", "name", tpdf->units, level, 1);
+    }
+    if (tpdf->dflt) {
+        yin_print_open(out, "default", "value", tpdf->dflt, level, 1);
+    }
+    level--;
+
+    yin_print_close(out, "typedef", level);
+}
+
+static void
+yin_print_identity(struct lyout *out, int level, const struct lys_ident *ident)
+{
+    int close;
+    const struct lys_module *mod;
+
+    close = (yin_has_snode_common((struct lys_node *)ident) || ident->base ? 0 : 1);
+
+    yin_print_open(out, "identity", "name", ident->name, level, close);
+
+    if (!close) {
+        level++;
+        yin_print_snode_common(out, level, (struct lys_node *)ident);
+        if (ident->base) {
+            ly_print(out, "%*s<base name=\"", LEVEL, INDENT);
+            mod = (ident->base->module->type ? ((struct lys_submodule *)ident->base->module)->belongsto : ident->base->module);
+            if (ident->module != mod) {
+                ly_print(out, "%s:", transform_module_name2import_prefix(ident->module, mod->name));
+            }
+            ly_print(out, "%s\"/>\n", ident->base->name);
+        }
+        level--;
+
+        yin_print_close(out, "identity", level);
+    }
+}
+
+static void
+yin_print_container(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i;
+    struct lys_node *sub;
+    struct lys_node_container *cont = (struct lys_node_container *)node;
+
+    yin_print_open(out, "container", "name", node->name, level, 0);
+
+    level++;
+    yin_print_nacmext(out, level, node, node->module);
+
+    if (cont->when) {
+        yin_print_when(out, level, node->module, cont->when);
+    }
+
+    for (i = 0; i < cont->features_size; i++) {
+        yin_print_iffeature(out, level, node->module, cont->features[i]);
+    }
+
+    for (i = 0; i < cont->must_size; i++) {
+        yin_print_must(out, level, node->module, &cont->must[i]);
+    }
+
+    if (cont->presence) {
+        yin_print_open(out, "presence", "value", cont->presence, level, 1);
+    }
+
+    yin_print_snode_common2(out, level, node);
+
+    for (i = 0; i < cont->tpdf_size; i++) {
+        yin_print_typedef(out, level, node->module, &cont->tpdf[i]);
+    }
+
+    LY_TREE_FOR(node->child, sub) {
+        /* augment and data from submodules */
+        if (sub->module != node->module) {
+            continue;
+        }
+        yin_print_snode(out, level, sub,
+                        LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
+                        LYS_USES | LYS_GROUPING | LYS_ANYXML);
+    }
+    level--;
+
+    yin_print_close(out, "container", level);
+}
+
+static void
+yin_print_case(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i;
+    struct lys_node *sub;
+    struct lys_node_case *cas = (struct lys_node_case *)node;
+
+    yin_print_open(out, "case", "name", cas->name, level, 0);
+
+    level++;
+    yin_print_nacmext(out, level, node, node->module);
+    yin_print_snode_common2(out, level, node);
+
+    for (i = 0; i < cas->features_size; i++) {
+        yin_print_iffeature(out, level, node->module, cas->features[i]);
+    }
+
+    if (cas->when) {
+        yin_print_when(out, level, node->module, cas->when);
+    }
+
+    LY_TREE_FOR(node->child, sub) {
+        /* augment and data from submodules */
+        if (sub->module != node->module) {
+            continue;
+        }
+        yin_print_snode(out, level, sub,
+                        LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
+                        LYS_USES | LYS_ANYXML);
+    }
+    level--;
+
+    yin_print_close(out, "case", level);
+}
+
+static void
+yin_print_choice(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i;
+    struct lys_node *sub;
+    struct lys_node_choice *choice = (struct lys_node_choice *)node;
+
+    yin_print_open(out, "choice", "name", node->name, level, 0);
+
+    level++;
+    yin_print_nacmext(out, level, node, node->module);
+    if (choice->dflt) {
+        yin_print_open(out, "default", "value", choice->dflt->name, level, 1);
+    }
+
+    yin_print_snode_common2(out, level, node);
+
+    for (i = 0; i < choice->features_size; i++) {
+        yin_print_iffeature(out, level, node->module, choice->features[i]);
+    }
+
+    if (choice->when) {
+        yin_print_when(out, level, node->module, choice->when);
+    }
+
+    LY_TREE_FOR(node->child, sub) {
+        /* augment and data from submodules */
+        if (sub->module != node->module) {
+                continue;
+        }
+        yin_print_snode(out, level, sub,
+                        LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_CASE);
+    }
+    level--;
+
+    yin_print_close(out, "choice", level);
+}
+
+static void
+yin_print_leaf(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i;
+    struct lys_node_leaf *leaf = (struct lys_node_leaf *)node;
+
+    yin_print_open(out, "leaf", "name", node->name, level, 0);
+
+    level++;
+    yin_print_nacmext(out, level, node, node->module);
+    if (leaf->when) {
+        yin_print_when(out, level, node->module, leaf->when);
+    }
+    for (i = 0; i < leaf->features_size; i++) {
+        yin_print_iffeature(out, level, node->module, leaf->features[i]);
+    }
+    for (i = 0; i < leaf->must_size; i++) {
+        yin_print_must(out, level, node->module, &leaf->must[i]);
+    }
+    yin_print_snode_common2(out, level, node);
+    yin_print_type(out, level, node->module, &leaf->type);
+    if (leaf->units) {
+        yin_print_open(out, "units", "name", leaf->units, level, 1);
+    }
+    if (leaf->dflt) {
+        yin_print_open(out, "default", "value", leaf->dflt, level, 1);
+    }
+    level--;
+
+    yin_print_close(out, "leaf", level);
+}
+
+static void
+yin_print_anyxml(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i, close;
+    struct lys_node_anyxml *anyxml = (struct lys_node_anyxml *)node;
+
+    close = (yin_has_nacmext(node) || yin_has_snode_common2(node) || anyxml->features_size || anyxml->must_size
+            || anyxml->when ? 0 : 1);
+
+    yin_print_open(out, "anyxml", "name", anyxml->name, level, close);
+
+    if (!close) {
+        level++;
+        yin_print_nacmext(out, level, node, node->module);
+        yin_print_snode_common2(out, level, node);
+        for (i = 0; i < anyxml->features_size; i++) {
+            yin_print_iffeature(out, level, node->module, anyxml->features[i]);
+        }
+        for (i = 0; i < anyxml->must_size; i++) {
+            yin_print_must(out, level, node->module, &anyxml->must[i]);
+        }
+        if (anyxml->when) {
+            yin_print_when(out, level, node->module, anyxml->when);
+        }
+        level--;
+
+        yin_print_close(out, "anyxml", level);
+    }
+}
+
+static void
+yin_print_leaflist(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i;
+    struct lys_node_leaflist *llist = (struct lys_node_leaflist *)node;
+
+    yin_print_open(out, "leaf-list", "name", node->name, level, 0);
+
+    level++;
+    yin_print_nacmext(out, level, node, node->module);
+    if (llist->when) {
+        yin_print_when(out, level, llist->module, llist->when);
+    }
+    for (i = 0; i < llist->features_size; i++) {
+        yin_print_iffeature(out, level, node->module, llist->features[i]);
+    }
+    for (i = 0; i < llist->must_size; i++) {
+        yin_print_must(out, level, node->module, &llist->must[i]);
+    }
+    yin_print_snode_common2(out, level, node);
+    yin_print_type(out, level, node->module, &llist->type);
+    if (llist->units) {
+        yin_print_open(out, "units", "name", llist->units, level, 1);
+    }
+    if (llist->min > 0) {
+        yin_print_unsigned(out, "min-elements", "value", llist->min, level);
+    }
+    if (llist->max > 0) {
+        yin_print_unsigned(out, "max-elements", "value", llist->max, level);
+    }
+    if (llist->flags & LYS_USERORDERED) {
+        yin_print_open(out, "ordered-by", "value", "user", level, 1);
+    }
+    level--;
+
+    yin_print_close(out, "leaf-list", level);
+}
+
+static void
+yin_print_list(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i;
+    struct lys_node *sub;
+    struct lys_node_list *list = (struct lys_node_list *)node;
+
+    yin_print_open(out, "list", "name", node->name, level, 0);
+
+    level++;
+    yin_print_nacmext(out, level, node, node->module);
+    if (list->when) {
+        yin_print_when(out, level, list->module, list->when);
+    }
+    for (i = 0; i < list->features_size; i++) {
+        yin_print_iffeature(out, level, node->module, list->features[i]);
+    }
+    for (i = 0; i < list->must_size; i++) {
+        yin_print_must(out, level, list->module, &list->must[i]);
+    }
+    if (list->keys_size) {
+        ly_print(out, "%*s<key value=\"", LEVEL, INDENT);
+        for (i = 0; i < list->keys_size; i++) {
+            ly_print(out, "%s%s", list->keys[i]->name, i + 1 < list->keys_size ? " " : "");
+        }
+        ly_print(out, "\"/>\n");
+    }
+    for (i = 0; i < list->unique_size; i++) {
+        yin_print_unique(out, level, &list->unique[i]);
+    }
+    yin_print_snode_common2(out, level, node);
+    if (list->min > 0) {
+        yin_print_unsigned(out, "min-elements", "value", list->min, level);
+    }
+    if (list->max > 0) {
+        yin_print_unsigned(out, "max-elements", "value", list->max, level);
+    }
+    if (list->flags & LYS_USERORDERED) {
+        yin_print_open(out, "ordered-by", "value", "user", level, 1);
+    }
+
+    for (i = 0; i < list->tpdf_size; i++) {
+        yin_print_typedef(out, level, list->module, &list->tpdf[i]);
+    }
+    LY_TREE_FOR(node->child, sub) {
+        /* augment and data from submodules */
+        if (sub->module != node->module) {
+            continue;
+        }
+        yin_print_snode(out, level, sub,
+                        LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
+                        LYS_USES | LYS_GROUPING | LYS_ANYXML);
+    }
+    level--;
+
+    yin_print_close(out, "list", level);
+}
+
+static void
+yin_print_grouping(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i;
+    struct lys_node *child;
+    struct lys_node_grp *grp = (struct lys_node_grp *)node;
+
+    yin_print_open(out, "grouping", "name", node->name, level, 0);
+
+    level++;
+    yin_print_snode_common(out, level, node);
+
+    for (i = 0; i < grp->tpdf_size; i++) {
+        yin_print_typedef(out, level, node->module, &grp->tpdf[i]);
+    }
+
+    LY_TREE_FOR(node->child, child) {
+        yin_print_snode(out, level, child,
+                        LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
+                        LYS_USES | LYS_GROUPING | LYS_ANYXML);
+    }
+    level--;
+
+    yin_print_close(out, "grouping", level);
+}
+
+static void
+yin_print_uses(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i, close;
+    struct lys_node_uses *uses = (struct lys_node_uses *)node;
+    const struct lys_module *mod;
+
+    close = (yin_has_nacmext(node) || yin_has_snode_common(node) || uses->features_size || uses->when
+            || uses->refine_size || uses->augment_size ? 0 : 1);
+
+    ly_print(out, "%*s<uses name=\"", LEVEL, INDENT);
+    if (node->child) {
+        mod = (node->child->module->type ? ((struct lys_submodule *)node->child->module)->belongsto : node->child->module);
+        if (node->module != mod) {
+            ly_print(out, "%s:", transform_module_name2import_prefix(node->module, mod->name));
+        }
+    }
+    ly_print(out, "%s\"%s>\n", uses->name, (close ? "/" : ""));
+
+    if (!close) {
+        level++;
+        yin_print_nacmext(out, level, node, node->module);
+        yin_print_snode_common(out, level, node);
+        for (i = 0; i < uses->features_size; i++) {
+            yin_print_iffeature(out, level, node->module, uses->features[i]);
+        }
+        if (uses->when) {
+            yin_print_when(out, level, node->module, uses->when);
+        }
+
+        for (i = 0; i < uses->refine_size; i++) {
+            yin_print_refine(out, level, node->module, &uses->refine[i]);
+        }
+
+        for (i = 0; i < uses->augment_size; i++) {
+            yin_print_augment(out, level, node->module, &uses->augment[i]);
+        }
+        level--;
+
+        yin_print_close(out, "uses", level);
+    }
+}
+
+static void
+yin_print_input_output(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i;
+    struct lys_node *sub;
+    struct lys_node_rpc_inout *inout = (struct lys_node_rpc_inout *)node;
+
+    ly_print(out, "%*s<%s>\n", LEVEL, INDENT, (inout->nodetype == LYS_INPUT ? "input" : "output"));
+
+    level++;
+    for (i = 0; i < inout->tpdf_size; i++) {
+        yin_print_typedef(out, level, node->module, &inout->tpdf[i]);
+    }
+
+    LY_TREE_FOR(node->child, sub) {
+        /* augment and data from submodules */
+        if (sub->module != node->module) {
+            continue;
+        }
+        yin_print_snode(out, level, sub,
+                        LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
+                        LYS_USES | LYS_GROUPING | LYS_ANYXML);
+    }
+    level--;
+
+    yin_print_close(out, (inout->nodetype == LYS_INPUT ? "input" : "output"), level);
+}
+
+static void
+yin_print_rpc(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i, close;
+    struct lys_node *sub;
+    struct lys_node_rpc *rpc = (struct lys_node_rpc *)node;
+
+    close = (yin_has_snode_common(node) || rpc->features_size || rpc->tpdf_size || node->child ? 0 : 1);
+
+    yin_print_open(out, "rpc", "name", node->name, level, close);
+
+    if (!close) {
+        level++;
+        yin_print_snode_common(out, level, node);
+
+        for (i = 0; i < rpc->features_size; i++) {
+            yin_print_iffeature(out, level, node->module, rpc->features[i]);
+        }
+
+        for (i = 0; i < rpc->tpdf_size; i++) {
+            yin_print_typedef(out, level, node->module, &rpc->tpdf[i]);
+        }
+
+        LY_TREE_FOR(node->child, sub) {
+            /* augment and data from submodules */
+            if (sub->module != node->module) {
+                continue;
+            }
+            yin_print_snode(out, level, sub, LYS_GROUPING | LYS_INPUT | LYS_OUTPUT);
+        }
+        level--;
+
+        yin_print_close(out, "rcp", level);
+    }
+}
+
+static void
+yin_print_notif(struct lyout *out, int level, const struct lys_node *node)
+{
+    int i, close;
+    struct lys_node *sub;
+    struct lys_node_notif *notif = (struct lys_node_notif *)node;
+
+    close = (yin_has_snode_common(node) || notif->features_size || notif->tpdf_size || node->child ? 0 : 1);
+
+    yin_print_open(out, "notification", "name", node->name, level, close);
+
+    if (!close) {
+        level++;
+        yin_print_snode_common(out, level, node);
+
+        for (i = 0; i < notif->features_size; i++) {
+            yin_print_iffeature(out, level, node->module, notif->features[i]);
+        }
+
+        for (i = 0; i < notif->tpdf_size; i++) {
+            yin_print_typedef(out, level, node->module, &notif->tpdf[i]);
+        }
+
+        LY_TREE_FOR(node->child, sub) {
+            /* augment and data from submodules */
+            if (sub->module != node->module) {
+                continue;
+            }
+            yin_print_snode(out, level, sub,
+                            LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
+                            LYS_USES | LYS_GROUPING | LYS_ANYXML);
+        }
+        level--;
+
+        yin_print_close(out, "notification", level);
+    }
+}
+
+static void
+yin_print_snode(struct lyout *out, int level, const struct lys_node *node, int mask)
+{
+    switch (node->nodetype & mask) {
+    case LYS_CONTAINER:
+        yin_print_container(out, level, node);
+        break;
+    case LYS_CHOICE:
+        yin_print_choice(out, level, node);
+        break;
+    case LYS_LEAF:
+        yin_print_leaf(out, level, node);
+        break;
+    case LYS_LEAFLIST:
+        yin_print_leaflist(out, level, node);
+        break;
+    case LYS_LIST:
+        yin_print_list(out, level, node);
+        break;
+    case LYS_USES:
+        yin_print_uses(out, level, node);
+        break;
+    case LYS_GROUPING:
+        yin_print_grouping(out, level, node);
+        break;
+    case LYS_ANYXML:
+        yin_print_anyxml(out, level, node);
+        break;
+    case LYS_CASE:
+        yin_print_case(out, level, node);
+        break;
+    case LYS_INPUT:
+    case LYS_OUTPUT:
+        yin_print_input_output(out, level, node);
+        break;
+    default:
+        break;
+    }
+}
+
+static void
+yin_print_namespaces(struct lyout *out, const struct lys_module *module)
+{
+    unsigned int i, lvl;
+
+    if (module->type) {
+        lvl = 11;
+    } else {
+        lvl = 8;
+    }
+
+    ly_print(out, "%*sxmlns=\"%s\"", lvl, INDENT, LY_NSYIN);
+    if (!module->type) {
+        ly_print(out, "\n%*sxmlns:%s=\"%s\"", lvl, INDENT, module->prefix, module->ns);
+    }
+    for (i = 0; i < module->imp_size; ++i) {
+        if (module->imp[i].external) {
+            continue;
+        }
+        ly_print(out, "\n%*sxmlns:%s=\"%s\"", lvl, INDENT, module->imp[i].prefix, module->imp[i].module->ns);
+    }
+}
+
+int
+yin_print_model(struct lyout *out, const struct lys_module *module)
+{
+    unsigned int i;
+    int level = 0, close;
+#define LEVEL (level*2)
+
+    struct lys_node *node;
+
+    ly_print(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+
+    if (module->deviated) {
+        ly_print(out, "<!-- DEVIATED -->\n");
+    }
+
+    /* (sub)module-header-stmts */
+    if (module->type) {
+        ly_print(out, "<submodule name=\"%s\"\n", module->name);
+        yin_print_namespaces(out, module);
+        ly_print(out, ">\n");
+
+        level++;
+        if (module->version) {
+            yin_print_open(out, "yang-version", "value",
+                           ((struct lys_submodule *)module)->belongsto->version == 2 ? "1.1" : "1", level, 1);
+        }
+        yin_print_open(out, "belongs-to", "module", ((struct lys_submodule *)module)->belongsto->name, level, 0);
+
+        level++;
+        yin_print_open(out, "prefix", "value", module->prefix, level, 1);
+        level--;
+
+        yin_print_close(out, "belongs-to", level);
+    } else {
+        ly_print(out, "<module name=\"%s\"\n", module->name);
+        yin_print_namespaces(out, module);
+        ly_print(out, ">\n");
+
+        level++;
+        if (module->version) {
+            yin_print_open(out, "yang-version", "value", module->version == 2 ? "1.1" : "1", level, 1);
+        }
+        yin_print_open(out, "namespace", "uri", module->ns, level, 1);
+        yin_print_open(out, "prefix", "value", module->prefix, level, 1);
+    }
+
+    /* linkage-stmts */
+    for (i = 0; i < module->imp_size; i++) {
+        if (module->imp[i].external) {
+            continue;
+        }
+        yin_print_open(out, "import", "module", module->imp[i].module->name, level, 0);
+
+        level++;
+        yin_print_open(out, "prefix", "value", module->imp[i].prefix, level, 1);
+        if (module->imp[i].rev[0]) {
+            yin_print_open(out, "revision-date", "date", module->imp[i].rev, level, 1);
+        }
+        level--;
+
+        yin_print_close(out, "import", level);
+    }
+    for (i = 0; i < module->inc_size; i++) {
+        if (module->inc[i].external) {
+            continue;
+        }
+
+        close = (module->inc[i].rev[0] ? 0 : 1);
+        yin_print_open(out, "include", "value", module->inc[i].submodule->name, level, close);
+
+        if (!close) {
+            level++;
+            yin_print_open(out, "revision-date", "date", module->inc[i].rev, level, 1);
+            level--;
+
+            yin_print_close(out, "include", level);
+        }
+    }
+
+    /* meta-stmts */
+    if (module->org) {
+        yin_print_text(out, level, "organization", module->org);
+    }
+    if (module->contact) {
+        yin_print_text(out, level, "contact", module->contact);
+    }
+    if (module->dsc) {
+        yin_print_text(out, level, "description", module->dsc);
+    }
+    if (module->ref) {
+        yin_print_text(out, level, "reference", module->ref);
+    }
+
+    /* revision-stmts */
+    for (i = 0; i < module->rev_size; i++) {
+        close = (module->rev[i].dsc || module->rev[i].ref ? 0 : 1);
+        yin_print_open(out, "revision", "date", module->rev[i].date, level, close);
+
+        if (!close) {
+            level++;
+            if (module->rev[i].dsc) {
+                yin_print_text(out, level, "description", module->rev[i].dsc);
+            }
+            if (module->rev[i].ref) {
+                yin_print_text(out, level, "reference", module->rev[i].ref);
+            }
+            level--;
+
+            yin_print_close(out, "revision", level);
+        }
+    }
+
+    /* body-stmts */
+    for (i = 0; i < module->features_size; i++) {
+        yin_print_feature(out, level, &module->features[i]);
+    }
+
+    for (i = 0; i < module->ident_size; i++) {
+        yin_print_identity(out, level, &module->ident[i]);
+    }
+
+    for (i = 0; i < module->tpdf_size; i++) {
+        yin_print_typedef(out, level, module, &module->tpdf[i]);
+    }
+
+    for (i = 0; i < module->deviation_size; ++i) {
+        yin_print_deviation(out, level, module, &module->deviation[i]);
+    }
+
+    LY_TREE_FOR(module->data, node) {
+        if (node->module != module) {
+            continue;
+        }
+
+        switch (node->nodetype) {
+        case LYS_RPC:
+            yin_print_rpc(out, level, node);
+            break;
+        case LYS_NOTIF:
+            yin_print_notif(out, level, node);
+            break;
+        default:
+            yin_print_snode(out, level, node,
+                             LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
+                             LYS_USES | LYS_GROUPING | LYS_ANYXML);
+            break;
+        }
+    }
+
+    for (i = 0; i < module->augment_size; i++) {
+        yin_print_augment(out, level, module, &module->augment[i]);
+    }
+
+    if (module->type) {
+        ly_print(out, "</submodule>\n");
+    } else {
+        ly_print(out, "</module>\n");
+    }
+
+    return EXIT_SUCCESS;
+#undef LEVEL
+}
+
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 93ec090..fa21473 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -191,7 +191,7 @@
 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, \todo not yet supported */
+    LYS_OUT_YIN = 2,     /**< YIN schema output format */
     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 */
 } LYS_OUTFORMAT;