yang - add deviate replace statement
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 8816f07..fe4f728 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -1197,9 +1197,11 @@
 }
 
 void *
-yang_read_type(void *parent, char *value, int type, int line)
+yang_read_type(struct lys_module *module, void *parent, char *value, int type, int line)
 {
     struct yang_type *typ;
+    struct type_deviation *dev;
+    struct lys_tpdf *tmp_parent;
 
     typ = calloc(1, sizeof *typ);
     if (!typ) {
@@ -1226,10 +1228,44 @@
     case TYPEDEF_KEYWORD:
         ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
         typ->type = &((struct lys_tpdf *)parent)->type;
+        break;
+    case REPLACE_KEYWORD:
+        /* deviation replace type*/
+        dev = (struct type_deviation *)parent;
+        if (dev->deviate->type) {
+            LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "type", "deviation");
+            goto error;
+        }
+        /* check target node type */
+        if (dev->target->nodetype == LYS_LEAF) {
+            typ->type = &((struct lys_node_leaf *)dev->target)->type;
+        } else if (dev->target->nodetype == LYS_LEAFLIST) {
+            typ->type = &((struct lys_node_leaflist *)dev->target)->type;
+        } else {
+            LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "type");
+            LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"type\" property.");
+            goto error;
+        }
+
+        /* remove type and initialize it */
+        lys_type_free(module->ctx, typ->type);
+        tmp_parent = typ->type->parent;
+        memset(typ->type, 0, sizeof *typ->type);
+        typ->type->parent = tmp_parent;
+
+        /* replace it with the value specified in deviation */
+        /* HACK for unres */
+        typ->type->der = (struct lys_tpdf *)typ;
+        dev->deviate->type = typ->type;
+        break;
     }
     typ->name = value;
     typ->line = line;
     return typ;
+
+error:
+    free(typ);
+    return NULL;
 }
 
 void *
@@ -1741,16 +1777,6 @@
 
     dev->deviate->units = lydict_insert_zc(ctx, value);
 
-    /* apply to target */
-    if (dev->deviate->mod == LY_DEVIATE_ADD) {
-        /* check that there is no current value */
-        if (*stritem) {
-            LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
-            LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
-            goto error;
-        }
-    }
-
     if (dev->deviate->mod == LY_DEVIATE_DEL) {
         /* check values */
         if (*stritem != dev->deviate->units) {
@@ -1760,7 +1786,21 @@
         }
         /* remove current units value of the target */
         lydict_remove(ctx, *stritem);
-    } else { /* add (already checked) and replace */
+    } else {
+        if (dev->deviate->mod == LY_DEVIATE_ADD) {
+            /* check that there is no current value */
+            if (*stritem) {
+                LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
+                goto error;
+            }
+        } else { /* replace */
+            if (!*stritem) {
+                LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
+                goto error;
+            }
+        }
         /* remove current units value of the target ... */
         lydict_remove(ctx, *stritem);
 
@@ -1891,15 +1931,6 @@
     if (dev->target->nodetype == LYS_CHOICE) {
         choice = (struct lys_node_choice *)dev->target;
 
-        if (dev->deviate->mod == LY_DEVIATE_ADD) {
-            /* check that there is no current value */
-            if (choice->dflt) {
-                LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
-                LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
-                goto error;
-            }
-        }
-
         rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
         if (rc || !node) {
             LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
@@ -1912,7 +1943,22 @@
                 goto error;
             }
             choice->dflt = NULL;
-        } else { /* add (already checked) and replace */
+        } else {
+            if (dev->deviate->mod == LY_DEVIATE_ADD) {
+                /* check that there is no current value */
+                if (choice->dflt) {
+                    LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
+                    goto error;
+                }
+            } else { /* replace*/
+                if (!choice->dflt) {
+                    LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
+                    goto error;
+                }
+            }
+
             choice->dflt = node;
             if (!choice->dflt) {
                 /* default branch not found */
@@ -1923,14 +1969,6 @@
     } else if (dev->target->nodetype == LYS_LEAF) {
         leaf = (struct lys_node_leaf *)dev->target;
 
-        if (dev->deviate->mod == LY_DEVIATE_ADD) {
-            /* check that there is no current value */
-            if (leaf->dflt) {
-                LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
-                LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
-                goto error;
-            }
-        }
         if (dev->deviate->mod == LY_DEVIATE_DEL) {
             if (!leaf->dflt || (leaf->dflt != dev->deviate->dflt)) {
                 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
@@ -1940,7 +1978,21 @@
             /* remove value */
             lydict_remove(ctx, leaf->dflt);
             leaf->dflt = NULL;
-        } else { /* add (already checked) and replace */
+        } else {
+            if (dev->deviate->mod == LY_DEVIATE_ADD) {
+                /* check that there is no current value */
+                if (leaf->dflt) {
+                    LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
+                    goto error;
+                }
+            } else { /* replace*/
+                if (!leaf->dflt) {
+                    LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
+                    goto error;
+                }
+            }
             /* remove value */
             lydict_remove(ctx, leaf->dflt);
 
@@ -2012,9 +2064,14 @@
             LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
             goto error;
         }
+    } else { /* replace */
+        if (!(dev->target->flags & LYS_MAND_MASK)) {
+            LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
+            LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
+            goto error;
+        }
     }
 
-    /* add (already checked) and replace */
     /* remove current mandatory value of the target ... */
     dev->target->flags &= ~LYS_MAND_MASK;
 
@@ -2053,8 +2110,10 @@
 
     if (type) {
         dev->deviate->max = value;
+        dev->deviate->max_set = 1;
     } else {
         dev->deviate->min = value;
+        dev->deviate->min_set = 1;
     }
 
     if (dev->deviate->mod == LY_DEVIATE_ADD) {
@@ -2064,6 +2123,9 @@
             LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
             goto error;
         }
+    } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
+        /* unfortunately, there is no way to check reliably that there
+         * was a value before, it could have been the default */
     }
 
     /* add (already checked) and replace */