blob: 68d44b03d9f2500d76876818d59923d5b665d354 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
Michal Vasko2d162e12015-09-24 14:33:29 +02002 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02004 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02005 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * 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
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
Radek Krejci54f6fb32016-02-24 12:56:39 +010014
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020015#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020016
Radek Krejci812b10a2015-05-28 16:48:25 +020017#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020018#include <ctype.h>
Radek Krejcib051f722016-02-25 15:12:21 +010019#include <limits.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010022#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010024#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020025#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010026#include <unistd.h>
27#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020028
29#include "common.h"
30#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020031#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020032#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010033#include "xml.h"
Michal Vasko5b3492c2016-07-20 09:37:40 +020034#include "xpath.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020035#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020037#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010038#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020039
Radek Krejci8d6b7422017-02-03 14:42:13 +010040static int lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vasko1c007172017-03-10 10:20:44 +010041 int in_grp, struct unres_schema *unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020042
Radek Krejci9ff0a922016-07-14 13:08:05 +020043API const struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010044lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020045{
Radek Krejci9ff0a922016-07-14 13:08:05 +020046 int i;
Radek Krejci48061fb2015-08-05 15:41:07 +020047
Radek Krejci27fe55e2016-09-13 17:13:35 +020048 if (!node) {
49 return NULL;
50 }
51
Radek Krejci48061fb2015-08-05 15:41:07 +020052check:
53 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
54 /* input/output does not have if-feature, so skip them */
55
56 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020057 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci69b8d922016-07-27 13:13:41 +020058 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020059 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020060 }
61 }
62 }
63
64 if (!recursive) {
65 return NULL;
66 }
67
68 /* go through parents */
69 if (node->nodetype == LYS_AUGMENT) {
70 /* go to parent actually means go to the target node */
71 node = ((struct lys_node_augment *)node)->target;
Michal Vasko17549192017-03-13 10:19:33 +010072 if (!node) {
73 /* unresolved augment, let's say it's enabled */
74 return NULL;
75 }
Radek Krejci48061fb2015-08-05 15:41:07 +020076 } else if (node->parent) {
77 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020078 } else {
79 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020080 }
81
Radek Krejci074bf852015-08-19 14:22:16 +020082 if (recursive == 2) {
83 /* continue only if the node cannot have a data instance */
84 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
85 return NULL;
86 }
87 }
88 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020089}
90
Michal Vasko1dca6882015-10-22 14:29:42 +020091int
Michal Vasko36cbaa42015-12-14 13:15:48 +010092lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
93 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020094{
Radek Krejcic071c542016-01-27 14:57:51 +010095 const struct lys_node *node, *parent = NULL;
96 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010097 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020098
Michal Vasko36cbaa42015-12-14 13:15:48 +010099 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +0200100 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +0200101
Michal Vasko36cbaa42015-12-14 13:15:48 +0100102 /* fill the lengths in case the caller is so indifferent */
103 if (!mod_name_len) {
104 mod_name_len = strlen(mod_name);
105 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200106 if (!nam_len) {
107 nam_len = strlen(name);
108 }
109
Michal Vasko9e635ac2016-10-17 11:44:09 +0200110 while (siblings && (siblings->nodetype == LYS_USES)) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200111 siblings = siblings->child;
112 }
Michal Vasko9e635ac2016-10-17 11:44:09 +0200113 if (!siblings) {
114 /* unresolved uses */
115 return EXIT_FAILURE;
116 }
117
Michal Vasko680f8b42016-10-17 10:27:37 +0200118 if (siblings->nodetype == LYS_GROUPING) {
119 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
120 if (node->nodetype == LYS_GROUPING) {
121 /* we went through all the siblings, only groupings there - no valid sibling */
122 return EXIT_FAILURE;
123 }
124 /* update siblings to be valid */
125 siblings = node;
126 }
127
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200128 /* set parent correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100129 parent = lys_parent(siblings);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200130
Michal Vasko680f8b42016-10-17 10:27:37 +0200131 /* go up all uses */
132 while (parent && (parent->nodetype == LYS_USES)) {
133 parent = lys_parent(parent);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200134 }
135
Radek Krejcic071c542016-01-27 14:57:51 +0100136 if (!parent) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200137 /* handle situation when there is a top-level uses referencing a foreign grouping */
138 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
139 mod = lys_node_module(node);
Michal Vasko1dca6882015-10-22 14:29:42 +0200140 }
141
Radek Krejcic071c542016-01-27 14:57:51 +0100142 /* try to find the node */
143 node = NULL;
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100144 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
Radek Krejcic071c542016-01-27 14:57:51 +0100145 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100146 /* module name comparison */
147 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200148 if (!ly_strequal(node_mod_name, mod_name, 1) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100149 continue;
150 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200151
Radek Krejcic071c542016-01-27 14:57:51 +0100152 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200153 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100154 if (ret) {
155 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200156 }
Radek Krejcic071c542016-01-27 14:57:51 +0100157 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200158 }
159 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200160 }
161
162 return EXIT_FAILURE;
163}
164
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200165int
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100166lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, int nam_len,
167 LYS_NODE type, const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200168{
Michal Vasko24476fa2017-03-08 12:33:48 +0100169 const struct lys_node *node, *parent;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200170
171 assert(siblings && name);
172 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
173
Michal Vasko24476fa2017-03-08 12:33:48 +0100174 parent = lys_parent(siblings);
175 while (parent && (parent->nodetype == LYS_USES)) {
176 parent = lys_parent(parent);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200177 }
178
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200179 if (!mod) {
180 mod = siblings->module;
181 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200182
Michal Vasko4f0dad02016-02-15 14:08:23 +0100183 /* try to find the node */
184 node = NULL;
Michal Vasko24476fa2017-03-08 12:33:48 +0100185 while ((node = lys_getnext(node, parent, mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100186 if (!type || (node->nodetype & type)) {
187 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200188 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100189 continue;
190 }
191
Michal Vasko4f0dad02016-02-15 14:08:23 +0100192 /* direct name check */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100193 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100194 if (ret) {
195 *ret = node;
196 }
197 return EXIT_SUCCESS;
198 }
Radek Krejcic071c542016-01-27 14:57:51 +0100199 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200200 }
201
202 return EXIT_FAILURE;
203}
204
Michal Vasko1e62a092015-12-01 12:27:20 +0100205API const struct lys_node *
206lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200207{
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100208 const struct lys_node *next, *aug_parent;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100209 struct lys_node **snode;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200210
Michal Vasko24476fa2017-03-08 12:33:48 +0100211 if ((!parent && !module) || (parent && (parent->nodetype == LYS_USES) && !(options & LYS_GETNEXT_PARENTUSES))) {
212 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
213 return NULL;
214 }
215
Radek Krejci8bc87f62015-09-02 16:19:05 +0200216 if (!last) {
217 /* first call */
218
219 /* get know where to start */
220 if (parent) {
221 /* schema subtree */
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100222 snode = lys_child(parent, LYS_UNKNOWN);
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100223 /* do not return anything if the augment does not have any children */
224 if (!snode || ((parent->nodetype == LYS_AUGMENT) && ((*snode)->parent != parent))) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100225 return NULL;
226 }
227 next = last = *snode;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200228 } else {
229 /* top level data */
230 assert(module);
231 next = last = module->data;
232 }
Radek Krejci972724f2016-08-12 15:24:40 +0200233 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
234 /* continue with uses content */
235 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200236 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200237 /* continue after the last returned value */
238 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200239 }
240
241repeat:
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100242 if (parent && (parent->nodetype == LYS_AUGMENT) && next) {
243 /* do not return anything outside the parent augment */
244 aug_parent = next->parent;
245 do {
246 while (aug_parent && (aug_parent->nodetype != LYS_AUGMENT)) {
247 aug_parent = aug_parent->parent;
248 }
249 if (aug_parent) {
250 if (aug_parent == parent) {
251 break;
252 }
253 aug_parent = ((struct lys_node_augment *)aug_parent)->target;
254 }
255
256 } while (aug_parent);
257 if (!aug_parent) {
258 return NULL;
259 }
260 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200261 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200262 if (options & LYS_GETNEXT_WITHGROUPING) {
263 return next;
264 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200265 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200266 }
267
Radek Krejci972724f2016-08-12 15:24:40 +0200268 if (!next) { /* cover case when parent is augment */
269 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200270 /* no next element */
271 return NULL;
272 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200273 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200274 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200275 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200276 } else {
277 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200278 }
279
280 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200281 case LYS_INPUT:
282 case LYS_OUTPUT:
283 if (options & LYS_GETNEXT_WITHINOUT) {
284 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200285 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200286 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200287 } else {
288 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200289 }
Radek Krejci972724f2016-08-12 15:24:40 +0200290 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200291
Michal Vaskoa5835e92015-10-20 15:07:39 +0200292 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200293 if (options & LYS_GETNEXT_WITHCASE) {
294 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200295 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200296 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200297 } else {
298 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200299 }
Radek Krejci972724f2016-08-12 15:24:40 +0200300 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200301
Michal Vasko1dca6882015-10-22 14:29:42 +0200302 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200303 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200304 if (options & LYS_GETNEXT_WITHUSES) {
305 return next;
306 } else if (next->child) {
307 next = next->child;
308 } else {
309 next = next->next;
310 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200311 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200312
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200313 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200314 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200315 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200316 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200317 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200318 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200319 case LYS_LIST:
320 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200321 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200322
Radek Krejci972724f2016-08-12 15:24:40 +0200323 case LYS_CONTAINER:
324 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
325 if (next->child) {
326 /* go into */
327 next = next->child;
328 } else {
329 next = next->next;
330 }
331 goto repeat;
332 } else {
333 return next;
334 }
335
Radek Krejci8bc87f62015-09-02 16:19:05 +0200336 case LYS_CHOICE:
337 if (options & LYS_GETNEXT_WITHCHOICE) {
338 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200339 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200340 /* go into */
341 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200342 } else {
343 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200344 }
Radek Krejci972724f2016-08-12 15:24:40 +0200345 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200346
Radek Krejci7f40ce32015-08-12 20:38:46 +0200347 default:
348 /* we should not be here */
349 return NULL;
350 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200351}
352
Radek Krejcibf285832017-01-26 16:05:41 +0100353void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200354lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200355{
Radek Krejcif95b6292017-02-13 15:57:37 +0100356 struct lys_node *parent, *first, **pp;
Radek Krejcic071c542016-01-27 14:57:51 +0100357 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200358
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200359 if (!node) {
360 return;
361 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200363 /* unlink from data model if necessary */
364 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100365 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100366 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100367 if (main_module->data == node) {
368 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200369 }
370 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200372 /* store pointers to important nodes */
373 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200374 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200375 /* handle augments - first, unlink it from the augment parent ... */
376 if (parent->child == node) {
377 parent->child = node->next;
378 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100379
380 if (parent->flags & LYS_NOTAPPLIED) {
381 /* data are not connected in the target, so we cannot continue with the target as a parent */
382 parent = NULL;
383 } else {
384 /* data are connected in target, so we will continue with the target as a parent */
385 parent = ((struct lys_node_augment *)parent)->target;
386 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200387 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200389 /* unlink from parent */
390 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100391 if (parent->nodetype == LYS_EXT) {
392 pp = (struct lys_node **)lys_ext_complex_get_substmt(lys_snode2stmt(node->nodetype),
393 (struct lys_ext_instance_complex*)parent, NULL);
394 if (*pp == node) {
395 *pp = node->next;
396 }
397 } else if (parent->child == node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200398 parent->child = node->next;
399 }
400 node->parent = NULL;
401 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200403 /* unlink from siblings */
404 if (node->prev == node) {
405 /* there are no more siblings */
406 return;
407 }
408 if (node->next) {
409 node->next->prev = node->prev;
410 } else {
411 /* unlinking the last element */
412 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100413 if (parent->nodetype == LYS_EXT) {
414 first = *(struct lys_node **)pp;
415 } else {
416 first = parent->child;
417 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200418 } else {
419 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200420 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200421 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200422 }
423 }
424 first->prev = node->prev;
425 }
426 if (node->prev->next) {
427 node->prev->next = node->next;
428 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200429
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200430 /* clean up the unlinked element */
431 node->next = NULL;
432 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200433}
434
Michal Vasko563ef092015-09-04 13:17:23 +0200435struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100436lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200437{
438 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200439
440 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200441 /* top-level augment, look into module (uses augment is handled correctly below) */
442 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
Radek Krejci115fa882017-03-01 16:15:07 +0100443 par_iter = lys_main_module(par_iter->parent->module)->data;
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200444 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200445 break;
446 }
447 }
448
Michal Vasko6f929da2015-10-02 16:23:25 +0200449 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200450 continue;
451 }
452
453 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
454 if (!stop) {
455 stop = par_iter;
456 } else if (iter == stop) {
457 break;
458 }
459 if (iter->nodetype != LYS_GROUPING) {
460 continue;
461 }
462
Radek Krejcif8426a72015-10-31 23:14:03 +0100463 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200464 return (struct lys_node_grp *)iter;
465 }
466 }
467 }
468
Michal Vasko563ef092015-09-04 13:17:23 +0200469 return NULL;
470}
471
Radek Krejci10c760e2015-08-14 14:45:43 +0200472/*
473 * get next grouping in the root's subtree, in the
474 * first call, tha last is NULL
475 */
476static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200477lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200478{
Radek Krejci10c760e2015-08-14 14:45:43 +0200479 struct lys_node *last = (struct lys_node *)lastgrp;
480 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200481
Radek Krejci10c760e2015-08-14 14:45:43 +0200482 assert(root);
483
484 if (!last) {
485 last = root;
486 }
487
488 while (1) {
489 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
490 next = last->child;
491 } else {
492 next = NULL;
493 }
494 if (!next) {
495 if (last == root) {
496 /* we are done */
497 return NULL;
498 }
499
500 /* no children, go to siblings */
501 next = last->next;
502 }
503 while (!next) {
504 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100505 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200506 /* we are done */
507 return NULL;
508 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200509 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100510 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200511 }
512
513 if (next->nodetype == LYS_GROUPING) {
514 return (struct lys_node_grp *)next;
515 }
516
517 last = next;
518 }
519}
520
Michal Vasko0d343d12015-08-24 14:57:36 +0200521/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200522int
Radek Krejci07911992015-08-14 15:13:31 +0200523lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
524{
Michal Vasko563ef092015-09-04 13:17:23 +0200525 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200526 struct lys_node_grp *grp;
Radek Krejcif95b6292017-02-13 15:57:37 +0100527 int down, up;
Radek Krejci07911992015-08-14 15:13:31 +0200528
529 assert(node);
530
531 if (!parent) {
532 assert(module);
533 } else {
534 module = parent->module;
535 }
Radek Krejci115fa882017-03-01 16:15:07 +0100536 module = lys_main_module(module);
Radek Krejci07911992015-08-14 15:13:31 +0200537
538 switch (node->nodetype) {
539 case LYS_GROUPING:
540 /* 6.2.1, rule 6 */
541 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100542 start = *lys_child(parent, LYS_GROUPING);
543 if (!start) {
Radek Krejci07911992015-08-14 15:13:31 +0200544 down = 0;
545 start = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100546 } else {
547 down = 1;
548 }
549 if (parent->nodetype == LYS_EXT) {
550 up = 0;
551 } else {
552 up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200553 }
554 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100555 down = up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200556 start = module->data;
557 }
558 /* go up */
Radek Krejcif95b6292017-02-13 15:57:37 +0100559 if (up && lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100560 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200561 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200562 }
563 /* go down, because grouping can be defined after e.g. container in which is collision */
564 if (down) {
565 for (iter = start, stop = NULL; iter; iter = iter->prev) {
566 if (!stop) {
567 stop = start;
568 } else if (iter == stop) {
569 break;
570 }
571 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
572 continue;
573 }
574
575 grp = NULL;
576 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100577 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100578 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200579 return EXIT_FAILURE;
580 }
581 }
582 }
583 }
584 break;
585 case LYS_LEAF:
586 case LYS_LEAFLIST:
587 case LYS_LIST:
588 case LYS_CONTAINER:
589 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200590 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200591 /* 6.2.1, rule 7 */
592 if (parent) {
593 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200594 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
595 if (iter->nodetype == LYS_AUGMENT) {
596 if (((struct lys_node_augment *)iter)->target) {
597 /* augment is resolved, go up */
598 iter = ((struct lys_node_augment *)iter)->target;
599 continue;
600 }
601 /* augment is not resolved, this is the final parent */
602 break;
603 }
Radek Krejci07911992015-08-14 15:13:31 +0200604 iter = iter->parent;
605 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200606
Radek Krejci07911992015-08-14 15:13:31 +0200607 if (!iter) {
608 stop = NULL;
609 iter = module->data;
Radek Krejcif95b6292017-02-13 15:57:37 +0100610 } else if (iter->nodetype == LYS_EXT) {
611 stop = iter;
612 iter = *lys_child(iter, node->nodetype);
Radek Krejci07911992015-08-14 15:13:31 +0200613 } else {
614 stop = iter;
615 iter = iter->child;
616 }
617 } else {
618 stop = NULL;
619 iter = module->data;
620 }
621 while (iter) {
622 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
623 iter = iter->child;
624 continue;
625 }
626
Radek Krejcibf2abff2016-08-23 15:51:52 +0200627 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100628 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100629 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200630 return EXIT_FAILURE;
631 }
632 }
633
634 /* special case for choice - we must check the choice's name as
635 * well as the names of nodes under the choice
636 */
637 if (iter->nodetype == LYS_CHOICE) {
638 iter = iter->child;
639 continue;
640 }
641
642 /* go to siblings */
643 if (!iter->next) {
644 /* no sibling, go to parent's sibling */
645 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200646 /* for parent LYS_AUGMENT */
647 if (iter->parent == stop) {
648 iter = stop;
649 break;
650 }
651 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200652 if (iter && iter->next) {
653 break;
654 }
655 } while (iter != stop);
656
657 if (iter == stop) {
658 break;
659 }
660 }
661 iter = iter->next;
662 }
663 break;
664 case LYS_CASE:
665 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100666 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100667 start = *lys_child(parent, LYS_CASE);
Radek Krejcic071c542016-01-27 14:57:51 +0100668 } else {
669 start = module->data;
670 }
671
672 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200673 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200674 continue;
675 }
676
Radek Krejci749190d2016-02-18 16:26:25 +0100677 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100678 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200679 return EXIT_FAILURE;
680 }
681 }
682 break;
683 default:
684 /* no check needed */
685 break;
686 }
687
688 return EXIT_SUCCESS;
689}
690
Michal Vasko0d343d12015-08-24 14:57:36 +0200691/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200692int
Radek Krejci10c760e2015-08-14 14:45:43 +0200693lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
694{
Radek Krejcif95b6292017-02-13 15:57:37 +0100695 struct lys_node *iter, *next, **pchild;
Radek Krejci41a349b2016-10-24 19:21:59 +0200696 struct lys_node_inout *in, *out, *inout;
Radek Krejci744c2d42017-03-26 13:30:00 -0500697 struct lys_node_case *c;
698 int type, shortcase = 0;
Radek Krejcif95b6292017-02-13 15:57:37 +0100699 void *p;
700 struct lyext_substmt *info = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200702 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200703
Radek Krejci10c760e2015-08-14 14:45:43 +0200704 if (parent) {
705 type = parent->nodetype;
706 module = parent->module;
707 } else {
708 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100709 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200710 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200711 }
712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200713 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200714 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200715 case LYS_CONTAINER:
716 case LYS_LIST:
717 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100718 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200719 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200720 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200721 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200722 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
723 return EXIT_FAILURE;
724 }
725 break;
Radek Krejci76512572015-08-04 09:47:08 +0200726 case LYS_INPUT:
727 case LYS_OUTPUT:
728 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200730 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200731 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100732 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733 return EXIT_FAILURE;
734 }
735 break;
Radek Krejci76512572015-08-04 09:47:08 +0200736 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200737 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200738 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100739 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200740 return EXIT_FAILURE;
741 }
Radek Krejci744c2d42017-03-26 13:30:00 -0500742 if (child->nodetype != LYS_CASE) {
743 shortcase = 1;
744 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200745 break;
Radek Krejci76512572015-08-04 09:47:08 +0200746 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200747 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200748 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100749 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200750 return EXIT_FAILURE;
751 }
752 break;
Radek Krejci76512572015-08-04 09:47:08 +0200753 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200754 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200755 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100756 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200757 return EXIT_FAILURE;
758 }
759 break;
Radek Krejci76512572015-08-04 09:47:08 +0200760 case LYS_LEAF:
761 case LYS_LEAFLIST:
762 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200763 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100764 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vasko51e5c582017-01-19 14:16:39 +0100765 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100766 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200767 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200768 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200769 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200770 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100771 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100772 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200773 return EXIT_FAILURE;
774 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200775 break;
776 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200777 /* top level */
778 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200779 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200780 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100781 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200782 return EXIT_FAILURE;
783 }
Radek Krejcif95b6292017-02-13 15:57:37 +0100784 break;
785 case LYS_EXT:
786 /* plugin-defined */
787 p = lys_ext_complex_get_substmt(lys_snode2stmt(child->nodetype), (struct lys_ext_instance_complex*)parent, &info);
788 if (!p) {
789 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype),
790 ((struct lys_ext_instance_complex*)parent)->def->name);
791 return EXIT_FAILURE;
792 }
793 /* TODO check cardinality */
Radek Krejcic071c542016-01-27 14:57:51 +0100794 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200795 }
796
797 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200798 if (lys_check_id(child, parent, module)) {
799 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200800 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200802 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200803 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200804 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200805
Radek Krejcif95b6292017-02-13 15:57:37 +0100806 if ((child->nodetype & (LYS_INPUT | LYS_OUTPUT)) && parent->nodetype != LYS_EXT) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200807 /* replace the implicit input/output node */
808 if (child->nodetype == LYS_OUTPUT) {
809 inout = (struct lys_node_inout *)parent->child->next;
810 } else { /* LYS_INPUT */
811 inout = (struct lys_node_inout *)parent->child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200812 parent->child = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200813 }
814 if (inout->next) {
815 child->next = inout->next;
816 inout->next->prev = child;
817 inout->next = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200818 } else {
Radek Krejci41a349b2016-10-24 19:21:59 +0200819 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200820 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200821 child->prev = inout->prev;
822 if (inout->prev->next) {
823 inout->prev->next = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200824 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200825 inout->prev = (struct lys_node *)inout;
826 child->parent = parent;
827 inout->parent = NULL;
828 lys_node_free((struct lys_node *)inout, NULL, 0);
829 } else {
Radek Krejci744c2d42017-03-26 13:30:00 -0500830 if (shortcase) {
831 /* create the implicit case to allow it to serve as a target of the augments,
832 * it won't be printed, but it will be present in the tree */
833 c = calloc(1, sizeof *c);
834 c->name = lydict_insert(module->ctx, child->name, 0);
835 c->flags = LYS_IMPLICIT;
836 c->module = module;
837 c->nodetype = LYS_CASE;
838 c->prev = (struct lys_node*)c;
839 lys_node_addchild(parent, module, (struct lys_node*)c);
840 parent = (struct lys_node*)c;
841 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200842 /* connect the child correctly */
843 if (!parent) {
844 if (module->data) {
845 module->data->prev->next = child;
846 child->prev = module->data->prev;
847 module->data->prev = child;
848 } else {
849 module->data = child;
850 }
851 } else {
Radek Krejci30bfcd22017-01-27 16:54:48 +0100852 next = NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +0100853 pchild = lys_child(parent, child->nodetype);
854 assert(pchild);
855
856 if (!(*pchild)) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200857 /* the only/first child of the parent */
Radek Krejcif95b6292017-02-13 15:57:37 +0100858 *pchild = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200859 child->parent = parent;
860 iter = child;
Radek Krejci30bfcd22017-01-27 16:54:48 +0100861 } else if (type == LYS_AUGMENT) {
862 /* add a new child as a last child of the augment (no matter if applied or not) */
Radek Krejcif95b6292017-02-13 15:57:37 +0100863 for (iter = (*pchild)->prev; iter->parent != parent; iter = iter->prev);
Radek Krejci30bfcd22017-01-27 16:54:48 +0100864 next = iter->next;
865 iter->next = child;
866 child->prev = iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200867 } else {
868 /* add a new child at the end of parent's child list */
Radek Krejcif95b6292017-02-13 15:57:37 +0100869 iter = (*pchild)->prev;
Radek Krejci41a349b2016-10-24 19:21:59 +0200870 iter->next = child;
871 child->prev = iter;
872 }
873 while (iter->next) {
874 iter = iter->next;
875 iter->parent = parent;
876 }
Radek Krejci30bfcd22017-01-27 16:54:48 +0100877 if (next) {
878 /* we are in applied augment, its target has some additional nodes after the nodes from this augment */
879 iter->next = next;
880 next->prev = iter;
881 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100882 (*pchild)->prev = iter;
Radek Krejci30bfcd22017-01-27 16:54:48 +0100883 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200884 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200885 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200886
Michal Vaskoe022a562016-09-27 14:24:15 +0200887 /* check config value (but ignore them in groupings and augments) */
Radek Krejcif95b6292017-02-13 15:57:37 +0100888 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); iter = iter->parent);
Michal Vaskoe022a562016-09-27 14:24:15 +0200889 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200890 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
891 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
892 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +0100893 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200894 return EXIT_FAILURE;
895 }
896 }
897
Radek Krejci41771502016-04-14 17:52:32 +0200898 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200899 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200900 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200901 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200902 /* store it only into container or list - the only data inner nodes */
903 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
904 if (iter->flags & LYS_INCL_STATUS) {
905 /* done, someone else set it already from here */
906 break;
907 }
908 /* set flag about including status data */
909 iter->flags |= LYS_INCL_STATUS;
910 }
911 }
912 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200913
914 /* create implicit input/output nodes to have available them as possible target for augment */
915 if (child->nodetype & (LYS_RPC | LYS_ACTION)) {
916 in = calloc(1, sizeof *in);
917 in->nodetype = LYS_INPUT;
918 in->name = lydict_insert(child->module->ctx, "input", 5);
919 out = calloc(1, sizeof *out);
920 out->name = lydict_insert(child->module->ctx, "output", 6);
921 out->nodetype = LYS_OUTPUT;
922 in->module = out->module = child->module;
923 in->parent = out->parent = child;
924 in->flags = out->flags = LYS_IMPLICIT;
925 in->next = (struct lys_node *)out;
926 in->prev = (struct lys_node *)out;
927 out->prev = (struct lys_node *)in;
928 child->child = (struct lys_node *)in;
929 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200931}
932
Radek Krejcia1df1682016-04-11 14:56:59 +0200933static const struct lys_module *
934lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200935{
Radek Krejcia1df1682016-04-11 14:56:59 +0200936 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200937 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200938 unsigned int len;
Radek Krejcia68ddeb2017-02-24 12:49:44 +0100939 void *reallocated;
940 struct lys_ext_instance_complex *op;
941 struct lys_type **type;
Radek Krejcic6efdcb2017-03-01 10:07:15 +0100942 int i;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200943
Radek Krejci00a0e712016-10-26 10:24:46 +0200944 ly_err_clean(1);
Radek Krejcif347abc2016-06-22 10:18:47 +0200945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 if (!ctx || !data) {
947 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
948 return NULL;
949 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200950
Radek Krejcia1df1682016-04-11 14:56:59 +0200951 if (!internal && format == LYS_IN_YANG) {
952 /* enlarge data by 2 bytes for flex */
953 len = strlen(data);
954 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
955 if (!enlarged_data) {
956 LOGMEM;
957 return NULL;
958 }
959 memcpy(enlarged_data, data, len);
960 enlarged_data[len] = enlarged_data[len + 1] = '\0';
961 data = enlarged_data;
962 }
963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200965 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100966 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200967 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200968 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100969 mod = yang_read_module(ctx, data, 0, NULL, 1);
970 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200971 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200972 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200973 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200974 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200975
Radek Krejcia1df1682016-04-11 14:56:59 +0200976 free(enlarged_data);
Radek Krejcia68ddeb2017-02-24 12:49:44 +0100977
978 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
979 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
980 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
981 * the anotation definitions available in the internal schema structure. There is another hack in schema
982 * printers to do not print this internally added annotation. */
983 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
984 reallocated = realloc(mod->ext, (mod->ext_size + 3) * sizeof *mod->ext);
985 if (!reallocated) {
986 LOGMEM;
987 lys_free(mod, NULL, 1);
988 return NULL;
989 }
990 mod->ext = reallocated;
991 /* 1) edit-config's operation */
992 op = calloc(1, sizeof(struct lys_ext_instance_complex) + 5 * sizeof(void*) + sizeof(uint16_t));
993 mod->ext[mod->ext_size] = (struct lys_ext_instance *)op;
994 op->arg_value = lydict_insert(ctx, "operation", 9);
995 op->def = &ctx->models.list[0]->extensions[0];
996 op->ext_type = LYEXT_COMPLEX;
Radek Krejcif2a65342017-02-24 15:13:06 +0100997 op->module = op->parent = mod;
Radek Krejcia68ddeb2017-02-24 12:49:44 +0100998 op->parent_type = LYEXT_PAR_MODULE;
999 op->substmt = ((struct lyext_plugin_complex *)op->def->plugin)->substmt;
1000 op->nodetype = LYS_EXT;
1001 type = (struct lys_type**)&op->content; /* type is stored at offset 0 */
1002 *type = calloc(1, sizeof(struct lys_type));
1003 (*type)->base = LY_TYPE_ENUM;
1004 (*type)->der = ly_types[LY_TYPE_ENUM];
1005 (*type)->parent = (struct lys_tpdf *)op;
1006 (*type)->info.enums.count = 5;
1007 (*type)->info.enums.enm = calloc(5, sizeof *(*type)->info.enums.enm);
1008 (*type)->info.enums.enm[0].value = 0;
1009 (*type)->info.enums.enm[0].name = lydict_insert(ctx, "merge", 5);
1010 (*type)->info.enums.enm[1].value = 1;
1011 (*type)->info.enums.enm[1].name = lydict_insert(ctx, "replace", 7);
1012 (*type)->info.enums.enm[2].value = 2;
1013 (*type)->info.enums.enm[2].name = lydict_insert(ctx, "create", 6);
1014 (*type)->info.enums.enm[3].value = 3;
1015 (*type)->info.enums.enm[3].name = lydict_insert(ctx, "delete", 6);
1016 (*type)->info.enums.enm[4].value = 4;
1017 (*type)->info.enums.enm[4].name = lydict_insert(ctx, "remove", 6);
1018 mod->ext_size++;
1019
1020 /* 2) filter's type */
1021 op = calloc(1, sizeof(struct lys_ext_instance_complex) + 5 * sizeof(void*) + sizeof(uint16_t));
1022 mod->ext[mod->ext_size] = (struct lys_ext_instance *)op;
1023 op->arg_value = lydict_insert(ctx, "type", 4);
1024 op->def = &ctx->models.list[0]->extensions[0];
1025 op->ext_type = LYEXT_COMPLEX;
Radek Krejcif2a65342017-02-24 15:13:06 +01001026 op->module = op->parent = mod;
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001027 op->parent_type = LYEXT_PAR_MODULE;
1028 op->substmt = ((struct lyext_plugin_complex *)op->def->plugin)->substmt;
1029 op->nodetype = LYS_EXT;
1030 type = (struct lys_type**)&op->content; /* type is stored at offset 0 */
1031 *type = calloc(1, sizeof(struct lys_type));
1032 (*type)->base = LY_TYPE_ENUM;
1033 (*type)->der = ly_types[LY_TYPE_ENUM];
1034 (*type)->parent = (struct lys_tpdf *)op;
1035 (*type)->info.enums.count = 2;
1036 (*type)->info.enums.enm = calloc(2, sizeof *(*type)->info.enums.enm);
1037 (*type)->info.enums.enm[0].value = 0;
1038 (*type)->info.enums.enm[0].name = lydict_insert(ctx, "subtree", 7);
1039 (*type)->info.enums.enm[1].value = 1;
1040 (*type)->info.enums.enm[1].name = lydict_insert(ctx, "xpath", 5);
Radek Krejci69dcc4d2017-03-01 10:27:27 +01001041 for (i = mod->features_size; i > 0; i--) {
1042 if (!strcmp(mod->features[i - 1].name, "xpath")) {
Radek Krejcic6efdcb2017-03-01 10:07:15 +01001043 (*type)->info.enums.enm[1].iffeature_size = 1;
1044 (*type)->info.enums.enm[1].iffeature = calloc(1, sizeof(struct lys_feature));
1045 (*type)->info.enums.enm[1].iffeature[0].expr = malloc(sizeof(uint8_t));
1046 *(*type)->info.enums.enm[1].iffeature[0].expr = 3; /* LYS_IFF_F */
1047 (*type)->info.enums.enm[1].iffeature[0].features = malloc(sizeof(struct lys_feature*));
Radek Krejci69dcc4d2017-03-01 10:27:27 +01001048 (*type)->info.enums.enm[1].iffeature[0].features[0] = &mod->features[i - 1];
Radek Krejcic6efdcb2017-03-01 10:07:15 +01001049 break;
1050 }
1051 }
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001052 mod->ext_size++;
1053
1054 /* 3) filter's select */
1055 op = calloc(1, sizeof(struct lys_ext_instance_complex) + 5 * sizeof(void*) + sizeof(uint16_t));
1056 mod->ext[mod->ext_size] = (struct lys_ext_instance *)op;
1057 op->arg_value = lydict_insert(ctx, "select", 6);
1058 op->def = &ctx->models.list[0]->extensions[0];
1059 op->ext_type = LYEXT_COMPLEX;
Radek Krejcif2a65342017-02-24 15:13:06 +01001060 op->module = op->parent = mod;
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001061 op->parent_type = LYEXT_PAR_MODULE;
1062 op->substmt = ((struct lyext_plugin_complex *)op->def->plugin)->substmt;
1063 op->nodetype = LYS_EXT;
1064 type = (struct lys_type**)&op->content; /* type is stored at offset 0 */
1065 *type = calloc(1, sizeof(struct lys_type));
1066 (*type)->base = LY_TYPE_STRING;
1067 (*type)->der = ly_types[LY_TYPE_STRING];
1068 (*type)->parent = (struct lys_tpdf *)op;
1069 mod->ext_size++;
1070 }
1071
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001072 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001073}
1074
Radek Krejcia1df1682016-04-11 14:56:59 +02001075API const struct lys_module *
1076lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1077{
1078 return lys_parse_mem_(ctx, data, format, 0);
1079}
1080
Michal Vasko5a721fd2016-02-16 12:16:48 +01001081struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001082lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001083{
Michal Vasko5b998712017-01-26 10:34:06 +01001084 char *enlarged_data = NULL;
Michal Vasko5a721fd2016-02-16 12:16:48 +01001085 struct lys_submodule *submod = NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001086 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001088 assert(module);
1089 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001090
Michal Vasko5b998712017-01-26 10:34:06 +01001091 if (format == LYS_IN_YANG) {
1092 /* enlarge data by 2 bytes for flex */
1093 len = strlen(data);
1094 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
1095 if (!enlarged_data) {
1096 LOGMEM;
1097 return NULL;
1098 }
1099 memcpy(enlarged_data, data, len);
1100 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1101 data = enlarged_data;
1102 }
1103
Radek Krejcic071c542016-01-27 14:57:51 +01001104 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001105 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001107 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001108 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001109 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001110 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001111 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001112 submod = yang_read_submodule(module, data, 0, unres);
1113 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001114 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001115 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001116 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001117 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001118
Michal Vasko5b998712017-01-26 10:34:06 +01001119 free(enlarged_data);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001120 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001121}
1122
Michal Vasko1e62a092015-12-01 12:27:20 +01001123API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001124lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1125{
1126 int fd;
1127 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +02001128 const char *rev, *dot, *filename;
1129 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +01001130
1131 if (!ctx || !path) {
1132 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1133 return NULL;
1134 }
1135
1136 fd = open(path, O_RDONLY);
1137 if (fd == -1) {
1138 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1139 return NULL;
1140 }
1141
1142 ret = lys_parse_fd(ctx, fd, format);
1143 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001144
Radek Krejcid80c8602016-10-25 11:56:03 +02001145 if (!ret) {
1146 /* error */
1147 return NULL;
1148 }
1149
1150 /* check that name and revision match filename */
1151 filename = strrchr(path, '/');
1152 if (!filename) {
1153 filename = path;
1154 } else {
1155 filename++;
1156 }
1157 rev = strchr(filename, '@');
1158 dot = strrchr(filename, '.');
1159
1160 /* name */
1161 len = strlen(ret->name);
1162 if (strncmp(filename, ret->name, len) ||
1163 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Radek Krejcic0c82302016-10-25 14:21:33 +02001164 LOGWRN("File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +02001165 }
1166 if (rev) {
1167 len = dot - ++rev;
1168 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
1169 LOGWRN("File name \"%s\" does not match module revision \"%s\".", filename,
1170 ret->rev_size ? ret->rev[0].date : "none");
1171 }
1172 }
1173
1174 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001175 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001176 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001177 }
1178
Michal Vasko662610a2015-12-07 11:25:45 +01001179 return ret;
1180}
1181
1182API const struct lys_module *
1183lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001184{
Michal Vasko1e62a092015-12-01 12:27:20 +01001185 const struct lys_module *module;
Radek Krejci0fb11502017-01-31 16:45:42 +01001186 size_t length;
Radek Krejci63a91a92015-07-29 13:31:04 +02001187 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001188 char buf[PATH_MAX];
1189 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001190
1191 if (!ctx || fd < 0) {
1192 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1193 return NULL;
1194 }
1195
Radek Krejci0fb11502017-01-31 16:45:42 +01001196 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001197 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001198 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001199 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001200 } else if (!addr) {
1201 LOGERR(LY_EINVAL, "Empty schema file.");
Pavol Vicane36ea262015-11-12 11:57:47 +01001202 return NULL;
1203 }
Radek Krejci0fb11502017-01-31 16:45:42 +01001204
Radek Krejcia1df1682016-04-11 14:56:59 +02001205 module = lys_parse_mem_(ctx, addr, format, 1);
Radek Krejci0fb11502017-01-31 16:45:42 +01001206 lyp_munmap(addr, length);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001207
Radek Krejcia77904e2016-02-25 16:23:45 +01001208 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001209 /* get URI if there is /proc */
1210 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001211 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1212 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1213 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1214 }
1215 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001216 }
Radek Krejcib051f722016-02-25 15:12:21 +01001217 }
1218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001219 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001220}
1221
Michal Vasko5a721fd2016-02-16 12:16:48 +01001222struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001223lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001224{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001225 struct lys_submodule *submodule;
Radek Krejci0fb11502017-01-31 16:45:42 +01001226 size_t length;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001227 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001229 assert(module);
1230 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001231
Radek Krejci0fb11502017-01-31 16:45:42 +01001232 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001233 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001234 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001235 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001236 } else if (!addr) {
1237 LOGERR(LY_EINVAL, "Empty submodule schema file.");
Michal Vasko2e7241e2016-02-15 16:06:34 +01001238 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001239 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001240
Michal Vasko5b998712017-01-26 10:34:06 +01001241 /* get the main module */
1242 module = lys_main_module(module);
1243
1244 switch (format) {
1245 case LYS_IN_YIN:
1246 submodule = yin_read_submodule(module, addr, unres);
1247 break;
1248 case LYS_IN_YANG:
1249 submodule = yang_read_submodule(module, addr, 0, unres);
1250 break;
1251 default:
Michal Vasko85d41522017-02-24 09:49:16 +01001252 LOGINT;
1253 return NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001254 }
1255
Radek Krejcic645a3a2017-01-31 16:59:00 +01001256 lyp_munmap(addr, length);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001257 return submodule;
1258
Radek Krejciefaeba32015-05-27 14:30:57 +02001259}
1260
Radek Krejcibf285832017-01-26 16:05:41 +01001261int
1262lys_ext_iter(struct lys_ext_instance **ext, uint8_t ext_size, uint8_t start, LYEXT_SUBSTMT substmt)
1263{
1264 unsigned int u;
1265
1266 for (u = start; u < ext_size; u++) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001267 if (ext[u]->insubstmt == substmt) {
Radek Krejcibf285832017-01-26 16:05:41 +01001268 return u;
1269 }
1270 }
1271
1272 return -1;
1273}
1274
Radek Krejcifdc0d702017-01-23 15:58:38 +01001275/*
1276 * duplicate extension instance
1277 */
1278int
Radek Krejci8d6b7422017-02-03 14:42:13 +01001279lys_ext_dup(struct lys_module *mod, struct lys_ext_instance **orig, uint8_t size,
Radek Krejcifdc0d702017-01-23 15:58:38 +01001280 void *parent, LYEXT_PAR parent_type, struct lys_ext_instance ***new, struct unres_schema *unres)
1281{
1282 int i;
1283 uint8_t u = 0;
1284 struct lys_ext_instance **result;
1285 struct unres_ext *info, *info_orig;
1286
1287 assert(new);
1288
1289 if (!size) {
1290 if (orig) {
1291 LOGINT;
1292 return EXIT_FAILURE;
1293 }
1294 (*new) = NULL;
1295 return EXIT_SUCCESS;
1296 }
1297
1298 (*new) = result = calloc(size, sizeof *result);
1299 for (u = 0; u < size; u++) {
Radek Krejci9722c6d2017-02-03 15:39:01 +01001300 /* TODO cover complex extension instances */
1301
Radek Krejcifdc0d702017-01-23 15:58:38 +01001302 if (orig[u]) {
1303 /* resolved extension instance, just duplicate it */
Radek Krejci8de8f612017-02-16 15:03:32 +01001304 switch(orig[u]->ext_type) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001305 case LYEXT_FLAG:
1306 result[u] = malloc(sizeof(struct lys_ext_instance));
1307 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001308 case LYEXT_COMPLEX:
1309 result[u] = calloc(1, ((struct lyext_plugin_complex*)orig[u]->def->plugin)->instance_size);
Radek Krejcif95b6292017-02-13 15:57:37 +01001310 ((struct lys_ext_instance_complex*)result[u])->nodetype = LYS_EXT;
Radek Krejci9722c6d2017-02-03 15:39:01 +01001311 ((struct lys_ext_instance_complex*)result[u])->module = mod;
Radek Krejcifebdad72017-02-06 11:35:51 +01001312 ((struct lys_ext_instance_complex*)result[u])->substmt = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001313 /* TODO duplicate data in extension instance content */
1314 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001315 }
1316 /* generic part */
1317 result[u]->def = orig[u]->def;
1318 result[u]->flags = 0;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001319 result[u]->arg_value = lydict_insert(mod->ctx, orig[u]->arg_value, 0);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001320 result[u]->parent = parent;
1321 result[u]->parent_type = parent_type;
Radek Krejcifebdad72017-02-06 11:35:51 +01001322 result[u]->insubstmt = orig[u]->insubstmt;
1323 result[u]->insubstmt_index = orig[u]->insubstmt_index;
Radek Krejci8de8f612017-02-16 15:03:32 +01001324 result[u]->ext_type = orig[u]->ext_type;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001325
1326 /* extensions */
1327 orig[u]->ext = NULL;
1328 result[u]->ext_size = orig[u]->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001329 if (lys_ext_dup(mod, orig[u]->ext, orig[u]->ext_size, result[u],
Radek Krejcif0bb3602017-01-25 17:05:08 +01001330 LYEXT_PAR_EXTINST, &result[u]->ext, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001331 goto error;
1332 }
1333 } else {
1334 /* original extension is not yet resolved, so duplicate it in unres */
1335 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1336 if (i == -1) {
1337 /* extension not found in unres */
1338 LOGINT;
1339 goto error;
1340 }
1341 info_orig = unres->str_snode[i];
1342 info = malloc(sizeof *info);
1343 info->datatype = info_orig->datatype;
1344 if (info->datatype == LYS_IN_YIN) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001345 info->data.yin = lyxml_dup_elem(mod->ctx, info_orig->data.yin, NULL, 1);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001346 } /* else TODO YANG */
1347 info->parent = parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001348 info->mod = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001349 info->parent_type = parent_type;
1350 info->ext_index = u;
1351 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1352 goto error;
1353 }
1354 }
1355 }
1356
1357 return EXIT_SUCCESS;
1358
1359error:
1360 (*new) = NULL;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001361 lys_extension_instances_free(mod->ctx, result, u);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001362 return EXIT_FAILURE;
1363}
1364
Radek Krejci1d82ef62015-08-07 14:44:40 +02001365static struct lys_restr *
Radek Krejci8d6b7422017-02-03 14:42:13 +01001366lys_restr_dup(struct lys_module *mod, struct lys_restr *old, int size, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001367{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001368 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001369 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001370
Radek Krejci3733a802015-06-19 13:43:21 +02001371 if (!size) {
1372 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001373 }
Radek Krejci3733a802015-06-19 13:43:21 +02001374
1375 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001376 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001377 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001378 return NULL;
1379 }
Radek Krejci3733a802015-06-19 13:43:21 +02001380 for (i = 0; i < size; i++) {
Radek Krejci77f22b22017-01-17 15:23:03 +01001381 result[i].ext_size = old[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001382 lys_ext_dup(mod, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_RESTR, &result[i].ext, unres);
1383 result[i].expr = lydict_insert(mod->ctx, old[i].expr, 0);
1384 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1385 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1386 result[i].eapptag = lydict_insert(mod->ctx, old[i].eapptag, 0);
1387 result[i].emsg = lydict_insert(mod->ctx, old[i].emsg, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001388 }
1389
1390 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001391}
1392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001393void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001394lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001395{
1396 assert(ctx);
1397 if (!restr) {
1398 return;
1399 }
1400
Radek Krejcifccd1442017-01-16 10:26:57 +01001401 lys_extension_instances_free(ctx, restr->ext, restr->ext_size);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001402 lydict_remove(ctx, restr->expr);
1403 lydict_remove(ctx, restr->dsc);
1404 lydict_remove(ctx, restr->ref);
1405 lydict_remove(ctx, restr->eapptag);
1406 lydict_remove(ctx, restr->emsg);
1407}
1408
Pavol Vican05810b62016-11-23 14:07:22 +01001409void
Radek Krejci5323b492017-01-16 15:40:11 +01001410lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size)
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001411{
1412 uint8_t i;
1413
1414 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci5323b492017-01-16 15:40:11 +01001415 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001416 free(iffeature[i].expr);
1417 free(iffeature[i].features);
1418 }
1419 free(iffeature);
1420}
1421
Michal Vaskob84f88a2015-09-24 13:16:10 +02001422static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001423type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vasko1c007172017-03-10 10:20:44 +01001424 LY_DATA_TYPE base, int in_grp, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001425{
1426 int i;
1427
1428 switch (base) {
1429 case LY_TYPE_BINARY:
1430 if (old->info.binary.length) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001431 new->info.binary.length = lys_restr_dup(mod, old->info.binary.length, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001432 }
1433 break;
1434
1435 case LY_TYPE_BITS:
1436 new->info.bits.count = old->info.bits.count;
1437 if (new->info.bits.count) {
1438 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1439 if (!new->info.bits.bit) {
1440 LOGMEM;
1441 return -1;
1442 }
1443 for (i = 0; i < new->info.bits.count; i++) {
1444 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1445 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1446 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1447 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1448 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001449 new->info.bits.bit[i].ext_size = old->info.bits.bit[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001450 if (lys_ext_dup(mod, old->info.bits.bit[i].ext, old->info.bits.bit[i].ext_size,
Radek Krejcif0bb3602017-01-25 17:05:08 +01001451 &new->info.bits.bit[i], LYEXT_PAR_TYPE_BIT,
1452 &new->info.bits.bit[i].ext, unres)) {
1453 return -1;
1454 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001455 }
1456 }
1457 break;
1458
1459 case LY_TYPE_DEC64:
1460 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001461 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001462 if (old->info.dec64.range) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001463 new->info.dec64.range = lys_restr_dup(mod, old->info.dec64.range, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001464 }
1465 break;
1466
1467 case LY_TYPE_ENUM:
1468 new->info.enums.count = old->info.enums.count;
1469 if (new->info.enums.count) {
1470 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1471 if (!new->info.enums.enm) {
1472 LOGMEM;
1473 return -1;
1474 }
1475 for (i = 0; i < new->info.enums.count; i++) {
1476 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1477 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1478 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1479 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1480 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001481 new->info.enums.enm[i].ext_size = old->info.enums.enm[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001482 if (lys_ext_dup(mod, old->info.enums.enm[i].ext, old->info.enums.enm[i].ext_size,
Radek Krejcif0bb3602017-01-25 17:05:08 +01001483 &new->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM,
1484 &new->info.enums.enm[i].ext, unres)) {
1485 return -1;
1486 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001487 }
1488 }
1489 break;
1490
1491 case LY_TYPE_IDENT:
Michal Vaskoaffc37f2016-10-10 18:05:03 +00001492 new->info.ident.count = old->info.ident.count;
Michal Vasko878e38d2016-09-05 12:17:53 +02001493 if (old->info.ident.count) {
1494 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1495 if (!new->info.ident.ref) {
1496 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001497 return -1;
1498 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001499 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1500 } else {
1501 /* there can be several unresolved base identities, duplicate them all */
1502 i = -1;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001503 do {
1504 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1505 if (i != -1) {
1506 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1507 return -1;
1508 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001509 }
1510 --i;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001511 } while (i > -1);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001512 }
1513 break;
1514
1515 case LY_TYPE_INST:
1516 new->info.inst.req = old->info.inst.req;
1517 break;
1518
1519 case LY_TYPE_INT8:
1520 case LY_TYPE_INT16:
1521 case LY_TYPE_INT32:
1522 case LY_TYPE_INT64:
1523 case LY_TYPE_UINT8:
1524 case LY_TYPE_UINT16:
1525 case LY_TYPE_UINT32:
1526 case LY_TYPE_UINT64:
1527 if (old->info.num.range) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001528 new->info.num.range = lys_restr_dup(mod, old->info.num.range, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001529 }
1530 break;
1531
1532 case LY_TYPE_LEAFREF:
1533 if (old->info.lref.path) {
1534 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko1c007172017-03-10 10:20:44 +01001535 if (!in_grp && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001536 return -1;
1537 }
1538 }
1539 break;
1540
1541 case LY_TYPE_STRING:
1542 if (old->info.str.length) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001543 new->info.str.length = lys_restr_dup(mod, old->info.str.length, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001544 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01001545 new->info.str.patterns = lys_restr_dup(mod, old->info.str.patterns, old->info.str.pat_count, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001546 new->info.str.pat_count = old->info.str.pat_count;
1547 break;
1548
1549 case LY_TYPE_UNION:
1550 new->info.uni.count = old->info.uni.count;
1551 if (new->info.uni.count) {
1552 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1553 if (!new->info.uni.types) {
1554 LOGMEM;
1555 return -1;
1556 }
1557 for (i = 0; i < new->info.uni.count; i++) {
Michal Vasko1c007172017-03-10 10:20:44 +01001558 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), in_grp, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001559 return -1;
1560 }
1561 }
1562 }
1563 break;
1564
1565 default:
1566 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1567 break;
1568 }
1569 return EXIT_SUCCESS;
1570}
1571
1572struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001573lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
Michal Vasko1c007172017-03-10 10:20:44 +01001574 int in_grp, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001575{
1576 struct yang_type *new;
1577
1578 new = calloc(1, sizeof *new);
1579 if (!new) {
1580 LOGMEM;
1581 return NULL;
1582 }
1583 new->flags = old->flags;
1584 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001585 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001586 new->type = type;
1587 if (!new->name) {
1588 LOGMEM;
1589 goto error;
1590 }
Michal Vasko1c007172017-03-10 10:20:44 +01001591 if (type_dup(module, parent, type, old->type, new->base, in_grp, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001592 new->type->base = new->base;
1593 lys_type_free(module->ctx, new->type);
1594 memset(&new->type->info, 0, sizeof new->type->info);
1595 goto error;
1596 }
1597 return new;
1598
1599 error:
1600 free(new);
1601 return NULL;
1602}
1603
Radek Krejci43ce4b72017-01-04 11:02:38 +01001604API const void *
1605lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1606{
1607 if (!ext) {
1608 return NULL;
1609 }
1610
Radek Krejcifebdad72017-02-06 11:35:51 +01001611 switch (ext->insubstmt) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001612 case LYEXT_SUBSTMT_SELF:
1613 case LYEXT_SUBSTMT_MODIFIER:
1614 case LYEXT_SUBSTMT_VERSION:
1615 return NULL;
1616 case LYEXT_SUBSTMT_ARGUMENT:
1617 if (ext->parent_type == LYEXT_PAR_EXT) {
1618 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1619 }
1620 break;
1621 case LYEXT_SUBSTMT_BASE:
1622 if (ext->parent_type == LYEXT_PAR_TYPE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001623 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001624 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001625 return ((struct lys_ident*)ext->parent)->base[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001626 }
1627 break;
1628 case LYEXT_SUBSTMT_BELONGSTO:
1629 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1630 return ((struct lys_submodule*)ext->parent)->belongsto;
1631 }
1632 break;
1633 case LYEXT_SUBSTMT_CONFIG:
1634 case LYEXT_SUBSTMT_MANDATORY:
1635 if (ext->parent_type == LYEXT_PAR_NODE) {
1636 return &((struct lys_node*)ext->parent)->flags;
1637 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1638 return &((struct lys_deviate*)ext->parent)->flags;
1639 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1640 return &((struct lys_refine*)ext->parent)->flags;
1641 }
1642 break;
1643 case LYEXT_SUBSTMT_CONTACT:
1644 if (ext->parent_type == LYEXT_PAR_MODULE) {
1645 return ((struct lys_module*)ext->parent)->contact;
1646 }
1647 break;
1648 case LYEXT_SUBSTMT_DEFAULT:
1649 if (ext->parent_type == LYEXT_PAR_NODE) {
1650 switch (((struct lys_node*)ext->parent)->nodetype) {
1651 case LYS_LEAF:
1652 case LYS_LEAFLIST:
1653 /* in case of leaf, the index is supposed to be 0, so it will return the
1654 * correct pointer despite the leaf structure does not have dflt as array */
Radek Krejcifebdad72017-02-06 11:35:51 +01001655 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001656 case LYS_CHOICE:
1657 return ((struct lys_node_choice*)ext->parent)->dflt;
1658 default:
1659 /* internal error */
1660 break;
1661 }
1662 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1663 return ((struct lys_tpdf*)ext->parent)->dflt;
1664 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001665 return ((struct lys_deviate*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001666 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001667 return &((struct lys_refine*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001668 }
1669 break;
1670 case LYEXT_SUBSTMT_DESCRIPTION:
1671 switch (ext->parent_type) {
1672 case LYEXT_PAR_NODE:
1673 return ((struct lys_node*)ext->parent)->dsc;
1674 case LYEXT_PAR_MODULE:
1675 return ((struct lys_module*)ext->parent)->dsc;
1676 case LYEXT_PAR_IMPORT:
1677 return ((struct lys_import*)ext->parent)->dsc;
1678 case LYEXT_PAR_INCLUDE:
1679 return ((struct lys_include*)ext->parent)->dsc;
1680 case LYEXT_PAR_EXT:
1681 return ((struct lys_ext*)ext->parent)->dsc;
1682 case LYEXT_PAR_FEATURE:
1683 return ((struct lys_feature*)ext->parent)->dsc;
1684 case LYEXT_PAR_TPDF:
1685 return ((struct lys_tpdf*)ext->parent)->dsc;
1686 case LYEXT_PAR_TYPE_BIT:
1687 return ((struct lys_type_bit*)ext->parent)->dsc;
1688 case LYEXT_PAR_TYPE_ENUM:
1689 return ((struct lys_type_enum*)ext->parent)->dsc;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001690 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001691 return ((struct lys_restr*)ext->parent)->dsc;
1692 case LYEXT_PAR_WHEN:
1693 return ((struct lys_when*)ext->parent)->dsc;
1694 case LYEXT_PAR_IDENT:
1695 return ((struct lys_ident*)ext->parent)->dsc;
1696 case LYEXT_PAR_DEVIATION:
1697 return ((struct lys_deviation*)ext->parent)->dsc;
1698 case LYEXT_PAR_REVISION:
1699 return ((struct lys_revision*)ext->parent)->dsc;
1700 case LYEXT_PAR_REFINE:
1701 return ((struct lys_refine*)ext->parent)->dsc;
1702 default:
1703 break;
1704 }
1705 break;
1706 case LYEXT_SUBSTMT_ERRTAG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001707 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001708 return ((struct lys_restr*)ext->parent)->eapptag;
1709 }
1710 break;
1711 case LYEXT_SUBSTMT_ERRMSG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001712 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001713 return ((struct lys_restr*)ext->parent)->emsg;
1714 }
1715 break;
1716 case LYEXT_SUBSTMT_DIGITS:
1717 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
1718 return &((struct lys_type*)ext->parent)->info.dec64.dig;
1719 }
1720 break;
1721 case LYEXT_SUBSTMT_KEY:
1722 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1723 return ((struct lys_node_list*)ext->parent)->keys;
1724 }
1725 break;
1726 case LYEXT_SUBSTMT_MAX:
1727 if (ext->parent_type == LYEXT_PAR_NODE) {
1728 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1729 return &((struct lys_node_list*)ext->parent)->max;
1730 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1731 return &((struct lys_node_leaflist*)ext->parent)->max;
1732 }
1733 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1734 return &((struct lys_refine*)ext->parent)->mod.list.max;
1735 }
1736 break;
1737 case LYEXT_SUBSTMT_MIN:
1738 if (ext->parent_type == LYEXT_PAR_NODE) {
1739 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1740 return &((struct lys_node_list*)ext->parent)->min;
1741 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1742 return &((struct lys_node_leaflist*)ext->parent)->min;
1743 }
1744 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1745 return &((struct lys_refine*)ext->parent)->mod.list.min;
1746 }
1747 break;
1748 case LYEXT_SUBSTMT_NAMESPACE:
1749 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
1750 return ((struct lys_module*)ext->parent)->ns;
1751 }
1752 break;
1753 case LYEXT_SUBSTMT_ORDEREDBY:
1754 if (ext->parent_type == LYEXT_PAR_NODE &&
1755 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
1756 return &((struct lys_node_list*)ext->parent)->flags;
1757 }
1758 break;
1759 case LYEXT_SUBSTMT_ORGANIZATION:
1760 if (ext->parent_type == LYEXT_PAR_MODULE) {
1761 return ((struct lys_module*)ext->parent)->org;
1762 }
1763 break;
1764 case LYEXT_SUBSTMT_PATH:
1765 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1766 return ((struct lys_type*)ext->parent)->info.lref.path;
1767 }
1768 break;
1769 case LYEXT_SUBSTMT_POSITION:
1770 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
1771 return &((struct lys_type_bit*)ext->parent)->pos;
1772 }
1773 break;
1774 case LYEXT_SUBSTMT_PREFIX:
1775 if (ext->parent_type == LYEXT_PAR_MODULE) {
1776 /* covers also lys_submodule */
1777 return ((struct lys_module*)ext->parent)->prefix;
1778 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
1779 return ((struct lys_import*)ext->parent)->prefix;
1780 }
1781 break;
1782 case LYEXT_SUBSTMT_PRESENCE:
1783 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
1784 return ((struct lys_node_container*)ext->parent)->presence;
1785 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1786 return ((struct lys_refine*)ext->parent)->mod.presence;
1787 }
1788 break;
1789 case LYEXT_SUBSTMT_REFERENCE:
1790 switch (ext->parent_type) {
1791 case LYEXT_PAR_NODE:
1792 return ((struct lys_node*)ext->parent)->ref;
1793 case LYEXT_PAR_MODULE:
1794 return ((struct lys_module*)ext->parent)->ref;
1795 case LYEXT_PAR_IMPORT:
1796 return ((struct lys_import*)ext->parent)->ref;
1797 case LYEXT_PAR_INCLUDE:
1798 return ((struct lys_include*)ext->parent)->ref;
1799 case LYEXT_PAR_EXT:
1800 return ((struct lys_ext*)ext->parent)->ref;
1801 case LYEXT_PAR_FEATURE:
1802 return ((struct lys_feature*)ext->parent)->ref;
1803 case LYEXT_PAR_TPDF:
1804 return ((struct lys_tpdf*)ext->parent)->ref;
1805 case LYEXT_PAR_TYPE_BIT:
1806 return ((struct lys_type_bit*)ext->parent)->ref;
1807 case LYEXT_PAR_TYPE_ENUM:
1808 return ((struct lys_type_enum*)ext->parent)->ref;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001809 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001810 return ((struct lys_restr*)ext->parent)->ref;
1811 case LYEXT_PAR_WHEN:
1812 return ((struct lys_when*)ext->parent)->ref;
1813 case LYEXT_PAR_IDENT:
1814 return ((struct lys_ident*)ext->parent)->ref;
1815 case LYEXT_PAR_DEVIATION:
1816 return ((struct lys_deviation*)ext->parent)->ref;
1817 case LYEXT_PAR_REVISION:
1818 return ((struct lys_revision*)ext->parent)->ref;
1819 case LYEXT_PAR_REFINE:
1820 return ((struct lys_refine*)ext->parent)->ref;
1821 default:
1822 break;
1823 }
1824 break;
Radek Krejcibe336392017-02-07 10:54:24 +01001825 case LYEXT_SUBSTMT_REQINSTANCE:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001826 if (ext->parent_type == LYEXT_PAR_TYPE) {
1827 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1828 return &((struct lys_type*)ext->parent)->info.lref.req;
1829 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
1830 return &((struct lys_type*)ext->parent)->info.inst.req;
1831 }
1832 }
1833 break;
1834 case LYEXT_SUBSTMT_REVISIONDATE:
1835 if (ext->parent_type == LYEXT_PAR_IMPORT) {
1836 return ((struct lys_import*)ext->parent)->rev;
1837 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
1838 return ((struct lys_include*)ext->parent)->rev;
1839 }
1840 break;
1841 case LYEXT_SUBSTMT_STATUS:
1842 switch (ext->parent_type) {
1843 case LYEXT_PAR_NODE:
1844 case LYEXT_PAR_IDENT:
1845 case LYEXT_PAR_TPDF:
1846 case LYEXT_PAR_EXT:
1847 case LYEXT_PAR_FEATURE:
1848 case LYEXT_PAR_TYPE_ENUM:
1849 case LYEXT_PAR_TYPE_BIT:
1850 /* in all structures the flags member is at the same offset */
1851 return &((struct lys_node*)ext->parent)->flags;
1852 default:
1853 break;
1854 }
1855 break;
1856 case LYEXT_SUBSTMT_UNIQUE:
1857 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001858 return &((struct lys_deviate*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001859 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001860 return &((struct lys_node_list*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001861 }
1862 break;
1863 case LYEXT_SUBSTMT_UNITS:
1864 if (ext->parent_type == LYEXT_PAR_NODE &&
1865 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1866 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
1867 return ((struct lys_node_leaf*)ext->parent)->units;
1868 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1869 return ((struct lys_tpdf*)ext->parent)->units;
1870 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1871 return ((struct lys_deviate*)ext->parent)->units;
1872 }
1873 break;
1874 case LYEXT_SUBSTMT_VALUE:
1875 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
1876 return &((struct lys_type_enum*)ext->parent)->value;
1877 }
1878 break;
1879 case LYEXT_SUBSTMT_YINELEM:
1880 if (ext->parent_type == LYEXT_PAR_EXT) {
1881 return &((struct lys_ext*)ext->parent)->flags;
1882 }
1883 break;
1884 }
1885 LOGINT;
1886 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01001887}
1888
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001889static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001890lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vasko1c007172017-03-10 10:20:44 +01001891 int in_grp, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001892{
1893 int i;
1894
Michal Vasko1dca6882015-10-22 14:29:42 +02001895 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001896 new->base = old->base;
1897 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001898 new->parent = (struct lys_tpdf *)parent;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001899 new->ext_size = old->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001900 if (lys_ext_dup(mod, old->ext, old->ext_size, new, LYEXT_PAR_TYPE, &new->ext, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01001901 return -1;
Radek Krejcie534c132016-11-23 13:32:31 +01001902 }
Radek Krejci3733a802015-06-19 13:43:21 +02001903
Michal Vasko1c007172017-03-10 10:20:44 +01001904 i = unres_schema_find(unres, -1, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001905 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001906 /* HACK (serious one) for unres */
1907 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001908 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Michal Vasko1c007172017-03-10 10:20:44 +01001909 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, in_grp, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001910 } else {
1911 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1912 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001913 /* all these unres additions can fail even though they did not before */
Michal Vasko1c007172017-03-10 10:20:44 +01001914 if (!new->der || (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent) == -1)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001915 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001916 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001917 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001918 }
1919
Michal Vasko1c007172017-03-10 10:20:44 +01001920 return type_dup(mod, parent, new, old, new->base, in_grp, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001921}
1922
1923void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001924lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001925{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001926 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001928 assert(ctx);
1929 if (!type) {
1930 return;
1931 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001932
Michal Vasko1dca6882015-10-22 14:29:42 +02001933 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001934
Radek Krejcie534c132016-11-23 13:32:31 +01001935 lys_extension_instances_free(ctx, type->ext, type->ext_size);
1936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001937 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001938 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001939 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001940 free(type->info.binary.length);
1941 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001942 case LY_TYPE_BITS:
1943 for (i = 0; i < type->info.bits.count; i++) {
1944 lydict_remove(ctx, type->info.bits.bit[i].name);
1945 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1946 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001947 lys_iffeature_free(ctx, type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci9b15fea2017-01-23 11:31:43 +01001948 lys_extension_instances_free(ctx, type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001949 }
1950 free(type->info.bits.bit);
1951 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001952
1953 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001954 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001955 free(type->info.dec64.range);
1956 break;
1957
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001958 case LY_TYPE_ENUM:
1959 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001960 lydict_remove(ctx, type->info.enums.enm[i].name);
1961 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1962 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001963 lys_iffeature_free(ctx, type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci9b15fea2017-01-23 11:31:43 +01001964 lys_extension_instances_free(ctx, type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001965 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001966 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001967 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001968
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001969 case LY_TYPE_INT8:
1970 case LY_TYPE_INT16:
1971 case LY_TYPE_INT32:
1972 case LY_TYPE_INT64:
1973 case LY_TYPE_UINT8:
1974 case LY_TYPE_UINT16:
1975 case LY_TYPE_UINT32:
1976 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001977 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001978 free(type->info.num.range);
1979 break;
1980
Radek Krejcidc4c1412015-06-19 15:39:54 +02001981 case LY_TYPE_LEAFREF:
1982 lydict_remove(ctx, type->info.lref.path);
1983 break;
1984
Radek Krejci3733a802015-06-19 13:43:21 +02001985 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001986 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001987 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001988 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001989 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001990 }
1991 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001992 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001993
Radek Krejcie4c366b2015-07-02 10:11:31 +02001994 case LY_TYPE_UNION:
1995 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001996 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001997 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001998 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001999 break;
2000
Michal Vaskod3282192016-09-05 11:27:57 +02002001 case LY_TYPE_IDENT:
2002 free(type->info.ident.ref);
2003 break;
2004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005 default:
Michal Vaskod3282192016-09-05 11:27:57 +02002006 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002007 break;
2008 }
Radek Krejci5a065542015-05-22 15:02:07 +02002009}
2010
Radek Krejci1d82ef62015-08-07 14:44:40 +02002011static void
2012lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002013{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002014 assert(ctx);
2015 if (!tpdf) {
2016 return;
2017 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002019 lydict_remove(ctx, tpdf->name);
2020 lydict_remove(ctx, tpdf->dsc);
2021 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002022
Radek Krejci1d82ef62015-08-07 14:44:40 +02002023 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002025 lydict_remove(ctx, tpdf->units);
2026 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01002027
2028 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002029}
2030
Radek Krejci1d82ef62015-08-07 14:44:40 +02002031static struct lys_when *
Radek Krejci8d6b7422017-02-03 14:42:13 +01002032lys_when_dup(struct lys_module *mod, struct lys_when *old, struct unres_schema *unres)
Radek Krejci00768f42015-06-18 17:04:04 +02002033{
Radek Krejci76512572015-08-04 09:47:08 +02002034 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02002035
2036 if (!old) {
2037 return NULL;
2038 }
2039
2040 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01002041 if (!new) {
2042 LOGMEM;
2043 return NULL;
2044 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002045 new->cond = lydict_insert(mod->ctx, old->cond, 0);
2046 new->dsc = lydict_insert(mod->ctx, old->dsc, 0);
2047 new->ref = lydict_insert(mod->ctx, old->ref, 0);
Radek Krejcif0bb3602017-01-25 17:05:08 +01002048 new->ext_size = old->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002049 lys_ext_dup(mod, old->ext, old->ext_size, new, LYEXT_PAR_WHEN, &new->ext, unres);
Radek Krejci00768f42015-06-18 17:04:04 +02002050
2051 return new;
2052}
2053
Michal Vasko0308dd62015-10-07 09:14:40 +02002054void
Radek Krejci1d82ef62015-08-07 14:44:40 +02002055lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002056{
2057 if (!w) {
2058 return;
2059 }
2060
Radek Krejci5323b492017-01-16 15:40:11 +01002061 lys_extension_instances_free(ctx, w->ext, w->ext_size);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002062 lydict_remove(ctx, w->cond);
2063 lydict_remove(ctx, w->dsc);
2064 lydict_remove(ctx, w->ref);
2065
2066 free(w);
2067}
2068
Radek Krejcib7f5e412015-08-13 10:15:51 +02002069static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002070lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02002071{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002072 struct lys_node *next, *sub;
2073
Radek Krejcic071c542016-01-27 14:57:51 +01002074 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01002075 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002076 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002077 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002078 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002079 }
2080
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002081 lydict_remove(ctx, aug->target_name);
2082 lydict_remove(ctx, aug->dsc);
2083 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002084
Radek Krejci5323b492017-01-16 15:40:11 +01002085 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01002086 lys_extension_instances_free(ctx, aug->ext, aug->ext_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002087
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002088 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002089}
2090
Radek Krejci1d82ef62015-08-07 14:44:40 +02002091static void
2092lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02002093{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 assert(ctx);
2095 if (!ident) {
2096 return;
2097 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002098
Radek Krejci018f1f52016-08-03 16:01:20 +02002099 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02002100 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 lydict_remove(ctx, ident->name);
2102 lydict_remove(ctx, ident->dsc);
2103 lydict_remove(ctx, ident->ref);
Radek Krejci5323b492017-01-16 15:40:11 +01002104 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01002105 lys_extension_instances_free(ctx, ident->ext, ident->ext_size);
Radek Krejci6793db02015-05-22 17:49:54 +02002106
2107}
2108
Radek Krejci1d82ef62015-08-07 14:44:40 +02002109static void
2110lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002111{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002113
Radek Krejcid12f57b2015-08-06 10:43:39 +02002114 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002116 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 }
2118 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002119}
2120
Radek Krejci1d82ef62015-08-07 14:44:40 +02002121static void
Michal Vasko44fb6382016-06-29 11:12:27 +02002122lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02002123{
2124 int i;
2125
2126 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
2127 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002128 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002129 }
2130 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002131
2132 for (i = 0; i < io->must_size; i++) {
2133 lys_restr_free(ctx, &io->must[i]);
2134 }
2135 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002136}
2137
Radek Krejci1d82ef62015-08-07 14:44:40 +02002138static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02002139lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
2140{
2141 int i;
2142
2143 for (i = 0; i < notif->must_size; i++) {
2144 lys_restr_free(ctx, &notif->must[i]);
2145 }
2146 free(notif->must);
2147
2148 for (i = 0; i < notif->tpdf_size; i++) {
2149 lys_tpdf_free(ctx, &notif->tpdf[i]);
2150 }
2151 free(notif->tpdf);
2152}
2153static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02002154lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02002155{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002159 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 }
2161 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002162
Radek Krejci1d82ef62015-08-07 14:44:40 +02002163 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002164}
2165
Radek Krejci1d82ef62015-08-07 14:44:40 +02002166static void
2167lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02002168{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002170
Radek Krejci85a54be2016-10-20 12:39:56 +02002171 /* leafref backlinks */
2172 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002174 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002175 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 }
2177 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002178
Radek Krejci1d82ef62015-08-07 14:44:40 +02002179 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002180
Radek Krejci1d82ef62015-08-07 14:44:40 +02002181 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 lydict_remove(ctx, leaf->units);
2183 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002184}
2185
Radek Krejci1d82ef62015-08-07 14:44:40 +02002186static void
2187lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02002188{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002190
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002191 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002192 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002193 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002194 }
2195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002197 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 }
2199 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002200
Pavol Vican38321d02016-08-16 14:56:02 +02002201 for (i = 0; i < llist->dflt_size; i++) {
2202 lydict_remove(ctx, llist->dflt[i]);
2203 }
2204 free(llist->dflt);
2205
Radek Krejci1d82ef62015-08-07 14:44:40 +02002206 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002207
Radek Krejci1d82ef62015-08-07 14:44:40 +02002208 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002210}
2211
Radek Krejci1d82ef62015-08-07 14:44:40 +02002212static void
2213lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002214{
Radek Krejci581ce772015-11-10 17:22:40 +01002215 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 /* handle only specific parts for LY_NODE_LIST */
2218 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002219 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 }
2221 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002224 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 }
2226 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002227
Radek Krejci1d82ef62015-08-07 14:44:40 +02002228 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002231 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002232 lydict_remove(ctx, list->unique[i].expr[j]);
2233 }
2234 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 }
2236 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002239}
2240
Radek Krejci1d82ef62015-08-07 14:44:40 +02002241static void
2242lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002243{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 /* handle only specific parts for LY_NODE_CONTAINER */
2247 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002250 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 }
2252 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002255 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 }
2257 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002258
Radek Krejci1d82ef62015-08-07 14:44:40 +02002259 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002260}
2261
Radek Krejci1d82ef62015-08-07 14:44:40 +02002262static void
2263lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02002264{
2265 lydict_remove(ctx, f->name);
2266 lydict_remove(ctx, f->dsc);
2267 lydict_remove(ctx, f->ref);
Radek Krejci5323b492017-01-16 15:40:11 +01002268 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size);
Radek Krejci9de2c042016-10-19 16:53:06 +02002269 ly_set_free(f->depfeatures);
Radek Krejcie534c132016-11-23 13:32:31 +01002270 lys_extension_instances_free(ctx, f->ext, f->ext_size);
2271}
2272
2273static void
2274lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e)
2275{
2276 lydict_remove(ctx, e->name);
2277 lydict_remove(ctx, e->dsc);
2278 lydict_remove(ctx, e->ref);
2279 lydict_remove(ctx, e->argument);
2280 lys_extension_instances_free(ctx, e->ext, e->ext_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002281}
2282
Radek Krejci1d82ef62015-08-07 14:44:40 +02002283static void
Michal Vaskoff006c12016-02-17 11:15:19 +01002284lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02002285{
Radek Krejci581ce772015-11-10 17:22:40 +01002286 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002287 struct ly_ctx *ctx;
2288 struct lys_node *next, *elem;
2289
2290 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002291
2292 lydict_remove(ctx, dev->target_name);
2293 lydict_remove(ctx, dev->dsc);
2294 lydict_remove(ctx, dev->ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002295 lys_extension_instances_free(ctx, dev->ext, dev->ext_size);
Radek Krejcieb00f512015-07-01 16:44:58 +02002296
Pavol Vican64d0b762016-08-25 10:44:59 +02002297 if (!dev->deviate) {
2298 return ;
2299 }
2300
Michal Vaskoff006c12016-02-17 11:15:19 +01002301 /* the module was freed, but we only need the context from orig_node, use ours */
2302 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2303 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2304 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2305 elem->module = module;
2306
2307 LY_TREE_DFS_END(dev->orig_node, next, elem);
2308 }
2309 lys_node_free(dev->orig_node, NULL, 0);
2310 } else {
2311 /* it's just a shallow copy, freeing one node */
2312 dev->orig_node->module = module;
2313 lys_node_free(dev->orig_node, NULL, 1);
2314 }
2315
Radek Krejcieb00f512015-07-01 16:44:58 +02002316 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002317 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size);
2318
Radek Krejcid5a5c282016-08-15 15:38:08 +02002319 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002320 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002321 }
2322 free(dev->deviate[i].dflt);
2323
Radek Krejcieb00f512015-07-01 16:44:58 +02002324 lydict_remove(ctx, dev->deviate[i].units);
2325
2326 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2327 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002328 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002329 }
2330 free(dev->deviate[i].must);
2331
2332 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002333 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2334 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2335 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002336 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002337 }
2338 free(dev->deviate[i].unique);
2339 }
2340 }
2341 free(dev->deviate);
2342}
2343
Radek Krejci1d82ef62015-08-07 14:44:40 +02002344static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002345lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02002346{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002347 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002350 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 lydict_remove(ctx, uses->refine[i].dsc);
2352 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002353
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002354 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002355 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 }
2357 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002358
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002359 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002360 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002361 }
2362 free(uses->refine[i].dflt);
2363
Radek Krejcie534c132016-11-23 13:32:31 +01002364 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size);
2365
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002366 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 lydict_remove(ctx, uses->refine[i].mod.presence);
2368 }
2369 }
2370 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002372 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002373 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 }
2375 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002376
Radek Krejci1d82ef62015-08-07 14:44:40 +02002377 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002378}
2379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002381lys_node_free(struct lys_node *node, void (*private_destructor)(const struct lys_node *node, void *priv), int shallow)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002382{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002384 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002386 if (!node) {
2387 return;
2388 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002390 assert(node->module);
2391 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002393 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002394
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002395 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002396 if (node->priv && private_destructor) {
2397 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002398 }
2399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002400 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002401 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002402 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci5323b492017-01-16 15:40:11 +01002403 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002404 lydict_remove(ctx, node->dsc);
2405 lydict_remove(ctx, node->ref);
2406 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002407
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002408 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002409 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002410 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002411 }
2412 }
2413
Radek Krejcie534c132016-11-23 13:32:31 +01002414 lys_extension_instances_free(ctx, node->ext, node->ext_size);
2415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 /* specific part */
2417 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002418 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002419 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002420 break;
Radek Krejci76512572015-08-04 09:47:08 +02002421 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002422 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002423 break;
Radek Krejci76512572015-08-04 09:47:08 +02002424 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002425 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002426 break;
Radek Krejci76512572015-08-04 09:47:08 +02002427 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002428 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002429 break;
Radek Krejci76512572015-08-04 09:47:08 +02002430 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002431 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 break;
Radek Krejci76512572015-08-04 09:47:08 +02002433 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002434 case LYS_ANYDATA:
2435 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002436 break;
Radek Krejci76512572015-08-04 09:47:08 +02002437 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002438 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 break;
Radek Krejci76512572015-08-04 09:47:08 +02002440 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002441 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002442 break;
Radek Krejci76512572015-08-04 09:47:08 +02002443 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002444 /* do nothing */
2445 break;
Radek Krejci76512572015-08-04 09:47:08 +02002446 case LYS_GROUPING:
2447 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002448 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002449 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002450 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002451 case LYS_NOTIF:
2452 lys_notif_free(ctx, (struct lys_node_notif *)node);
2453 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002454 case LYS_INPUT:
2455 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02002456 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002457 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01002458 case LYS_EXT:
Michal Vasko591e0b22015-08-13 13:53:43 +02002459 case LYS_UNKNOWN:
2460 LOGINT;
2461 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 }
Radek Krejci5a065542015-05-22 15:02:07 +02002463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002464 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002465 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002466 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002467}
2468
Radek Krejci2eee5c02016-12-06 19:18:05 +01002469API struct lys_module *
2470lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002471{
2472 struct ly_ctx *ctx;
2473 int i;
2474
2475 if (!mod || mod->implemented) {
2476 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002477 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002478 }
2479
2480 ctx = mod->ctx;
2481 for (i = 0; i < ctx->models.used; i++) {
2482 if (!ctx->models.list[i]->implemented) {
2483 continue;
2484 }
2485
2486 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2487 /* we have some revision of the module implemented */
2488 return ctx->models.list[i];
2489 }
2490 }
2491
2492 /* we have no revision of the module implemented, return the module itself,
2493 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002494 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002495}
2496
2497const struct lys_module *
Radek Krejcie534c132016-11-23 13:32:31 +01002498lys_get_import_module_ns(const struct lys_module *module, const char *ns)
2499{
2500 int i;
2501
2502 assert(module && ns);
2503
Radek Krejcic789d692017-01-11 11:31:14 +01002504 if (module->type) {
2505 /* the module is actually submodule and to get the namespace, we need the main module */
2506 if (ly_strequal(((struct lys_submodule *)module)->belongsto->ns, ns, 0)) {
2507 return ((struct lys_submodule *)module)->belongsto;
2508 }
2509 } else {
2510 /* modul's own namespace */
2511 if (ly_strequal(module->ns, ns, 0)) {
2512 return module;
2513 }
Radek Krejcie534c132016-11-23 13:32:31 +01002514 }
2515
2516 /* imported modules */
2517 for (i = 0; i < module->imp_size; ++i) {
2518 if (ly_strequal(module->imp[i].module->ns, ns, 0)) {
2519 return module->imp[i].module;
2520 }
2521 }
2522
2523 return NULL;
2524}
2525
2526const struct lys_module *
Michal Vasko1e62a092015-12-01 12:27:20 +01002527lys_get_import_module(const struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len)
Michal Vasko8ce24d72015-10-21 11:27:26 +02002528{
Radek Krejcic071c542016-01-27 14:57:51 +01002529 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02002530 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002531 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002532
Michal Vaskoa7789a82016-02-11 15:42:55 +01002533 assert(!prefix || !name);
2534
Michal Vaskob6729c62015-10-21 12:09:47 +02002535 if (prefix && !pref_len) {
2536 pref_len = strlen(prefix);
2537 }
2538 if (name && !name_len) {
2539 name_len = strlen(name);
2540 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002541
Radek Krejcic4283442016-04-22 09:19:27 +02002542 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002543
2544 /* module own prefix, submodule own prefix, (sub)module own name */
2545 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2546 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002547 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002548 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002549 }
2550
Michal Vasko89563fc2016-07-28 16:19:35 +02002551 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02002552 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002553 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2554 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002555 return module->imp[i].module;
2556 }
2557 }
2558
Michal Vasko89563fc2016-07-28 16:19:35 +02002559 /* module required by a foreign grouping, deviation, or submodule */
2560 if (name) {
2561 str = strndup(name, name_len);
2562 if (!str) {
2563 LOGMEM;
2564 return NULL;
2565 }
2566 main_module = ly_ctx_get_module(module->ctx, str, NULL);
2567 free(str);
2568 return main_module;
2569 }
2570
Michal Vasko8ce24d72015-10-21 11:27:26 +02002571 return NULL;
2572}
2573
Michal Vasko13b15832015-08-19 11:04:48 +02002574/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002575static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002576module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002577{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002578 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002579 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002580 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002582 assert(module->ctx);
2583 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002584
Michal Vaskob746fff2016-02-11 11:37:50 +01002585 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002586 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002587 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002588 lydict_remove(ctx, module->imp[i].dsc);
2589 lydict_remove(ctx, module->imp[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002590 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size);
Radek Krejci225376f2016-02-16 17:36:22 +01002591 }
Radek Krejcidce51452015-06-16 15:20:08 +02002592 free(module->imp);
2593
Radek Krejcic071c542016-01-27 14:57:51 +01002594 /* submodules don't have data tree, the data nodes
2595 * are placed in the main module altogether */
2596 if (!module->type) {
2597 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002598 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002599 }
Radek Krejci21181962015-06-30 14:11:00 +02002600 }
Radek Krejci5a065542015-05-22 15:02:07 +02002601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002602 lydict_remove(ctx, module->dsc);
2603 lydict_remove(ctx, module->ref);
2604 lydict_remove(ctx, module->org);
2605 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002606 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002607
Radek Krejcieb00f512015-07-01 16:44:58 +02002608 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002609 for (i = 0; i < module->rev_size; i++) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01002610 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002611 lydict_remove(ctx, module->rev[i].dsc);
2612 lydict_remove(ctx, module->rev[i].ref);
2613 }
2614 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002615
Radek Krejcieb00f512015-07-01 16:44:58 +02002616 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002617 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002618 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002619 }
2620 module->ident_size = 0;
2621 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002622
Radek Krejcieb00f512015-07-01 16:44:58 +02002623 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002624 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002625 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002626 }
2627 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002628
Radek Krejcie534c132016-11-23 13:32:31 +01002629 /* extension instances */
2630 lys_extension_instances_free(ctx, module->ext, module->ext_size);
2631
Radek Krejcieb00f512015-07-01 16:44:58 +02002632 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002633 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002634 lydict_remove(ctx, module->inc[i].dsc);
2635 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002636 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size);
Radek Krejcic071c542016-01-27 14:57:51 +01002637 /* complete submodule free is done only from main module since
2638 * submodules propagate their includes to the main module */
2639 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002640 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002641 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002642 }
2643 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002644
Radek Krejcieb00f512015-07-01 16:44:58 +02002645 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002646 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002647 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002648 }
2649 free(module->augment);
2650
Radek Krejcieb00f512015-07-01 16:44:58 +02002651 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002652 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002653 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002654 }
2655 free(module->features);
2656
Radek Krejcieb00f512015-07-01 16:44:58 +02002657 /* deviations */
2658 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002659 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002660 }
2661 free(module->deviation);
2662
Radek Krejcie534c132016-11-23 13:32:31 +01002663 /* extensions */
2664 for (i = 0; i < module->extensions_size; i++) {
2665 lys_extension_free(ctx, &module->extensions[i]);
2666 }
2667 free(module->extensions);
2668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002669 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002670 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002671}
2672
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002673void
Michal Vaskob746fff2016-02-11 11:37:50 +01002674lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002675{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002676 if (!submodule) {
2677 return;
2678 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002680 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002681 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002683 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002684
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002685 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002686}
2687
Radek Krejci3a5501d2016-07-18 22:03:34 +02002688static int
2689ingrouping(const struct lys_node *node)
2690{
2691 const struct lys_node *iter = node;
2692 assert(node);
2693
2694 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2695 if (!iter) {
2696 return 0;
2697 } else {
2698 return 1;
2699 }
2700}
2701
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002702/*
2703 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2704 */
2705static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002706lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002707 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002708{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002709 struct lys_node *retval = NULL, *iter, *p;
Michal Vaskofe31cc02017-03-10 15:52:31 +01002710 struct lys_module *tmp_mod;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002711 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002712 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002713 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002714 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002715 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002716
Michal Vaskoc07187d2015-08-13 15:20:57 +02002717 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002718 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002719 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002720 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002721 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002722 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002723 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002724 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002725 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002726 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002727 struct lys_node_anydata *any = NULL;
2728 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002729 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002730 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002731 struct lys_node_rpc_action *rpc = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002732 struct lys_node_inout *io = NULL;
Radek Krejcic43151c2017-03-12 07:10:52 +01002733 struct lys_node_notif *ntf = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002734 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002735 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002737 /* we cannot just duplicate memory since the strings are stored in
2738 * dictionary and we need to update dictionary counters.
2739 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002740
Radek Krejci1d82ef62015-08-07 14:44:40 +02002741 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002742 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002744 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 break;
2746
Radek Krejci76512572015-08-04 09:47:08 +02002747 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002748 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002749 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002750 break;
2751
Radek Krejci76512572015-08-04 09:47:08 +02002752 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002753 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002754 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002755 break;
2756
Radek Krejci76512572015-08-04 09:47:08 +02002757 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002758 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002759 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002760 break;
2761
Radek Krejci76512572015-08-04 09:47:08 +02002762 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002763 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002764 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 break;
2766
Radek Krejci76512572015-08-04 09:47:08 +02002767 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002768 case LYS_ANYDATA:
2769 any = calloc(1, sizeof *any);
2770 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002771 break;
2772
Radek Krejci76512572015-08-04 09:47:08 +02002773 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002775 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002776 break;
2777
Radek Krejci76512572015-08-04 09:47:08 +02002778 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002780 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002781 break;
2782
Radek Krejci76512572015-08-04 09:47:08 +02002783 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002784 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002785 rpc = calloc(1, sizeof *rpc);
2786 retval = (struct lys_node *)rpc;
2787 break;
2788
Radek Krejci76512572015-08-04 09:47:08 +02002789 case LYS_INPUT:
2790 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002791 io = calloc(1, sizeof *io);
2792 retval = (struct lys_node *)io;
2793 break;
2794
Radek Krejci76512572015-08-04 09:47:08 +02002795 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002796 ntf = calloc(1, sizeof *ntf);
2797 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002798 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002800 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002801 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002802 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002803 }
Radek Krejcib388c152015-06-04 17:03:03 +02002804
Michal Vasko253035f2015-12-17 16:58:13 +01002805 if (!retval) {
2806 LOGMEM;
2807 return NULL;
2808 }
2809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002810 /*
2811 * duplicate generic part of the structure
2812 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002813 retval->name = lydict_insert(ctx, node->name, 0);
2814 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2815 retval->ref = lydict_insert(ctx, node->ref, 0);
2816 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002818 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002819 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002821 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002822
Radek Krejcif0bb3602017-01-25 17:05:08 +01002823 retval->ext_size = node->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002824 if (lys_ext_dup(module, node->ext, node->ext_size, retval, LYEXT_PAR_NODE, &retval->ext, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002825 goto error;
2826 }
2827
Radek Krejci06214042016-11-04 16:25:58 +01002828 if (node->iffeature_size) {
2829 retval->iffeature_size = node->iffeature_size;
2830 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2831 if (!retval->iffeature) {
2832 LOGMEM;
2833 goto error;
2834 }
Michal Vasko253035f2015-12-17 16:58:13 +01002835 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002836
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002837 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002838 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002839 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2840 if (size1) {
2841 /* there is something to duplicate */
2842
2843 /* duplicate compiled expression */
2844 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2845 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2846 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2847
2848 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002849 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002850 for (j = 0; (unsigned int)j < size2; j++) {
2851 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2852 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002853 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002854 /* feature is resolved in origin, so copy it
2855 * - duplication is used for instantiating groupings
2856 * and if-feature inside grouping is supposed to be
2857 * resolved inside the original grouping, so we want
2858 * to keep pointers to features from the grouping
2859 * context */
2860 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2861 } else if (rc == -1) {
2862 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002863 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002864 }
2865 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01002866
2867 /* duplicate if-feature's extensions */
2868 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002869 if (lys_ext_dup(module, node->iffeature[i].ext, node->iffeature[i].ext_size,
Radek Krejcif0bb3602017-01-25 17:05:08 +01002870 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, unres)) {
2871 goto error;
2872 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002873 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002874
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002875 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01002876 p = parent;
2877 do {
2878 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
2879 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002880 if (iter) {
2881 flags = iter->flags & LYS_CONFIG_MASK;
2882 } else {
2883 /* default */
2884 flags = LYS_CONFIG_W;
2885 }
2886
2887 switch (finalize) {
2888 case 1:
2889 /* inherit config flags */
2890 if (retval->flags & LYS_CONFIG_SET) {
2891 /* skip nodes with an explicit config value */
2892 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
2893 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +01002894 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002895 goto error;
2896 }
2897 break;
2898 }
2899
2900 if (retval->nodetype != LYS_USES) {
2901 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
2902 }
2903 break;
2904 case 2:
2905 /* erase config flags */
2906 retval->flags &= ~LYS_CONFIG_MASK;
2907 retval->flags &= ~LYS_CONFIG_SET;
2908 break;
2909 }
2910
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002911 /* connect it to the parent */
2912 if (lys_node_addchild(parent, retval->module, retval)) {
2913 goto error;
2914 }
Radek Krejcidce51452015-06-16 15:20:08 +02002915
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002916 /* go recursively */
2917 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002918 LY_TREE_FOR(node->child, iter) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002919 if (iter->nodetype & LYS_GROUPING) {
2920 /* do not instantiate groupings */
2921 continue;
2922 }
Radek Krejci6ff885d2017-01-03 14:06:22 +01002923 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002924 goto error;
2925 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 }
2927 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002928
2929 if (finalize == 1) {
2930 /* check that configuration lists have keys
2931 * - we really want to check keys_size in original node, because the keys are
2932 * not yet resolved here, it is done below in nodetype specific part */
2933 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
2934 && !((struct lys_node_list *)node)->keys_size) {
2935 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
2936 goto error;
2937 }
2938 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002939 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002940 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002941 }
2942
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002943 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 * duplicate specific part of the structure
2945 */
2946 switch (node->nodetype) {
2947 case LYS_CONTAINER:
2948 if (cont_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002949 cont->when = lys_when_dup(module, cont_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002950 }
2951 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002953 cont->must_size = cont_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002954 cont->must = lys_restr_dup(module, cont_orig->must, cont->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955
Radek Krejcif0bb3602017-01-25 17:05:08 +01002956 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
2957
2958 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 case LYS_CHOICE:
2960 if (choice_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002961 choice->when = lys_when_dup(module, choice_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002962 }
2963
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002964 if (!shallow) {
2965 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002966 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2967 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2968 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002969 if (rc) {
2970 if (rc == EXIT_FAILURE) {
2971 LOGINT;
2972 }
2973 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002974 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002975 } else {
2976 /* useless to check return value, we don't know whether
2977 * there really wasn't any default defined or it just hasn't
2978 * been resolved, we just hope for the best :)
2979 */
2980 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002981 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002982 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002983 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002984 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 break;
2986
2987 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002988 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002989 goto error;
2990 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002991 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2992
2993 if (leaf_orig->dflt) {
2994 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vaskofe31cc02017-03-10 15:52:31 +01002995 if (!ingrouping(retval) || (leaf->type.base != LY_TYPE_LEAFREF)) {
Radek Krejci968f6942017-03-25 15:55:01 -05002996 /* problem is when it is an identityref referencing an identity from a module
2997 * and we are using the grouping in a different module */
Radek Krejcid06f5a42017-03-25 16:03:42 -05002998 if (leaf->type.base == LY_TYPE_IDENT) {
Michal Vaskofe31cc02017-03-10 15:52:31 +01002999 tmp_mod = leaf_orig->module;
3000 } else {
3001 tmp_mod = module;
3002 }
3003 if (unres_schema_add_node(tmp_mod, unres, &leaf->type, UNRES_TYPE_DFLT,
3004 (struct lys_node *)(&leaf->dflt)) == -1) {
3005 goto error;
3006 }
Michal Vasko49168a22015-08-17 16:35:41 +02003007 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003008 }
3009
3010 leaf->must_size = leaf_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01003011 leaf->must = lys_restr_dup(module, leaf_orig->must, leaf->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003012
3013 if (leaf_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01003014 leaf->when = lys_when_dup(module, leaf_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003015 }
3016 break;
3017
3018 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02003019 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02003020 goto error;
3021 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003022 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
3023
3024 llist->min = llist_orig->min;
3025 llist->max = llist_orig->max;
3026
3027 llist->must_size = llist_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01003028 llist->must = lys_restr_dup(module, llist_orig->must, llist->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029
Radek Krejci51673202016-11-01 17:00:32 +01003030 llist->dflt_size = llist_orig->dflt_size;
3031 llist->dflt = malloc(llist->dflt_size * sizeof *llist->dflt);
3032 for (i = 0; i < llist->dflt_size; i++) {
3033 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
Michal Vaskofe31cc02017-03-10 15:52:31 +01003034 if (!ingrouping(retval) || (llist->type.base != LY_TYPE_LEAFREF)) {
3035 if ((llist->type.base == LY_TYPE_IDENT) && !strchr(llist->dflt[i], ':') && (module != llist_orig->module)) {
3036 tmp_mod = llist_orig->module;
3037 } else {
3038 tmp_mod = module;
3039 }
3040 if (unres_schema_add_node(tmp_mod, unres, &llist->type, UNRES_TYPE_DFLT,
3041 (struct lys_node *)(&llist->dflt[i])) == -1) {
3042 goto error;
3043 }
Radek Krejci51673202016-11-01 17:00:32 +01003044 }
3045 }
3046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047 if (llist_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01003048 llist->when = lys_when_dup(module, llist_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003049 }
3050 break;
3051
3052 case LYS_LIST:
3053 list->min = list_orig->min;
3054 list->max = list_orig->max;
3055
3056 list->must_size = list_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01003057 list->must = lys_restr_dup(module, list_orig->must, list->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003058
Radek Krejcif0bb3602017-01-25 17:05:08 +01003059 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Michal Vasko38d01f72015-06-15 09:41:06 +02003060
Radek Krejci581ce772015-11-10 17:22:40 +01003061 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02003062 if (list->keys_size) {
3063 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejci5c08a992016-11-02 13:30:04 +01003064 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Michal Vasko253035f2015-12-17 16:58:13 +01003065 if (!list->keys) {
3066 LOGMEM;
3067 goto error;
3068 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003069
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003070 if (!shallow) {
Radek Krejci5c08a992016-11-02 13:30:04 +01003071 /* the keys are going to be resolved only if the list is instantiated in data tree, not just
3072 * in another grouping */
3073 for (iter = parent; iter && iter->nodetype != LYS_GROUPING; iter = iter->parent);
3074 if (!iter && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
3075 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003076 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003077 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003078 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02003079 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003080 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003081
Radek Krejci581ce772015-11-10 17:22:40 +01003082 list->unique_size = list_orig->unique_size;
3083 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003084 if (!list->unique) {
3085 LOGMEM;
3086 goto error;
3087 }
Radek Krejci581ce772015-11-10 17:22:40 +01003088 for (i = 0; i < list->unique_size; ++i) {
3089 list->unique[i].expr_size = list_orig->unique[i].expr_size;
3090 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01003091 if (!list->unique[i].expr) {
3092 LOGMEM;
3093 goto error;
3094 }
Radek Krejci581ce772015-11-10 17:22:40 +01003095 for (j = 0; j < list->unique[i].expr_size; j++) {
3096 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
3097
3098 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02003099 unique_info = malloc(sizeof *unique_info);
3100 unique_info->list = (struct lys_node *)list;
3101 unique_info->expr = list->unique[i].expr[j];
3102 unique_info->trg_type = &list->unique[i].trg_type;
3103 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 }
3105 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 if (list_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01003108 list->when = lys_when_dup(module, list_orig->when, unres);
Radek Krejciefaeba32015-05-27 14:30:57 +02003109 }
Radek Krejcidce51452015-06-16 15:20:08 +02003110 break;
3111
3112 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003113 case LYS_ANYDATA:
3114 any->must_size = any_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01003115 any->must = lys_restr_dup(module, any_orig->must, any->must_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003116
Radek Krejcibf2abff2016-08-23 15:51:52 +02003117 if (any_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01003118 any->when = lys_when_dup(module, any_orig->when, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003119 }
3120 break;
3121
3122 case LYS_USES:
3123 uses->grp = uses_orig->grp;
3124
3125 if (uses_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01003126 uses->when = lys_when_dup(module, uses_orig->when, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003127 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003128 /* it is not needed to duplicate refine, nor augment. They are already applied to the uses children */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003129 break;
3130
3131 case LYS_CASE:
3132 if (cs_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01003133 cs->when = lys_when_dup(module, cs_orig->when, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02003134 }
3135 break;
3136
Radek Krejci96935402016-11-04 16:27:28 +01003137 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02003138 case LYS_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 case LYS_INPUT:
3140 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02003141 case LYS_NOTIF:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003142 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003143 break;
3144
3145 default:
3146 /* LY_NODE_AUGMENT */
3147 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02003148 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003149 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003150
3151 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02003152
3153error:
3154
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003155 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02003156 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003157}
3158
Radek Krejcib3142312016-11-09 11:04:12 +01003159int
3160lys_has_xpath(const struct lys_node *node)
3161{
3162 assert(node);
3163
3164 switch (node->nodetype) {
3165 case LYS_AUGMENT:
3166 if (((struct lys_node_augment *)node)->when) {
3167 return 1;
3168 }
3169 break;
3170 case LYS_CASE:
3171 if (((struct lys_node_case *)node)->when) {
3172 return 1;
3173 }
3174 break;
3175 case LYS_CHOICE:
3176 if (((struct lys_node_choice *)node)->when) {
3177 return 1;
3178 }
3179 break;
3180 case LYS_ANYDATA:
3181 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3182 return 1;
3183 }
3184 break;
3185 case LYS_LEAF:
3186 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3187 return 1;
3188 }
3189 break;
3190 case LYS_LEAFLIST:
3191 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3192 return 1;
3193 }
3194 break;
3195 case LYS_LIST:
3196 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3197 return 1;
3198 }
3199 break;
3200 case LYS_CONTAINER:
3201 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3202 return 1;
3203 }
3204 break;
3205 case LYS_INPUT:
3206 case LYS_OUTPUT:
3207 if (((struct lys_node_inout *)node)->must_size) {
3208 return 1;
3209 }
3210 break;
3211 case LYS_NOTIF:
3212 if (((struct lys_node_notif *)node)->must_size) {
3213 return 1;
3214 }
3215 break;
3216 case LYS_USES:
3217 if (((struct lys_node_uses *)node)->when) {
3218 return 1;
3219 }
3220 break;
3221 default:
3222 /* does not have XPath */
3223 break;
3224 }
3225
3226 return 0;
3227}
3228
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003229struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003230lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003231 struct unres_schema *unres, int shallow)
3232{
3233 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003234 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003235 struct lys_node *result, *iter, *next;
3236
3237 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003238 /* get know where in schema tree we are to know what should be done during instantiation of the grouping */
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003239 for (p = parent;
3240 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3241 p = lys_parent(p));
3242 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3243 }
3244
Radek Krejci6ff885d2017-01-03 14:06:22 +01003245 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003246 if (finalize) {
3247 /* check xpath expressions in the instantiated tree */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003248 for (iter = next = result; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003249 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003250 /* invalid xpath */
3251 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003252 }
3253
3254 /* select next item */
3255 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3256 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3257 next = NULL;
3258 } else {
3259 next = iter->child;
3260 }
3261 if (!next) {
3262 /* no children, try siblings */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003263 if (iter == result) {
3264 /* we are done, no next element to process */
3265 break;
3266 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003267 next = iter->next;
3268 }
3269 while (!next) {
3270 /* parent is already processed, go to its sibling */
3271 iter = lys_parent(iter);
Radek Krejci7212e0a2017-03-08 15:58:22 +01003272 if (lys_parent(iter) == lys_parent(result)) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003273 /* we are done, no next element to process */
3274 break;
3275 }
3276 next = iter->next;
3277 }
3278 }
3279 }
3280
3281 return result;
3282}
3283
Michal Vasko13b15832015-08-19 11:04:48 +02003284void
Michal Vaskoff006c12016-02-17 11:15:19 +01003285lys_node_switch(struct lys_node *dst, struct lys_node *src)
3286{
3287 struct lys_node *child;
3288
Michal Vaskob42b6972016-06-06 14:21:30 +02003289 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003290
3291 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02003292 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01003293 dst->prev->next = src;
3294 }
3295
3296 /* sibling prev */
3297 if (dst->next) {
3298 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02003299 } else {
3300 for (child = dst->prev; child->prev->next; child = child->prev);
3301 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003302 }
3303
3304 /* next */
3305 src->next = dst->next;
3306 dst->next = NULL;
3307
3308 /* prev */
3309 if (dst->prev != dst) {
3310 src->prev = dst->prev;
3311 }
3312 dst->prev = dst;
3313
3314 /* parent child */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003315 if (dst->parent) {
3316 if (dst->parent->child == dst) {
3317 dst->parent->child = src;
3318 }
Radek Krejci115fa882017-03-01 16:15:07 +01003319 } else if (lys_main_module(dst->module)->data == dst) {
3320 lys_main_module(dst->module)->data = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003321 }
3322
3323 /* parent */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003324 src->parent = dst->parent; dst->parent = NULL;
3325
Michal Vaskoff006c12016-02-17 11:15:19 +01003326
3327 /* child parent */
3328 LY_TREE_FOR(dst->child, child) {
3329 if (child->parent == dst) {
3330 child->parent = src;
3331 }
3332 }
3333
3334 /* child */
3335 src->child = dst->child;
3336 dst->child = NULL;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003337
3338 /* node-specific data */
3339 switch (dst->nodetype) {
3340 case LYS_CONTAINER:
3341 ((struct lys_node_container *)src)->tpdf_size = ((struct lys_node_container *)dst)->tpdf_size;
3342 ((struct lys_node_container *)src)->tpdf = ((struct lys_node_container *)dst)->tpdf;
3343 ((struct lys_node_container *)dst)->tpdf_size = 0;
3344 ((struct lys_node_container *)dst)->tpdf = NULL;
3345 break;
3346 case LYS_LIST:
3347 ((struct lys_node_list *)src)->tpdf_size = ((struct lys_node_list *)dst)->tpdf_size;
3348 ((struct lys_node_list *)src)->tpdf = ((struct lys_node_list *)dst)->tpdf;
3349 ((struct lys_node_list *)dst)->tpdf_size = 0;
3350 ((struct lys_node_list *)dst)->tpdf = NULL;
3351 break;
3352 case LYS_RPC:
3353 case LYS_ACTION:
3354 ((struct lys_node_rpc_action *)src)->tpdf_size = ((struct lys_node_rpc_action *)dst)->tpdf_size;
3355 ((struct lys_node_rpc_action *)src)->tpdf = ((struct lys_node_rpc_action *)dst)->tpdf;
3356 ((struct lys_node_rpc_action *)dst)->tpdf_size = 0;
3357 ((struct lys_node_rpc_action *)dst)->tpdf = NULL;
3358 break;
3359 case LYS_NOTIF:
3360 ((struct lys_node_notif *)src)->tpdf_size = ((struct lys_node_notif *)dst)->tpdf_size;
3361 ((struct lys_node_notif *)src)->tpdf = ((struct lys_node_notif *)dst)->tpdf;
3362 ((struct lys_node_notif *)dst)->tpdf_size = 0;
3363 ((struct lys_node_notif *)dst)->tpdf = NULL;
3364 break;
3365 case LYS_INPUT:
3366 case LYS_OUTPUT:
3367 ((struct lys_node_inout *)src)->tpdf_size = ((struct lys_node_inout *)dst)->tpdf_size;
3368 ((struct lys_node_inout *)src)->tpdf = ((struct lys_node_inout *)dst)->tpdf;
3369 ((struct lys_node_inout *)dst)->tpdf_size = 0;
3370 ((struct lys_node_inout *)dst)->tpdf = NULL;
3371 break;
3372 default:
3373 /* nothing special */
3374 break;
3375 }
3376
Michal Vaskoff006c12016-02-17 11:15:19 +01003377}
3378
3379void
Michal Vasko627975a2016-02-11 11:39:03 +01003380lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int remove_from_ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003381{
3382 struct ly_ctx *ctx;
3383 int i;
3384
3385 if (!module) {
3386 return;
3387 }
3388
3389 /* remove schema from the context */
3390 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003391 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003392 for (i = 0; i < ctx->models.used; i++) {
3393 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003394 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003395 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003396 memmove(&ctx->models.list[i], ctx->models.list[i + 1], (ctx->models.used - i) * sizeof *ctx->models.list);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003397 ctx->models.list[ctx->models.used] = NULL;
3398 /* we are done */
3399 break;
3400 }
3401 }
3402 }
3403
3404 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003405 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003406
3407 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003408 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003409
3410 free(module);
3411}
Radek Krejci7e97c352015-06-19 16:26:34 +02003412
Radek Krejci9de2c042016-10-19 16:53:06 +02003413static void
3414lys_features_disable_recursive(struct lys_feature *f)
3415{
3416 unsigned int i;
3417 struct lys_feature *depf;
3418
3419 /* disable the feature */
3420 f->flags &= ~LYS_FENABLED;
3421
3422 /* by disabling feature we have to disable also all features that depends on this feature */
3423 if (f->depfeatures) {
3424 for (i = 0; i < f->depfeatures->number; i++) {
3425 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3426 if (depf->flags & LYS_FENABLED) {
3427 lys_features_disable_recursive(depf);
3428 }
3429 }
3430 }
3431}
3432
3433
Radek Krejci7e97c352015-06-19 16:26:34 +02003434/*
3435 * op: 1 - enable, 0 - disable
3436 */
3437static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003438lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003439{
3440 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003441 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003442 int progress, faili, failj, failk;
3443
3444 uint8_t fsize;
3445 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003446
3447 if (!module || !name || !strlen(name)) {
3448 return EXIT_FAILURE;
3449 }
3450
3451 if (!strcmp(name, "*")) {
3452 /* enable all */
3453 all = 1;
3454 }
3455
Radek Krejcia889c1f2016-10-19 15:50:11 +02003456 progress = failk = 1;
3457 while (progress && failk) {
3458 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3459 if (i == -1) {
3460 fsize = module->features_size;
3461 f = module->features;
3462 } else {
3463 fsize = module->inc[i].submodule->features_size;
3464 f = module->inc[i].submodule->features;
3465 }
3466
3467 for (j = 0; j < fsize; j++) {
3468 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003469 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3470 if (all) {
3471 /* skip already set features */
3472 continue;
3473 } else {
3474 /* feature already set correctly */
3475 return EXIT_SUCCESS;
3476 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003477 }
3478
3479 if (op) {
3480 /* check referenced features if they are enabled */
3481 for (k = 0; k < f[j].iffeature_size; k++) {
3482 if (!resolve_iffeature(&f[j].iffeature[k])) {
3483 if (all) {
3484 faili = i;
3485 failj = j;
3486 failk = k + 1;
3487 break;
3488 } else {
3489 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3490 f[j].name, k + 1);
3491 return EXIT_FAILURE;
3492 }
3493 }
3494 }
3495
3496 if (k == f[j].iffeature_size) {
3497 /* the last check passed, do the change */
3498 f[j].flags |= LYS_FENABLED;
3499 progress++;
3500 }
3501 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003502 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003503 progress++;
3504 }
3505 if (!all) {
3506 /* stop in case changing a single feature */
3507 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003508 }
3509 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003510 }
3511 }
3512 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003513 if (failk) {
3514 /* print info about the last failing feature */
3515 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3516 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3517 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003518 }
3519
3520 if (all) {
3521 return EXIT_SUCCESS;
3522 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003523 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003524 return EXIT_FAILURE;
3525 }
3526}
3527
3528API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003529lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003530{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003531 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003532}
3533
3534API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003535lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003536{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003537 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003538}
3539
3540API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003541lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003542{
3543 int i, j;
3544
3545 if (!module || !feature) {
3546 return -1;
3547 }
3548
3549 /* search for the specified feature */
3550 /* module itself */
3551 for (i = 0; i < module->features_size; i++) {
3552 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003553 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003554 return 1;
3555 } else {
3556 return 0;
3557 }
3558 }
3559 }
3560
3561 /* submodules */
3562 for (j = 0; j < module->inc_size; j++) {
3563 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3564 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003565 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003566 return 1;
3567 } else {
3568 return 0;
3569 }
3570 }
3571 }
3572 }
3573
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003574 /* feature definition not found */
3575 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003576}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003577
Radek Krejci96a10da2015-07-30 11:00:14 +02003578API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003579lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003580{
Radek Krejci96a10da2015-07-30 11:00:14 +02003581 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003582 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003583 unsigned int count;
3584
3585 if (!module) {
3586 return NULL;
3587 }
3588
3589 count = module->features_size;
3590 for (i = 0; i < module->inc_size; i++) {
3591 count += module->inc[i].submodule->features_size;
3592 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003593 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01003594 if (!result) {
3595 LOGMEM;
3596 return NULL;
3597 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003598 if (states) {
3599 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01003600 if (!(*states)) {
3601 LOGMEM;
3602 free(result);
3603 return NULL;
3604 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003605 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003606 count = 0;
3607
3608 /* module itself */
3609 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003610 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003611 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003612 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003613 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003614 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003615 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003616 }
3617 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003618 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003619 }
3620
3621 /* submodules */
3622 for (j = 0; j < module->inc_size; j++) {
3623 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003624 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003625 if (states) {
3626 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3627 (*states)[count] = 1;
3628 } else {
3629 (*states)[count] = 0;
3630 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003631 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003632 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003633 }
3634 }
3635
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003636 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003637 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003638
3639 return result;
3640}
Michal Vaskobaefb032015-09-24 14:52:10 +02003641
Radek Krejci6910a032016-04-13 10:06:21 +02003642API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003643lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003644{
Michal Vaskof53187d2017-01-13 13:23:14 +01003645 if (!node) {
3646 return NULL;
3647 }
3648
Radek Krejcic071c542016-01-27 14:57:51 +01003649 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3650}
3651
Radek Krejci6910a032016-04-13 10:06:21 +02003652API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003653lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003654{
Michal Vaskof53187d2017-01-13 13:23:14 +01003655 if (!module) {
3656 return NULL;
3657 }
3658
Michal Vasko320e8532016-02-15 13:11:57 +01003659 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3660}
3661
Michal Vaskobaefb032015-09-24 14:52:10 +02003662API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003663lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003664{
Radek Krejcif95b6292017-02-13 15:57:37 +01003665 struct lys_node *parent;
3666
3667 if (!node) {
Michal Vaskobaefb032015-09-24 14:52:10 +02003668 return NULL;
3669 }
3670
Radek Krejcif95b6292017-02-13 15:57:37 +01003671 if (node->nodetype == LYS_EXT) {
3672 if (((struct lys_ext_instance_complex*)node)->parent_type != LYEXT_PAR_NODE) {
3673 return NULL;
3674 }
3675 parent = (struct lys_node*)((struct lys_ext_instance_complex*)node)->parent;
3676 } else if (!node->parent) {
3677 return NULL;
3678 } else {
3679 parent = node->parent;
Michal Vaskobaefb032015-09-24 14:52:10 +02003680 }
3681
Radek Krejcif95b6292017-02-13 15:57:37 +01003682 if (parent->nodetype == LYS_AUGMENT) {
3683 return ((struct lys_node_augment *)parent)->target;
3684 } else {
3685 return parent;
3686 }
3687}
3688
3689struct lys_node **
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01003690lys_child(const struct lys_node *node, LYS_NODE nodetype)
Radek Krejcif95b6292017-02-13 15:57:37 +01003691{
3692 void *pp;
3693 assert(node);
3694
3695 if (node->nodetype == LYS_EXT) {
3696 pp = lys_ext_complex_get_substmt(lys_snode2stmt(nodetype), (struct lys_ext_instance_complex*)node, NULL);
3697 if (!pp) {
3698 return NULL;
3699 }
3700 return (struct lys_node **)pp;
3701 } else {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01003702 return (struct lys_node **)&node->child;
Radek Krejcif95b6292017-02-13 15:57:37 +01003703 }
Michal Vaskobaefb032015-09-24 14:52:10 +02003704}
Michal Vasko1b229152016-01-13 11:28:38 +01003705
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003706API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003707lys_set_private(const struct lys_node *node, void *priv)
3708{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003709 void *prev;
3710
Michal Vasko1b229152016-01-13 11:28:38 +01003711 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003712 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
3713 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003714 }
3715
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003716 prev = node->priv;
3717 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003718
3719 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003720}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003721
Michal Vasko01c6fd22016-05-20 11:43:05 +02003722int
3723lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3724{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003725 struct lys_node_leaf *iter = leafref_target;
3726
Michal Vasko48a573d2016-07-01 11:46:02 +02003727 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003728 LOGINT;
3729 return -1;
3730 }
3731
Pavol Vican93175152016-08-30 15:34:44 +02003732 /* check for config flag */
Radek Krejcic688ca02017-03-20 12:54:39 +01003733 if (((struct lys_node_leaf*)leafref)->type.info.lref.req != -1 &&
3734 (leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
Pavol Vican93175152016-08-30 15:34:44 +02003735 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
Radek Krejcid831dd42017-03-16 12:59:30 +01003736 "The leafref %s is config but refers to a non-config %s.",
Pavol Vican93175152016-08-30 15:34:44 +02003737 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
3738 return -1;
3739 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003740 /* check for cycles */
3741 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3742 if ((void *)iter == (void *)leafref) {
3743 /* cycle detected */
3744 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3745 return -1;
3746 }
3747 iter = iter->type.info.lref.target;
3748 }
3749
3750 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003751 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02003752 if (!leafref_target->backlinks) {
3753 leafref_target->backlinks = (void*)ly_set_new();
3754 if (!leafref_target->backlinks) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003755 LOGMEM;
3756 return -1;
3757 }
3758 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003759 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003760
3761 return 0;
3762}
3763
Michal Vasko8548e082016-07-22 12:00:18 +02003764/* not needed currently */
3765#if 0
3766
Michal Vasko5b3492c2016-07-20 09:37:40 +02003767static const char *
3768lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3769{
3770 struct lys_module *prev_mod;
3771 uint32_t str_len, mod_len, buf_idx;
3772
Radek Krejcibf2abff2016-08-23 15:51:52 +02003773 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003774 LOGINT;
3775 return NULL;
3776 }
3777
3778 buf_idx = buf_len - 1;
3779 buf[buf_idx] = '\0';
3780
3781 while (node) {
3782 if (lys_parent(node)) {
3783 prev_mod = lys_node_module(lys_parent(node));
3784 } else {
3785 prev_mod = NULL;
3786 }
3787
Radek Krejcibf2abff2016-08-23 15:51:52 +02003788 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003789 str_len = strlen(node->name);
3790
3791 if (prev_mod != node->module) {
3792 mod_len = strlen(node->module->name);
3793 } else {
3794 mod_len = 0;
3795 }
3796
3797 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3798 LOGINT;
3799 return NULL;
3800 }
3801
3802 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3803
3804 buf[buf_idx] = '/';
3805 if (mod_len) {
3806 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3807 buf[buf_idx + 1 + mod_len] = ':';
3808 }
3809 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3810 }
3811
3812 node = lys_parent(node);
3813 }
3814
3815 return buf + buf_idx;
3816}
3817
Michal Vasko8548e082016-07-22 12:00:18 +02003818#endif
3819
3820API struct ly_set *
Michal Vasko2611e192017-01-23 10:33:21 +01003821lys_find_xpath(struct ly_ctx *ctx, const struct lys_node *node, const char *expr, int options)
Michal Vasko46a4bf92016-09-08 08:23:49 +02003822{
3823 struct lyxp_set set;
3824 struct ly_set *ret_set;
3825 uint32_t i;
Michal Vaskodb1da032016-09-08 10:07:38 +02003826 int opts;
Michal Vasko46a4bf92016-09-08 08:23:49 +02003827
Michal Vasko2611e192017-01-23 10:33:21 +01003828 if ((!ctx && !node) || !expr) {
Michal Vasko46a4bf92016-09-08 08:23:49 +02003829 ly_errno = LY_EINVAL;
3830 return NULL;
3831 }
3832
Michal Vasko2611e192017-01-23 10:33:21 +01003833 if (!node) {
3834 node = ly_ctx_get_node(ctx, NULL, "/ietf-yang-library:modules-state");
3835 if (!node) {
3836 ly_errno = LY_EINT;
3837 return NULL;
3838 }
3839 }
3840
Michal Vasko46a4bf92016-09-08 08:23:49 +02003841 memset(&set, 0, sizeof set);
3842
Michal Vaskodb1da032016-09-08 10:07:38 +02003843 opts = LYXP_SNODE;
3844 if (options & LYS_FIND_OUTPUT) {
3845 opts |= LYXP_SNODE_OUTPUT;
3846 }
3847
Michal Vaskodb1da032016-09-08 10:07:38 +02003848 if (lyxp_atomize(expr, node, LYXP_NODE_ELEM, &set, opts)) {
Michal Vaskoc90f3ff2017-01-23 13:51:58 +01003849 /* just find a relevant node to put in path, if it fails, use the original one */
3850 for (i = 0; i < set.used; ++i) {
3851 if (set.val.snodes[i].in_ctx == 1) {
3852 node = set.val.snodes[i].snode;
3853 break;
3854 }
3855 }
Michal Vasko46a4bf92016-09-08 08:23:49 +02003856 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003857 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko46a4bf92016-09-08 08:23:49 +02003858 return NULL;
3859 }
3860
3861 ret_set = ly_set_new();
3862
3863 for (i = 0; i < set.used; ++i) {
3864 if (!set.val.snodes[i].in_ctx) {
3865 continue;
3866 }
3867 assert(set.val.snodes[i].in_ctx == 1);
3868
3869 switch (set.val.snodes[i].type) {
3870 case LYXP_NODE_ELEM:
3871 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
3872 ly_set_free(ret_set);
3873 free(set.val.snodes);
3874 return NULL;
3875 }
3876 break;
3877 default:
3878 /* ignore roots, text and attr should not ever appear */
3879 break;
3880 }
3881 }
3882
3883 free(set.val.snodes);
3884 return ret_set;
3885}
3886
3887API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02003888lys_xpath_atomize(const struct lys_node *cur_snode, enum lyxp_node_type cur_snode_type, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02003889{
Michal Vasko508a50d2016-09-07 14:50:33 +02003890 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003891 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003892 uint32_t i;
3893
Michal Vaskob94a5e42016-09-08 14:01:56 +02003894 if (!cur_snode || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02003895 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003896 }
3897
Michal Vaskob94a5e42016-09-08 14:01:56 +02003898 /* adjust the root */
3899 if ((cur_snode_type == LYXP_NODE_ROOT) || (cur_snode_type == LYXP_NODE_ROOT_CONFIG)) {
3900 do {
3901 cur_snode = lys_getnext(NULL, NULL, lys_node_module(cur_snode), 0);
3902 } while ((cur_snode_type == LYXP_NODE_ROOT_CONFIG) && (cur_snode->flags & LYS_CONFIG_R));
3903 }
3904
Michal Vasko508a50d2016-09-07 14:50:33 +02003905 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003906
3907 if (options & LYXP_MUST) {
3908 options &= ~LYXP_MUST;
3909 options |= LYXP_SNODE_MUST;
3910 } else if (options & LYXP_WHEN) {
3911 options &= ~LYXP_WHEN;
3912 options |= LYXP_SNODE_WHEN;
3913 } else {
3914 options |= LYXP_SNODE;
3915 }
3916
Michal Vasko508a50d2016-09-07 14:50:33 +02003917 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
3918 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003919 LOGVAL(LYE_SPEC, LY_VLOG_LYS, cur_snode, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02003920 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003921 }
3922
Michal Vasko8548e082016-07-22 12:00:18 +02003923 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003924
Michal Vasko508a50d2016-09-07 14:50:33 +02003925 for (i = 0; i < set.used; ++i) {
3926 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003927 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003928 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003929 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003930 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003931 return NULL;
3932 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003933 break;
3934 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003935 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003936 break;
3937 }
3938 }
3939
Michal Vasko508a50d2016-09-07 14:50:33 +02003940 free(set.val.snodes);
3941 return ret_set;
3942}
3943
3944API struct ly_set *
3945lys_node_xpath_atomize(const struct lys_node *node, int options)
3946{
3947 const struct lys_node *next, *elem, *parent, *tmp;
3948 struct lyxp_set set;
3949 struct ly_set *ret_set;
3950 uint16_t i;
3951
3952 if (!node) {
3953 return NULL;
3954 }
3955
3956 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3957 if (!parent) {
3958 /* not in input, output, or notification */
3959 return NULL;
3960 }
3961
3962 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003963 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003964 return NULL;
3965 }
3966
3967 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003968 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_XPATH_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003969 /* elem has no dependencies from other subtrees and local nodes get discarded */
3970 goto next_iter;
3971 }
3972
Michal Vasko769f8032017-01-24 13:11:55 +01003973 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003974 ly_set_free(ret_set);
3975 free(set.val.snodes);
3976 return NULL;
3977 }
3978
3979 for (i = 0; i < set.used; ++i) {
3980 switch (set.val.snodes[i].type) {
3981 case LYXP_NODE_ELEM:
3982 if (options & LYXP_NO_LOCAL) {
3983 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3984 if (tmp) {
3985 /* in local subtree, discard */
3986 break;
3987 }
3988 }
3989 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3990 ly_set_free(ret_set);
3991 free(set.val.snodes);
3992 return NULL;
3993 }
3994 break;
3995 default:
3996 /* ignore roots, text and attr should not ever appear */
3997 break;
3998 }
3999 }
4000
4001 free(set.val.snodes);
4002 if (!(options & LYXP_RECURSIVE)) {
4003 break;
4004 }
4005next_iter:
4006 LY_TREE_DFS_END(node, next, elem);
4007 }
4008
Michal Vasko8548e082016-07-22 12:00:18 +02004009 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004010}
4011
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004012static void
Radek Krejci0ec51da2016-12-14 16:42:03 +01004013apply_aug(struct lys_node_augment *augment)
4014{
4015 struct lys_node *last;
4016
4017 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
4018
4019 /* reconnect augmenting data into the target - add them to the target child list */
4020 if (augment->target->child) {
4021 last = augment->target->child->prev;
4022 last->next = augment->child;
4023 augment->target->child->prev = augment->child->prev;
4024 augment->child->prev = last;
4025 } else {
4026 augment->target->child = augment->child;
4027 }
4028
4029 /* remove the flag about not applicability */
4030 augment->flags &= ~LYS_NOTAPPLIED;
4031}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004032
Radek Krejcib2541a32016-12-12 16:45:57 +01004033static void
4034remove_aug(struct lys_node_augment *augment)
4035{
4036 struct lys_node *last, *elem;
4037
Radek Krejci9086a7e2017-03-25 13:20:21 -05004038 if (!augment->target || (augment->flags & LYS_NOTAPPLIED)) {
4039 /* skip not resolved augments OR already not applied augment */
Radek Krejcib2541a32016-12-12 16:45:57 +01004040 return;
4041 }
4042
4043 elem = augment->child;
4044 if (elem) {
4045 LY_TREE_FOR(elem, last) {
4046 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
4047 break;
4048 }
4049 }
4050 /* elem is first augment child, last is the last child */
4051
4052 /* parent child ptr */
4053 if (augment->target->child == elem) {
4054 augment->target->child = last->next;
4055 }
4056
4057 /* parent child next ptr */
4058 if (elem->prev->next) {
4059 elem->prev->next = last->next;
4060 }
4061
4062 /* parent child prev ptr */
4063 if (last->next) {
4064 last->next->prev = elem->prev;
4065 } else if (augment->target->child) {
4066 augment->target->child->prev = elem->prev;
4067 }
4068
4069 /* update augment children themselves */
4070 elem->prev = last;
4071 last->next = NULL;
4072 }
4073
Radek Krejci0ec51da2016-12-14 16:42:03 +01004074 /* augment->target still keeps the resolved target, but for lys_augment_free()
4075 * we have to keep information that this augment is not applied to free its data */
4076 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01004077}
4078
Radek Krejci30bfcd22017-01-27 16:54:48 +01004079/*
4080 * @param[in] module - the module where the deviation is defined
4081 */
4082static void
4083lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module)
4084{
4085 int ret;
4086 char *parent_path;
4087 struct lys_node *target = NULL, *parent;
4088
4089 if (!dev->deviate) {
4090 return ;
4091 }
4092
4093 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
4094 if (dev->orig_node) {
4095 /* removing not-supported deviation ... */
4096 if (strrchr(dev->target_name, '/') != dev->target_name) {
4097 /* ... from a parent */
4098
4099 /* reconnect to its previous position */
4100 parent = dev->orig_node->parent;
4101 if (parent) {
4102 /* the original node was actually from augment, we have to get know if the augment is
4103 * applied (its module is enabled and implemented). If yes, the node will be connected
4104 * to the augment and the linkage with the target will be fixed if needed, otherwise
4105 * it will be connected only to the augment */
4106 /* first, connect it into the augment */
4107 lys_node_addchild(parent, NULL, dev->orig_node);
4108 if (!parent->module->disabled && parent->module->implemented) {
4109 /* augment is supposed to be applied, so fix pointers in target and the status of the original node */
4110 if (parent->child == dev->orig_node) {
4111 /* the only node in augment */
4112 dev->orig_node->flags |= LYS_NOTAPPLIED;
4113 apply_aug((struct lys_node_augment *)parent);
4114 } else {
4115 /* other nodes from augment applied, nothing more needed in target, everything was done
4116 * by lys_node_addchild() */
4117 dev->orig_node->flags |= parent->child->flags & LYS_NOTAPPLIED;
4118 }
4119 } else {
4120 /* augment is not supposed to be applied */
4121 dev->orig_node->flags |= LYS_NOTAPPLIED;
4122 }
4123 } else {
4124 /* non-augment, non-toplevel */
4125 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
4126 ret = resolve_augment_schema_nodeid(parent_path, NULL, module, 1,
4127 (const struct lys_node **)&target);
4128 free(parent_path);
4129 if (ret || !target) {
4130 LOGINT;
4131 return;
4132 }
4133 lys_node_addchild(target, NULL, dev->orig_node);
4134 }
4135 } else {
4136 /* ... from top-level data */
4137 lys_node_addchild(NULL, (struct lys_module *)dev->orig_node->module, dev->orig_node);
4138 }
4139
4140 dev->orig_node = NULL;
4141 } else {
4142 /* adding not-supported deviation */
4143 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1,
4144 (const struct lys_node **)&target);
4145 if (ret || !target) {
4146 LOGINT;
4147 return;
4148 }
4149
4150 /* unlink and store the original node */
4151 parent = target->parent;
4152 lys_node_unlink(target);
4153 if (parent && parent->nodetype == LYS_AUGMENT) {
4154 /* hack for augment, because when the original will be sometime reconnected back, we actually need
4155 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
4156 * path), so we need to remember the augment as an addition */
4157 target->parent = parent;
4158 }
4159 dev->orig_node = target;
4160 }
4161 } else {
4162 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1,
4163 (const struct lys_node **)&target);
4164 if (ret || !target) {
4165 LOGINT;
4166 return;
4167 }
4168
4169 lys_node_switch(target, dev->orig_node);
4170 dev->orig_node = target;
4171 }
4172}
4173
4174/* temporarily removes or applies deviations, updates module deviation flag accordingly */
4175void
4176lys_switch_deviations(struct lys_module *module)
4177{
4178 uint32_t i = 0, j;
4179 const struct lys_module *mod;
4180 const char *ptr;
4181
4182 if (module->deviated) {
4183 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
4184 if (mod == module) {
4185 continue;
4186 }
4187
4188 for (j = 0; j < mod->deviation_size; ++j) {
4189 ptr = strstr(mod->deviation[j].target_name, module->name);
4190 if (ptr && ptr[strlen(module->name)] == ':') {
4191 lys_switch_deviation(&mod->deviation[j], mod);
4192 }
4193 }
4194 }
4195
4196 if (module->deviated == 2) {
4197 module->deviated = 1;
4198 } else {
4199 module->deviated = 2;
4200 }
4201 }
4202}
4203
4204static void
4205apply_dev(struct lys_deviation *dev, const struct lys_module *module)
4206{
4207 lys_switch_deviation(dev, module);
4208
4209 assert(dev->orig_node);
4210 lys_node_module(dev->orig_node)->deviated = 1;
4211}
4212
4213static void
4214remove_dev(struct lys_deviation *dev, const struct lys_module *module)
4215{
4216 uint32_t idx = 0, j;
4217 const struct lys_module *mod;
4218 struct lys_module *target_mod;
4219 const char *ptr;
4220
4221 if (dev->orig_node) {
4222 target_mod = lys_node_module(dev->orig_node);
4223 } else {
4224 LOGINT;
4225 return;
4226 }
4227 lys_switch_deviation(dev, module);
4228
4229 /* clear the deviation flag if possible */
4230 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4231 if ((mod == module) || (mod == target_mod)) {
4232 continue;
4233 }
4234
4235 for (j = 0; j < mod->deviation_size; ++j) {
4236 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4237 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4238 /* some other module deviation targets the inspected module, flag remains */
4239 break;
4240 }
4241 }
4242
4243 if (j < mod->deviation_size) {
4244 break;
4245 }
4246 }
4247
4248 if (!mod) {
4249 target_mod->deviated = 0;
4250 }
4251}
4252
4253void
4254lys_sub_module_apply_devs_augs(struct lys_module *module)
4255{
4256 uint8_t u, v;
4257
4258 /* remove applied deviations */
4259 for (u = 0; u < module->deviation_size; ++u) {
4260 apply_dev(&module->deviation[u], module);
4261 }
4262 /* remove applied augments */
4263 for (u = 0; u < module->augment_size; ++u) {
4264 apply_aug(&module->augment[u]);
4265 }
4266
4267 /* remove deviation and augments defined in submodules */
4268 for (v = 0; v < module->inc_size; ++v) {
4269 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4270 apply_dev(&module->inc[v].submodule->deviation[u], module);
4271 }
4272
4273 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4274 apply_aug(&module->inc[v].submodule->augment[u]);
4275 }
4276 }
4277}
4278
Radek Krejcib2541a32016-12-12 16:45:57 +01004279void
4280lys_sub_module_remove_devs_augs(struct lys_module *module)
4281{
4282 uint8_t u, v;
4283
4284 /* remove applied deviations */
4285 for (u = 0; u < module->deviation_size; ++u) {
4286 remove_dev(&module->deviation[u], module);
4287 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004288 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004289 for (u = 0; u < module->augment_size; ++u) {
4290 remove_aug(&module->augment[u]);
4291 }
4292
4293 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004294 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01004295 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4296 remove_dev(&module->inc[v].submodule->deviation[u], module);
Radek Krejcidbc15262016-06-16 14:58:29 +02004297 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004298
Radek Krejcib2541a32016-12-12 16:45:57 +01004299 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4300 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004301 }
4302 }
4303}
4304
Radek Krejci27fe55e2016-09-13 17:13:35 +02004305static int
4306lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
4307{
4308 struct lys_node *root, *next, *node;
4309 uint8_t i;
4310
4311 for (i = 0; i < module->augment_size; i++) {
4312 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02004313 if (!module->augment[i].target
4314 && (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004315 return -1;
4316 }
4317 }
4318 LY_TREE_FOR(module->data, root) {
4319 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4320 LY_TREE_DFS_BEGIN(root, next, node) {
4321 if (node->nodetype == LYS_GROUPING) {
4322 goto nextsibling;
4323 }
4324 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4325 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4326 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4327 UNRES_TYPE_LEAFREF, node) == -1) {
4328 return EXIT_FAILURE;
4329 }
4330 }
4331 }
4332
4333 /* modified LY_TREE_DFS_END */
4334 next = node->child;
4335 /* child exception for leafs, leaflists and anyxml without children */
4336 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4337 next = NULL;
4338 }
4339 if (!next) {
4340nextsibling:
4341 /* no children */
4342 if (node == root) {
4343 /* we are done, root has no children */
4344 break;
4345 }
4346 /* try siblings */
4347 next = node->next;
4348 }
4349 while (!next) {
4350 /* parent is already processed, go to its sibling */
4351 node = lys_parent(node);
4352 /* no siblings, go back through parents */
4353 if (lys_parent(node) == lys_parent(root)) {
4354 /* we are done, no next element to process */
4355 break;
4356 }
4357 next = node->next;
4358 }
4359 }
4360 }
4361
4362 return EXIT_SUCCESS;
4363}
4364
4365API int
4366lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004367{
4368 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004369 struct unres_schema *unres;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004370 int i, j, disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004371
Radek Krejci27fe55e2016-09-13 17:13:35 +02004372 if (!module) {
4373 ly_errno = LY_EINVAL;
4374 return EXIT_FAILURE;
4375 }
4376
4377 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004378
4379 if (module->disabled) {
4380 disabled = 1;
4381 lys_set_enabled(module);
4382 }
4383
Michal Vasko26055752016-05-03 11:36:31 +02004384 if (module->implemented) {
4385 return EXIT_SUCCESS;
4386 }
4387
4388 ctx = module->ctx;
4389
4390 for (i = 0; i < ctx->models.used; ++i) {
4391 if (module == ctx->models.list[i]) {
4392 continue;
4393 }
4394
4395 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4396 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004397 if (disabled) {
4398 /* set it back disabled */
4399 lys_set_disabled(module);
4400 }
Michal Vasko26055752016-05-03 11:36:31 +02004401 return EXIT_FAILURE;
4402 }
4403 }
4404
Radek Krejci27fe55e2016-09-13 17:13:35 +02004405 unres = calloc(1, sizeof *unres);
4406 if (!unres) {
4407 LOGMEM;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004408 if (disabled) {
4409 /* set it back disabled */
4410 lys_set_disabled(module);
4411 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004412 return EXIT_FAILURE;
4413 }
4414 /* recursively make the module implemented */
4415 ((struct lys_module *)module)->implemented = 1;
4416 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
4417 goto error;
4418 }
4419 /* process augments in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004420 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004421 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
4422 /* apply augment */
Radek Krejcic8c22532016-11-09 15:11:24 +01004423 if (!module->inc[i].submodule->augment[j].target
4424 && (unres_schema_add_node((struct lys_module *)module->inc[j].submodule, unres,
4425 &module->inc[i].submodule->augment[j], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01004426
Radek Krejci27fe55e2016-09-13 17:13:35 +02004427 goto error;
4428 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004429 }
4430 }
Radek Krejcidf46e222016-11-08 11:57:37 +01004431 /* try again resolve augments in other modules possibly augmenting this one,
4432 * since we have just enabled it
4433 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004434 /* resolve rest of unres items */
4435 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4436 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004437 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004438 unres_schema_free((struct lys_module *)module, &unres);
Michal Vasko26055752016-05-03 11:36:31 +02004439
4440 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004441
4442error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004443
4444 if (disabled) {
4445 /* set it back disabled */
4446 lys_set_disabled(module);
4447 }
4448
Radek Krejci27fe55e2016-09-13 17:13:35 +02004449 ((struct lys_module *)module)->implemented = 0;
4450 unres_schema_free((struct lys_module *)module, &unres);
4451 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004452}
4453
4454void
4455lys_submodule_module_data_free(struct lys_submodule *submodule)
4456{
4457 struct lys_node *next, *elem;
4458
4459 /* remove parsed data */
4460 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4461 if (elem->module == (struct lys_module *)submodule) {
4462 lys_node_free(elem, NULL, 0);
4463 }
4464 }
4465}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004466
4467int
4468lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
4469{
4470 uint8_t i;
4471
4472 for (i = 0; i < list->keys_size; i++) {
4473 if (list->keys[i] == leaf) {
4474 return i + 1;
4475 }
4476 }
4477
4478 return 0;
4479}
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004480
4481API char *
4482lys_path(const struct lys_node *node)
4483{
4484 char *buf_backup = NULL, *buf = ly_buf(), *result = NULL;
4485 uint16_t index = LY_BUF_SIZE - 1;
4486
4487 if (!node) {
4488 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
4489 return NULL;
4490 }
4491
4492 /* backup the shared internal buffer */
4493 if (ly_buf_used && buf[0]) {
4494 buf_backup = strndup(buf, LY_BUF_SIZE - 1);
4495 }
4496 ly_buf_used++;
4497
4498 /* build the path */
4499 buf[index] = '\0';
Michal Vasko5efa25c2017-01-10 11:34:30 +01004500 ly_vlog_build_path_reverse(LY_VLOG_LYS, node, buf, &index, 0);
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004501 result = strdup(&buf[index]);
4502
4503 /* restore the shared internal buffer */
4504 if (buf_backup) {
4505 strcpy(buf, buf_backup);
4506 free(buf_backup);
4507 }
4508 ly_buf_used--;
4509
4510 return result;
4511}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004512
Radek Krejci8d6b7422017-02-03 14:42:13 +01004513static void
4514lys_extcomplex_free_str(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext, LY_STMT stmt)
4515{
4516 struct lyext_substmt *info;
Radek Krejcib71243e2017-02-08 16:20:08 +01004517 const char **str, ***a;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004518 int c;
4519
4520 str = lys_ext_complex_get_substmt(stmt, ext, &info);
4521 if (!str || !(*str)) {
4522 return;
4523 }
4524 if (info->cardinality >= LY_STMT_CARD_SOME) {
4525 /* we have array */
Radek Krejcib71243e2017-02-08 16:20:08 +01004526 a = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01004527 for (str = (*(const char ***)str), c = 0; str[c]; c++) {
4528 lydict_remove(ctx, str[c]);
Radek Krejci8d6b7422017-02-03 14:42:13 +01004529 }
Radek Krejci56c80412017-02-09 10:44:16 +01004530 free(a[0]);
4531 if (stmt == LY_STMT_BELONGSTO) {
4532 for (str = a[1], c = 0; str[c]; c++) {
4533 lydict_remove(ctx, str[c]);
4534 }
4535 free(a[1]);
PavolVican99c70722017-02-18 17:25:52 +01004536 } else if (stmt == LY_STMT_ARGUMENT) {
4537 free(a[1]);
Radek Krejci56c80412017-02-09 10:44:16 +01004538 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004539 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01004540 lydict_remove(ctx, str[0]);
4541 if (stmt == LY_STMT_BELONGSTO) {
4542 lydict_remove(ctx, str[1]);
4543 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004544 }
4545}
4546void
4547lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size)
4548{
Radek Krejcif8d05c22017-02-10 15:33:35 +01004549 unsigned int i, j, k;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004550 struct lyext_substmt *substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004551 void **pp, **start;
Radek Krejcif95b6292017-02-13 15:57:37 +01004552 struct lys_node *siter, *snext;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004553
4554#define EXTCOMPLEX_FREE_STRUCT(STMT, TYPE, FUNC, FREE, ARGS...) \
Radek Krejcib84686f2017-02-09 16:04:55 +01004555 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)e[i], NULL); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004556 if (!pp || !(*pp)) { break; } \
Radek Krejcib84686f2017-02-09 16:04:55 +01004557 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004558 for (start = pp = *pp; *pp; pp++) { \
4559 FUNC(ctx, (TYPE *)(*pp), ##ARGS); \
4560 if (FREE) { free(*pp); } \
4561 } \
4562 free(start); \
4563 } else { /* single item */ \
4564 FUNC(ctx, (TYPE *)(*pp), ##ARGS); \
4565 if (FREE) { free(*pp); } \
4566 }
4567
4568 if (!size || !e || !(*e)) {
4569 return;
4570 }
4571
4572 for (i = 0; i < size; i++) {
4573 if (!e[i]) {
4574 continue;
4575 }
4576
4577 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
4578 /* no free, this is just a shadow copy of the original extension instance */
4579 } else {
4580 if (e[i]->flags & (LYEXT_OPT_YANG)) {
4581 free(e[i]->def); /* remove name of instance extension */
PavolVican19dc6152017-02-06 12:04:15 +01004582 e[i]->def = NULL;
PavolVicandb0e8172017-02-20 00:46:09 +01004583 yang_free_ext_data((struct yang_ext_substmt *)e[i]->parent); /* remove backup part of yang file */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004584 }
4585 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size);
4586 lydict_remove(ctx, e[i]->arg_value);
4587 }
4588
4589 if (e[i]->def && e[i]->def->plugin && e[i]->def->plugin->type == LYEXT_COMPLEX) {
Radek Krejcifebdad72017-02-06 11:35:51 +01004590 substmt = ((struct lys_ext_instance_complex *)e[i])->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004591 for (j = 0; substmt[j].stmt; j++) {
4592 switch(substmt[j].stmt) {
4593 case LY_STMT_DESCRIPTION:
4594 case LY_STMT_REFERENCE:
4595 case LY_STMT_UNITS:
Radek Krejcib71243e2017-02-08 16:20:08 +01004596 case LY_STMT_ARGUMENT:
4597 case LY_STMT_DEFAULT:
4598 case LY_STMT_ERRTAG:
4599 case LY_STMT_ERRMSG:
4600 case LY_STMT_PREFIX:
4601 case LY_STMT_NAMESPACE:
4602 case LY_STMT_PRESENCE:
4603 case LY_STMT_REVISIONDATE:
4604 case LY_STMT_KEY:
4605 case LY_STMT_BASE:
4606 case LY_STMT_BELONGSTO:
4607 case LY_STMT_CONTACT:
4608 case LY_STMT_ORGANIZATION:
4609 case LY_STMT_PATH:
Radek Krejci8d6b7422017-02-03 14:42:13 +01004610 lys_extcomplex_free_str(ctx, (struct lys_ext_instance_complex *)e[i], substmt[j].stmt);
4611 break;
4612 case LY_STMT_TYPE:
4613 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPE, struct lys_type, lys_type_free, 1);
4614 break;
Radek Krejci63fc0962017-02-15 13:20:18 +01004615 case LY_STMT_TYPEDEF:
4616 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPEDEF, struct lys_tpdf, lys_tpdf_free, 1);
4617 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004618 case LY_STMT_IFFEATURE:
4619 EXTCOMPLEX_FREE_STRUCT(LY_STMT_IFFEATURE, struct lys_iffeature, lys_iffeature_free, 0, 1);
4620 break;
Radek Krejci5496fae2017-02-10 13:26:48 +01004621 case LY_STMT_MAX:
4622 case LY_STMT_MIN:
4623 case LY_STMT_POSITION:
PavolVican2ed9f4e2017-02-16 00:08:45 +01004624 case LY_STMT_VALUE:
Radek Krejcif8d05c22017-02-10 15:33:35 +01004625 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
Radek Krejci716cd7a2017-02-15 12:23:41 +01004626 if (substmt[j].cardinality >= LY_STMT_CARD_SOME && *pp) {
Radek Krejcif8d05c22017-02-10 15:33:35 +01004627 for(k = 0; ((uint32_t**)(*pp))[k]; k++) {
4628 free(((uint32_t**)(*pp))[k]);
4629 }
4630 }
4631 free(*pp);
4632 break;
4633 case LY_STMT_DIGITS:
Radek Krejcib84686f2017-02-09 16:04:55 +01004634 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
4635 /* free the array */
4636 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4637 free(*pp);
4638 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004639 break;
Radek Krejci37f9ba32017-02-10 16:50:35 +01004640 case LY_STMT_MODULE:
4641 /* modules are part of the context, so they will be freed there */
4642 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
4643 /* free the array */
4644 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4645 free(*pp);
4646 }
4647 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01004648 case LY_STMT_ACTION:
Radek Krejcib31762b2017-02-15 10:48:42 +01004649 case LY_STMT_ANYDATA:
4650 case LY_STMT_ANYXML:
4651 case LY_STMT_CASE:
4652 case LY_STMT_CHOICE:
4653 case LY_STMT_CONTAINER:
4654 case LY_STMT_GROUPING:
4655 case LY_STMT_INPUT:
4656 case LY_STMT_LEAF:
4657 case LY_STMT_LEAFLIST:
4658 case LY_STMT_LIST:
4659 case LY_STMT_NOTIFICATION:
4660 case LY_STMT_OUTPUT:
4661 case LY_STMT_RPC:
4662 case LY_STMT_USES:
Radek Krejcif95b6292017-02-13 15:57:37 +01004663 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4664 LY_TREE_FOR_SAFE((struct lys_node *)(*pp), snext, siter) {
4665 lys_node_free(siter, NULL, 0);
4666 }
Radek Krejcib31762b2017-02-15 10:48:42 +01004667 *pp = NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01004668 break;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004669 case LY_STMT_UNIQUE:
4670 pp = lys_ext_complex_get_substmt(LY_STMT_UNIQUE, (struct lys_ext_instance_complex *)e[i], NULL);
4671 if (!pp || !(*pp)) {
4672 break;
4673 }
4674 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
4675 for (start = pp = *pp; *pp; pp++) {
4676 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
4677 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
4678 }
4679 free((*(struct lys_unique**)pp)->expr);
4680 free(*pp);
4681 }
4682 free(start);
4683 } else { /* single item */
4684 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
4685 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
4686 }
4687 free((*(struct lys_unique**)pp)->expr);
4688 free(*pp);
4689 }
4690 break;
Radek Krejciaa9c5202017-02-15 16:10:14 +01004691 case LY_STMT_LENGTH:
4692 case LY_STMT_MUST:
4693 case LY_STMT_PATTERN:
4694 case LY_STMT_RANGE:
4695 EXTCOMPLEX_FREE_STRUCT(substmt[j].stmt, struct lys_restr, lys_restr_free, 1);
4696 break;
Radek Krejcic5cc5302017-02-16 10:07:46 +01004697 case LY_STMT_WHEN:
4698 EXTCOMPLEX_FREE_STRUCT(LY_STMT_WHEN, struct lys_when, lys_when_free, 0);
4699 break;
Radek Krejci7417a082017-02-16 11:07:59 +01004700 case LY_STMT_REVISION:
4701 pp = lys_ext_complex_get_substmt(LY_STMT_REVISION, (struct lys_ext_instance_complex *)e[i], NULL);
4702 if (!pp || !(*pp)) {
4703 break;
4704 }
4705 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
4706 for (start = pp = *pp; *pp; pp++) {
4707 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
4708 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
4709 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
4710 (*(struct lys_revision**)pp)->ext_size);
4711 free(*pp);
4712 }
4713 free(start);
4714 } else { /* single item */
4715 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
4716 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
4717 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
4718 (*(struct lys_revision**)pp)->ext_size);
4719 free(*pp);
4720 }
4721 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004722 default:
Radek Krejcib84686f2017-02-09 16:04:55 +01004723 /* nothing to free */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004724 break;
4725 }
4726 }
4727 }
4728
4729 free(e[i]);
4730 }
4731 free(e);
4732
4733#undef EXTCOMPLEX_FREE_STRUCT
4734}