blob: d17bec2d248f1bf44489ae3ca890b91496a30740 [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,
Radek Krejci5138e9f2017-04-12 13:10:46 +020041 int in_grp, int shallow, 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 Vaskobb520442017-05-23 10:55:18 +0200166lys_getnext_data(const struct lys_module *mod, const struct lys_node *parent, const char *name, int nam_len,
167 LYS_NODE type, const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200168{
Michal Vaskobb520442017-05-23 10:55:18 +0200169 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200170
Michal Vaskobb520442017-05-23 10:55:18 +0200171 assert((mod || parent) && name);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200172 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
173
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200174 if (!mod) {
Michal Vaskobb520442017-05-23 10:55:18 +0200175 mod = lys_node_module(parent);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200176 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200177
Michal Vasko4f0dad02016-02-15 14:08:23 +0100178 /* try to find the node */
179 node = NULL;
Michal Vasko24476fa2017-03-08 12:33:48 +0100180 while ((node = lys_getnext(node, parent, mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100181 if (!type || (node->nodetype & type)) {
182 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200183 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100184 continue;
185 }
186
Michal Vasko4f0dad02016-02-15 14:08:23 +0100187 /* direct name check */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100188 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100189 if (ret) {
190 *ret = node;
191 }
192 return EXIT_SUCCESS;
193 }
Radek Krejcic071c542016-01-27 14:57:51 +0100194 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200195 }
196
197 return EXIT_FAILURE;
198}
199
Michal Vasko1e62a092015-12-01 12:27:20 +0100200API const struct lys_node *
201lys_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 +0200202{
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100203 const struct lys_node *next, *aug_parent;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100204 struct lys_node **snode;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200205
Michal Vasko24476fa2017-03-08 12:33:48 +0100206 if ((!parent && !module) || (parent && (parent->nodetype == LYS_USES) && !(options & LYS_GETNEXT_PARENTUSES))) {
207 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
208 return NULL;
209 }
210
Radek Krejci8bc87f62015-09-02 16:19:05 +0200211 if (!last) {
212 /* first call */
213
214 /* get know where to start */
215 if (parent) {
216 /* schema subtree */
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100217 snode = lys_child(parent, LYS_UNKNOWN);
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100218 /* do not return anything if the augment does not have any children */
Radek Krejcibb08db32017-07-03 11:29:17 +0200219 if (!snode || !(*snode) || ((parent->nodetype == LYS_AUGMENT) && ((*snode)->parent != parent))) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100220 return NULL;
221 }
222 next = last = *snode;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200223 } else {
224 /* top level data */
225 assert(module);
226 next = last = module->data;
227 }
Radek Krejci972724f2016-08-12 15:24:40 +0200228 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
229 /* continue with uses content */
230 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200231 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200232 /* continue after the last returned value */
233 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200234 }
235
236repeat:
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100237 if (parent && (parent->nodetype == LYS_AUGMENT) && next) {
238 /* do not return anything outside the parent augment */
239 aug_parent = next->parent;
240 do {
241 while (aug_parent && (aug_parent->nodetype != LYS_AUGMENT)) {
242 aug_parent = aug_parent->parent;
243 }
244 if (aug_parent) {
245 if (aug_parent == parent) {
246 break;
247 }
248 aug_parent = ((struct lys_node_augment *)aug_parent)->target;
249 }
250
251 } while (aug_parent);
252 if (!aug_parent) {
253 return NULL;
254 }
255 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200256 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200257 if (options & LYS_GETNEXT_WITHGROUPING) {
258 return next;
259 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200260 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200261 }
262
Radek Krejci972724f2016-08-12 15:24:40 +0200263 if (!next) { /* cover case when parent is augment */
264 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200265 /* no next element */
266 return NULL;
267 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200268 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200269 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200270 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200271 } else {
272 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200273 }
274
275 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200276 case LYS_INPUT:
277 case LYS_OUTPUT:
278 if (options & LYS_GETNEXT_WITHINOUT) {
279 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200280 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200281 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200282 } else {
283 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200284 }
Radek Krejci972724f2016-08-12 15:24:40 +0200285 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200286
Michal Vaskoa5835e92015-10-20 15:07:39 +0200287 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200288 if (options & LYS_GETNEXT_WITHCASE) {
289 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200290 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200291 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200292 } else {
293 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200294 }
Radek Krejci972724f2016-08-12 15:24:40 +0200295 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200296
Michal Vasko1dca6882015-10-22 14:29:42 +0200297 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200298 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200299 if (options & LYS_GETNEXT_WITHUSES) {
300 return next;
301 } else if (next->child) {
302 next = next->child;
303 } else {
304 next = next->next;
305 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200306 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200307
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200308 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200309 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200310 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200311 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200312 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200313 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200314 case LYS_LIST:
315 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200316 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200317
Radek Krejci972724f2016-08-12 15:24:40 +0200318 case LYS_CONTAINER:
319 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
320 if (next->child) {
321 /* go into */
322 next = next->child;
323 } else {
324 next = next->next;
325 }
326 goto repeat;
327 } else {
328 return next;
329 }
330
Radek Krejci8bc87f62015-09-02 16:19:05 +0200331 case LYS_CHOICE:
332 if (options & LYS_GETNEXT_WITHCHOICE) {
333 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200334 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200335 /* go into */
336 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200337 } else {
338 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200339 }
Radek Krejci972724f2016-08-12 15:24:40 +0200340 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200341
Radek Krejci7f40ce32015-08-12 20:38:46 +0200342 default:
343 /* we should not be here */
344 return NULL;
345 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200346}
347
Radek Krejcibf285832017-01-26 16:05:41 +0100348void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200349lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200350{
Radek Krejcif95b6292017-02-13 15:57:37 +0100351 struct lys_node *parent, *first, **pp;
Radek Krejcic071c542016-01-27 14:57:51 +0100352 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200354 if (!node) {
355 return;
356 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200358 /* unlink from data model if necessary */
359 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100360 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100361 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100362 if (main_module->data == node) {
363 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200364 }
365 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200367 /* store pointers to important nodes */
368 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200369 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200370 /* handle augments - first, unlink it from the augment parent ... */
371 if (parent->child == node) {
Radek Krejcic9d78692017-08-24 17:17:18 +0200372 parent->child = (node->next && node->next->parent == parent) ? node->next : NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200373 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100374
375 if (parent->flags & LYS_NOTAPPLIED) {
376 /* data are not connected in the target, so we cannot continue with the target as a parent */
377 parent = NULL;
378 } else {
379 /* data are connected in target, so we will continue with the target as a parent */
380 parent = ((struct lys_node_augment *)parent)->target;
381 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200382 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200384 /* unlink from parent */
385 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100386 if (parent->nodetype == LYS_EXT) {
387 pp = (struct lys_node **)lys_ext_complex_get_substmt(lys_snode2stmt(node->nodetype),
388 (struct lys_ext_instance_complex*)parent, NULL);
389 if (*pp == node) {
390 *pp = node->next;
391 }
392 } else if (parent->child == node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200393 parent->child = node->next;
394 }
395 node->parent = NULL;
396 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200398 /* unlink from siblings */
399 if (node->prev == node) {
400 /* there are no more siblings */
401 return;
402 }
403 if (node->next) {
404 node->next->prev = node->prev;
405 } else {
406 /* unlinking the last element */
407 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100408 if (parent->nodetype == LYS_EXT) {
409 first = *(struct lys_node **)pp;
410 } else {
411 first = parent->child;
412 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200413 } else {
414 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200415 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200416 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200417 }
418 }
419 first->prev = node->prev;
420 }
421 if (node->prev->next) {
422 node->prev->next = node->next;
423 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200424
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200425 /* clean up the unlinked element */
426 node->next = NULL;
427 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200428}
429
Michal Vasko563ef092015-09-04 13:17:23 +0200430struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100431lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200432{
433 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200434
435 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200436 /* top-level augment, look into module (uses augment is handled correctly below) */
437 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
Radek Krejci115fa882017-03-01 16:15:07 +0100438 par_iter = lys_main_module(par_iter->parent->module)->data;
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200439 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200440 break;
441 }
442 }
443
Michal Vasko6f929da2015-10-02 16:23:25 +0200444 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200445 continue;
446 }
447
448 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
449 if (!stop) {
450 stop = par_iter;
451 } else if (iter == stop) {
452 break;
453 }
454 if (iter->nodetype != LYS_GROUPING) {
455 continue;
456 }
457
Radek Krejcif8426a72015-10-31 23:14:03 +0100458 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200459 return (struct lys_node_grp *)iter;
460 }
461 }
462 }
463
Michal Vasko563ef092015-09-04 13:17:23 +0200464 return NULL;
465}
466
Radek Krejci10c760e2015-08-14 14:45:43 +0200467/*
468 * get next grouping in the root's subtree, in the
469 * first call, tha last is NULL
470 */
471static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200472lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200473{
Radek Krejci10c760e2015-08-14 14:45:43 +0200474 struct lys_node *last = (struct lys_node *)lastgrp;
475 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200476
Radek Krejci10c760e2015-08-14 14:45:43 +0200477 assert(root);
478
479 if (!last) {
480 last = root;
481 }
482
483 while (1) {
484 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
485 next = last->child;
486 } else {
487 next = NULL;
488 }
489 if (!next) {
490 if (last == root) {
491 /* we are done */
492 return NULL;
493 }
494
495 /* no children, go to siblings */
496 next = last->next;
497 }
498 while (!next) {
499 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100500 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200501 /* we are done */
502 return NULL;
503 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200504 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100505 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200506 }
507
508 if (next->nodetype == LYS_GROUPING) {
509 return (struct lys_node_grp *)next;
510 }
511
512 last = next;
513 }
514}
515
Michal Vasko0d343d12015-08-24 14:57:36 +0200516/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200517int
Radek Krejci07911992015-08-14 15:13:31 +0200518lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
519{
Michal Vasko563ef092015-09-04 13:17:23 +0200520 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200521 struct lys_node_grp *grp;
Radek Krejcif95b6292017-02-13 15:57:37 +0100522 int down, up;
Radek Krejci07911992015-08-14 15:13:31 +0200523
524 assert(node);
525
526 if (!parent) {
527 assert(module);
528 } else {
529 module = parent->module;
530 }
Radek Krejci115fa882017-03-01 16:15:07 +0100531 module = lys_main_module(module);
Radek Krejci07911992015-08-14 15:13:31 +0200532
533 switch (node->nodetype) {
534 case LYS_GROUPING:
535 /* 6.2.1, rule 6 */
536 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100537 start = *lys_child(parent, LYS_GROUPING);
538 if (!start) {
Radek Krejci07911992015-08-14 15:13:31 +0200539 down = 0;
540 start = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100541 } else {
542 down = 1;
543 }
544 if (parent->nodetype == LYS_EXT) {
545 up = 0;
546 } else {
547 up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200548 }
549 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100550 down = up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200551 start = module->data;
552 }
553 /* go up */
Radek Krejcif95b6292017-02-13 15:57:37 +0100554 if (up && lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100555 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200556 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200557 }
558 /* go down, because grouping can be defined after e.g. container in which is collision */
559 if (down) {
560 for (iter = start, stop = NULL; iter; iter = iter->prev) {
561 if (!stop) {
562 stop = start;
563 } else if (iter == stop) {
564 break;
565 }
566 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
567 continue;
568 }
569
570 grp = NULL;
571 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100572 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100573 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200574 return EXIT_FAILURE;
575 }
576 }
577 }
578 }
579 break;
580 case LYS_LEAF:
581 case LYS_LEAFLIST:
582 case LYS_LIST:
583 case LYS_CONTAINER:
584 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200585 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200586 /* 6.2.1, rule 7 */
587 if (parent) {
588 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200589 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
590 if (iter->nodetype == LYS_AUGMENT) {
591 if (((struct lys_node_augment *)iter)->target) {
592 /* augment is resolved, go up */
593 iter = ((struct lys_node_augment *)iter)->target;
594 continue;
595 }
596 /* augment is not resolved, this is the final parent */
597 break;
598 }
Radek Krejci07911992015-08-14 15:13:31 +0200599 iter = iter->parent;
600 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200601
Radek Krejci07911992015-08-14 15:13:31 +0200602 if (!iter) {
603 stop = NULL;
604 iter = module->data;
Radek Krejcif95b6292017-02-13 15:57:37 +0100605 } else if (iter->nodetype == LYS_EXT) {
606 stop = iter;
607 iter = *lys_child(iter, node->nodetype);
Radek Krejci07911992015-08-14 15:13:31 +0200608 } else {
609 stop = iter;
610 iter = iter->child;
611 }
612 } else {
613 stop = NULL;
614 iter = module->data;
615 }
616 while (iter) {
617 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
618 iter = iter->child;
619 continue;
620 }
621
Radek Krejcibf2abff2016-08-23 15:51:52 +0200622 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100623 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100624 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200625 return EXIT_FAILURE;
626 }
627 }
628
629 /* special case for choice - we must check the choice's name as
630 * well as the names of nodes under the choice
631 */
632 if (iter->nodetype == LYS_CHOICE) {
633 iter = iter->child;
634 continue;
635 }
636
637 /* go to siblings */
638 if (!iter->next) {
639 /* no sibling, go to parent's sibling */
640 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200641 /* for parent LYS_AUGMENT */
642 if (iter->parent == stop) {
643 iter = stop;
644 break;
645 }
646 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200647 if (iter && iter->next) {
648 break;
649 }
650 } while (iter != stop);
651
652 if (iter == stop) {
653 break;
654 }
655 }
656 iter = iter->next;
657 }
658 break;
659 case LYS_CASE:
660 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100661 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100662 start = *lys_child(parent, LYS_CASE);
Radek Krejcic071c542016-01-27 14:57:51 +0100663 } else {
664 start = module->data;
665 }
666
667 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200668 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200669 continue;
670 }
671
Radek Krejci749190d2016-02-18 16:26:25 +0100672 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100673 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200674 return EXIT_FAILURE;
675 }
676 }
677 break;
678 default:
679 /* no check needed */
680 break;
681 }
682
683 return EXIT_SUCCESS;
684}
685
Michal Vasko0d343d12015-08-24 14:57:36 +0200686/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200687int
Radek Krejci10c760e2015-08-14 14:45:43 +0200688lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
689{
Radek Krejcic9d78692017-08-24 17:17:18 +0200690 struct lys_node *iter, **pchild;
Radek Krejci41a349b2016-10-24 19:21:59 +0200691 struct lys_node_inout *in, *out, *inout;
Radek Krejci744c2d42017-03-26 13:30:00 -0500692 struct lys_node_case *c;
693 int type, shortcase = 0;
Radek Krejcif95b6292017-02-13 15:57:37 +0100694 void *p;
695 struct lyext_substmt *info = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200697 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200698
Radek Krejci10c760e2015-08-14 14:45:43 +0200699 if (parent) {
700 type = parent->nodetype;
701 module = parent->module;
702 } else {
703 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100704 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200705 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200706 }
707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200708 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200709 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200710 case LYS_CONTAINER:
711 case LYS_LIST:
712 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100713 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200714 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200715 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200716 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200717 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
718 return EXIT_FAILURE;
719 }
720 break;
Radek Krejci76512572015-08-04 09:47:08 +0200721 case LYS_INPUT:
722 case LYS_OUTPUT:
723 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200724 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200725 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200726 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100727 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200728 return EXIT_FAILURE;
729 }
730 break;
Radek Krejci76512572015-08-04 09:47:08 +0200731 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200732 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200733 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100734 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200735 return EXIT_FAILURE;
736 }
Radek Krejci744c2d42017-03-26 13:30:00 -0500737 if (child->nodetype != LYS_CASE) {
738 shortcase = 1;
739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200740 break;
Radek Krejci76512572015-08-04 09:47:08 +0200741 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200742 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200743 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100744 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200745 return EXIT_FAILURE;
746 }
747 break;
Radek Krejci76512572015-08-04 09:47:08 +0200748 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200749 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200750 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100751 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200752 return EXIT_FAILURE;
753 }
754 break;
Radek Krejci76512572015-08-04 09:47:08 +0200755 case LYS_LEAF:
756 case LYS_LEAFLIST:
757 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200758 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100759 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vasko51e5c582017-01-19 14:16:39 +0100760 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100761 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200762 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200763 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200764 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200765 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100766 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100767 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200768 return EXIT_FAILURE;
769 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200770 break;
771 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200772 /* top level */
773 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200774 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200775 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100776 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200777 return EXIT_FAILURE;
778 }
Radek Krejcif95b6292017-02-13 15:57:37 +0100779 break;
780 case LYS_EXT:
781 /* plugin-defined */
782 p = lys_ext_complex_get_substmt(lys_snode2stmt(child->nodetype), (struct lys_ext_instance_complex*)parent, &info);
783 if (!p) {
784 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype),
785 ((struct lys_ext_instance_complex*)parent)->def->name);
786 return EXIT_FAILURE;
787 }
788 /* TODO check cardinality */
Radek Krejcic071c542016-01-27 14:57:51 +0100789 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200790 }
791
792 /* check identifier uniqueness */
Michal Vasko15a43372017-09-25 14:12:42 +0200793 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && lys_check_id(child, parent, module)) {
Radek Krejci07911992015-08-14 15:13:31 +0200794 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200795 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200797 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200798 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200799 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200800
Radek Krejcif95b6292017-02-13 15:57:37 +0100801 if ((child->nodetype & (LYS_INPUT | LYS_OUTPUT)) && parent->nodetype != LYS_EXT) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200802 /* replace the implicit input/output node */
803 if (child->nodetype == LYS_OUTPUT) {
804 inout = (struct lys_node_inout *)parent->child->next;
805 } else { /* LYS_INPUT */
806 inout = (struct lys_node_inout *)parent->child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200807 parent->child = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200808 }
809 if (inout->next) {
810 child->next = inout->next;
811 inout->next->prev = child;
812 inout->next = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200813 } else {
Radek Krejci41a349b2016-10-24 19:21:59 +0200814 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200815 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200816 child->prev = inout->prev;
817 if (inout->prev->next) {
818 inout->prev->next = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200819 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200820 inout->prev = (struct lys_node *)inout;
821 child->parent = parent;
822 inout->parent = NULL;
823 lys_node_free((struct lys_node *)inout, NULL, 0);
824 } else {
Radek Krejci744c2d42017-03-26 13:30:00 -0500825 if (shortcase) {
826 /* create the implicit case to allow it to serve as a target of the augments,
827 * it won't be printed, but it will be present in the tree */
828 c = calloc(1, sizeof *c);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200829 LY_CHECK_ERR_RETURN(!c, LOGMEM, EXIT_FAILURE);
Radek Krejci744c2d42017-03-26 13:30:00 -0500830 c->name = lydict_insert(module->ctx, child->name, 0);
831 c->flags = LYS_IMPLICIT;
832 c->module = module;
833 c->nodetype = LYS_CASE;
834 c->prev = (struct lys_node*)c;
835 lys_node_addchild(parent, module, (struct lys_node*)c);
836 parent = (struct lys_node*)c;
837 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200838 /* connect the child correctly */
839 if (!parent) {
840 if (module->data) {
841 module->data->prev->next = child;
842 child->prev = module->data->prev;
843 module->data->prev = child;
844 } else {
845 module->data = child;
846 }
847 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100848 pchild = lys_child(parent, child->nodetype);
849 assert(pchild);
850
Radek Krejcic9d78692017-08-24 17:17:18 +0200851 child->parent = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100852 if (!(*pchild)) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200853 /* the only/first child of the parent */
Radek Krejcif95b6292017-02-13 15:57:37 +0100854 *pchild = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200855 iter = child;
856 } else {
857 /* add a new child at the end of parent's child list */
Radek Krejcif95b6292017-02-13 15:57:37 +0100858 iter = (*pchild)->prev;
Radek Krejci41a349b2016-10-24 19:21:59 +0200859 iter->next = child;
860 child->prev = iter;
861 }
862 while (iter->next) {
863 iter = iter->next;
864 iter->parent = parent;
865 }
Radek Krejcic9d78692017-08-24 17:17:18 +0200866 (*pchild)->prev = iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200867 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200868 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200869
Michal Vaskoe022a562016-09-27 14:24:15 +0200870 /* check config value (but ignore them in groupings and augments) */
Radek Krejcif95b6292017-02-13 15:57:37 +0100871 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); iter = iter->parent);
Michal Vaskoe022a562016-09-27 14:24:15 +0200872 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200873 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
874 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
875 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +0100876 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200877 return EXIT_FAILURE;
878 }
879 }
880
Radek Krejci41771502016-04-14 17:52:32 +0200881 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200882 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200883 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200884 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200885 /* store it only into container or list - the only data inner nodes */
886 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
887 if (iter->flags & LYS_INCL_STATUS) {
888 /* done, someone else set it already from here */
889 break;
890 }
891 /* set flag about including status data */
892 iter->flags |= LYS_INCL_STATUS;
893 }
894 }
895 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200896
897 /* create implicit input/output nodes to have available them as possible target for augment */
Radek Krejci60251232017-08-24 17:13:08 +0200898 if ((child->nodetype & (LYS_RPC | LYS_ACTION)) && !child->child) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200899 in = calloc(1, sizeof *in);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200900 out = calloc(1, sizeof *out);
901 if (!in || !out) {
902 LOGMEM;
903 free(in);
904 free(out);
905 return EXIT_FAILURE;
906 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200907 in->nodetype = LYS_INPUT;
908 in->name = lydict_insert(child->module->ctx, "input", 5);
Radek Krejci41a349b2016-10-24 19:21:59 +0200909 out->nodetype = LYS_OUTPUT;
Radek Krejcia8d111f2017-05-31 13:57:37 +0200910 out->name = lydict_insert(child->module->ctx, "output", 6);
Radek Krejci41a349b2016-10-24 19:21:59 +0200911 in->module = out->module = child->module;
912 in->parent = out->parent = child;
913 in->flags = out->flags = LYS_IMPLICIT;
914 in->next = (struct lys_node *)out;
915 in->prev = (struct lys_node *)out;
916 out->prev = (struct lys_node *)in;
917 child->child = (struct lys_node *)in;
918 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200919 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200920}
921
Michal Vasko29245662017-04-18 15:56:31 +0200922const struct lys_module *
Michal Vaskofb98dc42018-01-11 13:38:28 +0100923lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, const char *revision, int internal, int implement)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200924{
Radek Krejcia1df1682016-04-11 14:56:59 +0200925 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200926 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200927 unsigned int len;
Radek Krejcicf748252017-09-04 11:11:14 +0200928 struct ly_ctx *ctx_prev = ly_parser_data.ctx;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200929
Radek Krejcicf748252017-09-04 11:11:14 +0200930 ly_err_clean(ctx, 1);
Radek Krejcif347abc2016-06-22 10:18:47 +0200931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200932 if (!ctx || !data) {
933 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
934 return NULL;
935 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200936
Radek Krejcicf748252017-09-04 11:11:14 +0200937 /* set parser context */
938 ly_parser_data.ctx = ctx;
939
Radek Krejcia1df1682016-04-11 14:56:59 +0200940 if (!internal && format == LYS_IN_YANG) {
941 /* enlarge data by 2 bytes for flex */
942 len = strlen(data);
943 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200944 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM, NULL);
Radek Krejcia1df1682016-04-11 14:56:59 +0200945 memcpy(enlarged_data, data, len);
946 enlarged_data[len] = enlarged_data[len + 1] = '\0';
947 data = enlarged_data;
948 }
949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200951 case LYS_IN_YIN:
Michal Vaskofb98dc42018-01-11 13:38:28 +0100952 mod = yin_read_module(ctx, data, revision, implement);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200953 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200954 case LYS_IN_YANG:
Michal Vaskofb98dc42018-01-11 13:38:28 +0100955 mod = yang_read_module(ctx, data, 0, revision, implement);
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100956 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200957 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200958 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200959 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200960 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200961
Radek Krejcia1df1682016-04-11 14:56:59 +0200962 free(enlarged_data);
Radek Krejcia68ddeb2017-02-24 12:49:44 +0100963
964 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
965 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
966 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
967 * the anotation definitions available in the internal schema structure. There is another hack in schema
968 * printers to do not print this internally added annotation. */
969 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
Radek Krejci5b190662017-04-13 08:56:14 +0200970 if (lyp_add_ietf_netconf_annotations(mod)) {
Michal Vasko10681e82018-01-16 14:54:16 +0100971 lys_free(mod, NULL, 1, 1);
Radek Krejcia68ddeb2017-02-24 12:49:44 +0100972 return NULL;
973 }
Radek Krejcia68ddeb2017-02-24 12:49:44 +0100974 }
975
Radek Krejcicf748252017-09-04 11:11:14 +0200976 /* reset parser context */
977 ly_parser_data.ctx = ctx_prev;
978
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200979 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200980}
981
Radek Krejcia1df1682016-04-11 14:56:59 +0200982API const struct lys_module *
983lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
984{
Michal Vaskofb98dc42018-01-11 13:38:28 +0100985 return lys_parse_mem_(ctx, data, format, NULL, 0, 1);
Radek Krejcia1df1682016-04-11 14:56:59 +0200986}
987
Michal Vasko5a721fd2016-02-16 12:16:48 +0100988struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +0100989lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200990{
Michal Vasko5b998712017-01-26 10:34:06 +0100991 char *enlarged_data = NULL;
Michal Vasko5a721fd2016-02-16 12:16:48 +0100992 struct lys_submodule *submod = NULL;
Michal Vasko5b998712017-01-26 10:34:06 +0100993 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200995 assert(module);
996 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200997
Michal Vasko5b998712017-01-26 10:34:06 +0100998 if (format == LYS_IN_YANG) {
999 /* enlarge data by 2 bytes for flex */
1000 len = strlen(data);
1001 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001002 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM, NULL);
Michal Vasko5b998712017-01-26 10:34:06 +01001003 memcpy(enlarged_data, data, len);
1004 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1005 data = enlarged_data;
1006 }
1007
Radek Krejcic071c542016-01-27 14:57:51 +01001008 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001009 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001012 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001013 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001014 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001015 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001016 submod = yang_read_submodule(module, data, 0, unres);
1017 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001018 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001019 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001020 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001021 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001022
Michal Vasko5b998712017-01-26 10:34:06 +01001023 free(enlarged_data);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001024 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001025}
1026
Michal Vasko1e62a092015-12-01 12:27:20 +01001027API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001028lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1029{
1030 int fd;
1031 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +02001032 const char *rev, *dot, *filename;
1033 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +01001034
1035 if (!ctx || !path) {
1036 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1037 return NULL;
1038 }
1039
1040 fd = open(path, O_RDONLY);
1041 if (fd == -1) {
1042 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1043 return NULL;
1044 }
1045
1046 ret = lys_parse_fd(ctx, fd, format);
1047 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001048
Radek Krejcid80c8602016-10-25 11:56:03 +02001049 if (!ret) {
1050 /* error */
1051 return NULL;
1052 }
1053
1054 /* check that name and revision match filename */
1055 filename = strrchr(path, '/');
1056 if (!filename) {
1057 filename = path;
1058 } else {
1059 filename++;
1060 }
1061 rev = strchr(filename, '@');
1062 dot = strrchr(filename, '.');
1063
1064 /* name */
1065 len = strlen(ret->name);
1066 if (strncmp(filename, ret->name, len) ||
1067 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Radek Krejcic0c82302016-10-25 14:21:33 +02001068 LOGWRN("File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +02001069 }
1070 if (rev) {
1071 len = dot - ++rev;
1072 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
1073 LOGWRN("File name \"%s\" does not match module revision \"%s\".", filename,
1074 ret->rev_size ? ret->rev[0].date : "none");
1075 }
1076 }
1077
1078 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001079 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001080 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001081 }
1082
Michal Vasko662610a2015-12-07 11:25:45 +01001083 return ret;
1084}
1085
1086API const struct lys_module *
1087lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001088{
Michal Vaskofb98dc42018-01-11 13:38:28 +01001089 return lys_parse_fd_(ctx, fd, format, NULL, 1);
1090}
1091
1092const struct lys_module *
1093lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, const char *revision, int implement)
1094{
Michal Vasko1e62a092015-12-01 12:27:20 +01001095 const struct lys_module *module;
Radek Krejci0fb11502017-01-31 16:45:42 +01001096 size_t length;
Radek Krejci63a91a92015-07-29 13:31:04 +02001097 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001098 char buf[PATH_MAX];
1099 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001100
1101 if (!ctx || fd < 0) {
1102 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1103 return NULL;
1104 }
1105
Radek Krejci0fb11502017-01-31 16:45:42 +01001106 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001107 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001108 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001109 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001110 } else if (!addr) {
1111 LOGERR(LY_EINVAL, "Empty schema file.");
Pavol Vicane36ea262015-11-12 11:57:47 +01001112 return NULL;
1113 }
Radek Krejci0fb11502017-01-31 16:45:42 +01001114
Michal Vaskofb98dc42018-01-11 13:38:28 +01001115 module = lys_parse_mem_(ctx, addr, format, revision, 1, implement);
Radek Krejci0fb11502017-01-31 16:45:42 +01001116 lyp_munmap(addr, length);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001117
Radek Krejcia77904e2016-02-25 16:23:45 +01001118 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001119 /* get URI if there is /proc */
1120 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001121 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1122 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1123 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1124 }
1125 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001126 }
Radek Krejcib051f722016-02-25 15:12:21 +01001127 }
1128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001129 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001130}
1131
Michal Vasko5a721fd2016-02-16 12:16:48 +01001132struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001133lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001134{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001135 struct lys_submodule *submodule;
Radek Krejci0fb11502017-01-31 16:45:42 +01001136 size_t length;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001137 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001139 assert(module);
1140 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001141
Radek Krejci0fb11502017-01-31 16:45:42 +01001142 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001143 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001144 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001145 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001146 } else if (!addr) {
1147 LOGERR(LY_EINVAL, "Empty submodule schema file.");
Michal Vasko2e7241e2016-02-15 16:06:34 +01001148 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001149 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001150
Michal Vasko5b998712017-01-26 10:34:06 +01001151 /* get the main module */
1152 module = lys_main_module(module);
1153
1154 switch (format) {
1155 case LYS_IN_YIN:
1156 submodule = yin_read_submodule(module, addr, unres);
1157 break;
1158 case LYS_IN_YANG:
1159 submodule = yang_read_submodule(module, addr, 0, unres);
1160 break;
1161 default:
Michal Vasko85d41522017-02-24 09:49:16 +01001162 LOGINT;
1163 return NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001164 }
1165
Radek Krejcic645a3a2017-01-31 16:59:00 +01001166 lyp_munmap(addr, length);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001167 return submodule;
1168
Radek Krejciefaeba32015-05-27 14:30:57 +02001169}
1170
Radek Krejcibf285832017-01-26 16:05:41 +01001171int
1172lys_ext_iter(struct lys_ext_instance **ext, uint8_t ext_size, uint8_t start, LYEXT_SUBSTMT substmt)
1173{
1174 unsigned int u;
1175
1176 for (u = start; u < ext_size; u++) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001177 if (ext[u]->insubstmt == substmt) {
Radek Krejcibf285832017-01-26 16:05:41 +01001178 return u;
1179 }
1180 }
1181
1182 return -1;
1183}
1184
Radek Krejcifdc0d702017-01-23 15:58:38 +01001185/*
1186 * duplicate extension instance
1187 */
1188int
Radek Krejci5138e9f2017-04-12 13:10:46 +02001189lys_ext_dup(struct lys_module *mod, struct lys_ext_instance **orig, uint8_t size, void *parent, LYEXT_PAR parent_type,
1190 struct lys_ext_instance ***new, int shallow, struct unres_schema *unres)
Radek Krejcifdc0d702017-01-23 15:58:38 +01001191{
1192 int i;
1193 uint8_t u = 0;
1194 struct lys_ext_instance **result;
1195 struct unres_ext *info, *info_orig;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001196 size_t len;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001197
1198 assert(new);
1199
1200 if (!size) {
1201 if (orig) {
1202 LOGINT;
1203 return EXIT_FAILURE;
1204 }
1205 (*new) = NULL;
1206 return EXIT_SUCCESS;
1207 }
1208
1209 (*new) = result = calloc(size, sizeof *result);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001210 LY_CHECK_ERR_RETURN(!result, LOGMEM, EXIT_FAILURE);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001211 for (u = 0; u < size; u++) {
1212 if (orig[u]) {
1213 /* resolved extension instance, just duplicate it */
Radek Krejci8de8f612017-02-16 15:03:32 +01001214 switch(orig[u]->ext_type) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001215 case LYEXT_FLAG:
1216 result[u] = malloc(sizeof(struct lys_ext_instance));
Radek Krejcia8d111f2017-05-31 13:57:37 +02001217 LY_CHECK_ERR_GOTO(!result[u], LOGMEM, error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001218 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001219 case LYEXT_COMPLEX:
fanchanghu8d86f6b2017-06-10 12:49:54 +08001220 len = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->instance_size;
1221 result[u] = calloc(1, len);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001222 LY_CHECK_ERR_GOTO(!result[u], LOGMEM, error);
1223
Radek Krejcifebdad72017-02-06 11:35:51 +01001224 ((struct lys_ext_instance_complex*)result[u])->substmt = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001225 /* TODO duplicate data in extension instance content */
fanchanghu8d86f6b2017-06-10 12:49:54 +08001226 memcpy((void*)result[u] + sizeof(**orig), (void*)orig[u] + sizeof(**orig), len - sizeof(**orig));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001227 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001228 }
1229 /* generic part */
1230 result[u]->def = orig[u]->def;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001231 result[u]->flags = LYEXT_OPT_CONTENT;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001232 result[u]->arg_value = lydict_insert(mod->ctx, orig[u]->arg_value, 0);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001233 result[u]->parent = parent;
1234 result[u]->parent_type = parent_type;
Radek Krejcifebdad72017-02-06 11:35:51 +01001235 result[u]->insubstmt = orig[u]->insubstmt;
1236 result[u]->insubstmt_index = orig[u]->insubstmt_index;
Radek Krejci8de8f612017-02-16 15:03:32 +01001237 result[u]->ext_type = orig[u]->ext_type;
Radek Krejci7f1d47e2017-04-12 15:29:02 +02001238 result[u]->priv = NULL;
1239 result[u]->nodetype = LYS_EXT;
1240 result[u]->module = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001241
1242 /* extensions */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001243 result[u]->ext_size = orig[u]->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001244 if (lys_ext_dup(mod, orig[u]->ext, orig[u]->ext_size, result[u],
Radek Krejci5138e9f2017-04-12 13:10:46 +02001245 LYEXT_PAR_EXTINST, &result[u]->ext, shallow, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001246 goto error;
1247 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001248
1249 /* in case of shallow copy (duplication for deviation), duplicate only the link to private data
1250 * in a new copy, otherwise (grouping instantiation) do not duplicate the private data */
1251 if (shallow) {
1252 result[u]->priv = orig[u]->priv;
1253 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01001254 } else {
1255 /* original extension is not yet resolved, so duplicate it in unres */
1256 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1257 if (i == -1) {
1258 /* extension not found in unres */
1259 LOGINT;
1260 goto error;
1261 }
1262 info_orig = unres->str_snode[i];
1263 info = malloc(sizeof *info);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001264 LY_CHECK_ERR_GOTO(!info, LOGMEM, error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001265 info->datatype = info_orig->datatype;
1266 if (info->datatype == LYS_IN_YIN) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001267 info->data.yin = lyxml_dup_elem(mod->ctx, info_orig->data.yin, NULL, 1);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001268 } /* else TODO YANG */
1269 info->parent = parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001270 info->mod = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001271 info->parent_type = parent_type;
1272 info->ext_index = u;
1273 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1274 goto error;
1275 }
1276 }
1277 }
1278
1279 return EXIT_SUCCESS;
1280
1281error:
1282 (*new) = NULL;
Radek Krejci5138e9f2017-04-12 13:10:46 +02001283 lys_extension_instances_free(mod->ctx, result, u, NULL);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001284 return EXIT_FAILURE;
1285}
1286
Radek Krejci1d82ef62015-08-07 14:44:40 +02001287static struct lys_restr *
Radek Krejci5138e9f2017-04-12 13:10:46 +02001288lys_restr_dup(struct lys_module *mod, struct lys_restr *old, int size, int shallow, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001289{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001290 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001291 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001292
Radek Krejci3733a802015-06-19 13:43:21 +02001293 if (!size) {
1294 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001295 }
Radek Krejci3733a802015-06-19 13:43:21 +02001296
1297 result = calloc(size, sizeof *result);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001298 LY_CHECK_ERR_RETURN(!result, LOGMEM, NULL);
1299
Radek Krejci3733a802015-06-19 13:43:21 +02001300 for (i = 0; i < size; i++) {
Radek Krejci77f22b22017-01-17 15:23:03 +01001301 result[i].ext_size = old[i].ext_size;
Radek Krejci5138e9f2017-04-12 13:10:46 +02001302 lys_ext_dup(mod, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_RESTR, &result[i].ext, shallow, unres);
Radek Krejci8d6b7422017-02-03 14:42:13 +01001303 result[i].expr = lydict_insert(mod->ctx, old[i].expr, 0);
1304 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1305 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1306 result[i].eapptag = lydict_insert(mod->ctx, old[i].eapptag, 0);
1307 result[i].emsg = lydict_insert(mod->ctx, old[i].emsg, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001308 }
1309
1310 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001311}
1312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001313void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001314lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr,
1315 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci0bd5db42015-06-19 13:30:07 +02001316{
1317 assert(ctx);
1318 if (!restr) {
1319 return;
1320 }
1321
Radek Krejci5138e9f2017-04-12 13:10:46 +02001322 lys_extension_instances_free(ctx, restr->ext, restr->ext_size, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001323 lydict_remove(ctx, restr->expr);
1324 lydict_remove(ctx, restr->dsc);
1325 lydict_remove(ctx, restr->ref);
1326 lydict_remove(ctx, restr->eapptag);
1327 lydict_remove(ctx, restr->emsg);
1328}
1329
Pavol Vican05810b62016-11-23 14:07:22 +01001330void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001331lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size,
Frank Rimplerc4db1c72017-09-12 12:56:39 +00001332 int shallow, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001333{
1334 uint8_t i;
1335
1336 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001337 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size, private_destructor);
Michal Vasko15a43372017-09-25 14:12:42 +02001338 if (!shallow) {
Frank Rimpler2a503f52017-09-12 15:21:18 +00001339 free(iffeature[i].expr);
1340 free(iffeature[i].features);
1341 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001342 }
1343 free(iffeature);
1344}
1345
Michal Vaskob84f88a2015-09-24 13:16:10 +02001346static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001347type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001348 LY_DATA_TYPE base, int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001349{
1350 int i;
Radek Krejcidce5f972017-09-12 15:47:49 +02001351 unsigned int u;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001352
1353 switch (base) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001354 case LY_TYPE_BINARY:
1355 if (old->info.binary.length) {
1356 new->info.binary.length = lys_restr_dup(mod, old->info.binary.length, 1, shallow, unres);
1357 }
1358 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001359
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001360 case LY_TYPE_BITS:
1361 new->info.bits.count = old->info.bits.count;
1362 if (new->info.bits.count) {
1363 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1364 LY_CHECK_ERR_RETURN(!new->info.bits.bit, LOGMEM, -1);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001365
Radek Krejcidce5f972017-09-12 15:47:49 +02001366 for (u = 0; u < new->info.bits.count; u++) {
1367 new->info.bits.bit[u].name = lydict_insert(mod->ctx, old->info.bits.bit[u].name, 0);
1368 new->info.bits.bit[u].dsc = lydict_insert(mod->ctx, old->info.bits.bit[u].dsc, 0);
1369 new->info.bits.bit[u].ref = lydict_insert(mod->ctx, old->info.bits.bit[u].ref, 0);
1370 new->info.bits.bit[u].flags = old->info.bits.bit[u].flags;
1371 new->info.bits.bit[u].pos = old->info.bits.bit[u].pos;
1372 new->info.bits.bit[u].ext_size = old->info.bits.bit[u].ext_size;
1373 if (lys_ext_dup(mod, old->info.bits.bit[u].ext, old->info.bits.bit[u].ext_size,
1374 &new->info.bits.bit[u], LYEXT_PAR_TYPE_BIT,
1375 &new->info.bits.bit[u].ext, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001376 return -1;
1377 }
1378 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001379 }
1380 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001381
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001382 case LY_TYPE_DEC64:
1383 new->info.dec64.dig = old->info.dec64.dig;
1384 new->info.dec64.div = old->info.dec64.div;
1385 if (old->info.dec64.range) {
1386 new->info.dec64.range = lys_restr_dup(mod, old->info.dec64.range, 1, shallow, unres);
1387 }
1388 break;
1389
1390 case LY_TYPE_ENUM:
1391 new->info.enums.count = old->info.enums.count;
1392 if (new->info.enums.count) {
1393 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1394 LY_CHECK_ERR_RETURN(!new->info.enums.enm, LOGMEM, -1);
1395
Radek Krejcidce5f972017-09-12 15:47:49 +02001396 for (u = 0; u < new->info.enums.count; u++) {
1397 new->info.enums.enm[u].name = lydict_insert(mod->ctx, old->info.enums.enm[u].name, 0);
1398 new->info.enums.enm[u].dsc = lydict_insert(mod->ctx, old->info.enums.enm[u].dsc, 0);
1399 new->info.enums.enm[u].ref = lydict_insert(mod->ctx, old->info.enums.enm[u].ref, 0);
1400 new->info.enums.enm[u].flags = old->info.enums.enm[u].flags;
1401 new->info.enums.enm[u].value = old->info.enums.enm[u].value;
1402 new->info.enums.enm[u].ext_size = old->info.enums.enm[u].ext_size;
1403 if (lys_ext_dup(mod, old->info.enums.enm[u].ext, old->info.enums.enm[u].ext_size,
1404 &new->info.enums.enm[u], LYEXT_PAR_TYPE_ENUM,
1405 &new->info.enums.enm[u].ext, shallow, unres)) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001406 return -1;
1407 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001408 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001409 }
1410 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001411
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001412 case LY_TYPE_IDENT:
1413 new->info.ident.count = old->info.ident.count;
1414 if (old->info.ident.count) {
1415 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1416 LY_CHECK_ERR_RETURN(!new->info.ident.ref, LOGMEM, -1);
1417 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1418 } else {
1419 /* there can be several unresolved base identities, duplicate them all */
1420 i = -1;
1421 do {
1422 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1423 if (i != -1) {
1424 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001425 return -1;
1426 }
1427 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001428 --i;
1429 } while (i > -1);
1430 }
1431 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001432
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001433 case LY_TYPE_INST:
1434 new->info.inst.req = old->info.inst.req;
1435 break;
1436
1437 case LY_TYPE_INT8:
1438 case LY_TYPE_INT16:
1439 case LY_TYPE_INT32:
1440 case LY_TYPE_INT64:
1441 case LY_TYPE_UINT8:
1442 case LY_TYPE_UINT16:
1443 case LY_TYPE_UINT32:
1444 case LY_TYPE_UINT64:
1445 if (old->info.num.range) {
1446 new->info.num.range = lys_restr_dup(mod, old->info.num.range, 1, shallow, unres);
1447 }
1448 break;
1449
1450 case LY_TYPE_LEAFREF:
1451 if (old->info.lref.path) {
1452 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1453 if (!in_grp && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
1454 return -1;
1455 }
1456 }
1457 break;
1458
1459 case LY_TYPE_STRING:
1460 if (old->info.str.length) {
1461 new->info.str.length = lys_restr_dup(mod, old->info.str.length, 1, shallow, unres);
1462 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001463 if (old->info.str.pat_count) {
1464 new->info.str.patterns = lys_restr_dup(mod, old->info.str.patterns, old->info.str.pat_count, shallow, unres);
1465 new->info.str.pat_count = old->info.str.pat_count;
Michal Vaskofcd974b2017-08-22 10:17:49 +02001466#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001467 if (!in_grp) {
1468 new->info.str.patterns_pcre = malloc(new->info.str.pat_count * 2 * sizeof *new->info.str.patterns_pcre);
1469 LY_CHECK_ERR_RETURN(!new->info.str.patterns_pcre, LOGMEM, -1);
Radek Krejcia4c107d2017-10-27 14:19:26 +02001470 for (u = 0; u < new->info.str.pat_count; u++) {
1471 if (lyp_precompile_pattern(&new->info.str.patterns[u].expr[1],
1472 (pcre**)&new->info.str.patterns_pcre[2 * u],
1473 (pcre_extra**)&new->info.str.patterns_pcre[2 * u + 1])) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001474 free(new->info.str.patterns_pcre);
1475 new->info.str.patterns_pcre = NULL;
1476 return -1;
1477 }
1478 }
1479 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001480#endif
Radek Krejcib53154b2017-07-19 09:14:13 +02001481 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001482 break;
1483
1484 case LY_TYPE_UNION:
1485 new->info.uni.has_ptr_type = old->info.uni.has_ptr_type;
1486 new->info.uni.count = old->info.uni.count;
1487 if (new->info.uni.count) {
1488 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1489 LY_CHECK_ERR_RETURN(!new->info.uni.types, LOGMEM, -1);
1490
Radek Krejcidce5f972017-09-12 15:47:49 +02001491 for (u = 0; u < new->info.uni.count; u++) {
1492 if (lys_type_dup(mod, parent, &(new->info.uni.types[u]), &(old->info.uni.types[u]), in_grp,
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001493 shallow, unres)) {
1494 return -1;
1495 }
1496 }
1497 }
1498 break;
1499
1500 default:
1501 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1502 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001503 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001504
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001505 return EXIT_SUCCESS;
1506}
1507
1508struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001509lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
Radek Krejci5138e9f2017-04-12 13:10:46 +02001510 int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001511{
1512 struct yang_type *new;
1513
1514 new = calloc(1, sizeof *new);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001515 LY_CHECK_ERR_RETURN(!new, LOGMEM, NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001516 new->flags = old->flags;
1517 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001518 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001519 new->type = type;
1520 if (!new->name) {
1521 LOGMEM;
1522 goto error;
1523 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001524 if (type_dup(module, parent, type, old->type, new->base, in_grp, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001525 new->type->base = new->base;
Radek Krejci5138e9f2017-04-12 13:10:46 +02001526 lys_type_free(module->ctx, new->type, NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001527 memset(&new->type->info, 0, sizeof new->type->info);
1528 goto error;
1529 }
1530 return new;
1531
1532 error:
1533 free(new);
1534 return NULL;
1535}
1536
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001537int
1538lys_copy_union_leafrefs(struct lys_module *mod, struct lys_node *parent, struct lys_type *type, struct lys_type *prev_new,
1539 struct unres_schema *unres)
1540{
1541 struct lys_type new;
Radek Krejcidce5f972017-09-12 15:47:49 +02001542 unsigned int i, top_type;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001543 struct lys_ext_instance **ext;
1544 uint8_t ext_size;
1545 void *reloc;
1546
1547 if (!prev_new) {
1548 /* this is the "top-level" type, meaning it is a real type and no typedef directly above */
1549 top_type = 1;
1550
1551 memset(&new, 0, sizeof new);
1552
1553 new.module_name = lydict_insert(mod->ctx, type->module_name, 0);
1554 new.base = type->base;
1555 new.parent = (struct lys_tpdf *)parent;
1556
1557 prev_new = &new;
1558 } else {
1559 /* this is not top-level type, just a type of a typedef */
1560 top_type = 0;
1561 }
1562
Radek Krejci9c5cb6d2017-08-09 11:15:23 +02001563 assert(type->der);
1564 if (type->der->module) {
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001565 /* typedef, skip it, but keep the extensions */
1566 ext_size = type->ext_size;
Radek Krejci068425c2017-08-09 11:23:17 +02001567 if (lys_ext_dup(mod, type->ext, type->ext_size, prev_new, LYEXT_PAR_TYPE, &ext, 0, unres)) {
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001568 return -1;
1569 }
1570 if (prev_new->ext) {
1571 reloc = realloc(prev_new->ext, (prev_new->ext_size + ext_size) * sizeof *prev_new->ext);
1572 LY_CHECK_ERR_RETURN(!reloc, LOGMEM, -1);
Radek Krejci70379e22017-08-09 11:21:07 +02001573 prev_new->ext = reloc;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001574
1575 memcpy(prev_new->ext + prev_new->ext_size, ext, ext_size * sizeof *ext);
1576 free(ext);
1577
1578 prev_new->ext_size += ext_size;
1579 } else {
1580 prev_new->ext = ext;
1581 prev_new->ext_size = ext_size;
1582 }
1583
1584 if (lys_copy_union_leafrefs(mod, parent, &type->der->type, prev_new, unres)) {
1585 return -1;
1586 }
1587 } else {
1588 /* type, just make a deep copy */
1589 switch (type->base) {
1590 case LY_TYPE_UNION:
1591 prev_new->info.uni.has_ptr_type = type->info.uni.has_ptr_type;
1592 prev_new->info.uni.count = type->info.uni.count;
1593 /* this cannot be a typedef anymore */
1594 assert(prev_new->info.uni.count);
1595
1596 prev_new->info.uni.types = calloc(prev_new->info.uni.count, sizeof *prev_new->info.uni.types);
1597 LY_CHECK_ERR_RETURN(!prev_new->info.uni.types, LOGMEM, -1);
1598
1599 for (i = 0; i < prev_new->info.uni.count; i++) {
1600 if (lys_copy_union_leafrefs(mod, parent, &(type->info.uni.types[i]), &(prev_new->info.uni.types[i]), unres)) {
1601 return -1;
1602 }
1603 }
1604
1605 prev_new->der = type->der;
1606 break;
1607 default:
1608 if (lys_type_dup(mod, parent, prev_new, type, 0, 0, unres)) {
1609 return -1;
1610 }
1611 break;
1612 }
1613 }
1614
1615 if (top_type) {
1616 memcpy(type, prev_new, sizeof *type);
1617 }
1618 return EXIT_SUCCESS;
1619}
1620
Radek Krejci43ce4b72017-01-04 11:02:38 +01001621API const void *
1622lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1623{
1624 if (!ext) {
1625 return NULL;
1626 }
1627
Radek Krejcifebdad72017-02-06 11:35:51 +01001628 switch (ext->insubstmt) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001629 case LYEXT_SUBSTMT_SELF:
1630 case LYEXT_SUBSTMT_MODIFIER:
1631 case LYEXT_SUBSTMT_VERSION:
1632 return NULL;
1633 case LYEXT_SUBSTMT_ARGUMENT:
1634 if (ext->parent_type == LYEXT_PAR_EXT) {
1635 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1636 }
1637 break;
1638 case LYEXT_SUBSTMT_BASE:
1639 if (ext->parent_type == LYEXT_PAR_TYPE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001640 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001641 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001642 return ((struct lys_ident*)ext->parent)->base[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001643 }
1644 break;
1645 case LYEXT_SUBSTMT_BELONGSTO:
1646 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1647 return ((struct lys_submodule*)ext->parent)->belongsto;
1648 }
1649 break;
1650 case LYEXT_SUBSTMT_CONFIG:
1651 case LYEXT_SUBSTMT_MANDATORY:
1652 if (ext->parent_type == LYEXT_PAR_NODE) {
1653 return &((struct lys_node*)ext->parent)->flags;
1654 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1655 return &((struct lys_deviate*)ext->parent)->flags;
1656 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1657 return &((struct lys_refine*)ext->parent)->flags;
1658 }
1659 break;
1660 case LYEXT_SUBSTMT_CONTACT:
1661 if (ext->parent_type == LYEXT_PAR_MODULE) {
1662 return ((struct lys_module*)ext->parent)->contact;
1663 }
1664 break;
1665 case LYEXT_SUBSTMT_DEFAULT:
1666 if (ext->parent_type == LYEXT_PAR_NODE) {
1667 switch (((struct lys_node*)ext->parent)->nodetype) {
1668 case LYS_LEAF:
1669 case LYS_LEAFLIST:
1670 /* in case of leaf, the index is supposed to be 0, so it will return the
1671 * correct pointer despite the leaf structure does not have dflt as array */
Radek Krejcifebdad72017-02-06 11:35:51 +01001672 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001673 case LYS_CHOICE:
1674 return ((struct lys_node_choice*)ext->parent)->dflt;
1675 default:
1676 /* internal error */
1677 break;
1678 }
1679 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1680 return ((struct lys_tpdf*)ext->parent)->dflt;
1681 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001682 return ((struct lys_deviate*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001683 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001684 return &((struct lys_refine*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001685 }
1686 break;
1687 case LYEXT_SUBSTMT_DESCRIPTION:
1688 switch (ext->parent_type) {
1689 case LYEXT_PAR_NODE:
1690 return ((struct lys_node*)ext->parent)->dsc;
1691 case LYEXT_PAR_MODULE:
1692 return ((struct lys_module*)ext->parent)->dsc;
1693 case LYEXT_PAR_IMPORT:
1694 return ((struct lys_import*)ext->parent)->dsc;
1695 case LYEXT_PAR_INCLUDE:
1696 return ((struct lys_include*)ext->parent)->dsc;
1697 case LYEXT_PAR_EXT:
1698 return ((struct lys_ext*)ext->parent)->dsc;
1699 case LYEXT_PAR_FEATURE:
1700 return ((struct lys_feature*)ext->parent)->dsc;
1701 case LYEXT_PAR_TPDF:
1702 return ((struct lys_tpdf*)ext->parent)->dsc;
1703 case LYEXT_PAR_TYPE_BIT:
1704 return ((struct lys_type_bit*)ext->parent)->dsc;
1705 case LYEXT_PAR_TYPE_ENUM:
1706 return ((struct lys_type_enum*)ext->parent)->dsc;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001707 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001708 return ((struct lys_restr*)ext->parent)->dsc;
1709 case LYEXT_PAR_WHEN:
1710 return ((struct lys_when*)ext->parent)->dsc;
1711 case LYEXT_PAR_IDENT:
1712 return ((struct lys_ident*)ext->parent)->dsc;
1713 case LYEXT_PAR_DEVIATION:
1714 return ((struct lys_deviation*)ext->parent)->dsc;
1715 case LYEXT_PAR_REVISION:
1716 return ((struct lys_revision*)ext->parent)->dsc;
1717 case LYEXT_PAR_REFINE:
1718 return ((struct lys_refine*)ext->parent)->dsc;
1719 default:
1720 break;
1721 }
1722 break;
1723 case LYEXT_SUBSTMT_ERRTAG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001724 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001725 return ((struct lys_restr*)ext->parent)->eapptag;
1726 }
1727 break;
1728 case LYEXT_SUBSTMT_ERRMSG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001729 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001730 return ((struct lys_restr*)ext->parent)->emsg;
1731 }
1732 break;
1733 case LYEXT_SUBSTMT_DIGITS:
1734 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
1735 return &((struct lys_type*)ext->parent)->info.dec64.dig;
1736 }
1737 break;
1738 case LYEXT_SUBSTMT_KEY:
1739 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1740 return ((struct lys_node_list*)ext->parent)->keys;
1741 }
1742 break;
1743 case LYEXT_SUBSTMT_MAX:
1744 if (ext->parent_type == LYEXT_PAR_NODE) {
1745 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1746 return &((struct lys_node_list*)ext->parent)->max;
1747 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1748 return &((struct lys_node_leaflist*)ext->parent)->max;
1749 }
1750 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1751 return &((struct lys_refine*)ext->parent)->mod.list.max;
1752 }
1753 break;
1754 case LYEXT_SUBSTMT_MIN:
1755 if (ext->parent_type == LYEXT_PAR_NODE) {
1756 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1757 return &((struct lys_node_list*)ext->parent)->min;
1758 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1759 return &((struct lys_node_leaflist*)ext->parent)->min;
1760 }
1761 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1762 return &((struct lys_refine*)ext->parent)->mod.list.min;
1763 }
1764 break;
1765 case LYEXT_SUBSTMT_NAMESPACE:
1766 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
1767 return ((struct lys_module*)ext->parent)->ns;
1768 }
1769 break;
1770 case LYEXT_SUBSTMT_ORDEREDBY:
1771 if (ext->parent_type == LYEXT_PAR_NODE &&
1772 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
1773 return &((struct lys_node_list*)ext->parent)->flags;
1774 }
1775 break;
1776 case LYEXT_SUBSTMT_ORGANIZATION:
1777 if (ext->parent_type == LYEXT_PAR_MODULE) {
1778 return ((struct lys_module*)ext->parent)->org;
1779 }
1780 break;
1781 case LYEXT_SUBSTMT_PATH:
1782 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1783 return ((struct lys_type*)ext->parent)->info.lref.path;
1784 }
1785 break;
1786 case LYEXT_SUBSTMT_POSITION:
1787 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
1788 return &((struct lys_type_bit*)ext->parent)->pos;
1789 }
1790 break;
1791 case LYEXT_SUBSTMT_PREFIX:
1792 if (ext->parent_type == LYEXT_PAR_MODULE) {
1793 /* covers also lys_submodule */
1794 return ((struct lys_module*)ext->parent)->prefix;
1795 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
1796 return ((struct lys_import*)ext->parent)->prefix;
1797 }
1798 break;
1799 case LYEXT_SUBSTMT_PRESENCE:
1800 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
1801 return ((struct lys_node_container*)ext->parent)->presence;
1802 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1803 return ((struct lys_refine*)ext->parent)->mod.presence;
1804 }
1805 break;
1806 case LYEXT_SUBSTMT_REFERENCE:
1807 switch (ext->parent_type) {
1808 case LYEXT_PAR_NODE:
1809 return ((struct lys_node*)ext->parent)->ref;
1810 case LYEXT_PAR_MODULE:
1811 return ((struct lys_module*)ext->parent)->ref;
1812 case LYEXT_PAR_IMPORT:
1813 return ((struct lys_import*)ext->parent)->ref;
1814 case LYEXT_PAR_INCLUDE:
1815 return ((struct lys_include*)ext->parent)->ref;
1816 case LYEXT_PAR_EXT:
1817 return ((struct lys_ext*)ext->parent)->ref;
1818 case LYEXT_PAR_FEATURE:
1819 return ((struct lys_feature*)ext->parent)->ref;
1820 case LYEXT_PAR_TPDF:
1821 return ((struct lys_tpdf*)ext->parent)->ref;
1822 case LYEXT_PAR_TYPE_BIT:
1823 return ((struct lys_type_bit*)ext->parent)->ref;
1824 case LYEXT_PAR_TYPE_ENUM:
1825 return ((struct lys_type_enum*)ext->parent)->ref;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001826 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001827 return ((struct lys_restr*)ext->parent)->ref;
1828 case LYEXT_PAR_WHEN:
1829 return ((struct lys_when*)ext->parent)->ref;
1830 case LYEXT_PAR_IDENT:
1831 return ((struct lys_ident*)ext->parent)->ref;
1832 case LYEXT_PAR_DEVIATION:
1833 return ((struct lys_deviation*)ext->parent)->ref;
1834 case LYEXT_PAR_REVISION:
1835 return ((struct lys_revision*)ext->parent)->ref;
1836 case LYEXT_PAR_REFINE:
1837 return ((struct lys_refine*)ext->parent)->ref;
1838 default:
1839 break;
1840 }
1841 break;
Radek Krejcibe336392017-02-07 10:54:24 +01001842 case LYEXT_SUBSTMT_REQINSTANCE:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001843 if (ext->parent_type == LYEXT_PAR_TYPE) {
1844 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1845 return &((struct lys_type*)ext->parent)->info.lref.req;
1846 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
1847 return &((struct lys_type*)ext->parent)->info.inst.req;
1848 }
1849 }
1850 break;
1851 case LYEXT_SUBSTMT_REVISIONDATE:
1852 if (ext->parent_type == LYEXT_PAR_IMPORT) {
1853 return ((struct lys_import*)ext->parent)->rev;
1854 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
1855 return ((struct lys_include*)ext->parent)->rev;
1856 }
1857 break;
1858 case LYEXT_SUBSTMT_STATUS:
1859 switch (ext->parent_type) {
1860 case LYEXT_PAR_NODE:
1861 case LYEXT_PAR_IDENT:
1862 case LYEXT_PAR_TPDF:
1863 case LYEXT_PAR_EXT:
1864 case LYEXT_PAR_FEATURE:
1865 case LYEXT_PAR_TYPE_ENUM:
1866 case LYEXT_PAR_TYPE_BIT:
1867 /* in all structures the flags member is at the same offset */
1868 return &((struct lys_node*)ext->parent)->flags;
1869 default:
1870 break;
1871 }
1872 break;
1873 case LYEXT_SUBSTMT_UNIQUE:
1874 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001875 return &((struct lys_deviate*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001876 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001877 return &((struct lys_node_list*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001878 }
1879 break;
1880 case LYEXT_SUBSTMT_UNITS:
1881 if (ext->parent_type == LYEXT_PAR_NODE &&
1882 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1883 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
1884 return ((struct lys_node_leaf*)ext->parent)->units;
1885 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1886 return ((struct lys_tpdf*)ext->parent)->units;
1887 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1888 return ((struct lys_deviate*)ext->parent)->units;
1889 }
1890 break;
1891 case LYEXT_SUBSTMT_VALUE:
1892 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
1893 return &((struct lys_type_enum*)ext->parent)->value;
1894 }
1895 break;
1896 case LYEXT_SUBSTMT_YINELEM:
1897 if (ext->parent_type == LYEXT_PAR_EXT) {
1898 return &((struct lys_ext*)ext->parent)->flags;
1899 }
1900 break;
1901 }
1902 LOGINT;
1903 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01001904}
1905
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001906static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001907lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci5138e9f2017-04-12 13:10:46 +02001908 int in_grp, int shallow, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001909{
1910 int i;
1911
Michal Vasko1dca6882015-10-22 14:29:42 +02001912 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001913 new->base = old->base;
1914 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001915 new->parent = (struct lys_tpdf *)parent;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001916 new->ext_size = old->ext_size;
Radek Krejci5138e9f2017-04-12 13:10:46 +02001917 if (lys_ext_dup(mod, old->ext, old->ext_size, new, LYEXT_PAR_TYPE, &new->ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01001918 return -1;
Radek Krejcie534c132016-11-23 13:32:31 +01001919 }
Radek Krejci3733a802015-06-19 13:43:21 +02001920
Michal Vasko1c007172017-03-10 10:20:44 +01001921 i = unres_schema_find(unres, -1, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001922 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001923 /* HACK (serious one) for unres */
1924 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001925 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001926 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, in_grp,
1927 shallow, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001928 } else {
1929 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1930 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001931 /* all these unres additions can fail even though they did not before */
Michal Vasko1c007172017-03-10 10:20:44 +01001932 if (!new->der || (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent) == -1)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001933 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001934 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001935 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001936 }
1937
Radek Krejci5138e9f2017-04-12 13:10:46 +02001938 return type_dup(mod, parent, new, old, new->base, in_grp, shallow, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001939}
1940
1941void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001942lys_type_free(struct ly_ctx *ctx, struct lys_type *type,
1943 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02001944{
Radek Krejcidce5f972017-09-12 15:47:49 +02001945 unsigned int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001947 assert(ctx);
1948 if (!type) {
1949 return;
1950 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001951
Michal Vasko1dca6882015-10-22 14:29:42 +02001952 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001953
Radek Krejci5138e9f2017-04-12 13:10:46 +02001954 lys_extension_instances_free(ctx, type->ext, type->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01001955
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001956 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001957 case LY_TYPE_BINARY:
Radek Krejci5138e9f2017-04-12 13:10:46 +02001958 lys_restr_free(ctx, type->info.binary.length, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001959 free(type->info.binary.length);
1960 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001961 case LY_TYPE_BITS:
1962 for (i = 0; i < type->info.bits.count; i++) {
1963 lydict_remove(ctx, type->info.bits.bit[i].name);
1964 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1965 lydict_remove(ctx, type->info.bits.bit[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00001966 lys_iffeature_free(ctx, type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size, 0,
Radek Krejci5138e9f2017-04-12 13:10:46 +02001967 private_destructor);
1968 lys_extension_instances_free(ctx, type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size,
1969 private_destructor);
Radek Krejci994b6f62015-06-18 16:47:27 +02001970 }
1971 free(type->info.bits.bit);
1972 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001973
1974 case LY_TYPE_DEC64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02001975 lys_restr_free(ctx, type->info.dec64.range, private_destructor);
Radek Krejcif9401c32015-06-26 16:47:36 +02001976 free(type->info.dec64.range);
1977 break;
1978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001979 case LY_TYPE_ENUM:
1980 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001981 lydict_remove(ctx, type->info.enums.enm[i].name);
1982 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1983 lydict_remove(ctx, type->info.enums.enm[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00001984 lys_iffeature_free(ctx, type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size, 0,
Radek Krejci5138e9f2017-04-12 13:10:46 +02001985 private_destructor);
1986 lys_extension_instances_free(ctx, type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size,
1987 private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001988 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001989 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001991
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001992 case LY_TYPE_INT8:
1993 case LY_TYPE_INT16:
1994 case LY_TYPE_INT32:
1995 case LY_TYPE_INT64:
1996 case LY_TYPE_UINT8:
1997 case LY_TYPE_UINT16:
1998 case LY_TYPE_UINT32:
1999 case LY_TYPE_UINT64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002000 lys_restr_free(ctx, type->info.num.range, private_destructor);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02002001 free(type->info.num.range);
2002 break;
2003
Radek Krejcidc4c1412015-06-19 15:39:54 +02002004 case LY_TYPE_LEAFREF:
2005 lydict_remove(ctx, type->info.lref.path);
2006 break;
2007
Radek Krejci3733a802015-06-19 13:43:21 +02002008 case LY_TYPE_STRING:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002009 lys_restr_free(ctx, type->info.str.length, private_destructor);
Radek Krejci3733a802015-06-19 13:43:21 +02002010 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02002011 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002012 lys_restr_free(ctx, &type->info.str.patterns[i], private_destructor);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002013#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002014 if (type->info.str.patterns_pcre) {
2015 pcre_free((pcre*)type->info.str.patterns_pcre[2 * i]);
2016 pcre_free_study((pcre_extra*)type->info.str.patterns_pcre[2 * i + 1]);
2017 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02002018#endif
Radek Krejci5fbc9162015-06-19 14:11:11 +02002019 }
2020 free(type->info.str.patterns);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002021#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002022 free(type->info.str.patterns_pcre);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002023#endif
Radek Krejci3733a802015-06-19 13:43:21 +02002024 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002025
Radek Krejcie4c366b2015-07-02 10:11:31 +02002026 case LY_TYPE_UNION:
2027 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002028 lys_type_free(ctx, &type->info.uni.types[i], private_destructor);
Radek Krejcie4c366b2015-07-02 10:11:31 +02002029 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02002030 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002031 break;
2032
Michal Vaskod3282192016-09-05 11:27:57 +02002033 case LY_TYPE_IDENT:
2034 free(type->info.ident.ref);
2035 break;
2036
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002037 default:
Michal Vaskod3282192016-09-05 11:27:57 +02002038 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 break;
2040 }
Radek Krejci5a065542015-05-22 15:02:07 +02002041}
2042
Radek Krejci1d82ef62015-08-07 14:44:40 +02002043static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002044lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf,
2045 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002046{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 assert(ctx);
2048 if (!tpdf) {
2049 return;
2050 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052 lydict_remove(ctx, tpdf->name);
2053 lydict_remove(ctx, tpdf->dsc);
2054 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002055
Radek Krejci5138e9f2017-04-12 13:10:46 +02002056 lys_type_free(ctx, &tpdf->type, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002058 lydict_remove(ctx, tpdf->units);
2059 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01002060
Radek Krejci5138e9f2017-04-12 13:10:46 +02002061 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002062}
2063
Radek Krejci1d82ef62015-08-07 14:44:40 +02002064static struct lys_when *
Radek Krejci5138e9f2017-04-12 13:10:46 +02002065lys_when_dup(struct lys_module *mod, struct lys_when *old, int shallow, struct unres_schema *unres)
Radek Krejci00768f42015-06-18 17:04:04 +02002066{
Radek Krejci76512572015-08-04 09:47:08 +02002067 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02002068
2069 if (!old) {
2070 return NULL;
2071 }
2072
2073 new = calloc(1, sizeof *new);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002074 LY_CHECK_ERR_RETURN(!new, LOGMEM, NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01002075 new->cond = lydict_insert(mod->ctx, old->cond, 0);
2076 new->dsc = lydict_insert(mod->ctx, old->dsc, 0);
2077 new->ref = lydict_insert(mod->ctx, old->ref, 0);
Radek Krejcif0bb3602017-01-25 17:05:08 +01002078 new->ext_size = old->ext_size;
Radek Krejci5138e9f2017-04-12 13:10:46 +02002079 lys_ext_dup(mod, old->ext, old->ext_size, new, LYEXT_PAR_WHEN, &new->ext, shallow, unres);
Radek Krejci00768f42015-06-18 17:04:04 +02002080
2081 return new;
2082}
2083
Michal Vasko0308dd62015-10-07 09:14:40 +02002084void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002085lys_when_free(struct ly_ctx *ctx, struct lys_when *w,
2086 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002087{
2088 if (!w) {
2089 return;
2090 }
2091
Radek Krejci5138e9f2017-04-12 13:10:46 +02002092 lys_extension_instances_free(ctx, w->ext, w->ext_size, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002093 lydict_remove(ctx, w->cond);
2094 lydict_remove(ctx, w->dsc);
2095 lydict_remove(ctx, w->ref);
2096
2097 free(w);
2098}
2099
Radek Krejcib7f5e412015-08-13 10:15:51 +02002100static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002101lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug,
2102 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02002103{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002104 struct lys_node *next, *sub;
2105
Radek Krejcic071c542016-01-27 14:57:51 +01002106 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01002107 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002108 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002109 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002110 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002111 }
2112
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002113 lydict_remove(ctx, aug->target_name);
2114 lydict_remove(ctx, aug->dsc);
2115 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002116
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002117 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002118 lys_extension_instances_free(ctx, aug->ext, aug->ext_size, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002119
Radek Krejci5138e9f2017-04-12 13:10:46 +02002120 lys_when_free(ctx, aug->when, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002121}
2122
Radek Krejci1d82ef62015-08-07 14:44:40 +02002123static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002124lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident,
2125 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci6793db02015-05-22 17:49:54 +02002126{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 assert(ctx);
2128 if (!ident) {
2129 return;
2130 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002131
Radek Krejci018f1f52016-08-03 16:01:20 +02002132 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02002133 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 lydict_remove(ctx, ident->name);
2135 lydict_remove(ctx, ident->dsc);
2136 lydict_remove(ctx, ident->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002137 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002138 lys_extension_instances_free(ctx, ident->ext, ident->ext_size, private_destructor);
Radek Krejci6793db02015-05-22 17:49:54 +02002139
2140}
2141
Radek Krejci1d82ef62015-08-07 14:44:40 +02002142static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002143lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp,
2144 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002145{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002147
Radek Krejcid12f57b2015-08-06 10:43:39 +02002148 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002150 lys_tpdf_free(ctx, &grp->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 }
2152 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002153}
2154
Radek Krejci1d82ef62015-08-07 14:44:40 +02002155static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002156lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io,
2157 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcid12f57b2015-08-06 10:43:39 +02002158{
2159 int i;
2160
2161 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
2162 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002163 lys_tpdf_free(ctx, &io->tpdf[i], private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002164 }
2165 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002166
2167 for (i = 0; i < io->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002168 lys_restr_free(ctx, &io->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002169 }
2170 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002171}
2172
Radek Krejci1d82ef62015-08-07 14:44:40 +02002173static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002174lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif,
2175 void (*private_destructor)(const struct lys_node *node, void *priv))
Pavol Vican7cff97e2016-08-09 14:56:08 +02002176{
2177 int i;
2178
2179 for (i = 0; i < notif->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002180 lys_restr_free(ctx, &notif->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002181 }
2182 free(notif->must);
2183
2184 for (i = 0; i < notif->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002185 lys_tpdf_free(ctx, &notif->tpdf[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002186 }
2187 free(notif->tpdf);
2188}
2189static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002190lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml,
2191 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci537cf382015-06-04 11:07:01 +02002192{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002196 lys_restr_free(ctx, &anyxml->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 }
2198 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002199
Radek Krejci5138e9f2017-04-12 13:10:46 +02002200 lys_when_free(ctx, anyxml->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002201}
2202
Radek Krejci1d82ef62015-08-07 14:44:40 +02002203static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002204lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf,
2205 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002206{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002208
Radek Krejci85a54be2016-10-20 12:39:56 +02002209 /* leafref backlinks */
2210 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002213 lys_restr_free(ctx, &leaf->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 }
2215 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002216
Radek Krejci5138e9f2017-04-12 13:10:46 +02002217 lys_when_free(ctx, leaf->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002218
Radek Krejci5138e9f2017-04-12 13:10:46 +02002219 lys_type_free(ctx, &leaf->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 lydict_remove(ctx, leaf->units);
2221 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002222}
2223
Radek Krejci1d82ef62015-08-07 14:44:40 +02002224static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002225lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist,
2226 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002227{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002228 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002229
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002230 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002231 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002232 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002233 }
2234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 for (i = 0; i < llist->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002236 lys_restr_free(ctx, &llist->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 }
2238 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002239
Pavol Vican38321d02016-08-16 14:56:02 +02002240 for (i = 0; i < llist->dflt_size; i++) {
2241 lydict_remove(ctx, llist->dflt[i]);
2242 }
2243 free(llist->dflt);
2244
Radek Krejci5138e9f2017-04-12 13:10:46 +02002245 lys_when_free(ctx, llist->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002246
Radek Krejci5138e9f2017-04-12 13:10:46 +02002247 lys_type_free(ctx, &llist->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002249}
2250
Radek Krejci1d82ef62015-08-07 14:44:40 +02002251static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002252lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list,
2253 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002254{
Radek Krejci581ce772015-11-10 17:22:40 +01002255 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 /* handle only specific parts for LY_NODE_LIST */
2258 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002259 lys_tpdf_free(ctx, &list->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 }
2261 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 for (i = 0; i < list->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002264 lys_restr_free(ctx, &list->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 }
2266 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002267
Radek Krejci5138e9f2017-04-12 13:10:46 +02002268 lys_when_free(ctx, list->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002270 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002271 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002272 lydict_remove(ctx, list->unique[i].expr[j]);
2273 }
2274 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 }
2276 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002279}
2280
Radek Krejci1d82ef62015-08-07 14:44:40 +02002281static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002282lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont,
2283 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002284{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002287 /* handle only specific parts for LY_NODE_CONTAINER */
2288 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002291 lys_tpdf_free(ctx, &cont->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 }
2293 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002295 for (i = 0; i < cont->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002296 lys_restr_free(ctx, &cont->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 }
2298 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002299
Radek Krejci5138e9f2017-04-12 13:10:46 +02002300 lys_when_free(ctx, cont->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002301}
2302
Radek Krejci1d82ef62015-08-07 14:44:40 +02002303static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002304lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f,
2305 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci3cf9e222015-06-18 11:37:50 +02002306{
2307 lydict_remove(ctx, f->name);
2308 lydict_remove(ctx, f->dsc);
2309 lydict_remove(ctx, f->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002310 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size, 0, private_destructor);
Radek Krejci9de2c042016-10-19 16:53:06 +02002311 ly_set_free(f->depfeatures);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002312 lys_extension_instances_free(ctx, f->ext, f->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002313}
2314
2315static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002316lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e,
2317 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie534c132016-11-23 13:32:31 +01002318{
2319 lydict_remove(ctx, e->name);
2320 lydict_remove(ctx, e->dsc);
2321 lydict_remove(ctx, e->ref);
2322 lydict_remove(ctx, e->argument);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002323 lys_extension_instances_free(ctx, e->ext, e->ext_size, private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002324}
2325
Radek Krejci1d82ef62015-08-07 14:44:40 +02002326static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002327lys_deviation_free(struct lys_module *module, struct lys_deviation *dev,
2328 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcieb00f512015-07-01 16:44:58 +02002329{
Radek Krejci581ce772015-11-10 17:22:40 +01002330 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002331 struct ly_ctx *ctx;
2332 struct lys_node *next, *elem;
2333
2334 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002335
2336 lydict_remove(ctx, dev->target_name);
2337 lydict_remove(ctx, dev->dsc);
2338 lydict_remove(ctx, dev->ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002339 lys_extension_instances_free(ctx, dev->ext, dev->ext_size, private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002340
Pavol Vican64d0b762016-08-25 10:44:59 +02002341 if (!dev->deviate) {
2342 return ;
2343 }
2344
Michal Vaskoff006c12016-02-17 11:15:19 +01002345 /* the module was freed, but we only need the context from orig_node, use ours */
2346 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2347 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2348 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2349 elem->module = module;
2350
2351 LY_TREE_DFS_END(dev->orig_node, next, elem);
2352 }
2353 lys_node_free(dev->orig_node, NULL, 0);
2354 } else {
2355 /* it's just a shallow copy, freeing one node */
2356 dev->orig_node->module = module;
2357 lys_node_free(dev->orig_node, NULL, 1);
2358 }
2359
Radek Krejcieb00f512015-07-01 16:44:58 +02002360 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002361 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size, private_destructor);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002362
Radek Krejcid5a5c282016-08-15 15:38:08 +02002363 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002364 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002365 }
2366 free(dev->deviate[i].dflt);
2367
Radek Krejcieb00f512015-07-01 16:44:58 +02002368 lydict_remove(ctx, dev->deviate[i].units);
2369
2370 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2371 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002372 lys_restr_free(ctx, &dev->deviate[i].must[j], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002373 }
2374 free(dev->deviate[i].must);
2375
2376 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002377 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2378 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2379 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002380 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002381 }
2382 free(dev->deviate[i].unique);
2383 }
2384 }
2385 free(dev->deviate);
2386}
2387
Radek Krejci1d82ef62015-08-07 14:44:40 +02002388static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002389lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses,
2390 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02002391{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002392 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002394 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002395 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002396 lydict_remove(ctx, uses->refine[i].dsc);
2397 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002398
Radek Krejcifde04bd2017-09-13 16:38:38 +02002399 lys_iffeature_free(ctx, uses->refine[i].iffeature, uses->refine[i].iffeature_size, 0, private_destructor);
2400
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002401 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002402 lys_restr_free(ctx, &uses->refine[i].must[j], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002403 }
2404 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002405
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002406 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002407 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002408 }
2409 free(uses->refine[i].dflt);
2410
Radek Krejci5138e9f2017-04-12 13:10:46 +02002411 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002412
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002413 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002414 lydict_remove(ctx, uses->refine[i].mod.presence);
2415 }
2416 }
2417 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002419 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002420 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 }
2422 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002423
Radek Krejci5138e9f2017-04-12 13:10:46 +02002424 lys_when_free(ctx, uses->when, private_destructor);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002425}
2426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002427void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002428lys_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 +02002429{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002430 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002431 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 if (!node) {
2434 return;
2435 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002436
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437 assert(node->module);
2438 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002440 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002441
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002442 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002443 if (node->priv && private_destructor) {
2444 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002445 }
2446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002447 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002448 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002449 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002450 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size, shallow, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002451 lydict_remove(ctx, node->dsc);
2452 lydict_remove(ctx, node->ref);
2453 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002454
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002455 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002456 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002457 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002458 }
2459 }
2460
Radek Krejci5138e9f2017-04-12 13:10:46 +02002461 lys_extension_instances_free(ctx, node->ext, node->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002463 /* specific part */
2464 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002465 case LYS_CONTAINER:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002466 lys_container_free(ctx, (struct lys_node_container *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002467 break;
Radek Krejci76512572015-08-04 09:47:08 +02002468 case LYS_CHOICE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002469 lys_when_free(ctx, ((struct lys_node_choice *)node)->when, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002470 break;
Radek Krejci76512572015-08-04 09:47:08 +02002471 case LYS_LEAF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002472 lys_leaf_free(ctx, (struct lys_node_leaf *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 break;
Radek Krejci76512572015-08-04 09:47:08 +02002474 case LYS_LEAFLIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002475 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002476 break;
Radek Krejci76512572015-08-04 09:47:08 +02002477 case LYS_LIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002478 lys_list_free(ctx, (struct lys_node_list *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002479 break;
Radek Krejci76512572015-08-04 09:47:08 +02002480 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002481 case LYS_ANYDATA:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002482 lys_anydata_free(ctx, (struct lys_node_anydata *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483 break;
Radek Krejci76512572015-08-04 09:47:08 +02002484 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002485 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002486 break;
Radek Krejci76512572015-08-04 09:47:08 +02002487 case LYS_CASE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002488 lys_when_free(ctx, ((struct lys_node_case *)node)->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002489 break;
Radek Krejci76512572015-08-04 09:47:08 +02002490 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 /* do nothing */
2492 break;
Radek Krejci76512572015-08-04 09:47:08 +02002493 case LYS_GROUPING:
2494 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002495 case LYS_ACTION:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002496 lys_grp_free(ctx, (struct lys_node_grp *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002497 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002498 case LYS_NOTIF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002499 lys_notif_free(ctx, (struct lys_node_notif *)node, private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002500 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002501 case LYS_INPUT:
2502 case LYS_OUTPUT:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002503 lys_inout_free(ctx, (struct lys_node_inout *)node, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002504 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01002505 case LYS_EXT:
Michal Vasko591e0b22015-08-13 13:53:43 +02002506 case LYS_UNKNOWN:
2507 LOGINT;
2508 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002509 }
Radek Krejci5a065542015-05-22 15:02:07 +02002510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002511 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002512 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002513 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002514}
2515
Radek Krejci2eee5c02016-12-06 19:18:05 +01002516API struct lys_module *
2517lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002518{
2519 struct ly_ctx *ctx;
2520 int i;
2521
2522 if (!mod || mod->implemented) {
2523 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002524 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002525 }
2526
2527 ctx = mod->ctx;
2528 for (i = 0; i < ctx->models.used; i++) {
2529 if (!ctx->models.list[i]->implemented) {
2530 continue;
2531 }
2532
2533 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2534 /* we have some revision of the module implemented */
2535 return ctx->models.list[i];
2536 }
2537 }
2538
2539 /* we have no revision of the module implemented, return the module itself,
2540 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002541 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002542}
2543
Michal Vasko13b15832015-08-19 11:04:48 +02002544/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002545static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002546module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002547{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002548 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002549 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002550 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002551
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002552 assert(module->ctx);
2553 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002554
Michal Vaskob746fff2016-02-11 11:37:50 +01002555 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002556 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002557 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002558 lydict_remove(ctx, module->imp[i].dsc);
2559 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002560 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size, private_destructor);
Radek Krejci225376f2016-02-16 17:36:22 +01002561 }
Radek Krejcidce51452015-06-16 15:20:08 +02002562 free(module->imp);
2563
Radek Krejcic071c542016-01-27 14:57:51 +01002564 /* submodules don't have data tree, the data nodes
2565 * are placed in the main module altogether */
2566 if (!module->type) {
2567 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002568 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002569 }
Radek Krejci21181962015-06-30 14:11:00 +02002570 }
Radek Krejci5a065542015-05-22 15:02:07 +02002571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002572 lydict_remove(ctx, module->dsc);
2573 lydict_remove(ctx, module->ref);
2574 lydict_remove(ctx, module->org);
2575 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002576 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002577
Radek Krejcieb00f512015-07-01 16:44:58 +02002578 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002579 for (i = 0; i < module->rev_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002580 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002581 lydict_remove(ctx, module->rev[i].dsc);
2582 lydict_remove(ctx, module->rev[i].ref);
2583 }
2584 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002585
Radek Krejcieb00f512015-07-01 16:44:58 +02002586 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002587 for (i = 0; i < module->ident_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002588 lys_ident_free(ctx, &module->ident[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002589 }
2590 module->ident_size = 0;
2591 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002592
Radek Krejcieb00f512015-07-01 16:44:58 +02002593 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002594 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002595 lys_tpdf_free(ctx, &module->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002596 }
2597 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002598
Radek Krejcie534c132016-11-23 13:32:31 +01002599 /* extension instances */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002600 lys_extension_instances_free(ctx, module->ext, module->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002601
Radek Krejcieb00f512015-07-01 16:44:58 +02002602 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002603 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002604 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002605 }
2606 free(module->augment);
2607
Radek Krejcieb00f512015-07-01 16:44:58 +02002608 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002609 for (i = 0; i < module->features_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002610 lys_feature_free(ctx, &module->features[i], private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002611 }
2612 free(module->features);
2613
Radek Krejcieb00f512015-07-01 16:44:58 +02002614 /* deviations */
2615 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002616 lys_deviation_free(module, &module->deviation[i], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002617 }
2618 free(module->deviation);
2619
Radek Krejcie534c132016-11-23 13:32:31 +01002620 /* extensions */
2621 for (i = 0; i < module->extensions_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002622 lys_extension_free(ctx, &module->extensions[i], private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002623 }
2624 free(module->extensions);
2625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002626 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002627 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002628}
2629
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002630void
Michal Vaskob746fff2016-02-11 11:37:50 +01002631lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002632{
Michal Vasko10681e82018-01-16 14:54:16 +01002633 int i;
2634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002635 if (!submodule) {
2636 return;
2637 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002639 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002640 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002641
Michal Vasko10681e82018-01-16 14:54:16 +01002642 /* include */
2643 for (i = 0; i < submodule->inc_size; i++) {
2644 lydict_remove(submodule->ctx, submodule->inc[i].dsc);
2645 lydict_remove(submodule->ctx, submodule->inc[i].ref);
2646 lys_extension_instances_free(submodule->ctx, submodule->inc[i].ext, submodule->inc[i].ext_size, private_destructor);
2647 /* complete submodule free is done only from main module since
2648 * submodules propagate their includes to the main module */
2649 }
2650 free(submodule->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002652 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002653}
2654
Radek Krejcib53154b2017-07-19 09:14:13 +02002655int
2656lys_ingrouping(const struct lys_node *node)
Radek Krejci3a5501d2016-07-18 22:03:34 +02002657{
2658 const struct lys_node *iter = node;
2659 assert(node);
2660
2661 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2662 if (!iter) {
2663 return 0;
2664 } else {
2665 return 1;
2666 }
2667}
2668
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002669/*
2670 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2671 */
2672static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002673lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002674 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002675{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002676 struct lys_node *retval = NULL, *iter, *p;
Michal Vaskofe31cc02017-03-10 15:52:31 +01002677 struct lys_module *tmp_mod;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002678 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002679 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002680 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002681 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002682 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002683
Michal Vaskoc07187d2015-08-13 15:20:57 +02002684 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002685 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002686 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002687 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002688 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002689 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002690 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002691 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002692 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002693 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002694 struct lys_node_anydata *any = NULL;
2695 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002696 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002697 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002698 struct lys_node_rpc_action *rpc = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002699 struct lys_node_inout *io = NULL;
Radek Krejcic43151c2017-03-12 07:10:52 +01002700 struct lys_node_notif *ntf = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002701 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002702 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002704 /* we cannot just duplicate memory since the strings are stored in
2705 * dictionary and we need to update dictionary counters.
2706 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002707
Radek Krejci1d82ef62015-08-07 14:44:40 +02002708 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002709 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002710 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002711 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002712 break;
2713
Radek Krejci76512572015-08-04 09:47:08 +02002714 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002715 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002716 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002717 break;
2718
Radek Krejci76512572015-08-04 09:47:08 +02002719 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002720 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002721 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002722 break;
2723
Radek Krejci76512572015-08-04 09:47:08 +02002724 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002725 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002726 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 break;
2728
Radek Krejci76512572015-08-04 09:47:08 +02002729 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002730 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002731 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002732 break;
2733
Radek Krejci76512572015-08-04 09:47:08 +02002734 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002735 case LYS_ANYDATA:
2736 any = calloc(1, sizeof *any);
2737 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 break;
2739
Radek Krejci76512572015-08-04 09:47:08 +02002740 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002741 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002742 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 break;
2744
Radek Krejci76512572015-08-04 09:47:08 +02002745 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002746 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002747 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002748 break;
2749
Radek Krejci76512572015-08-04 09:47:08 +02002750 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002751 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002752 rpc = calloc(1, sizeof *rpc);
2753 retval = (struct lys_node *)rpc;
2754 break;
2755
Radek Krejci76512572015-08-04 09:47:08 +02002756 case LYS_INPUT:
2757 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002758 io = calloc(1, sizeof *io);
2759 retval = (struct lys_node *)io;
2760 break;
2761
Radek Krejci76512572015-08-04 09:47:08 +02002762 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002763 ntf = calloc(1, sizeof *ntf);
2764 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002765 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002766
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002767 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002768 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002769 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002770 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02002771 LY_CHECK_ERR_RETURN(!retval, LOGMEM, NULL);
Michal Vasko253035f2015-12-17 16:58:13 +01002772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002773 /*
2774 * duplicate generic part of the structure
2775 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002776 retval->name = lydict_insert(ctx, node->name, 0);
2777 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2778 retval->ref = lydict_insert(ctx, node->ref, 0);
2779 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002780
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002781 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002782 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002784 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002785
Radek Krejcif0bb3602017-01-25 17:05:08 +01002786 retval->ext_size = node->ext_size;
Radek Krejci5138e9f2017-04-12 13:10:46 +02002787 if (lys_ext_dup(module, node->ext, node->ext_size, retval, LYEXT_PAR_NODE, &retval->ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002788 goto error;
2789 }
2790
Radek Krejci06214042016-11-04 16:25:58 +01002791 if (node->iffeature_size) {
2792 retval->iffeature_size = node->iffeature_size;
2793 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002794 LY_CHECK_ERR_GOTO(!retval->iffeature, LOGMEM, error);
Michal Vasko253035f2015-12-17 16:58:13 +01002795 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002796
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002797 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002798 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002799 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2800 if (size1) {
2801 /* there is something to duplicate */
2802
2803 /* duplicate compiled expression */
2804 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2805 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002806 LY_CHECK_ERR_GOTO(!retval->iffeature[i].expr, LOGMEM, error);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002807 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2808
2809 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002810 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002811 LY_CHECK_ERR_GOTO(!retval->iffeature[i].features, LOGMEM; free(retval->iffeature[i].expr), error);
2812
Radek Krejci9ff0a922016-07-14 13:08:05 +02002813 for (j = 0; (unsigned int)j < size2; j++) {
2814 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2815 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002816 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002817 /* feature is resolved in origin, so copy it
2818 * - duplication is used for instantiating groupings
2819 * and if-feature inside grouping is supposed to be
2820 * resolved inside the original grouping, so we want
2821 * to keep pointers to features from the grouping
2822 * context */
2823 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2824 } else if (rc == -1) {
2825 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002826 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002827 }
2828 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01002829
2830 /* duplicate if-feature's extensions */
2831 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002832 if (lys_ext_dup(module, node->iffeature[i].ext, node->iffeature[i].ext_size,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002833 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002834 goto error;
2835 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002836 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002837
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002838 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01002839 p = parent;
2840 do {
2841 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
2842 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002843 if (iter) {
2844 flags = iter->flags & LYS_CONFIG_MASK;
2845 } else {
2846 /* default */
2847 flags = LYS_CONFIG_W;
2848 }
2849
2850 switch (finalize) {
2851 case 1:
2852 /* inherit config flags */
2853 if (retval->flags & LYS_CONFIG_SET) {
2854 /* skip nodes with an explicit config value */
2855 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
2856 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +01002857 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002858 goto error;
2859 }
2860 break;
2861 }
2862
2863 if (retval->nodetype != LYS_USES) {
2864 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
2865 }
Radek Krejci2cc25322017-09-06 16:32:02 +02002866
2867 /* inherit status */
Radek Krejcie2807ea2017-09-07 10:52:21 +02002868 if ((parent->flags & LYS_STATUS_MASK) > (retval->flags & LYS_STATUS_MASK)) {
2869 /* but do it only in case the parent has a stonger status */
2870 retval->flags &= ~LYS_STATUS_MASK;
2871 retval->flags |= (parent->flags & LYS_STATUS_MASK);
2872 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002873 break;
2874 case 2:
2875 /* erase config flags */
2876 retval->flags &= ~LYS_CONFIG_MASK;
2877 retval->flags &= ~LYS_CONFIG_SET;
2878 break;
2879 }
2880
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002881 /* connect it to the parent */
2882 if (lys_node_addchild(parent, retval->module, retval)) {
2883 goto error;
2884 }
Radek Krejcidce51452015-06-16 15:20:08 +02002885
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002886 /* go recursively */
2887 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002888 LY_TREE_FOR(node->child, iter) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002889 if (iter->nodetype & LYS_GROUPING) {
2890 /* do not instantiate groupings */
2891 continue;
2892 }
Radek Krejci6ff885d2017-01-03 14:06:22 +01002893 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002894 goto error;
2895 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002896 }
2897 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002898
2899 if (finalize == 1) {
2900 /* check that configuration lists have keys
2901 * - we really want to check keys_size in original node, because the keys are
2902 * not yet resolved here, it is done below in nodetype specific part */
2903 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
2904 && !((struct lys_node_list *)node)->keys_size) {
2905 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
2906 goto error;
2907 }
2908 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002909 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002910 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002911 }
2912
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002913 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 * duplicate specific part of the structure
2915 */
2916 switch (node->nodetype) {
2917 case LYS_CONTAINER:
2918 if (cont_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002919 cont->when = lys_when_dup(module, cont_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002920 LY_CHECK_GOTO(!cont->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002921 }
2922 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002923
Radek Krejcia8d111f2017-05-31 13:57:37 +02002924 if (cont_orig->must) {
2925 cont->must = lys_restr_dup(module, cont_orig->must, cont_orig->must_size, shallow, unres);
2926 LY_CHECK_GOTO(!cont->must, error);
2927 cont->must_size = cont_orig->must_size;
2928 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929
Radek Krejcif0bb3602017-01-25 17:05:08 +01002930 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
2931
2932 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002933 case LYS_CHOICE:
2934 if (choice_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002935 choice->when = lys_when_dup(module, choice_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002936 LY_CHECK_GOTO(!choice->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002937 }
2938
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002939 if (!shallow) {
2940 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002941 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2942 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2943 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002944 if (rc) {
2945 if (rc == EXIT_FAILURE) {
2946 LOGINT;
2947 }
2948 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002949 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002950 } else {
2951 /* useless to check return value, we don't know whether
2952 * there really wasn't any default defined or it just hasn't
2953 * been resolved, we just hope for the best :)
2954 */
2955 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002956 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002957 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002958 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002959 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002960 break;
2961
2962 case LYS_LEAF:
Radek Krejcib53154b2017-07-19 09:14:13 +02002963 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002964 goto error;
2965 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2967
2968 if (leaf_orig->dflt) {
2969 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejcib53154b2017-07-19 09:14:13 +02002970 if (!lys_ingrouping(retval) || (leaf->type.base != LY_TYPE_LEAFREF)) {
Radek Krejci968f6942017-03-25 15:55:01 -05002971 /* problem is when it is an identityref referencing an identity from a module
2972 * and we are using the grouping in a different module */
Radek Krejcid06f5a42017-03-25 16:03:42 -05002973 if (leaf->type.base == LY_TYPE_IDENT) {
Michal Vaskofe31cc02017-03-10 15:52:31 +01002974 tmp_mod = leaf_orig->module;
2975 } else {
2976 tmp_mod = module;
2977 }
2978 if (unres_schema_add_node(tmp_mod, unres, &leaf->type, UNRES_TYPE_DFLT,
2979 (struct lys_node *)(&leaf->dflt)) == -1) {
2980 goto error;
2981 }
Michal Vasko49168a22015-08-17 16:35:41 +02002982 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002983 }
2984
Radek Krejcia8d111f2017-05-31 13:57:37 +02002985 if (leaf_orig->must) {
2986 leaf->must = lys_restr_dup(module, leaf_orig->must, leaf_orig->must_size, shallow, unres);
2987 LY_CHECK_GOTO(!leaf->must, error);
2988 leaf->must_size = leaf_orig->must_size;
2989 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990
2991 if (leaf_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002992 leaf->when = lys_when_dup(module, leaf_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002993 LY_CHECK_GOTO(!leaf->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 }
2995 break;
2996
2997 case LYS_LEAFLIST:
Radek Krejcib53154b2017-07-19 09:14:13 +02002998 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002999 goto error;
3000 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003001 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
3002
3003 llist->min = llist_orig->min;
3004 llist->max = llist_orig->max;
3005
Radek Krejcia8d111f2017-05-31 13:57:37 +02003006 if (llist_orig->must) {
3007 llist->must = lys_restr_dup(module, llist_orig->must, llist_orig->must_size, shallow, unres);
3008 LY_CHECK_GOTO(!llist->must, error);
3009 llist->must_size = llist_orig->must_size;
3010 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011
Radek Krejcia8d111f2017-05-31 13:57:37 +02003012 if (llist_orig->dflt) {
3013 llist->dflt = malloc(llist_orig->dflt_size * sizeof *llist->dflt);
3014 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM, error);
3015 llist->dflt_size = llist_orig->dflt_size;
Radek Krejcia8d111f2017-05-31 13:57:37 +02003016
Radek Krejcic699e422017-06-02 15:18:58 +02003017 for (i = 0; i < llist->dflt_size; i++) {
3018 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
Radek Krejcib53154b2017-07-19 09:14:13 +02003019 if (!lys_ingrouping(retval) || (llist->type.base != LY_TYPE_LEAFREF)) {
Radek Krejcic699e422017-06-02 15:18:58 +02003020 if ((llist->type.base == LY_TYPE_IDENT) && !strchr(llist->dflt[i], ':') && (module != llist_orig->module)) {
3021 tmp_mod = llist_orig->module;
3022 } else {
3023 tmp_mod = module;
3024 }
3025 if (unres_schema_add_node(tmp_mod, unres, &llist->type, UNRES_TYPE_DFLT,
3026 (struct lys_node *)(&llist->dflt[i])) == -1) {
3027 goto error;
3028 }
Michal Vaskofe31cc02017-03-10 15:52:31 +01003029 }
Radek Krejci51673202016-11-01 17:00:32 +01003030 }
3031 }
3032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003033 if (llist_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003034 llist->when = lys_when_dup(module, llist_orig->when, shallow, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 }
3036 break;
3037
3038 case LYS_LIST:
3039 list->min = list_orig->min;
3040 list->max = list_orig->max;
3041
Radek Krejcia8d111f2017-05-31 13:57:37 +02003042 if (list_orig->must) {
3043 list->must = lys_restr_dup(module, list_orig->must, list_orig->must_size, shallow, unres);
3044 LY_CHECK_GOTO(!list->must, error);
3045 list->must_size = list_orig->must_size;
3046 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047
Radek Krejcif0bb3602017-01-25 17:05:08 +01003048 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Michal Vasko38d01f72015-06-15 09:41:06 +02003049
Radek Krejcia8d111f2017-05-31 13:57:37 +02003050 if (list_orig->keys_size) {
3051 list->keys = calloc(list_orig->keys_size, sizeof *list->keys);
3052 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM, error);
Radek Krejci5c08a992016-11-02 13:30:04 +01003053 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003054 list->keys_size = list_orig->keys_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02003055
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003056 if (!shallow) {
Radek Krejci5c08a992016-11-02 13:30:04 +01003057 /* the keys are going to be resolved only if the list is instantiated in data tree, not just
3058 * in another grouping */
3059 for (iter = parent; iter && iter->nodetype != LYS_GROUPING; iter = iter->parent);
3060 if (!iter && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
3061 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003062 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003063 } else {
Radek Krejcia8d111f2017-05-31 13:57:37 +02003064 memcpy(list->keys, list_orig->keys, list_orig->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02003065 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003066 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003067
Radek Krejcia8d111f2017-05-31 13:57:37 +02003068 if (list_orig->unique) {
3069 list->unique = malloc(list_orig->unique_size * sizeof *list->unique);
3070 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM, error);
3071 list->unique_size = list_orig->unique_size;
Radek Krejci581ce772015-11-10 17:22:40 +01003072
Radek Krejcic699e422017-06-02 15:18:58 +02003073 for (i = 0; i < list->unique_size; ++i) {
3074 list->unique[i].expr = malloc(list_orig->unique[i].expr_size * sizeof *list->unique[i].expr);
3075 LY_CHECK_ERR_GOTO(!list->unique[i].expr, LOGMEM, error);
3076 list->unique[i].expr_size = list_orig->unique[i].expr_size;
3077 for (j = 0; j < list->unique[i].expr_size; j++) {
3078 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
3079
3080 /* if it stays in unres list, duplicate it also there */
3081 unique_info = malloc(sizeof *unique_info);
3082 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM, error);
3083 unique_info->list = (struct lys_node *)list;
3084 unique_info->expr = list->unique[i].expr[j];
3085 unique_info->trg_type = &list->unique[i].trg_type;
3086 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
3087 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003088 }
3089 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003091 if (list_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003092 list->when = lys_when_dup(module, list_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003093 LY_CHECK_GOTO(!list->when, error);
Radek Krejciefaeba32015-05-27 14:30:57 +02003094 }
Radek Krejcidce51452015-06-16 15:20:08 +02003095 break;
3096
3097 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003098 case LYS_ANYDATA:
Radek Krejcia8d111f2017-05-31 13:57:37 +02003099 if (any_orig->must) {
3100 any->must = lys_restr_dup(module, any_orig->must, any_orig->must_size, shallow, unres);
3101 LY_CHECK_GOTO(!any->must, error);
3102 any->must_size = any_orig->must_size;
3103 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003104
Radek Krejcibf2abff2016-08-23 15:51:52 +02003105 if (any_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003106 any->when = lys_when_dup(module, any_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003107 LY_CHECK_GOTO(!any->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003108 }
3109 break;
3110
3111 case LYS_USES:
3112 uses->grp = uses_orig->grp;
3113
3114 if (uses_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003115 uses->when = lys_when_dup(module, uses_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003116 LY_CHECK_GOTO(!uses->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003117 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003118 /* it is not needed to duplicate refine, nor augment. They are already applied to the uses children */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003119 break;
3120
3121 case LYS_CASE:
3122 if (cs_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003123 cs->when = lys_when_dup(module, cs_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003124 LY_CHECK_GOTO(!cs->when, error);
Radek Krejcidce51452015-06-16 15:20:08 +02003125 }
3126 break;
3127
Radek Krejci96935402016-11-04 16:27:28 +01003128 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02003129 case LYS_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003130 case LYS_INPUT:
3131 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02003132 case LYS_NOTIF:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003133 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003134 break;
3135
3136 default:
3137 /* LY_NODE_AUGMENT */
3138 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02003139 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003140 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003141
3142 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02003143
3144error:
3145
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003146 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02003147 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003148}
3149
Radek Krejcib3142312016-11-09 11:04:12 +01003150int
3151lys_has_xpath(const struct lys_node *node)
3152{
3153 assert(node);
3154
3155 switch (node->nodetype) {
3156 case LYS_AUGMENT:
3157 if (((struct lys_node_augment *)node)->when) {
3158 return 1;
3159 }
3160 break;
3161 case LYS_CASE:
3162 if (((struct lys_node_case *)node)->when) {
3163 return 1;
3164 }
3165 break;
3166 case LYS_CHOICE:
3167 if (((struct lys_node_choice *)node)->when) {
3168 return 1;
3169 }
3170 break;
3171 case LYS_ANYDATA:
3172 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3173 return 1;
3174 }
3175 break;
3176 case LYS_LEAF:
3177 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3178 return 1;
3179 }
3180 break;
3181 case LYS_LEAFLIST:
3182 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3183 return 1;
3184 }
3185 break;
3186 case LYS_LIST:
3187 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3188 return 1;
3189 }
3190 break;
3191 case LYS_CONTAINER:
3192 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3193 return 1;
3194 }
3195 break;
3196 case LYS_INPUT:
3197 case LYS_OUTPUT:
3198 if (((struct lys_node_inout *)node)->must_size) {
3199 return 1;
3200 }
3201 break;
3202 case LYS_NOTIF:
3203 if (((struct lys_node_notif *)node)->must_size) {
3204 return 1;
3205 }
3206 break;
3207 case LYS_USES:
3208 if (((struct lys_node_uses *)node)->when) {
3209 return 1;
3210 }
3211 break;
3212 default:
3213 /* does not have XPath */
3214 break;
3215 }
3216
3217 return 0;
3218}
3219
Radek Krejci2cc25322017-09-06 16:32:02 +02003220/*
3221 * shallow -
3222 * - do not inherit status from the parent
3223 */
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003224struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003225lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003226 struct unres_schema *unres, int shallow)
3227{
3228 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003229 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003230 struct lys_node *result, *iter, *next;
3231
3232 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003233 /* 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 +02003234 for (p = parent;
3235 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3236 p = lys_parent(p));
3237 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3238 }
3239
Radek Krejci6ff885d2017-01-03 14:06:22 +01003240 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003241 if (finalize) {
3242 /* check xpath expressions in the instantiated tree */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003243 for (iter = next = result; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003244 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003245 /* invalid xpath */
3246 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003247 }
3248
3249 /* select next item */
3250 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3251 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3252 next = NULL;
3253 } else {
3254 next = iter->child;
3255 }
3256 if (!next) {
3257 /* no children, try siblings */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003258 if (iter == result) {
3259 /* we are done, no next element to process */
3260 break;
3261 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003262 next = iter->next;
3263 }
3264 while (!next) {
3265 /* parent is already processed, go to its sibling */
3266 iter = lys_parent(iter);
Radek Krejci7212e0a2017-03-08 15:58:22 +01003267 if (lys_parent(iter) == lys_parent(result)) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003268 /* we are done, no next element to process */
3269 break;
3270 }
3271 next = iter->next;
3272 }
3273 }
3274 }
3275
3276 return result;
3277}
3278
Michal Vasko13b15832015-08-19 11:04:48 +02003279void
Michal Vaskoff006c12016-02-17 11:15:19 +01003280lys_node_switch(struct lys_node *dst, struct lys_node *src)
3281{
3282 struct lys_node *child;
3283
Michal Vaskob42b6972016-06-06 14:21:30 +02003284 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003285
3286 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02003287 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01003288 dst->prev->next = src;
3289 }
3290
3291 /* sibling prev */
3292 if (dst->next) {
3293 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02003294 } else {
3295 for (child = dst->prev; child->prev->next; child = child->prev);
3296 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003297 }
3298
3299 /* next */
3300 src->next = dst->next;
3301 dst->next = NULL;
3302
3303 /* prev */
3304 if (dst->prev != dst) {
3305 src->prev = dst->prev;
3306 }
3307 dst->prev = dst;
3308
3309 /* parent child */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003310 if (dst->parent) {
3311 if (dst->parent->child == dst) {
3312 dst->parent->child = src;
3313 }
Radek Krejci115fa882017-03-01 16:15:07 +01003314 } else if (lys_main_module(dst->module)->data == dst) {
3315 lys_main_module(dst->module)->data = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003316 }
3317
3318 /* parent */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003319 src->parent = dst->parent; dst->parent = NULL;
3320
Michal Vaskoff006c12016-02-17 11:15:19 +01003321
3322 /* child parent */
3323 LY_TREE_FOR(dst->child, child) {
3324 if (child->parent == dst) {
3325 child->parent = src;
3326 }
3327 }
3328
3329 /* child */
3330 src->child = dst->child;
3331 dst->child = NULL;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003332
3333 /* node-specific data */
3334 switch (dst->nodetype) {
3335 case LYS_CONTAINER:
3336 ((struct lys_node_container *)src)->tpdf_size = ((struct lys_node_container *)dst)->tpdf_size;
3337 ((struct lys_node_container *)src)->tpdf = ((struct lys_node_container *)dst)->tpdf;
3338 ((struct lys_node_container *)dst)->tpdf_size = 0;
3339 ((struct lys_node_container *)dst)->tpdf = NULL;
3340 break;
3341 case LYS_LIST:
3342 ((struct lys_node_list *)src)->tpdf_size = ((struct lys_node_list *)dst)->tpdf_size;
3343 ((struct lys_node_list *)src)->tpdf = ((struct lys_node_list *)dst)->tpdf;
3344 ((struct lys_node_list *)dst)->tpdf_size = 0;
3345 ((struct lys_node_list *)dst)->tpdf = NULL;
3346 break;
3347 case LYS_RPC:
3348 case LYS_ACTION:
3349 ((struct lys_node_rpc_action *)src)->tpdf_size = ((struct lys_node_rpc_action *)dst)->tpdf_size;
3350 ((struct lys_node_rpc_action *)src)->tpdf = ((struct lys_node_rpc_action *)dst)->tpdf;
3351 ((struct lys_node_rpc_action *)dst)->tpdf_size = 0;
3352 ((struct lys_node_rpc_action *)dst)->tpdf = NULL;
3353 break;
3354 case LYS_NOTIF:
3355 ((struct lys_node_notif *)src)->tpdf_size = ((struct lys_node_notif *)dst)->tpdf_size;
3356 ((struct lys_node_notif *)src)->tpdf = ((struct lys_node_notif *)dst)->tpdf;
3357 ((struct lys_node_notif *)dst)->tpdf_size = 0;
3358 ((struct lys_node_notif *)dst)->tpdf = NULL;
3359 break;
3360 case LYS_INPUT:
3361 case LYS_OUTPUT:
3362 ((struct lys_node_inout *)src)->tpdf_size = ((struct lys_node_inout *)dst)->tpdf_size;
3363 ((struct lys_node_inout *)src)->tpdf = ((struct lys_node_inout *)dst)->tpdf;
3364 ((struct lys_node_inout *)dst)->tpdf_size = 0;
3365 ((struct lys_node_inout *)dst)->tpdf = NULL;
3366 break;
3367 default:
3368 /* nothing special */
3369 break;
3370 }
3371
Michal Vaskoff006c12016-02-17 11:15:19 +01003372}
3373
3374void
Michal Vasko10681e82018-01-16 14:54:16 +01003375lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int free_subs, int remove_from_ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003376{
3377 struct ly_ctx *ctx;
3378 int i;
3379
3380 if (!module) {
3381 return;
3382 }
3383
3384 /* remove schema from the context */
3385 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003386 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003387 for (i = 0; i < ctx->models.used; i++) {
3388 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003389 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003390 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003391 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 +02003392 ctx->models.list[ctx->models.used] = NULL;
3393 /* we are done */
3394 break;
3395 }
3396 }
3397 }
3398
3399 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003400 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003401
Michal Vasko10681e82018-01-16 14:54:16 +01003402 /* include */
3403 for (i = 0; i < module->inc_size; i++) {
3404 lydict_remove(ctx, module->inc[i].dsc);
3405 lydict_remove(ctx, module->inc[i].ref);
3406 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size, private_destructor);
3407 /* complete submodule free is done only from main module since
3408 * submodules propagate their includes to the main module */
3409 if (free_subs) {
3410 lys_submodule_free(module->inc[i].submodule, private_destructor);
3411 }
3412 }
3413 free(module->inc);
3414
Radek Krejcida04f4a2015-05-21 12:54:09 +02003415 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003416 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003417
3418 free(module);
3419}
Radek Krejci7e97c352015-06-19 16:26:34 +02003420
Radek Krejci9de2c042016-10-19 16:53:06 +02003421static void
3422lys_features_disable_recursive(struct lys_feature *f)
3423{
3424 unsigned int i;
3425 struct lys_feature *depf;
3426
3427 /* disable the feature */
3428 f->flags &= ~LYS_FENABLED;
3429
3430 /* by disabling feature we have to disable also all features that depends on this feature */
3431 if (f->depfeatures) {
3432 for (i = 0; i < f->depfeatures->number; i++) {
3433 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3434 if (depf->flags & LYS_FENABLED) {
3435 lys_features_disable_recursive(depf);
3436 }
3437 }
3438 }
3439}
3440
3441
Radek Krejci7e97c352015-06-19 16:26:34 +02003442/*
3443 * op: 1 - enable, 0 - disable
3444 */
3445static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003446lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003447{
3448 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003449 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003450 int progress, faili, failj, failk;
3451
3452 uint8_t fsize;
3453 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003454
3455 if (!module || !name || !strlen(name)) {
3456 return EXIT_FAILURE;
3457 }
3458
3459 if (!strcmp(name, "*")) {
3460 /* enable all */
3461 all = 1;
3462 }
3463
Radek Krejcia889c1f2016-10-19 15:50:11 +02003464 progress = failk = 1;
3465 while (progress && failk) {
3466 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3467 if (i == -1) {
3468 fsize = module->features_size;
3469 f = module->features;
3470 } else {
3471 fsize = module->inc[i].submodule->features_size;
3472 f = module->inc[i].submodule->features;
3473 }
3474
3475 for (j = 0; j < fsize; j++) {
3476 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003477 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3478 if (all) {
3479 /* skip already set features */
3480 continue;
3481 } else {
3482 /* feature already set correctly */
3483 return EXIT_SUCCESS;
3484 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003485 }
3486
3487 if (op) {
3488 /* check referenced features if they are enabled */
3489 for (k = 0; k < f[j].iffeature_size; k++) {
3490 if (!resolve_iffeature(&f[j].iffeature[k])) {
3491 if (all) {
3492 faili = i;
3493 failj = j;
3494 failk = k + 1;
3495 break;
3496 } else {
3497 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3498 f[j].name, k + 1);
3499 return EXIT_FAILURE;
3500 }
3501 }
3502 }
3503
3504 if (k == f[j].iffeature_size) {
3505 /* the last check passed, do the change */
3506 f[j].flags |= LYS_FENABLED;
3507 progress++;
3508 }
3509 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003510 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003511 progress++;
3512 }
3513 if (!all) {
3514 /* stop in case changing a single feature */
3515 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003516 }
3517 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003518 }
3519 }
3520 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003521 if (failk) {
3522 /* print info about the last failing feature */
3523 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3524 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3525 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003526 }
3527
3528 if (all) {
3529 return EXIT_SUCCESS;
3530 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003531 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003532 return EXIT_FAILURE;
3533 }
3534}
3535
3536API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003537lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003538{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003539 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003540}
3541
3542API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003543lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003544{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003545 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003546}
3547
3548API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003549lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003550{
3551 int i, j;
3552
3553 if (!module || !feature) {
3554 return -1;
3555 }
3556
3557 /* search for the specified feature */
3558 /* module itself */
3559 for (i = 0; i < module->features_size; i++) {
3560 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003561 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003562 return 1;
3563 } else {
3564 return 0;
3565 }
3566 }
3567 }
3568
3569 /* submodules */
3570 for (j = 0; j < module->inc_size; j++) {
3571 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3572 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003573 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003574 return 1;
3575 } else {
3576 return 0;
3577 }
3578 }
3579 }
3580 }
3581
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003582 /* feature definition not found */
3583 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003584}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003585
Radek Krejci96a10da2015-07-30 11:00:14 +02003586API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003587lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003588{
Radek Krejci96a10da2015-07-30 11:00:14 +02003589 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003590 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003591 unsigned int count;
3592
3593 if (!module) {
3594 return NULL;
3595 }
3596
3597 count = module->features_size;
3598 for (i = 0; i < module->inc_size; i++) {
3599 count += module->inc[i].submodule->features_size;
3600 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003601 result = malloc((count + 1) * sizeof *result);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003602 LY_CHECK_ERR_RETURN(!result, LOGMEM, NULL);
3603
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003604 if (states) {
3605 *states = malloc((count + 1) * sizeof **states);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003606 LY_CHECK_ERR_RETURN(!(*states), LOGMEM; free(result), NULL);
Michal Vasko2367e7c2015-07-07 11:33:44 +02003607 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003608 count = 0;
3609
3610 /* module itself */
3611 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003612 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003613 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003614 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003615 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003616 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003617 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003618 }
3619 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003620 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003621 }
3622
3623 /* submodules */
3624 for (j = 0; j < module->inc_size; j++) {
3625 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003626 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003627 if (states) {
3628 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3629 (*states)[count] = 1;
3630 } else {
3631 (*states)[count] = 0;
3632 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003633 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003634 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003635 }
3636 }
3637
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003638 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003639 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003640
3641 return result;
3642}
Michal Vaskobaefb032015-09-24 14:52:10 +02003643
Radek Krejci6910a032016-04-13 10:06:21 +02003644API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003645lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003646{
Michal Vaskof53187d2017-01-13 13:23:14 +01003647 if (!node) {
3648 return NULL;
3649 }
3650
Radek Krejcic071c542016-01-27 14:57:51 +01003651 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3652}
3653
Radek Krejci6910a032016-04-13 10:06:21 +02003654API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003655lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003656{
Michal Vaskof53187d2017-01-13 13:23:14 +01003657 if (!module) {
3658 return NULL;
3659 }
3660
Michal Vasko320e8532016-02-15 13:11:57 +01003661 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3662}
3663
Michal Vaskobaefb032015-09-24 14:52:10 +02003664API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003665lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003666{
Radek Krejcif95b6292017-02-13 15:57:37 +01003667 struct lys_node *parent;
3668
3669 if (!node) {
Michal Vaskobaefb032015-09-24 14:52:10 +02003670 return NULL;
3671 }
3672
Radek Krejcif95b6292017-02-13 15:57:37 +01003673 if (node->nodetype == LYS_EXT) {
3674 if (((struct lys_ext_instance_complex*)node)->parent_type != LYEXT_PAR_NODE) {
3675 return NULL;
3676 }
3677 parent = (struct lys_node*)((struct lys_ext_instance_complex*)node)->parent;
3678 } else if (!node->parent) {
3679 return NULL;
3680 } else {
3681 parent = node->parent;
Michal Vaskobaefb032015-09-24 14:52:10 +02003682 }
3683
Radek Krejcif95b6292017-02-13 15:57:37 +01003684 if (parent->nodetype == LYS_AUGMENT) {
3685 return ((struct lys_node_augment *)parent)->target;
3686 } else {
3687 return parent;
3688 }
3689}
3690
3691struct lys_node **
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01003692lys_child(const struct lys_node *node, LYS_NODE nodetype)
Radek Krejcif95b6292017-02-13 15:57:37 +01003693{
3694 void *pp;
3695 assert(node);
3696
3697 if (node->nodetype == LYS_EXT) {
3698 pp = lys_ext_complex_get_substmt(lys_snode2stmt(nodetype), (struct lys_ext_instance_complex*)node, NULL);
3699 if (!pp) {
3700 return NULL;
3701 }
3702 return (struct lys_node **)pp;
Michal Vasko54d4c202017-08-09 14:09:18 +02003703 } else if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Radek Krejcif7fe2cb2017-08-09 10:27:12 +02003704 return NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01003705 } else {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01003706 return (struct lys_node **)&node->child;
Radek Krejcif95b6292017-02-13 15:57:37 +01003707 }
Michal Vaskobaefb032015-09-24 14:52:10 +02003708}
Michal Vasko1b229152016-01-13 11:28:38 +01003709
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003710API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003711lys_set_private(const struct lys_node *node, void *priv)
3712{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003713 void *prev;
3714
Michal Vasko1b229152016-01-13 11:28:38 +01003715 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003716 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
3717 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003718 }
3719
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003720 prev = node->priv;
3721 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003722
3723 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003724}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003725
Michal Vasko01c6fd22016-05-20 11:43:05 +02003726int
3727lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3728{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003729 struct lys_node_leaf *iter = leafref_target;
3730
Michal Vasko48a573d2016-07-01 11:46:02 +02003731 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003732 LOGINT;
3733 return -1;
3734 }
3735
Pavol Vican93175152016-08-30 15:34:44 +02003736 /* check for config flag */
Radek Krejcic688ca02017-03-20 12:54:39 +01003737 if (((struct lys_node_leaf*)leafref)->type.info.lref.req != -1 &&
3738 (leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
Pavol Vican93175152016-08-30 15:34:44 +02003739 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
Radek Krejcid831dd42017-03-16 12:59:30 +01003740 "The leafref %s is config but refers to a non-config %s.",
Pavol Vican93175152016-08-30 15:34:44 +02003741 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
3742 return -1;
3743 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003744 /* check for cycles */
3745 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3746 if ((void *)iter == (void *)leafref) {
3747 /* cycle detected */
3748 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3749 return -1;
3750 }
3751 iter = iter->type.info.lref.target;
3752 }
3753
3754 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003755 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02003756 if (!leafref_target->backlinks) {
3757 leafref_target->backlinks = (void*)ly_set_new();
3758 if (!leafref_target->backlinks) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003759 LOGMEM;
3760 return -1;
3761 }
3762 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003763 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003764
3765 return 0;
3766}
3767
Michal Vasko8548e082016-07-22 12:00:18 +02003768/* not needed currently */
3769#if 0
3770
Michal Vasko5b3492c2016-07-20 09:37:40 +02003771static const char *
3772lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3773{
3774 struct lys_module *prev_mod;
3775 uint32_t str_len, mod_len, buf_idx;
3776
Radek Krejcibf2abff2016-08-23 15:51:52 +02003777 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003778 LOGINT;
3779 return NULL;
3780 }
3781
3782 buf_idx = buf_len - 1;
3783 buf[buf_idx] = '\0';
3784
3785 while (node) {
3786 if (lys_parent(node)) {
3787 prev_mod = lys_node_module(lys_parent(node));
3788 } else {
3789 prev_mod = NULL;
3790 }
3791
Radek Krejcibf2abff2016-08-23 15:51:52 +02003792 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003793 str_len = strlen(node->name);
3794
3795 if (prev_mod != node->module) {
3796 mod_len = strlen(node->module->name);
3797 } else {
3798 mod_len = 0;
3799 }
3800
3801 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3802 LOGINT;
3803 return NULL;
3804 }
3805
3806 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3807
3808 buf[buf_idx] = '/';
3809 if (mod_len) {
3810 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3811 buf[buf_idx + 1 + mod_len] = ':';
3812 }
3813 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3814 }
3815
3816 node = lys_parent(node);
3817 }
3818
3819 return buf + buf_idx;
3820}
3821
Michal Vasko8548e082016-07-22 12:00:18 +02003822#endif
3823
3824API struct ly_set *
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003825lys_xpath_atomize(const struct lys_node *ctx_node, enum lyxp_node_type ctx_node_type, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02003826{
Michal Vasko508a50d2016-09-07 14:50:33 +02003827 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003828 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003829 uint32_t i;
3830
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003831 if (!ctx_node || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02003832 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003833 }
3834
Michal Vaskob94a5e42016-09-08 14:01:56 +02003835 /* adjust the root */
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003836 if ((ctx_node_type == LYXP_NODE_ROOT) || (ctx_node_type == LYXP_NODE_ROOT_CONFIG)) {
Michal Vaskob94a5e42016-09-08 14:01:56 +02003837 do {
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003838 ctx_node = lys_getnext(NULL, NULL, lys_node_module(ctx_node), 0);
3839 } while ((ctx_node_type == LYXP_NODE_ROOT_CONFIG) && (ctx_node->flags & LYS_CONFIG_R));
Michal Vaskob94a5e42016-09-08 14:01:56 +02003840 }
3841
Michal Vasko508a50d2016-09-07 14:50:33 +02003842 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003843
3844 if (options & LYXP_MUST) {
3845 options &= ~LYXP_MUST;
3846 options |= LYXP_SNODE_MUST;
3847 } else if (options & LYXP_WHEN) {
3848 options &= ~LYXP_WHEN;
3849 options |= LYXP_SNODE_WHEN;
3850 } else {
3851 options |= LYXP_SNODE;
3852 }
3853
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003854 if (lyxp_atomize(expr, ctx_node, ctx_node_type, &set, options, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003855 free(set.val.snodes);
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003856 LOGVAL(LYE_SPEC, LY_VLOG_LYS, ctx_node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02003857 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003858 }
3859
Michal Vasko8548e082016-07-22 12:00:18 +02003860 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003861
Michal Vasko508a50d2016-09-07 14:50:33 +02003862 for (i = 0; i < set.used; ++i) {
3863 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003864 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003865 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003866 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003867 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003868 return NULL;
3869 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003870 break;
3871 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003872 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003873 break;
3874 }
3875 }
3876
Michal Vasko508a50d2016-09-07 14:50:33 +02003877 free(set.val.snodes);
3878 return ret_set;
3879}
3880
3881API struct ly_set *
3882lys_node_xpath_atomize(const struct lys_node *node, int options)
3883{
3884 const struct lys_node *next, *elem, *parent, *tmp;
3885 struct lyxp_set set;
3886 struct ly_set *ret_set;
3887 uint16_t i;
3888
3889 if (!node) {
3890 return NULL;
3891 }
3892
3893 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3894 if (!parent) {
3895 /* not in input, output, or notification */
3896 return NULL;
3897 }
3898
3899 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003900 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003901 return NULL;
3902 }
3903
3904 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003905 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_XPATH_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003906 /* elem has no dependencies from other subtrees and local nodes get discarded */
3907 goto next_iter;
3908 }
3909
Michal Vaskof96dfb62017-08-17 12:23:49 +02003910 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003911 ly_set_free(ret_set);
3912 free(set.val.snodes);
3913 return NULL;
3914 }
3915
3916 for (i = 0; i < set.used; ++i) {
3917 switch (set.val.snodes[i].type) {
3918 case LYXP_NODE_ELEM:
3919 if (options & LYXP_NO_LOCAL) {
3920 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3921 if (tmp) {
3922 /* in local subtree, discard */
3923 break;
3924 }
3925 }
3926 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3927 ly_set_free(ret_set);
3928 free(set.val.snodes);
3929 return NULL;
3930 }
3931 break;
3932 default:
3933 /* ignore roots, text and attr should not ever appear */
3934 break;
3935 }
3936 }
3937
3938 free(set.val.snodes);
3939 if (!(options & LYXP_RECURSIVE)) {
3940 break;
3941 }
3942next_iter:
3943 LY_TREE_DFS_END(node, next, elem);
3944 }
3945
Michal Vasko8548e082016-07-22 12:00:18 +02003946 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003947}
3948
Michal Vasko44ab1462017-05-18 13:18:36 +02003949/* logs */
3950int
3951apply_aug(struct lys_node_augment *augment, struct unres_schema *unres)
Radek Krejci0ec51da2016-12-14 16:42:03 +01003952{
Michal Vasko44ab1462017-05-18 13:18:36 +02003953 struct lys_node *child, *parent;
3954 int clear_config;
3955 unsigned int u;
Michal Vaskod02e30e2018-01-22 13:35:48 +01003956 uint8_t *v;
Michal Vasko44ab1462017-05-18 13:18:36 +02003957 struct lys_ext_instance *ext;
Radek Krejci0ec51da2016-12-14 16:42:03 +01003958
3959 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
3960
Radek Krejcic9d78692017-08-24 17:17:18 +02003961 if (!augment->child) {
3962 /* nothing to apply */
3963 goto success;
3964 }
3965
Michal Vaskobb520442017-05-23 10:55:18 +02003966 /* check that all the modules are implemented */
3967 for (parent = augment->target; parent; parent = lys_parent(parent)) {
3968 if (!lys_node_module(parent)->implemented) {
3969 if (lys_set_implemented(lys_node_module(parent))) {
3970 LOGERR(ly_errno, "Making the augment target module \"%s\" implemented failed.", lys_node_module(parent)->name);
3971 return -1;
3972 }
Michal Vaskobb520442017-05-23 10:55:18 +02003973 }
3974 }
3975
Radek Krejci0ec51da2016-12-14 16:42:03 +01003976 /* reconnect augmenting data into the target - add them to the target child list */
3977 if (augment->target->child) {
Michal Vasko44ab1462017-05-18 13:18:36 +02003978 child = augment->target->child->prev;
3979 child->next = augment->child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01003980 augment->target->child->prev = augment->child->prev;
Michal Vasko44ab1462017-05-18 13:18:36 +02003981 augment->child->prev = child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01003982 } else {
3983 augment->target->child = augment->child;
3984 }
3985
Michal Vasko44ab1462017-05-18 13:18:36 +02003986 /* inherit config information from actual parent */
3987 for (parent = augment->target; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); parent = lys_parent(parent));
3988 clear_config = (parent) ? 1 : 0;
3989 LY_TREE_FOR(augment->child, child) {
3990 if (inherit_config_flag(child, augment->target->flags & LYS_CONFIG_MASK, clear_config)) {
3991 return -1;
3992 }
3993 }
3994
3995 /* inherit extensions if any */
3996 for (u = 0; u < augment->target->ext_size; u++) {
3997 ext = augment->target->ext[u]; /* shortcut */
3998 if (ext && ext->def->plugin && (ext->def->plugin->flags & LYEXT_OPT_INHERIT)) {
Michal Vaskod02e30e2018-01-22 13:35:48 +01003999 v = malloc(sizeof *v);
4000 LY_CHECK_ERR_RETURN(!v, LOGMEM, -1);
4001 *v = u;
4002 if (unres_schema_add_node(lys_main_module(augment->module), unres, &augment->target->ext,
4003 UNRES_EXT_FINALIZE, (struct lys_node *)v) == -1) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004004 /* something really bad happend since the extension finalization is not actually
4005 * being resolved while adding into unres, so something more serious with the unres
4006 * list itself must happened */
4007 return -1;
4008 }
4009 }
4010 }
4011
Radek Krejcic9d78692017-08-24 17:17:18 +02004012success:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004013 /* remove the flag about not applicability */
4014 augment->flags &= ~LYS_NOTAPPLIED;
Michal Vasko44ab1462017-05-18 13:18:36 +02004015 return EXIT_SUCCESS;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004016}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004017
Radek Krejcib2541a32016-12-12 16:45:57 +01004018static void
4019remove_aug(struct lys_node_augment *augment)
4020{
4021 struct lys_node *last, *elem;
4022
Michal Vaskof1aa47d2017-09-21 12:09:29 +02004023 if ((augment->flags & LYS_NOTAPPLIED) || !augment->target) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004024 /* skip already not applied augment */
Radek Krejcib2541a32016-12-12 16:45:57 +01004025 return;
4026 }
4027
4028 elem = augment->child;
4029 if (elem) {
4030 LY_TREE_FOR(elem, last) {
4031 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
4032 break;
4033 }
4034 }
4035 /* elem is first augment child, last is the last child */
4036
4037 /* parent child ptr */
4038 if (augment->target->child == elem) {
4039 augment->target->child = last->next;
4040 }
4041
4042 /* parent child next ptr */
4043 if (elem->prev->next) {
4044 elem->prev->next = last->next;
4045 }
4046
4047 /* parent child prev ptr */
4048 if (last->next) {
4049 last->next->prev = elem->prev;
4050 } else if (augment->target->child) {
4051 augment->target->child->prev = elem->prev;
4052 }
4053
4054 /* update augment children themselves */
4055 elem->prev = last;
4056 last->next = NULL;
4057 }
4058
Radek Krejci0ec51da2016-12-14 16:42:03 +01004059 /* augment->target still keeps the resolved target, but for lys_augment_free()
4060 * we have to keep information that this augment is not applied to free its data */
4061 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01004062}
4063
Radek Krejci30bfcd22017-01-27 16:54:48 +01004064/*
4065 * @param[in] module - the module where the deviation is defined
4066 */
4067static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004068lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004069{
Radek Krejcic9d78692017-08-24 17:17:18 +02004070 int ret, reapply = 0;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004071 char *parent_path;
4072 struct lys_node *target = NULL, *parent;
Michal Vasko50576712017-07-28 12:28:33 +02004073 struct ly_set *set;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004074
4075 if (!dev->deviate) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004076 return;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004077 }
4078
4079 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
4080 if (dev->orig_node) {
4081 /* removing not-supported deviation ... */
4082 if (strrchr(dev->target_name, '/') != dev->target_name) {
4083 /* ... from a parent */
4084
4085 /* reconnect to its previous position */
4086 parent = dev->orig_node->parent;
Michal Vaskoa1074a52018-01-03 12:18:53 +01004087 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejcic9d78692017-08-24 17:17:18 +02004088 dev->orig_node->parent = NULL;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004089 /* the original node was actually from augment, we have to get know if the augment is
4090 * applied (its module is enabled and implemented). If yes, the node will be connected
4091 * to the augment and the linkage with the target will be fixed if needed, otherwise
4092 * it will be connected only to the augment */
Radek Krejcic9d78692017-08-24 17:17:18 +02004093 if (!(parent->flags & LYS_NOTAPPLIED)) {
4094 /* start with removing augment if applied before adding nodes, we have to make sure
4095 * that everything will be connect correctly */
4096 remove_aug((struct lys_node_augment *)parent);
4097 reapply = 1;
4098 }
4099 /* connect the deviated node back into the augment */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004100 lys_node_addchild(parent, NULL, dev->orig_node);
Radek Krejcic9d78692017-08-24 17:17:18 +02004101 if (reapply) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004102 /* augment is supposed to be applied, so fix pointers in target and the status of the original node */
Michal Vasko823fbe02017-12-14 11:01:40 +01004103 parent->flags |= LYS_NOTAPPLIED; /* allow apply_aug() */
4104 apply_aug((struct lys_node_augment *)parent, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004105 }
Michal Vaskoa1074a52018-01-03 12:18:53 +01004106 } else if (parent && (parent->nodetype == LYS_USES)) {
4107 /* uses child */
4108 lys_node_addchild(parent, NULL, dev->orig_node);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004109 } else {
4110 /* non-augment, non-toplevel */
4111 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
Michal Vasko50576712017-07-28 12:28:33 +02004112 ret = resolve_schema_nodeid(parent_path, NULL, module, &set, 0, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004113 free(parent_path);
Michal Vasko50576712017-07-28 12:28:33 +02004114 if (ret == -1) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004115 LOGINT;
Michal Vasko50576712017-07-28 12:28:33 +02004116 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004117 return;
4118 }
Michal Vasko50576712017-07-28 12:28:33 +02004119 target = set->set.s[0];
4120 ly_set_free(set);
4121
Radek Krejci30bfcd22017-01-27 16:54:48 +01004122 lys_node_addchild(target, NULL, dev->orig_node);
4123 }
4124 } else {
4125 /* ... from top-level data */
4126 lys_node_addchild(NULL, (struct lys_module *)dev->orig_node->module, dev->orig_node);
4127 }
4128
4129 dev->orig_node = NULL;
4130 } else {
4131 /* adding not-supported deviation */
Michal Vasko50576712017-07-28 12:28:33 +02004132 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4133 if (ret == -1) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004134 LOGINT;
Michal Vasko50576712017-07-28 12:28:33 +02004135 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004136 return;
4137 }
Michal Vasko50576712017-07-28 12:28:33 +02004138 target = set->set.s[0];
4139 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004140
4141 /* unlink and store the original node */
4142 parent = target->parent;
4143 lys_node_unlink(target);
Michal Vaskoa1074a52018-01-03 12:18:53 +01004144 if (parent && (parent->nodetype & (LYS_AUGMENT | LYS_USES))) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004145 /* hack for augment, because when the original will be sometime reconnected back, we actually need
4146 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
4147 * path), so we need to remember the augment as an addition */
Michal Vaskoa1074a52018-01-03 12:18:53 +01004148 /* we also need to remember the parent uses so that we connect it back to it when switching deviation state */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004149 target->parent = parent;
4150 }
4151 dev->orig_node = target;
4152 }
4153 } else {
Michal Vasko50576712017-07-28 12:28:33 +02004154 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4155 if (ret == -1) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004156 LOGINT;
Michal Vasko50576712017-07-28 12:28:33 +02004157 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004158 return;
4159 }
Michal Vasko50576712017-07-28 12:28:33 +02004160 target = set->set.s[0];
4161 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004162
4163 lys_node_switch(target, dev->orig_node);
4164 dev->orig_node = target;
4165 }
4166}
4167
4168/* temporarily removes or applies deviations, updates module deviation flag accordingly */
4169void
4170lys_switch_deviations(struct lys_module *module)
4171{
4172 uint32_t i = 0, j;
4173 const struct lys_module *mod;
4174 const char *ptr;
Michal Vasko44ab1462017-05-18 13:18:36 +02004175 struct unres_schema *unres;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004176
4177 if (module->deviated) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004178 unres = calloc(1, sizeof *unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004179 LY_CHECK_ERR_RETURN(!unres, LOGMEM, );
Michal Vasko44ab1462017-05-18 13:18:36 +02004180
Radek Krejci30bfcd22017-01-27 16:54:48 +01004181 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
4182 if (mod == module) {
4183 continue;
4184 }
4185
4186 for (j = 0; j < mod->deviation_size; ++j) {
4187 ptr = strstr(mod->deviation[j].target_name, module->name);
4188 if (ptr && ptr[strlen(module->name)] == ':') {
Michal Vasko44ab1462017-05-18 13:18:36 +02004189 lys_switch_deviation(&mod->deviation[j], mod, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004190 }
4191 }
4192 }
4193
4194 if (module->deviated == 2) {
4195 module->deviated = 1;
4196 } else {
4197 module->deviated = 2;
4198 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02004199 for (j = 0; j < module->inc_size; j++) {
4200 if (module->inc[j].submodule->deviated) {
4201 module->inc[j].submodule->deviated = module->deviated;
4202 }
4203 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004204
4205 if (unres->count) {
4206 resolve_unres_schema(module, unres);
4207 }
4208 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004209 }
4210}
4211
4212static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004213apply_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004214{
Michal Vasko44ab1462017-05-18 13:18:36 +02004215 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004216
4217 assert(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004218 lys_node_module(dev->orig_node)->deviated = 1; /* main module */
4219 dev->orig_node->module->deviated = 1; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004220}
4221
4222static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004223remove_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004224{
4225 uint32_t idx = 0, j;
4226 const struct lys_module *mod;
Radek Krejci29eac3d2017-06-01 16:50:02 +02004227 struct lys_module *target_mod, *target_submod;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004228 const char *ptr;
4229
4230 if (dev->orig_node) {
4231 target_mod = lys_node_module(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004232 target_submod = dev->orig_node->module;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004233 } else {
4234 LOGINT;
4235 return;
4236 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004237 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004238
4239 /* clear the deviation flag if possible */
4240 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4241 if ((mod == module) || (mod == target_mod)) {
4242 continue;
4243 }
4244
4245 for (j = 0; j < mod->deviation_size; ++j) {
4246 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4247 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4248 /* some other module deviation targets the inspected module, flag remains */
4249 break;
4250 }
4251 }
4252
4253 if (j < mod->deviation_size) {
4254 break;
4255 }
4256 }
4257
4258 if (!mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02004259 target_mod->deviated = 0; /* main module */
4260 target_submod->deviated = 0; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004261 }
4262}
4263
4264void
4265lys_sub_module_apply_devs_augs(struct lys_module *module)
4266{
4267 uint8_t u, v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004268 struct unres_schema *unres;
4269
4270 unres = calloc(1, sizeof *unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004271 LY_CHECK_ERR_RETURN(!unres, LOGMEM, );
Radek Krejci30bfcd22017-01-27 16:54:48 +01004272
4273 /* remove applied deviations */
4274 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004275 apply_dev(&module->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004276 }
4277 /* remove applied augments */
4278 for (u = 0; u < module->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004279 apply_aug(&module->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004280 }
4281
4282 /* remove deviation and augments defined in submodules */
4283 for (v = 0; v < module->inc_size; ++v) {
4284 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004285 apply_dev(&module->inc[v].submodule->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004286 }
4287
4288 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004289 apply_aug(&module->inc[v].submodule->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004290 }
4291 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004292
4293 if (unres->count) {
4294 resolve_unres_schema(module, unres);
4295 }
4296 /* nothing else left to do even if something is not resolved */
4297 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004298}
4299
Radek Krejcib2541a32016-12-12 16:45:57 +01004300void
4301lys_sub_module_remove_devs_augs(struct lys_module *module)
4302{
4303 uint8_t u, v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004304 struct unres_schema *unres;
4305
4306 unres = calloc(1, sizeof *unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004307 LY_CHECK_ERR_RETURN(!unres, LOGMEM, );
Radek Krejcib2541a32016-12-12 16:45:57 +01004308
4309 /* remove applied deviations */
4310 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004311 remove_dev(&module->deviation[u], module, unres);
Radek Krejcib2541a32016-12-12 16:45:57 +01004312 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004313 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004314 for (u = 0; u < module->augment_size; ++u) {
4315 remove_aug(&module->augment[u]);
4316 }
4317
4318 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004319 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01004320 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004321 remove_dev(&module->inc[v].submodule->deviation[u], module, unres);
Radek Krejcidbc15262016-06-16 14:58:29 +02004322 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004323
Radek Krejcib2541a32016-12-12 16:45:57 +01004324 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4325 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004326 }
4327 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004328
4329 if (unres->count) {
4330 resolve_unres_schema(module, unres);
4331 }
4332 /* nothing else left to do even if something is not resolved */
4333 unres_schema_free(module, &unres, 1);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004334}
4335
Radek Krejci27fe55e2016-09-13 17:13:35 +02004336static int
4337lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
4338{
4339 struct lys_node *root, *next, *node;
Radek Krejci9e6af732017-04-27 14:40:25 +02004340 uint16_t i, j;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004341
4342 for (i = 0; i < module->augment_size; i++) {
4343 /* apply augment */
Michal Vasko44ab1462017-05-18 13:18:36 +02004344 assert(module->augment[i].target);
4345 if (apply_aug(&module->augment[i], unres)) {
4346 return EXIT_FAILURE;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004347 }
4348 }
Radek Krejci9e6af732017-04-27 14:40:25 +02004349
4350 /* identities */
4351 for (i = 0; i < module->ident_size; i++) {
4352 for (j = 0; j < module->ident[i].base_size; j++) {
4353 resolve_identity_backlink_update(&module->ident[i], module->ident[i].base[j]);
4354 }
4355 }
4356
Radek Krejci27fe55e2016-09-13 17:13:35 +02004357 LY_TREE_FOR(module->data, root) {
4358 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4359 LY_TREE_DFS_BEGIN(root, next, node) {
4360 if (node->nodetype == LYS_GROUPING) {
4361 goto nextsibling;
4362 }
4363 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4364 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4365 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4366 UNRES_TYPE_LEAFREF, node) == -1) {
4367 return EXIT_FAILURE;
4368 }
4369 }
4370 }
4371
4372 /* modified LY_TREE_DFS_END */
4373 next = node->child;
4374 /* child exception for leafs, leaflists and anyxml without children */
4375 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4376 next = NULL;
4377 }
4378 if (!next) {
4379nextsibling:
4380 /* no children */
4381 if (node == root) {
4382 /* we are done, root has no children */
4383 break;
4384 }
4385 /* try siblings */
4386 next = node->next;
4387 }
4388 while (!next) {
4389 /* parent is already processed, go to its sibling */
4390 node = lys_parent(node);
4391 /* no siblings, go back through parents */
4392 if (lys_parent(node) == lys_parent(root)) {
4393 /* we are done, no next element to process */
4394 break;
4395 }
4396 next = node->next;
4397 }
4398 }
4399 }
4400
4401 return EXIT_SUCCESS;
4402}
4403
4404API int
4405lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004406{
4407 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004408 struct unres_schema *unres;
Radek Krejci9e6af732017-04-27 14:40:25 +02004409 int i, j, k, disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004410
Radek Krejci27fe55e2016-09-13 17:13:35 +02004411 if (!module) {
4412 ly_errno = LY_EINVAL;
4413 return EXIT_FAILURE;
4414 }
4415
4416 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004417
4418 if (module->disabled) {
4419 disabled = 1;
4420 lys_set_enabled(module);
4421 }
4422
Michal Vasko26055752016-05-03 11:36:31 +02004423 if (module->implemented) {
4424 return EXIT_SUCCESS;
4425 }
4426
4427 ctx = module->ctx;
4428
4429 for (i = 0; i < ctx->models.used; ++i) {
4430 if (module == ctx->models.list[i]) {
4431 continue;
4432 }
4433
4434 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4435 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004436 if (disabled) {
4437 /* set it back disabled */
4438 lys_set_disabled(module);
4439 }
Michal Vasko26055752016-05-03 11:36:31 +02004440 return EXIT_FAILURE;
4441 }
4442 }
4443
Radek Krejci27fe55e2016-09-13 17:13:35 +02004444 unres = calloc(1, sizeof *unres);
4445 if (!unres) {
4446 LOGMEM;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004447 if (disabled) {
4448 /* set it back disabled */
4449 lys_set_disabled(module);
4450 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004451 return EXIT_FAILURE;
4452 }
4453 /* recursively make the module implemented */
4454 ((struct lys_module *)module)->implemented = 1;
4455 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
4456 goto error;
4457 }
4458 /* process augments in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004459 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004460 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
4461 /* apply augment */
Michal Vasko44ab1462017-05-18 13:18:36 +02004462 assert(module->inc[i].submodule->augment[j].target);
4463 if (apply_aug(&module->inc[i].submodule->augment[j], unres)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004464 goto error;
4465 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004466 }
Radek Krejci9e6af732017-04-27 14:40:25 +02004467
4468 /* identities */
4469 for (j = 0; j < module->inc[i].submodule->ident_size; j++) {
4470 for (k = 0; k < module->inc[i].submodule->ident[j].base_size; k++) {
4471 resolve_identity_backlink_update(&module->inc[i].submodule->ident[j],
4472 module->inc[i].submodule->ident[j].base[k]);
4473 }
4474 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004475 }
Radek Krejcidf46e222016-11-08 11:57:37 +01004476 /* try again resolve augments in other modules possibly augmenting this one,
4477 * since we have just enabled it
4478 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004479 /* resolve rest of unres items */
4480 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4481 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004482 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004483 unres_schema_free(NULL, &unres, 0);
Michal Vasko26055752016-05-03 11:36:31 +02004484
Radek Krejci29eac3d2017-06-01 16:50:02 +02004485 /* reflect implemented flag in submodules */
4486 for (i = 0; i < module->inc_size; i++) {
4487 module->inc[i].submodule->implemented = 1;
4488 }
4489
Michal Vaskobe136f62017-09-21 12:08:39 +02004490 LOGVRB("Module \"%s%s%s\" now implemented.", module->name, (module->rev_size ? "@" : ""),
4491 (module->rev_size ? module->rev[0].date : ""));
Michal Vasko26055752016-05-03 11:36:31 +02004492 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004493
4494error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004495 if (disabled) {
4496 /* set it back disabled */
4497 lys_set_disabled(module);
4498 }
4499
Radek Krejci27fe55e2016-09-13 17:13:35 +02004500 ((struct lys_module *)module)->implemented = 0;
Michal Vasko44ab1462017-05-18 13:18:36 +02004501 unres_schema_free((struct lys_module *)module, &unres, 1);
Radek Krejci27fe55e2016-09-13 17:13:35 +02004502 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004503}
4504
4505void
4506lys_submodule_module_data_free(struct lys_submodule *submodule)
4507{
4508 struct lys_node *next, *elem;
4509
4510 /* remove parsed data */
4511 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4512 if (elem->module == (struct lys_module *)submodule) {
4513 lys_node_free(elem, NULL, 0);
4514 }
4515 }
4516}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004517
4518int
4519lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
4520{
4521 uint8_t i;
4522
4523 for (i = 0; i < list->keys_size; i++) {
4524 if (list->keys[i] == leaf) {
4525 return i + 1;
4526 }
4527 }
4528
4529 return 0;
4530}
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004531
4532API char *
Michal Vasko395b0a02018-01-22 09:36:20 +01004533lys_path(const struct lys_node *node, int options)
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004534{
Michal Vasko59631dd2017-10-02 11:56:11 +02004535 char *buf, *result;
4536 uint16_t start_idx, len;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004537
4538 if (!node) {
4539 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
4540 return NULL;
4541 }
4542
Michal Vasko59631dd2017-10-02 11:56:11 +02004543 buf = malloc(LY_BUF_SIZE);
4544 LY_CHECK_ERR_RETURN(!buf, LOGMEM, NULL);
4545 start_idx = LY_BUF_SIZE - 1;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004546
Michal Vasko59631dd2017-10-02 11:56:11 +02004547 buf[start_idx] = '\0';
Michal Vasko395b0a02018-01-22 09:36:20 +01004548 if (ly_vlog_build_path_reverse(LY_VLOG_LYS, node, &buf, &start_idx, &len, 1, !options)) {
Michal Vasko59631dd2017-10-02 11:56:11 +02004549 free(buf);
4550 return NULL;
4551 }
4552
4553 result = malloc(len + 1);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004554 if (!result) {
4555 LOGMEM;
Michal Vasko59631dd2017-10-02 11:56:11 +02004556 free(buf);
4557 return NULL;
Radek Krejcia8d111f2017-05-31 13:57:37 +02004558 }
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004559
Michal Vasko59631dd2017-10-02 11:56:11 +02004560 result = memcpy(result, &buf[start_idx], len);
4561 result[len] = '\0';
4562 free(buf);
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004563
4564 return result;
4565}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004566
Michal Vasko50576712017-07-28 12:28:33 +02004567API char *
4568lys_data_path(const struct lys_node *node)
4569{
4570 char *buf_backup = NULL, *buf = ly_buf(), *result = NULL;
4571 int i, used;
4572 struct ly_set *set;
4573 const struct lys_module *prev_mod;
4574
4575 if (!node) {
4576 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
4577 return NULL;
4578 }
4579
4580 /* backup the shared internal buffer */
4581 if (ly_buf_used && buf[0]) {
4582 buf_backup = strndup(buf, LY_BUF_SIZE - 1);
4583 }
4584 ly_buf_used++;
4585
4586 set = ly_set_new();
4587 LY_CHECK_ERR_GOTO(!set, LOGMEM, error);
4588
4589 while (node) {
4590 ly_set_add(set, (void *)node, 0);
4591 do {
4592 node = lys_parent(node);
4593 } while (node && (node->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
4594 }
4595
4596 prev_mod = NULL;
4597 used = 0;
4598 for (i = set->number - 1; i > -1; --i) {
4599 node = set->set.s[i];
4600 used += sprintf(buf + used, "/%s%s%s", (lys_node_module(node) == prev_mod ? "" : lys_node_module(node)->name),
4601 (lys_node_module(node) == prev_mod ? "" : ":"), node->name);
4602 prev_mod = lys_node_module(node);
4603 }
4604
4605 result = strdup(buf);
4606 LY_CHECK_ERR_GOTO(!result, LOGMEM, error);
4607
4608error:
4609 ly_set_free(set);
4610 /* restore the shared internal buffer */
4611 if (buf_backup) {
4612 strcpy(buf, buf_backup);
4613 free(buf_backup);
4614 }
4615 ly_buf_used--;
4616
4617 return result;
4618}
4619
Michal Vaskobb520442017-05-23 10:55:18 +02004620struct lys_node_augment *
4621lys_getnext_target_aug(struct lys_node_augment *last, const struct lys_module *mod, const struct lys_node *aug_target)
4622{
4623 int i, j, last_found;
4624
4625 if (!last) {
4626 last_found = 1;
4627 } else {
4628 last_found = 0;
4629 }
4630
4631 /* search module augments */
4632 for (i = 0; i < mod->augment_size; ++i) {
4633 if (!mod->augment[i].target) {
4634 /* still unresolved, skip */
4635 continue;
4636 }
4637
4638 if (mod->augment[i].target == aug_target) {
4639 if (last_found) {
4640 /* next match after last */
4641 return &mod->augment[i];
4642 }
4643
4644 if (&mod->augment[i] == last) {
4645 last_found = 1;
4646 }
4647 }
4648 }
4649
4650 /* search submodule augments */
4651 for (i = 0; i < mod->inc_size; ++i) {
4652 for (j = 0; j < mod->inc[i].submodule->augment_size; ++j) {
4653 if (!mod->inc[i].submodule->augment[j].target) {
4654 continue;
4655 }
4656
4657 if (mod->inc[i].submodule->augment[j].target == aug_target) {
4658 if (last_found) {
4659 /* next match after last */
4660 return &mod->inc[i].submodule->augment[j];
4661 }
4662
4663 if (&mod->inc[i].submodule->augment[j] == last) {
4664 last_found = 1;
4665 }
4666 }
4667 }
4668 }
4669
4670 return NULL;
4671}
4672
Michal Vasko50576712017-07-28 12:28:33 +02004673API struct ly_set *
4674lys_find_path(const struct lys_module *cur_module, const struct lys_node *cur_node, const char *path)
4675{
4676 struct ly_set *ret;
4677 int rc;
4678
4679 if ((!cur_module && !cur_node) || !path) {
4680 return NULL;
4681 }
4682
4683 rc = resolve_schema_nodeid(path, cur_node, cur_module, &ret, 1, 1);
4684 if (rc == -1) {
4685 return NULL;
4686 }
4687
4688 return ret;
4689}
4690
Radek Krejci8d6b7422017-02-03 14:42:13 +01004691static void
4692lys_extcomplex_free_str(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext, LY_STMT stmt)
4693{
4694 struct lyext_substmt *info;
Radek Krejcib71243e2017-02-08 16:20:08 +01004695 const char **str, ***a;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004696 int c;
4697
4698 str = lys_ext_complex_get_substmt(stmt, ext, &info);
4699 if (!str || !(*str)) {
4700 return;
4701 }
4702 if (info->cardinality >= LY_STMT_CARD_SOME) {
4703 /* we have array */
Radek Krejcib71243e2017-02-08 16:20:08 +01004704 a = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01004705 for (str = (*(const char ***)str), c = 0; str[c]; c++) {
4706 lydict_remove(ctx, str[c]);
Radek Krejci8d6b7422017-02-03 14:42:13 +01004707 }
Radek Krejci56c80412017-02-09 10:44:16 +01004708 free(a[0]);
4709 if (stmt == LY_STMT_BELONGSTO) {
4710 for (str = a[1], c = 0; str[c]; c++) {
4711 lydict_remove(ctx, str[c]);
4712 }
4713 free(a[1]);
PavolVican99c70722017-02-18 17:25:52 +01004714 } else if (stmt == LY_STMT_ARGUMENT) {
4715 free(a[1]);
Radek Krejci56c80412017-02-09 10:44:16 +01004716 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004717 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01004718 lydict_remove(ctx, str[0]);
4719 if (stmt == LY_STMT_BELONGSTO) {
4720 lydict_remove(ctx, str[1]);
4721 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004722 }
4723}
4724void
Radek Krejci5138e9f2017-04-12 13:10:46 +02004725lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size,
4726 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci8d6b7422017-02-03 14:42:13 +01004727{
Radek Krejcif8d05c22017-02-10 15:33:35 +01004728 unsigned int i, j, k;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004729 struct lyext_substmt *substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004730 void **pp, **start;
Radek Krejcif95b6292017-02-13 15:57:37 +01004731 struct lys_node *siter, *snext;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004732
4733#define EXTCOMPLEX_FREE_STRUCT(STMT, TYPE, FUNC, FREE, ARGS...) \
Radek Krejcib84686f2017-02-09 16:04:55 +01004734 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)e[i], NULL); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004735 if (!pp || !(*pp)) { break; } \
Radek Krejcib84686f2017-02-09 16:04:55 +01004736 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004737 for (start = pp = *pp; *pp; pp++) { \
Radek Krejci5138e9f2017-04-12 13:10:46 +02004738 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004739 if (FREE) { free(*pp); } \
4740 } \
4741 free(start); \
4742 } else { /* single item */ \
Radek Krejci5138e9f2017-04-12 13:10:46 +02004743 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004744 if (FREE) { free(*pp); } \
4745 }
4746
4747 if (!size || !e || !(*e)) {
4748 return;
4749 }
4750
4751 for (i = 0; i < size; i++) {
4752 if (!e[i]) {
4753 continue;
4754 }
4755
4756 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
4757 /* no free, this is just a shadow copy of the original extension instance */
4758 } else {
4759 if (e[i]->flags & (LYEXT_OPT_YANG)) {
4760 free(e[i]->def); /* remove name of instance extension */
PavolVican19dc6152017-02-06 12:04:15 +01004761 e[i]->def = NULL;
PavolVicandb0e8172017-02-20 00:46:09 +01004762 yang_free_ext_data((struct yang_ext_substmt *)e[i]->parent); /* remove backup part of yang file */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004763 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02004764 /* remove private object */
4765 if (e[i]->priv && private_destructor) {
4766 private_destructor((struct lys_node*)e[i], e[i]->priv);
4767 }
4768 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size, private_destructor);
Radek Krejci8d6b7422017-02-03 14:42:13 +01004769 lydict_remove(ctx, e[i]->arg_value);
4770 }
4771
fanchanghu8d86f6b2017-06-10 12:49:54 +08004772 if (e[i]->def && e[i]->def->plugin && e[i]->def->plugin->type == LYEXT_COMPLEX
4773 && ((e[i]->flags & LYEXT_OPT_CONTENT) == 0)) {
Radek Krejcifebdad72017-02-06 11:35:51 +01004774 substmt = ((struct lys_ext_instance_complex *)e[i])->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004775 for (j = 0; substmt[j].stmt; j++) {
4776 switch(substmt[j].stmt) {
4777 case LY_STMT_DESCRIPTION:
4778 case LY_STMT_REFERENCE:
4779 case LY_STMT_UNITS:
Radek Krejcib71243e2017-02-08 16:20:08 +01004780 case LY_STMT_ARGUMENT:
4781 case LY_STMT_DEFAULT:
4782 case LY_STMT_ERRTAG:
4783 case LY_STMT_ERRMSG:
4784 case LY_STMT_PREFIX:
4785 case LY_STMT_NAMESPACE:
4786 case LY_STMT_PRESENCE:
4787 case LY_STMT_REVISIONDATE:
4788 case LY_STMT_KEY:
4789 case LY_STMT_BASE:
4790 case LY_STMT_BELONGSTO:
4791 case LY_STMT_CONTACT:
4792 case LY_STMT_ORGANIZATION:
4793 case LY_STMT_PATH:
Radek Krejci8d6b7422017-02-03 14:42:13 +01004794 lys_extcomplex_free_str(ctx, (struct lys_ext_instance_complex *)e[i], substmt[j].stmt);
4795 break;
4796 case LY_STMT_TYPE:
4797 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPE, struct lys_type, lys_type_free, 1);
4798 break;
Radek Krejci63fc0962017-02-15 13:20:18 +01004799 case LY_STMT_TYPEDEF:
4800 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPEDEF, struct lys_tpdf, lys_tpdf_free, 1);
4801 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004802 case LY_STMT_IFFEATURE:
Frank Rimplerc4db1c72017-09-12 12:56:39 +00004803 EXTCOMPLEX_FREE_STRUCT(LY_STMT_IFFEATURE, struct lys_iffeature, lys_iffeature_free, 0, 1, 0);
Radek Krejci8d6b7422017-02-03 14:42:13 +01004804 break;
Radek Krejci5496fae2017-02-10 13:26:48 +01004805 case LY_STMT_MAX:
4806 case LY_STMT_MIN:
4807 case LY_STMT_POSITION:
PavolVican2ed9f4e2017-02-16 00:08:45 +01004808 case LY_STMT_VALUE:
Radek Krejcif8d05c22017-02-10 15:33:35 +01004809 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
Radek Krejci716cd7a2017-02-15 12:23:41 +01004810 if (substmt[j].cardinality >= LY_STMT_CARD_SOME && *pp) {
Radek Krejcif8d05c22017-02-10 15:33:35 +01004811 for(k = 0; ((uint32_t**)(*pp))[k]; k++) {
4812 free(((uint32_t**)(*pp))[k]);
4813 }
4814 }
4815 free(*pp);
4816 break;
4817 case LY_STMT_DIGITS:
Radek Krejcib84686f2017-02-09 16:04:55 +01004818 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
4819 /* free the array */
4820 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4821 free(*pp);
4822 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004823 break;
Radek Krejci37f9ba32017-02-10 16:50:35 +01004824 case LY_STMT_MODULE:
4825 /* modules are part of the context, so they will be freed there */
4826 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
4827 /* free the array */
4828 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4829 free(*pp);
4830 }
4831 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01004832 case LY_STMT_ACTION:
Radek Krejcib31762b2017-02-15 10:48:42 +01004833 case LY_STMT_ANYDATA:
4834 case LY_STMT_ANYXML:
4835 case LY_STMT_CASE:
4836 case LY_STMT_CHOICE:
4837 case LY_STMT_CONTAINER:
4838 case LY_STMT_GROUPING:
4839 case LY_STMT_INPUT:
4840 case LY_STMT_LEAF:
4841 case LY_STMT_LEAFLIST:
4842 case LY_STMT_LIST:
4843 case LY_STMT_NOTIFICATION:
4844 case LY_STMT_OUTPUT:
4845 case LY_STMT_RPC:
4846 case LY_STMT_USES:
Radek Krejcif95b6292017-02-13 15:57:37 +01004847 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4848 LY_TREE_FOR_SAFE((struct lys_node *)(*pp), snext, siter) {
4849 lys_node_free(siter, NULL, 0);
4850 }
Radek Krejcib31762b2017-02-15 10:48:42 +01004851 *pp = NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01004852 break;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004853 case LY_STMT_UNIQUE:
4854 pp = lys_ext_complex_get_substmt(LY_STMT_UNIQUE, (struct lys_ext_instance_complex *)e[i], NULL);
4855 if (!pp || !(*pp)) {
4856 break;
4857 }
4858 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
4859 for (start = pp = *pp; *pp; pp++) {
4860 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
4861 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
4862 }
4863 free((*(struct lys_unique**)pp)->expr);
4864 free(*pp);
4865 }
4866 free(start);
4867 } else { /* single item */
4868 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
4869 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
4870 }
4871 free((*(struct lys_unique**)pp)->expr);
4872 free(*pp);
4873 }
4874 break;
Radek Krejciaa9c5202017-02-15 16:10:14 +01004875 case LY_STMT_LENGTH:
4876 case LY_STMT_MUST:
4877 case LY_STMT_PATTERN:
4878 case LY_STMT_RANGE:
4879 EXTCOMPLEX_FREE_STRUCT(substmt[j].stmt, struct lys_restr, lys_restr_free, 1);
4880 break;
Radek Krejcic5cc5302017-02-16 10:07:46 +01004881 case LY_STMT_WHEN:
4882 EXTCOMPLEX_FREE_STRUCT(LY_STMT_WHEN, struct lys_when, lys_when_free, 0);
4883 break;
Radek Krejci7417a082017-02-16 11:07:59 +01004884 case LY_STMT_REVISION:
4885 pp = lys_ext_complex_get_substmt(LY_STMT_REVISION, (struct lys_ext_instance_complex *)e[i], NULL);
4886 if (!pp || !(*pp)) {
4887 break;
4888 }
4889 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
4890 for (start = pp = *pp; *pp; pp++) {
4891 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
4892 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
4893 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02004894 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01004895 free(*pp);
4896 }
4897 free(start);
4898 } else { /* single item */
4899 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
4900 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
4901 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02004902 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01004903 free(*pp);
4904 }
4905 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004906 default:
Radek Krejcib84686f2017-02-09 16:04:55 +01004907 /* nothing to free */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004908 break;
4909 }
4910 }
4911 }
4912
4913 free(e[i]);
4914 }
4915 free(e);
4916
4917#undef EXTCOMPLEX_FREE_STRUCT
4918}