parser BUGFIX support input/output deviations

Fixes #554
diff --git a/src/parser_yang.c b/src/parser_yang.c
index a331ac8..c1d98e5 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -4485,6 +4485,7 @@
     const char *value, *target_name;
     struct lys_node_leaflist *llist;
     struct lys_node_leaf *leaf;
+    struct lys_node_inout *inout;
     struct unres_schema tmp_unres;
     struct lys_module *mod;
 
@@ -4527,12 +4528,31 @@
         /* unlink and store the original node */
         parent = dev_target->parent;
         lys_node_unlink(dev_target);
-        if (parent && (parent->nodetype & (LYS_AUGMENT | LYS_USES))) {
-            /* hack for augment, because when the original will be sometime reconnected back, we actually need
-             * to reconnect it to both - the augment and its target (which is deduced from the deviations target
-             * path), so we need to remember the augment as an addition */
-            /* remember uses parent so we can reconnect to it */
-            dev_target->parent = parent;
+        if (parent) {
+            if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
+                /* hack for augment, because when the original will be sometime reconnected back, we actually need
+                 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
+                 * path), so we need to remember the augment as an addition */
+                /* remember uses parent so we can reconnect to it */
+                dev_target->parent = parent;
+            } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
+                /* re-create implicit node */
+                inout = calloc(1, sizeof *inout);
+                LY_CHECK_ERR_GOTO(!inout, LOGMEM(module->ctx), error);
+
+                inout->nodetype = dev_target->nodetype;
+                inout->name = lydict_insert(module->ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
+                inout->module = dev_target->module;
+                inout->flags = LYS_IMPLICIT;
+
+                /* insert it manually */
+                assert(parent->child && !parent->child->next
+                    && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
+                parent->child->next = (struct lys_node *)inout;
+                inout->prev = parent->child;
+                parent->child->prev = (struct lys_node *)inout;
+                inout->parent = parent;
+            }
         }
         dev->orig_node = dev_target;
     } else {
diff --git a/src/parser_yin.c b/src/parser_yin.c
index c980dab..2f15eae 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -2172,12 +2172,13 @@
     unsigned int u;
     struct ly_ctx *ctx = module->ctx;
     struct lys_deviate *d = NULL;
-    struct lys_node *node = NULL, *parent, *dev_target = NULL;
+    struct lys_node *node, *parent, *dev_target = NULL;
     struct lys_node_choice *choice = NULL;
     struct lys_node_leaf *leaf = NULL;
     struct ly_set *dflt_check = ly_set_new(), *set;
     struct lys_node_list *list = NULL;
     struct lys_node_leaflist *llist = NULL;
+    struct lys_node_inout *inout;
     struct lys_type *t = NULL;
     uint8_t *trg_must_size = NULL;
     struct lys_restr **trg_must = NULL;
@@ -2322,12 +2323,31 @@
             /* unlink and store the original node */
             parent = dev_target->parent;
             lys_node_unlink(dev_target);
-            if (parent && (parent->nodetype & (LYS_AUGMENT | LYS_USES))) {
-                /* hack for augment, because when the original will be sometime reconnected back, we actually need
-                 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
-                 * path), so we need to remember the augment as an addition */
-                /* remember uses parent so we can reconnect to it */
-                dev_target->parent = parent;
+            if (parent) {
+                if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
+                    /* hack for augment, because when the original will be sometime reconnected back, we actually need
+                     * to reconnect it to both - the augment and its target (which is deduced from the deviations target
+                     * path), so we need to remember the augment as an addition */
+                    /* remember uses parent so we can reconnect to it */
+                    dev_target->parent = parent;
+                } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
+                    /* re-create implicit node */
+                    inout = calloc(1, sizeof *inout);
+                    LY_CHECK_ERR_GOTO(!inout, LOGMEM(ctx), error);
+
+                    inout->nodetype = dev_target->nodetype;
+                    inout->name = lydict_insert(ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
+                    inout->module = dev_target->module;
+                    inout->flags = LYS_IMPLICIT;
+
+                    /* insert it manually */
+                    assert(parent->child && !parent->child->next
+                           && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
+                    parent->child->next = (struct lys_node *)inout;
+                    inout->prev = parent->child;
+                    parent->child->prev = (struct lys_node *)inout;
+                    inout->parent = parent;
+                }
             }
             dev->orig_node = dev_target;
 
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 0535c26..54297da 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -4110,6 +4110,7 @@
     int ret, reapply = 0;
     char *parent_path;
     struct lys_node *target = NULL, *parent;
+    struct lys_node_inout *inout;
     struct ly_set *set;
 
     if (!dev->deviate) {
@@ -4182,12 +4183,31 @@
             /* unlink and store the original node */
             parent = target->parent;
             lys_node_unlink(target);
-            if (parent && (parent->nodetype & (LYS_AUGMENT | LYS_USES))) {
-                /* hack for augment, because when the original will be sometime reconnected back, we actually need
-                 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
-                 * path), so we need to remember the augment as an addition */
-                /* we also need to remember the parent uses so that we connect it back to it when switching deviation state */
-                target->parent = parent;
+            if (parent) {
+                if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
+                    /* hack for augment, because when the original will be sometime reconnected back, we actually need
+                     * to reconnect it to both - the augment and its target (which is deduced from the deviations target
+                     * path), so we need to remember the augment as an addition */
+                    /* we also need to remember the parent uses so that we connect it back to it when switching deviation state */
+                    target->parent = parent;
+                } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
+                    /* re-create implicit node */
+                    inout = calloc(1, sizeof *inout);
+                    LY_CHECK_ERR_RETURN(!inout, LOGMEM(module->ctx), );
+
+                    inout->nodetype = target->nodetype;
+                    inout->name = lydict_insert(module->ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
+                    inout->module = target->module;
+                    inout->flags = LYS_IMPLICIT;
+
+                    /* insert it manually */
+                    assert(parent->child && !parent->child->next
+                    && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
+                    parent->child->next = (struct lys_node *)inout;
+                    inout->prev = parent->child;
+                    parent->child->prev = (struct lys_node *)inout;
+                    inout->parent = parent;
+                }
             }
             dev->orig_node = target;
         }