lys_features_change(const struct lys_module *module, const char *name, int op, int skip_checks)
{
    int all = 0;
    int i, j, k;
    int progress, faili = 0, failj = 0, failk = 0;

    uint8_t fsize;
    struct lys_feature *f;

    if (!module || !name || !strlen(name)) {
        LOGARG;
        return EXIT_FAILURE;
    }

    if (!strcmp(name, "*")) {
        /* enable all */
        all = 1;
    }

    progress = failk = 1;
    while (progress && failk) {
        for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
            if (i == -1) {
                fsize = module->features_size;
                f = module->features;
            } else {
                fsize = module->inc[i].submodule->features_size;
                f = module->inc[i].submodule->features;
            }

            for (j = 0; j < fsize; j++) {
                if (all || !strcmp(f[j].name, name)) {
                    if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
                        if (all) {
                            /* skip already set features */
                            continue;
                        } else {
                            /* feature already set correctly */
                            return EXIT_SUCCESS;
                        }
                    }

                    if (skip_checks) {
                        if (op) {
                            f[j].flags |= LYS_FENABLED;
                        } else {
                            f[j].flags &= ~LYS_FENABLED;
                        }
                        progress++;
                    } else {
                        if (op) {
                            /* check referenced features if they are enabled */
                            for (k = 0; k < f[j].iffeature_size; k++) {
                                if (!resolve_iffeature(&f[j].iffeature[k])) {
                                    if (all) {
                                        faili = i;
                                        failj = j;
                                        failk = k + 1;
                                        break;
                                    } else {
                                        LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
                                            f[j].name, k + 1);
                                        return EXIT_FAILURE;
                                    }
                                }
                            }

                            if (k == f[j].iffeature_size) {
                                /* the last check passed, do the change */
                                f[j].flags |= LYS_FENABLED;
                                progress++;
                            }
                        } else {
                            lys_features_disable_recursive(&f[j]);
                            progress++;
                        }
                    }
                    if (!all) {
                        /* stop in case changing a single feature */
                        return EXIT_SUCCESS;
                    }
                }
            }
        }
    }
    if (failk) {
        /* print info about the last failing feature */
        LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
               faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
        return EXIT_FAILURE;
    }

    if (all) {
        return EXIT_SUCCESS;
    } else {
        /* the specified feature not found */
        return EXIT_FAILURE;
    }
}