blob: 73c4fad90c5f5309f9e259bb24aed23ac5b1d78c [file] [log] [blame]
Radek Krejci3f5e3db2018-10-11 15:57:47 +02001/**
2 * @file tree_schema.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema tree implementation
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
Radek Krejci86d106e2018-10-18 09:53:19 +020014#define _DEFAULT_SOURCE
15
Radek Krejci151a5b72018-10-19 14:21:44 +020016#include <ctype.h>
Radek Krejci86d106e2018-10-18 09:53:19 +020017#include <errno.h>
18#include <fcntl.h>
19#include <linux/limits.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24#include <unistd.h>
Radek Krejci3f5e3db2018-10-11 15:57:47 +020025
26#include "libyang.h"
27#include "common.h"
Radek Krejci86d106e2018-10-18 09:53:19 +020028#include "context.h"
Radek Krejci70853c52018-10-15 14:46:16 +020029#include "tree_schema_internal.h"
Radek Krejci3f5e3db2018-10-11 15:57:47 +020030
Radek Krejcie53a8dc2018-10-17 12:52:40 +020031#define FREE_ARRAY(CTX, ARRAY, FUNC) {uint64_t c__; LY_ARRAY_FOR(ARRAY, c__){FUNC(CTX, LY_ARRAY_INDEX(ARRAY, c__), dict);}free(ARRAY);}
Radek Krejcidd4e8d42018-10-16 14:55:43 +020032#define FREE_MEMBER(CTX, MEMBER, FUNC) if (MEMBER) {FUNC(CTX, MEMBER, dict);free(MEMBER);}
Radek Krejci151a5b72018-10-19 14:21:44 +020033#define FREE_STRING(CTX, STRING, DICT) if (DICT && STRING) {lydict_remove(CTX, STRING);}
34#define FREE_STRINGS(CTX, ARRAY, DICT) {uint64_t c__; LY_ARRAY_FOR(ARRAY, c__){FREE_STRING(CTX, *(LY_ARRAY_INDEX(ARRAY, c__, const char*)), DICT);}free(ARRAY);}
Radek Krejci6f7feb62018-10-12 15:23:02 +020035
Radek Krejcidd4e8d42018-10-16 14:55:43 +020036static void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp, int dict);
37static void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node, int dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +020038
Radek Krejci86d106e2018-10-18 09:53:19 +020039#define LYSC_CTX_BUFSIZE 4086
40struct lysc_ctx {
41 struct lysc_module *mod;
42 uint16_t path_len;
43 char path[LYSC_CTX_BUFSIZE];
44};
45
Radek Krejci6f7feb62018-10-12 15:23:02 +020046static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020047lysp_stmt_free(struct ly_ctx *ctx, struct lysp_stmt *stmt, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020048{
49 struct lysp_stmt *child, *next;
50
Radek Krejci151a5b72018-10-19 14:21:44 +020051 FREE_STRING(ctx, stmt->stmt, dict);
52 FREE_STRING(ctx, stmt->arg, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +020053
54 LY_LIST_FOR_SAFE(stmt->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +020055 lysp_stmt_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +020056 }
57
58 free(stmt);
59}
60
61static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020062lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020063{
64 struct lysp_stmt *stmt, *next;
65
Radek Krejci151a5b72018-10-19 14:21:44 +020066 FREE_STRING(ctx, ext->name, dict);
67 FREE_STRING(ctx, ext->argument, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +020068
69 LY_LIST_FOR_SAFE(ext->child, next, stmt) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +020070 lysp_stmt_free(ctx, stmt, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +020071 }
72}
73
74static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020075lysp_import_free(struct ly_ctx *ctx, struct lysp_import *import, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020076{
Radek Krejci151a5b72018-10-19 14:21:44 +020077 FREE_STRING(ctx, import->name, dict);
78 FREE_STRING(ctx, import->prefix, dict);
79 FREE_STRING(ctx, import->dsc, dict);
80 FREE_STRING(ctx, import->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +020081 FREE_ARRAY(ctx, import->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +020082}
83
84static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020085lysp_include_free(struct ly_ctx *ctx, struct lysp_include *include, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020086{
Radek Krejci151a5b72018-10-19 14:21:44 +020087 FREE_STRING(ctx, include->name, dict);
88 FREE_STRING(ctx, include->dsc, dict);
89 FREE_STRING(ctx, include->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +020090 FREE_ARRAY(ctx, include->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +020091}
92
93static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020094lysp_revision_free(struct ly_ctx *ctx, struct lysp_revision *rev, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020095{
Radek Krejci151a5b72018-10-19 14:21:44 +020096 FREE_STRING(ctx, rev->dsc, dict);
97 FREE_STRING(ctx, rev->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +020098 FREE_ARRAY(ctx, rev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +020099}
100
101static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200102lysp_ext_free(struct ly_ctx *ctx, struct lysp_ext *ext, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200103{
Radek Krejci151a5b72018-10-19 14:21:44 +0200104 FREE_STRING(ctx, ext->name, dict);
105 FREE_STRING(ctx, ext->argument, dict);
106 FREE_STRING(ctx, ext->dsc, dict);
107 FREE_STRING(ctx, ext->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200108 FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200109}
110
111static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200112lysp_feature_free(struct ly_ctx *ctx, struct lysp_feature *feat, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200113{
Radek Krejci151a5b72018-10-19 14:21:44 +0200114 FREE_STRING(ctx, feat->name, dict);
115 FREE_STRINGS(ctx, feat->iffeatures, 1);
116 FREE_STRING(ctx, feat->dsc, dict);
117 FREE_STRING(ctx, feat->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200118 FREE_ARRAY(ctx, feat->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200119}
120
121static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200122lysp_ident_free(struct ly_ctx *ctx, struct lysp_ident *ident, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200123{
Radek Krejci151a5b72018-10-19 14:21:44 +0200124 FREE_STRING(ctx, ident->name, dict);
125 //FREE_STRINGS(ctx, ident->iffeatures, 1);
126 {
127 uint64_t c__;
128 for (c__ = 0; ident->iffeatures && c__ < (*((uint32_t*)(ident->iffeatures))); ++c__) {
129 if (1 && ((void*)((uint32_t*)((ident->iffeatures) + c__) + 1))) {
130 lydict_remove(ctx, *((char**)((uint32_t*)((ident->iffeatures) + c__) + 1)));
131 };
132 }
133 free(ident->iffeatures);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200134 }
Radek Krejci151a5b72018-10-19 14:21:44 +0200135 FREE_STRINGS(ctx, ident->bases, dict);
136 FREE_STRING(ctx, ident->dsc, dict);
137 FREE_STRING(ctx, ident->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200138 FREE_ARRAY(ctx, ident->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200139}
140
141static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200142lysp_restr_free(struct ly_ctx *ctx, struct lysp_restr *restr, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200143{
Radek Krejci151a5b72018-10-19 14:21:44 +0200144 FREE_STRING(ctx, restr->arg, dict);
145 FREE_STRING(ctx, restr->emsg, dict);
146 FREE_STRING(ctx, restr->eapptag, dict);
147 FREE_STRING(ctx, restr->dsc, dict);
148 FREE_STRING(ctx, restr->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200149 FREE_ARRAY(ctx, restr->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200150}
151
152static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200153lysp_type_enum_free(struct ly_ctx *ctx, struct lysp_type_enum *item, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200154{
Radek Krejci151a5b72018-10-19 14:21:44 +0200155 FREE_STRING(ctx, item->name, dict);
156 FREE_STRING(ctx, item->dsc, dict);
157 FREE_STRING(ctx, item->ref, dict);
158 FREE_STRINGS(ctx, item->iffeatures, 1);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200159 FREE_ARRAY(ctx, item->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200160}
161
162static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200163lysp_type_free(struct ly_ctx *ctx, struct lysp_type *type, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200164{
Radek Krejci151a5b72018-10-19 14:21:44 +0200165 FREE_STRING(ctx, type->name, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200166 FREE_MEMBER(ctx, type->range, lysp_restr_free);
167 FREE_MEMBER(ctx, type->length, lysp_restr_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200168 FREE_ARRAY(ctx, type->patterns, lysp_restr_free);
169 FREE_ARRAY(ctx, type->enums, lysp_type_enum_free);
170 FREE_ARRAY(ctx, type->bits, lysp_type_enum_free);
Radek Krejci151a5b72018-10-19 14:21:44 +0200171 FREE_STRING(ctx, type->path, dict);
172 FREE_STRINGS(ctx, type->bases, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200173 FREE_ARRAY(ctx, type->types, lysp_type_free);
174 FREE_ARRAY(ctx, type->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200175}
176
177static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200178lysp_tpdf_free(struct ly_ctx *ctx, struct lysp_tpdf *tpdf, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200179{
Radek Krejci151a5b72018-10-19 14:21:44 +0200180 FREE_STRING(ctx, tpdf->name, dict);
181 FREE_STRING(ctx, tpdf->units, dict);
182 FREE_STRING(ctx, tpdf->dflt, dict);
183 FREE_STRING(ctx, tpdf->dsc, dict);
184 FREE_STRING(ctx, tpdf->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200185 FREE_ARRAY(ctx, tpdf->exts, lysp_ext_instance_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200186 lysp_type_free(ctx, &tpdf->type, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200187}
188
189static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200190lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200191{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200192 struct lysp_node *node, *next;
193
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200194 FREE_ARRAY(ctx, inout->musts, lysp_restr_free);
195 FREE_ARRAY(ctx, inout->typedefs, lysp_tpdf_free);
196 FREE_ARRAY(ctx, inout->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200197 LY_LIST_FOR_SAFE(inout->data, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200198 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200199 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200200 FREE_ARRAY(ctx, inout->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200201
202}
203
204static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200205lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200206{
Radek Krejci151a5b72018-10-19 14:21:44 +0200207 FREE_STRING(ctx, action->name, dict);
208 FREE_STRING(ctx, action->dsc, dict);
209 FREE_STRING(ctx, action->ref, dict);
210 FREE_STRINGS(ctx, action->iffeatures, 1);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200211 FREE_ARRAY(ctx, action->typedefs, lysp_tpdf_free);
212 FREE_ARRAY(ctx, action->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200213 FREE_MEMBER(ctx, action->input, lysp_action_inout_free);
214 FREE_MEMBER(ctx, action->output, lysp_action_inout_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200215 FREE_ARRAY(ctx, action->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200216}
217
218static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200219lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200220{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200221 struct lysp_node *node, *next;
222
Radek Krejci151a5b72018-10-19 14:21:44 +0200223 FREE_STRING(ctx, notif->name, dict);
224 FREE_STRING(ctx, notif->dsc, dict);
225 FREE_STRING(ctx, notif->ref, dict);
226 FREE_STRINGS(ctx, notif->iffeatures, 1);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200227 FREE_ARRAY(ctx, notif->musts, lysp_restr_free);
228 FREE_ARRAY(ctx, notif->typedefs, lysp_tpdf_free);
229 FREE_ARRAY(ctx, notif->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200230 LY_LIST_FOR_SAFE(notif->data, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200231 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200232 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200233 FREE_ARRAY(ctx, notif->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200234}
235
236static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200237lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200238{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200239 struct lysp_node *node, *next;
240
Radek Krejci151a5b72018-10-19 14:21:44 +0200241 FREE_STRING(ctx, grp->name, dict);
242 FREE_STRING(ctx, grp->dsc, dict);
243 FREE_STRING(ctx, grp->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200244 FREE_ARRAY(ctx, grp->typedefs, lysp_tpdf_free);
245 FREE_ARRAY(ctx, grp->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200246 LY_LIST_FOR_SAFE(grp->data, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200247 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200248 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200249 FREE_ARRAY(ctx, grp->actions, lysp_action_free);
250 FREE_ARRAY(ctx, grp->notifs, lysp_notif_free);
251 FREE_ARRAY(ctx, grp->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200252}
253
254static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200255lysp_when_free(struct ly_ctx *ctx, struct lysp_when *when, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200256{
Radek Krejci151a5b72018-10-19 14:21:44 +0200257 FREE_STRING(ctx, when->cond, dict);
258 FREE_STRING(ctx, when->dsc, dict);
259 FREE_STRING(ctx, when->ref, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200260 FREE_ARRAY(ctx, when->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200261}
262
263static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200264lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200265{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200266 struct lysp_node *node, *next;
267
Radek Krejci151a5b72018-10-19 14:21:44 +0200268 FREE_STRING(ctx, augment->nodeid, dict);
269 FREE_STRING(ctx, augment->dsc, dict);
270 FREE_STRING(ctx, augment->ref, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200271 FREE_MEMBER(ctx, augment->when, lysp_when_free);
Radek Krejci151a5b72018-10-19 14:21:44 +0200272 FREE_STRINGS(ctx, augment->iffeatures, 1);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200273 LY_LIST_FOR_SAFE(augment->child, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200274 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200275 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200276 FREE_ARRAY(ctx, augment->actions, lysp_action_free);
277 FREE_ARRAY(ctx, augment->notifs, lysp_notif_free);
278 FREE_ARRAY(ctx, augment->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200279}
280
281static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200282lysp_deviate_free(struct ly_ctx *ctx, struct lysp_deviate *d, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200283{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200284 struct lysp_deviate_add *add = (struct lysp_deviate_add*)d;
285 struct lysp_deviate_rpl *rpl = (struct lysp_deviate_rpl*)d;
286
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200287 FREE_ARRAY(ctx, d->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200288 switch(d->mod) {
289 case LYS_DEV_NOT_SUPPORTED:
290 /* nothing to do */
291 break;
292 case LYS_DEV_ADD:
293 case LYS_DEV_DELETE: /* compatible for dynamically allocated data */
Radek Krejci151a5b72018-10-19 14:21:44 +0200294 FREE_STRING(ctx, add->units, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200295 FREE_ARRAY(ctx, add->musts, lysp_restr_free);
Radek Krejci151a5b72018-10-19 14:21:44 +0200296 FREE_STRINGS(ctx, add->uniques, dict);
297 FREE_STRINGS(ctx, add->dflts, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200298 break;
299 case LYS_DEV_REPLACE:
300 FREE_MEMBER(ctx, rpl->type, lysp_type_free);
Radek Krejci151a5b72018-10-19 14:21:44 +0200301 FREE_STRING(ctx, rpl->units, dict);
302 FREE_STRING(ctx, rpl->dflt, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200303 break;
304 default:
305 LOGINT(ctx);
306 break;
307 }
308}
309
310static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200311lysp_deviation_free(struct ly_ctx *ctx, struct lysp_deviation *dev, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200312{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200313 struct lysp_deviate *next, *iter;
314
Radek Krejci151a5b72018-10-19 14:21:44 +0200315 FREE_STRING(ctx, dev->nodeid, dict);
316 FREE_STRING(ctx, dev->dsc, dict);
317 FREE_STRING(ctx, dev->ref, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200318 LY_LIST_FOR_SAFE(dev->deviates, next, iter) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200319 lysp_deviate_free(ctx, iter, dict);
Michal Vasko8447f6a2018-10-15 10:56:16 +0200320 free(iter);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200321 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200322 FREE_ARRAY(ctx, dev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200323}
324
325static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200326lysp_refine_free(struct ly_ctx *ctx, struct lysp_refine *ref, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200327{
Radek Krejci151a5b72018-10-19 14:21:44 +0200328 FREE_STRING(ctx, ref->nodeid, dict);
329 FREE_STRING(ctx, ref->dsc, dict);
330 FREE_STRING(ctx, ref->ref, dict);
331 FREE_STRINGS(ctx, ref->iffeatures, 1);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200332 FREE_ARRAY(ctx, ref->musts, lysp_restr_free);
Radek Krejci151a5b72018-10-19 14:21:44 +0200333 FREE_STRING(ctx, ref->presence, dict);
334 FREE_STRINGS(ctx, ref->dflts, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200335 FREE_ARRAY(ctx, ref->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200336}
337
338static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200339lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200340{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200341 struct lysp_node *child, *next;
342
Radek Krejci151a5b72018-10-19 14:21:44 +0200343 FREE_STRING(ctx, node->name, dict);
344 FREE_STRING(ctx, node->dsc, dict);
345 FREE_STRING(ctx, node->ref, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200346 FREE_MEMBER(ctx, node->when, lysp_when_free);
Radek Krejci151a5b72018-10-19 14:21:44 +0200347 FREE_STRINGS(ctx, node->iffeatures, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200348 FREE_ARRAY(ctx, node->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200349
350 switch(node->nodetype) {
351 case LYS_CONTAINER:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200352 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->musts, lysp_restr_free);
Radek Krejci151a5b72018-10-19 14:21:44 +0200353 FREE_STRING(ctx, ((struct lysp_node_container*)node)->presence, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200354 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->typedefs, lysp_tpdf_free);
355 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200356 LY_LIST_FOR_SAFE(((struct lysp_node_container*)node)->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200357 lysp_node_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200358 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200359 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->actions, lysp_action_free);
360 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->notifs, lysp_notif_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200361 break;
362 case LYS_LEAF:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200363 FREE_ARRAY(ctx, ((struct lysp_node_leaf*)node)->musts, lysp_restr_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200364 lysp_type_free(ctx, &((struct lysp_node_leaf*)node)->type, dict);
Radek Krejci151a5b72018-10-19 14:21:44 +0200365 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->units, dict);
366 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->dflt, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200367 break;
368 case LYS_LEAFLIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200369 FREE_ARRAY(ctx, ((struct lysp_node_leaflist*)node)->musts, lysp_restr_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200370 lysp_type_free(ctx, &((struct lysp_node_leaflist*)node)->type, dict);
Radek Krejci151a5b72018-10-19 14:21:44 +0200371 FREE_STRING(ctx, ((struct lysp_node_leaflist*)node)->units, dict);
372 FREE_STRINGS(ctx, ((struct lysp_node_leaflist*)node)->dflts, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200373 break;
374 case LYS_LIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200375 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->musts, lysp_restr_free);
Radek Krejci151a5b72018-10-19 14:21:44 +0200376 FREE_STRING(ctx, ((struct lysp_node_list*)node)->key, dict);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200377 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->typedefs, lysp_tpdf_free);
378 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200379 LY_LIST_FOR_SAFE(((struct lysp_node_list*)node)->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200380 lysp_node_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200381 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200382 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->actions, lysp_action_free);
383 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->notifs, lysp_notif_free);
Radek Krejci151a5b72018-10-19 14:21:44 +0200384 FREE_STRINGS(ctx, ((struct lysp_node_list*)node)->uniques, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200385 break;
386 case LYS_CHOICE:
387 LY_LIST_FOR_SAFE(((struct lysp_node_choice*)node)->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200388 lysp_node_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200389 }
Radek Krejci151a5b72018-10-19 14:21:44 +0200390 FREE_STRING(ctx, ((struct lysp_node_choice*)node)->dflt, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200391 break;
392 case LYS_CASE:
393 LY_LIST_FOR_SAFE(((struct lysp_node_case*)node)->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200394 lysp_node_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200395 }
396 break;
397 case LYS_ANYDATA:
398 case LYS_ANYXML:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200399 FREE_ARRAY(ctx, ((struct lysp_node_anydata*)node)->musts, lysp_restr_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200400 break;
401 case LYS_USES:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200402 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->refines, lysp_refine_free);
403 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->augments, lysp_augment_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200404 break;
405 default:
406 LOGINT(ctx);
407 }
408
409 free(node);
410}
411
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200412static void
413lysp_module_free_(struct lysp_module *module, int dict)
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200414{
415 struct ly_ctx *ctx;
Radek Krejci6f7feb62018-10-12 15:23:02 +0200416 struct lysp_node *node, *next;
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200417
418 LY_CHECK_ARG_RET(NULL, module,);
419 ctx = module->ctx;
420
Radek Krejci151a5b72018-10-19 14:21:44 +0200421 FREE_STRING(ctx, module->name, dict);
422 FREE_STRING(ctx, module->filepath, dict);
423 FREE_STRING(ctx, module->ns, dict); /* or belongs-to */
424 FREE_STRING(ctx, module->prefix, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200425
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200426 FREE_ARRAY(ctx, module->imports, lysp_import_free);
427 FREE_ARRAY(ctx, module->includes, lysp_include_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200428
Radek Krejci151a5b72018-10-19 14:21:44 +0200429 FREE_STRING(ctx, module->org, dict);
430 FREE_STRING(ctx, module->contact, dict);
431 FREE_STRING(ctx, module->dsc, dict);
432 FREE_STRING(ctx, module->ref, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200433
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200434 FREE_ARRAY(ctx, module->revs, lysp_revision_free);
435 FREE_ARRAY(ctx, module->extensions, lysp_ext_free);
436 FREE_ARRAY(ctx, module->features, lysp_feature_free);
437 FREE_ARRAY(ctx, module->identities, lysp_ident_free);
438 FREE_ARRAY(ctx, module->typedefs, lysp_tpdf_free);
439 FREE_ARRAY(ctx, module->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200440 LY_LIST_FOR_SAFE(module->data, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200441 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200442 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200443 FREE_ARRAY(ctx, module->augments, lysp_augment_free);
444 FREE_ARRAY(ctx, module->rpcs, lysp_action_free);
445 FREE_ARRAY(ctx, module->notifs, lysp_notif_free);
446 FREE_ARRAY(ctx, module->deviations, lysp_deviation_free);
447 FREE_ARRAY(ctx, module->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200448
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200449 free(module);
450}
451
452API void
453lysp_module_free(struct lysp_module *module)
454{
Radek Krejci151a5b72018-10-19 14:21:44 +0200455 if (module) {
456 lysp_module_free_(module, 1);
457 }
458}
459
460static void
461lysc_iffeature_free(struct ly_ctx *UNUSED(ctx), struct lysc_iffeature *iff, int UNUSED(dict))
462{
463 free(iff->features);
464 free(iff->expr);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200465}
466
467static void
468lysc_feature_free(struct ly_ctx *ctx, struct lysc_feature *feat, int dict)
469{
Radek Krejci151a5b72018-10-19 14:21:44 +0200470 FREE_STRING(ctx, feat->name, dict);
471 FREE_ARRAY(ctx, feat->iffeatures, lysc_iffeature_free);
472 free(feat->depfeatures);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200473}
474
475static void
476lysc_module_free_(struct lysc_module *module, int dict)
477{
478 struct ly_ctx *ctx;
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200479
480 LY_CHECK_ARG_RET(NULL, module,);
481 ctx = module->ctx;
482
Radek Krejci151a5b72018-10-19 14:21:44 +0200483 FREE_STRING(ctx, module->name, dict);
484 FREE_STRING(ctx, module->ns, dict);
485 FREE_STRING(ctx, module->prefix, dict);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200486
487
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200488 FREE_ARRAY(ctx, module->features, lysc_feature_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200489
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200490
491 free(module);
492}
Radek Krejci70853c52018-10-15 14:46:16 +0200493
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200494API void
Radek Krejci86d106e2018-10-18 09:53:19 +0200495lysc_module_free(struct lysc_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200496{
Radek Krejci151a5b72018-10-19 14:21:44 +0200497 if (module) {
498 lysc_module_free_(module, 1);
499 }
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200500}
501
Radek Krejci86d106e2018-10-18 09:53:19 +0200502void
503lys_module_free(struct lys_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejci70853c52018-10-15 14:46:16 +0200504{
Radek Krejci86d106e2018-10-18 09:53:19 +0200505 if (!module) {
506 return;
507 }
Radek Krejci70853c52018-10-15 14:46:16 +0200508
Radek Krejci86d106e2018-10-18 09:53:19 +0200509 lysc_module_free(module->compiled, private_destructor);
510 lysp_module_free(module->parsed);
511 free(module);
512}
513
Radek Krejci151a5b72018-10-19 14:21:44 +0200514struct iff_stack {
515 int size;
516 int index; /* first empty item */
517 uint8_t *stack;
518};
519
Radek Krejci86d106e2018-10-18 09:53:19 +0200520static LY_ERR
Radek Krejci151a5b72018-10-19 14:21:44 +0200521iff_stack_push(struct iff_stack *stack, uint8_t value)
Radek Krejci86d106e2018-10-18 09:53:19 +0200522{
Radek Krejci151a5b72018-10-19 14:21:44 +0200523 if (stack->index == stack->size) {
524 stack->size += 4;
525 stack->stack = ly_realloc(stack->stack, stack->size * sizeof *stack->stack);
526 LY_CHECK_ERR_RET(!stack->stack, LOGMEM(NULL); stack->size = 0, LY_EMEM);
Radek Krejci70853c52018-10-15 14:46:16 +0200527 }
Radek Krejci151a5b72018-10-19 14:21:44 +0200528 stack->stack[stack->index++] = value;
Radek Krejci70853c52018-10-15 14:46:16 +0200529 return LY_SUCCESS;
530}
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200531
Radek Krejci151a5b72018-10-19 14:21:44 +0200532static uint8_t
533iff_stack_pop(struct iff_stack *stack)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200534{
Radek Krejci151a5b72018-10-19 14:21:44 +0200535 stack->index--;
536 return stack->stack[stack->index];
537}
538
539static void
540iff_stack_clean(struct iff_stack *stack)
541{
542 stack->size = 0;
543 free(stack->stack);
544}
545
546static void
547iff_setop(uint8_t *list, uint8_t op, int pos)
548{
549 uint8_t *item;
550 uint8_t mask = 3;
551
552 assert(pos >= 0);
553 assert(op <= 3); /* max 2 bits */
554
555 item = &list[pos / 4];
556 mask = mask << 2 * (pos % 4);
557 *item = (*item) & ~mask;
558 *item = (*item) | (op << 2 * (pos % 4));
559}
560
561static uint8_t
562iff_getop(uint8_t *list, int pos)
563{
564 uint8_t *item;
565 uint8_t mask = 3, result;
566
567 assert(pos >= 0);
568
569 item = &list[pos / 4];
570 result = (*item) & (mask << 2 * (pos % 4));
571 return result >> 2 * (pos % 4);
572}
573
574#define LYS_IFF_LP 0x04 /* ( */
575#define LYS_IFF_RP 0x08 /* ) */
576
577API int
578lysc_feature_value(const struct lysc_feature *feature)
579{
580 LY_CHECK_ARG_RET(NULL, feature, -1);
581 return feature->flags & LYS_FENABLED ? 1 : 0;
582}
583
584static struct lysc_feature *
585lysc_feature_find(struct lysc_module *mod, const char *name, size_t len)
586{
587 size_t i;
588 struct lysc_feature *f;
589
590 for (i = 0; i < len; ++i) {
591 if (name[i] == ':') {
592 /* we have a prefixed feature */
593 mod = lysc_module_find_prefix(mod, name, i);
594 LY_CHECK_RET(!mod, NULL);
595
596 name = &name[i + 1];
597 len = len - i - 1;
598 }
599 }
600
601 /* we have the correct module, get the feature */
602 LY_ARRAY_FOR(mod->features, i) {
603 f = LY_ARRAY_INDEX(mod->features, i);
604 if (!strncmp(f->name, name, len) && f->name[len] == '\0') {
605 return f;
606 }
607 }
608
609 return NULL;
610}
611
612static int
613lysc_iffeature_value_(const struct lysc_iffeature *iff, int *index_e, int *index_f)
614{
615 uint8_t op;
616 int a, b;
617
618 op = iff_getop(iff->expr, *index_e);
619 (*index_e)++;
620
621 switch (op) {
622 case LYS_IFF_F:
623 /* resolve feature */
624 return lysc_feature_value(*LY_ARRAY_INDEX(iff->features, (*index_f)++, struct lysc_feature*));
625 case LYS_IFF_NOT:
626 /* invert result */
627 return lysc_iffeature_value_(iff, index_e, index_f) ? 0 : 1;
628 case LYS_IFF_AND:
629 case LYS_IFF_OR:
630 a = lysc_iffeature_value_(iff, index_e, index_f);
631 b = lysc_iffeature_value_(iff, index_e, index_f);
632 if (op == LYS_IFF_AND) {
633 return a && b;
634 } else { /* LYS_IFF_OR */
635 return a || b;
636 }
637 }
638
639 return 0;
640}
641
642API int
643lysc_iffeature_value(const struct lysc_iffeature *iff)
644{
645 int index_e = 0, index_f = 0;
646
647 LY_CHECK_ARG_RET(NULL, iff, -1);
648
649 if (iff->expr) {
650 return lysc_iffeature_value_(iff, &index_e, &index_f);
651 }
652 return 0;
653}
654
655/*
656 * op: 1 - enable, 0 - disable
657 */
658/**
659 * @brief Enable/Disable the specified feature in the module.
660 *
661 * If the feature is already set to the desired value, LY_SUCCESS is returned.
662 * By changing the feature, also all the feature which depends on it via their
663 * if-feature statements are again evaluated (disabled if a if-feature statemen
664 * evaluates to false).
665 *
666 * @param[in] mod Compiled module where to set (search for) the feature.
667 * @param[in] name Name of the feature to set. Asterisk ('*') can be used to
668 * set all the features in the module.
669 * @param[in] value Desired value of the feature: 1 (enable) or 0 (disable).
670 * @return LY_ERR value.
671 */
672static LY_ERR
673lys_feature_change(const struct lysc_module *mod, const char *name, int value)
674{
675 int all = 0;
676 unsigned int u;
677 struct lysc_feature *f, **df;
678 struct lysc_iffeature *iff;
679 struct ly_set *changed;
680
681 if (!mod->features) {
682 LOGERR(mod->ctx, LY_EINVAL, "Unable to switch feature since the module \"%s\" has no features.", mod->name);
683 return LY_EINVAL;
684 }
685
686 if (!strcmp(name, "*")) {
687 /* enable all */
688 all = 1;
689 }
690 changed = ly_set_new();
691
692 for (u = 0; u < LY_ARRAY_SIZE(mod->features); ++u) {
693 f = LY_ARRAY_INDEX(mod->features, u);
694 if (all || !strcmp(f->name, name)) {
695 if ((value && (f->flags & LYS_FENABLED)) || (!value && !(f->flags & LYS_FENABLED))) {
696 if (all) {
697 /* skip already set features */
698 continue;
699 } else {
700 /* feature already set correctly */
701 ly_set_free(changed, NULL);
702 return LY_SUCCESS;
703 }
704 }
705
706 if (value) { /* enable */
707 /* check referenced features if they are enabled */
708 LY_ARRAY_FOR(f->iffeatures, struct lysc_iffeature, iff) {
709 if (!lysc_iffeature_value(iff)) {
710 if (all) {
711 LOGWRN(mod->ctx,
712 "Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
713 f->name);
714 goto next;
715 } else {
716 LOGERR(mod->ctx, LY_EDENIED,
717 "Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
718 f->name);
719 ly_set_free(changed, NULL);
720 return LY_EDENIED;
721 }
722 }
723 }
724 /* enable the feature */
725 f->flags |= LYS_FENABLED;
726 } else { /* disable */
727 /* disable the feature */
728 f->flags &= ~LYS_FENABLED;
729 }
730
731 /* remember the changed feature */
732 ly_set_add(changed, f, LY_SET_OPT_USEASLIST);
733
734 if (!all) {
735 /* stop in case changing a single feature */
736 break;
737 }
738 }
739next:
740 ;
741 }
742
743 if (!all && !changed->count) {
744 LOGERR(mod->ctx, LY_EINVAL, "Feature \"%s\" not found in module \"%s\".", name, mod->name);
745 ly_set_free(changed, NULL);
746 return LY_EINVAL;
747 }
748
749 /* reflect change(s) in the dependent features */
750 for (u = 0; u < changed->count; ++u) {
751 /* If a dependent feature is enabled, it can be now changed by the change (to false) of the value of
752 * its if-feature statements. The reverse logic, automatically enable feature when its feature is enabled
753 * is not done - by default, features are disabled and must be explicitely enabled. */
754 f = changed->objs[u];
755 LY_ARRAY_FOR(f->depfeatures, struct lysc_feature*, df) {
756 if (!((*df)->flags & LYS_FENABLED)) {
757 /* not enabled, nothing to do */
758 continue;
759 }
760 /* check the feature's if-features which could change by the previous change of our feature */
761 LY_ARRAY_FOR((*df)->iffeatures, struct lysc_iffeature, iff) {
762 if (!lysc_iffeature_value(iff)) {
763 /* the feature must be disabled now */
764 (*df)->flags &= ~LYS_FENABLED;
765 /* add the feature into the list of changed features */
766 ly_set_add(changed, *df, LY_SET_OPT_USEASLIST);
767 break;
768 }
769 }
770 }
771 }
772
773 ly_set_free(changed, NULL);
774 return LY_SUCCESS;
775}
776
777API LY_ERR
778lys_feature_enable(struct lys_module *module, const char *feature)
779{
780 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, LY_EINVAL);
781
782 return lys_feature_change(module->compiled, feature, 1);
783}
784
785API LY_ERR
786lys_feature_disable(struct lys_module *module, const char *feature)
787{
788 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, LY_EINVAL);
789
790 return lys_feature_change(module->compiled, feature, 0);
791}
792
793API int
794lys_feature_value(const struct lys_module *module, const char *feature)
795{
796 struct lysc_feature *f;
797 struct lysc_module *mod;
798 unsigned int u;
799
800 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, -1);
801 mod = module->compiled;
802
803 /* search for the specified feature */
804 for (u = 0; u < LY_ARRAY_SIZE(mod->features); ++u) {
805 f = LY_ARRAY_INDEX(mod->features, u);
806 if (!strcmp(f->name, feature)) {
807 if (f->flags & LYS_FENABLED) {
808 return 1;
809 } else {
810 return 0;
811 }
812 }
813 }
814
815 /* feature definition not found */
816 return -1;
817}
818
819static LY_ERR
820lys_compile_iffeature(struct lysc_ctx *ctx, const char *value, int UNUSED(options), struct lysc_iffeature *iff, struct lysc_feature *parent)
821{
822 const char *c = value;
823 int r, rc = EXIT_FAILURE;
824 int i, j, last_not, checkversion = 0;
825 unsigned int f_size = 0, expr_size = 0, f_exp = 1;
826 uint8_t op;
827 struct iff_stack stack = {0, 0, NULL};
828 struct lysc_feature *f, **df;
829
830 assert(c);
831
832 /* pre-parse the expression to get sizes for arrays, also do some syntax checks of the expression */
833 for (i = j = last_not = 0; c[i]; i++) {
834 if (c[i] == '(') {
835 j++;
836 checkversion = 1;
837 continue;
838 } else if (c[i] == ')') {
839 j--;
840 continue;
841 } else if (isspace(c[i])) {
842 checkversion = 1;
843 continue;
844 }
845
846 if (!strncmp(&c[i], "not", r = 3) || !strncmp(&c[i], "and", r = 3) || !strncmp(&c[i], "or", r = 2)) {
847 if (c[i + r] == '\0') {
848 LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
849 "Invalid value \"%s\" of if-feature - unexpected end of expression.", value);
850 return LY_EVALID;
851 } else if (!isspace(c[i + r])) {
852 /* feature name starting with the not/and/or */
853 last_not = 0;
854 f_size++;
855 } else if (c[i] == 'n') { /* not operation */
856 if (last_not) {
857 /* double not */
858 expr_size = expr_size - 2;
859 last_not = 0;
860 } else {
861 last_not = 1;
862 }
863 } else { /* and, or */
864 f_exp++;
865 /* not a not operation */
866 last_not = 0;
867 }
868 i += r;
869 } else {
870 f_size++;
871 last_not = 0;
872 }
873 expr_size++;
874
875 while (!isspace(c[i])) {
876 if (!c[i] || c[i] == ')') {
877 i--;
878 break;
879 }
880 i++;
881 }
882 }
883 if (j || f_exp != f_size) {
884 /* not matching count of ( and ) */
885 LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
886 "Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", value);
887 return LY_EVALID;
888 }
889
890 if (checkversion || expr_size > 1) {
891 /* check that we have 1.1 module */
892 if (ctx->mod->version != LYS_VERSION_1_1) {
893 LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
894 "Invalid value \"%s\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", value);
895 return LY_EVALID;
896 }
897 }
898
899 /* allocate the memory */
900 iff->expr = calloc((j = (expr_size / 4) + ((expr_size % 4) ? 1 : 0)), sizeof *iff->expr);
901 iff->features = malloc(sizeof(uint32_t) + (f_size * sizeof *iff->features));
902 stack.stack = malloc(expr_size * sizeof *stack.stack);
903 LY_CHECK_ERR_GOTO(!stack.stack || !iff->expr || !iff->features, LOGMEM(ctx->mod->ctx), error);
904
905 *((uint32_t*)iff->features) = f_size;
906 stack.size = expr_size;
907 f_size--; expr_size--; /* used as indexes from now */
908
909 for (i--; i >= 0; i--) {
910 if (c[i] == ')') {
911 /* push it on stack */
912 iff_stack_push(&stack, LYS_IFF_RP);
913 continue;
914 } else if (c[i] == '(') {
915 /* pop from the stack into result all operators until ) */
916 while((op = iff_stack_pop(&stack)) != LYS_IFF_RP) {
917 iff_setop(iff->expr, op, expr_size--);
918 }
919 continue;
920 } else if (isspace(c[i])) {
921 continue;
922 }
923
924 /* end of operator or operand -> find beginning and get what is it */
925 j = i + 1;
926 while (i >= 0 && !isspace(c[i]) && c[i] != '(') {
927 i--;
928 }
929 i++; /* go back by one step */
930
931 if (!strncmp(&c[i], "not", 3) && isspace(c[i + 3])) {
932 if (stack.index && stack.stack[stack.index - 1] == LYS_IFF_NOT) {
933 /* double not */
934 iff_stack_pop(&stack);
935 } else {
936 /* not has the highest priority, so do not pop from the stack
937 * as in case of AND and OR */
938 iff_stack_push(&stack, LYS_IFF_NOT);
939 }
940 } else if (!strncmp(&c[i], "and", 3) && isspace(c[i + 3])) {
941 /* as for OR - pop from the stack all operators with the same or higher
942 * priority and store them to the result, then push the AND to the stack */
943 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_AND) {
944 op = iff_stack_pop(&stack);
945 iff_setop(iff->expr, op, expr_size--);
946 }
947 iff_stack_push(&stack, LYS_IFF_AND);
948 } else if (!strncmp(&c[i], "or", 2) && isspace(c[i + 2])) {
949 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_OR) {
950 op = iff_stack_pop(&stack);
951 iff_setop(iff->expr, op, expr_size--);
952 }
953 iff_stack_push(&stack, LYS_IFF_OR);
954 } else {
955 /* feature name, length is j - i */
956
957 /* add it to the expression */
958 iff_setop(iff->expr, LYS_IFF_F, expr_size--);
959
960 /* now get the link to the feature definition */
961 f = lysc_feature_find(ctx->mod, &c[i], j - i);
962 LY_CHECK_ERR_GOTO(!f,
963 LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
964 "Invalid value \"%s\" of if-feature - unable to find feature \"%.*s\".", value, j - i, &c[i]);
965 rc = LY_EINVAL,
966 error)
967 *(LY_ARRAY_INDEX(iff->features, f_size, struct lysc_feature*)) = f;
968 if (parent) {
969 /* and add itself into the dependants list */
970 //LYSP_ARRAY_NEW_RET(ctx->mod->ctx, f->depfeatures, df, LY_EMEM);
971 if (!(f->depfeatures)) {
972 f->depfeatures = malloc(sizeof(uint32_t) + sizeof *(f->depfeatures));
973 *((uint32_t*)(f->depfeatures)) = 1;
974 } else {
975 ++(*((uint32_t*)(f->depfeatures)));
976 f->depfeatures = ly_realloc(f->depfeatures,
977 sizeof(uint32_t) + (*((uint32_t*)(f->depfeatures)) * sizeof *(f->depfeatures)));
978 if (!(f->depfeatures)) {
979 ly_log(ctx->mod->ctx, LY_LLERR, LY_EMEM, "Memory allocation failed (%s()).", __func__);
980 return LY_EMEM;
981 };
982 }
983 (df) = (void*)((uint32_t*)((f->depfeatures) + *((uint32_t*)(f->depfeatures)) - 1) + 1);
984 memset(df, 0, sizeof *(df));
985
986 *df = parent;
987
988 /* TODO check for circular dependency */
989 }
990 f_size--;
991 }
992 }
993 while (stack.index) {
994 op = iff_stack_pop(&stack);
995 iff_setop(iff->expr, op, expr_size--);
996 }
997
998 if (++expr_size || ++f_size) {
999 /* not all expected operators and operands found */
1000 LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1001 "Invalid value \"%s\" of if-feature - processing error.", value);
1002 rc = LY_EINT;
1003 } else {
1004 rc = LY_SUCCESS;
1005 }
1006
1007error:
1008 /* cleanup */
1009 iff_stack_clean(&stack);
1010
1011 return rc;
1012}
1013
1014static LY_ERR
1015lys_compile_feature(struct lysc_ctx *ctx, struct lysp_feature *feature_p, int options, struct lysc_feature *feature)
1016{
Radek Krejci86d106e2018-10-18 09:53:19 +02001017 unsigned int u;
1018 LY_ERR ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001019
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001020 if (options & LYSC_OPT_FREE_SP) {
1021 /* just switch the pointers */
1022 feature->name = feature_p->name;
1023 } else {
1024 /* keep refcounts correct for lysp_module_free() */
Radek Krejci86d106e2018-10-18 09:53:19 +02001025 feature->name = lydict_insert(ctx->mod->ctx, feature_p->name, 0);
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001026 }
1027 feature->flags = feature_p->flags;
1028
Radek Krejci151a5b72018-10-19 14:21:44 +02001029 if (feature_p->iffeatures) {
1030 /* allocate everything now */
1031 feature->iffeatures = calloc(1, sizeof(uint32_t) + (*((uint32_t*)(feature_p->iffeatures)) * sizeof *feature->iffeatures));
1032 *((uint32_t*)(feature->iffeatures)) = 0;
1033
1034 for (u = 0; u < LY_ARRAY_SIZE(feature_p->iffeatures); ++u) {
1035 ret = lys_compile_iffeature(ctx, *LY_ARRAY_INDEX(feature_p->iffeatures, u, const char *), options, LY_ARRAY_INDEX(feature->iffeatures, u), feature);
1036 LY_CHECK_RET(ret);
1037 ++(*((uint32_t*)(feature->iffeatures)));
1038 }
Radek Krejci86d106e2018-10-18 09:53:19 +02001039 }
1040
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001041 return LY_SUCCESS;
1042}
1043
1044LY_ERR
1045lys_compile(struct lysp_module *sp, int options, struct lysc_module **sc)
1046{
Radek Krejci86d106e2018-10-18 09:53:19 +02001047 struct lysc_ctx ctx = {0};
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001048 struct lysc_module *mod_c;
Radek Krejci151a5b72018-10-19 14:21:44 +02001049 unsigned int u;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001050 LY_ERR ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001051
1052 LY_CHECK_ARG_RET(NULL, sc, sp, sp->ctx, LY_EINVAL);
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001053
1054 if (sp->submodule) {
Radek Krejci86d106e2018-10-18 09:53:19 +02001055 LOGERR(sp->ctx, LY_EINVAL, "Submodules (%s) are not supposed to be compiled, compile only the main modules.", sp->name);
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001056 return LY_EINVAL;
1057 }
1058
Radek Krejci86d106e2018-10-18 09:53:19 +02001059 ctx.mod = mod_c = calloc(1, sizeof *mod_c);
1060 LY_CHECK_ERR_RET(!mod_c, LOGMEM(sp->ctx), LY_EMEM);
1061 mod_c->ctx = sp->ctx;
1062 mod_c->version = sp->version;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001063
1064 if (options & LYSC_OPT_FREE_SP) {
1065 /* just switch the pointers */
1066 mod_c->name = sp->name;
1067 mod_c->ns = sp->ns;
1068 mod_c->prefix = sp->prefix;
1069 } else {
1070 /* keep refcounts correct for lysp_module_free() */
Radek Krejci86d106e2018-10-18 09:53:19 +02001071 mod_c->name = lydict_insert(sp->ctx, sp->name, 0);
1072 mod_c->ns = lydict_insert(sp->ctx, sp->ns, 0);
1073 mod_c->prefix = lydict_insert(sp->ctx, sp->prefix, 0);
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001074 }
1075
1076 if (sp->features) {
Radek Krejci151a5b72018-10-19 14:21:44 +02001077 /* allocate everything now */
1078 mod_c->features = calloc(1, sizeof(uint32_t) + (*((uint32_t*)(sp->features)) * sizeof *mod_c->features));
1079 *((uint32_t*)(mod_c->features)) = 0;
1080
1081 for (u = 0; u < LY_ARRAY_SIZE(sp->features); ++u) {
1082 ret = lys_compile_feature(&ctx, LY_ARRAY_INDEX(sp->features, u), options, LY_ARRAY_INDEX(mod_c->features, u));
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001083 LY_CHECK_GOTO(ret != LY_SUCCESS, error);
Radek Krejci151a5b72018-10-19 14:21:44 +02001084 ++(*((uint32_t*)(mod_c->features)));
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001085 }
1086 }
1087
1088 if (options & LYSC_OPT_FREE_SP) {
1089 lysp_module_free_(sp, 0);
1090 }
1091
1092 (*sc) = mod_c;
1093 return LY_SUCCESS;
1094
1095error:
1096
1097 if (options & LYSC_OPT_FREE_SP) {
1098 lysc_module_free_(mod_c, 0);
1099 } else {
1100 lysc_module_free_(mod_c, 1);
1101 }
1102 return ret;
1103}
Radek Krejci86d106e2018-10-18 09:53:19 +02001104
1105const struct lys_module *
1106lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, const char *revision, int implement)
1107{
1108 struct lys_module *mod = NULL;
1109 LY_ERR ret;
1110
1111 LY_CHECK_ARG_RET(ctx, ctx, data, NULL);
1112
1113 mod = calloc(1, sizeof *mod);
1114 LY_CHECK_ERR_RET(!mod, LOGMEM(ctx), NULL);
1115
1116 switch (format) {
1117 case LYS_IN_YIN:
1118 /* TODO not yet supported
1119 mod = yin_read_module(ctx, data, revision, implement);
1120 */
1121 break;
1122 case LYS_IN_YANG:
1123 ret = yang_parse(ctx, data, &mod->parsed);
1124 LY_CHECK_RET(ret, NULL);
1125 break;
1126 default:
1127 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
1128 break;
1129 }
1130
1131 if (implement) {
1132 mod->parsed->implemented = 1;
1133 }
1134
1135 if (revision) {
1136 /* check revision of the parsed model */
1137 if (!mod->parsed->revs || strcmp(revision, LY_ARRAY_INDEX(mod->parsed->revs, 0, struct lysp_revision)->rev)) {
1138 LOGERR(ctx, LY_EINVAL, "Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
1139 mod->parsed->name, LY_ARRAY_INDEX(mod->parsed->revs, 0, struct lysp_revision)->rev, revision);
1140 lysp_module_free(mod->parsed);
1141 free(mod);
1142 return NULL;
1143 }
1144 }
1145
1146 /* check for duplicity in the context */
1147
1148 /* add into context */
1149 ly_set_add(&ctx->list, mod, LY_SET_OPT_USEASLIST);
1150
1151#if 0
1152 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
1153 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
1154 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
1155 * the anotation definitions available in the internal schema structure. There is another hack in schema
1156 * printers to do not print this internally added annotation. */
1157 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
1158 if (lyp_add_ietf_netconf_annotations(mod)) {
1159 lys_free(mod, NULL, 1, 1);
1160 return NULL;
1161 }
1162 }
1163#endif
1164
1165 return mod;
1166}
1167
1168API const struct lys_module *
1169lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1170{
1171 return lys_parse_mem_(ctx, data, format, NULL, 1);
1172}
1173
1174static void
1175lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
1176{
1177#ifdef __APPLE__
1178 char path[MAXPATHLEN];
1179#else
1180 int len;
1181 char path[PATH_MAX], proc_path[32];
1182#endif
1183
1184#ifdef __APPLE__
1185 if (fcntl(fd, F_GETPATH, path) != -1) {
1186 *filename = lydict_insert(ctx, path, 0);
1187 }
1188#else
1189 /* get URI if there is /proc */
1190 sprintf(proc_path, "/proc/self/fd/%d", fd);
1191 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
1192 *filename = lydict_insert(ctx, path, len);
1193 }
1194#endif
1195}
1196
1197const struct lys_module *
1198lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, const char *revision, int implement)
1199{
1200 const struct lys_module *mod;
1201 size_t length;
1202 char *addr;
1203
1204 LY_CHECK_ARG_RET(ctx, ctx, NULL);
1205 if (fd < 0) {
1206 LOGARG(ctx, fd);
1207 return NULL;
1208 }
1209
1210 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
1211 if (!addr) {
1212 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
1213 return NULL;
1214 }
1215
1216 mod = lys_parse_mem_(ctx, addr, format, revision, implement);
1217 ly_munmap(addr, length);
1218
1219 if (mod && !mod->parsed->filepath) {
1220 lys_parse_set_filename(ctx, &mod->parsed->filepath, fd);
1221 }
1222
1223 return mod;
1224}
1225
1226API const struct lys_module *
1227lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
1228{
1229 return lys_parse_fd_(ctx, fd, format, NULL, 1);
1230}
1231
1232API const struct lys_module *
1233lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1234{
1235 int fd;
1236 const struct lys_module *mod;
1237 const char *rev, *dot, *filename;
1238 size_t len;
1239
1240 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
1241
1242 fd = open(path, O_RDONLY);
1243 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
1244
1245 mod = lys_parse_fd(ctx, fd, format);
1246 close(fd);
1247 LY_CHECK_RET(!mod, NULL);
1248
1249 /* check that name and revision match filename */
1250 filename = strrchr(path, '/');
1251 if (!filename) {
1252 filename = path;
1253 } else {
1254 filename++;
1255 }
1256 rev = strchr(filename, '@');
1257 dot = strrchr(filename, '.');
1258
1259 /* name */
1260 len = strlen(mod->parsed->name);
1261 if (strncmp(filename, mod->parsed->name, len) ||
1262 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
1263 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, mod->parsed->name);
1264 }
1265 if (rev) {
1266 len = dot - ++rev;
1267 if (!mod->parsed->revs || len != 10 || strncmp(LY_ARRAY_INDEX(mod->parsed->revs, 0, struct lysp_revision)->rev, rev, len)) {
1268 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
1269 mod->parsed->revs ? LY_ARRAY_INDEX(mod->parsed->revs, 0, struct lysp_revision)->rev : "none");
1270 }
1271 }
1272
1273 if (!mod->parsed->filepath) {
1274 /* store URI */
1275 char rpath[PATH_MAX];
1276 if (realpath(path, rpath) != NULL) {
1277 mod->parsed->filepath = lydict_insert(ctx, rpath, 0);
1278 } else {
1279 mod->parsed->filepath = lydict_insert(ctx, path, 0);
1280 }
1281 }
1282
1283 return mod;
1284}
1285