blob: 8a40588097efb6c250a30cce54791771ab68d2f9 [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,
41 int tpdftype, 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;
Radek Krejci48061fb2015-08-05 15:41:07 +020072 } else if (node->parent) {
73 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020074 } else {
75 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020076 }
77
Radek Krejci074bf852015-08-19 14:22:16 +020078 if (recursive == 2) {
79 /* continue only if the node cannot have a data instance */
80 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
81 return NULL;
82 }
83 }
84 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020085}
86
Michal Vasko1dca6882015-10-22 14:29:42 +020087int
Michal Vasko36cbaa42015-12-14 13:15:48 +010088lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
89 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020090{
Radek Krejcic071c542016-01-27 14:57:51 +010091 const struct lys_node *node, *parent = NULL;
92 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010093 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020094
Michal Vasko36cbaa42015-12-14 13:15:48 +010095 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020096 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020097
Michal Vasko36cbaa42015-12-14 13:15:48 +010098 /* fill the lengths in case the caller is so indifferent */
99 if (!mod_name_len) {
100 mod_name_len = strlen(mod_name);
101 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200102 if (!nam_len) {
103 nam_len = strlen(name);
104 }
105
Michal Vasko9e635ac2016-10-17 11:44:09 +0200106 while (siblings && (siblings->nodetype == LYS_USES)) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200107 siblings = siblings->child;
108 }
Michal Vasko9e635ac2016-10-17 11:44:09 +0200109 if (!siblings) {
110 /* unresolved uses */
111 return EXIT_FAILURE;
112 }
113
Michal Vasko680f8b42016-10-17 10:27:37 +0200114 if (siblings->nodetype == LYS_GROUPING) {
115 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
116 if (node->nodetype == LYS_GROUPING) {
117 /* we went through all the siblings, only groupings there - no valid sibling */
118 return EXIT_FAILURE;
119 }
120 /* update siblings to be valid */
121 siblings = node;
122 }
123
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200124 /* set parent correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100125 parent = lys_parent(siblings);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200126
Michal Vasko680f8b42016-10-17 10:27:37 +0200127 /* go up all uses */
128 while (parent && (parent->nodetype == LYS_USES)) {
129 parent = lys_parent(parent);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200130 }
131
Radek Krejcic071c542016-01-27 14:57:51 +0100132 if (!parent) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200133 /* handle situation when there is a top-level uses referencing a foreign grouping */
134 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
135 mod = lys_node_module(node);
Michal Vasko1dca6882015-10-22 14:29:42 +0200136 }
137
Radek Krejcic071c542016-01-27 14:57:51 +0100138 /* try to find the node */
139 node = NULL;
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100140 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
Radek Krejcic071c542016-01-27 14:57:51 +0100141 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100142 /* module name comparison */
143 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200144 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 +0100145 continue;
146 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200147
Radek Krejcic071c542016-01-27 14:57:51 +0100148 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200149 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100150 if (ret) {
151 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200152 }
Radek Krejcic071c542016-01-27 14:57:51 +0100153 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200154 }
155 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200156 }
157
158 return EXIT_FAILURE;
159}
160
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200161int
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100162lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, int nam_len,
163 LYS_NODE type, const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200164{
Michal Vasko1e62a092015-12-01 12:27:20 +0100165 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200166
167 assert(siblings && name);
168 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
169
170 /* find the beginning */
171 while (siblings->prev->next) {
172 siblings = siblings->prev;
173 }
174
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200175 if (!mod) {
176 mod = siblings->module;
177 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200178
Michal Vasko4f0dad02016-02-15 14:08:23 +0100179 /* try to find the node */
180 node = NULL;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200181 while ((node = lys_getnext(node, lys_parent(siblings), mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100182 if (!type || (node->nodetype & type)) {
183 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200184 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100185 continue;
186 }
187
Michal Vasko4f0dad02016-02-15 14:08:23 +0100188 /* direct name check */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100189 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100190 if (ret) {
191 *ret = node;
192 }
193 return EXIT_SUCCESS;
194 }
Radek Krejcic071c542016-01-27 14:57:51 +0100195 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200196 }
197
198 return EXIT_FAILURE;
199}
200
Michal Vasko1e62a092015-12-01 12:27:20 +0100201API const struct lys_node *
202lys_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 +0200203{
Michal Vasko1e62a092015-12-01 12:27:20 +0100204 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200205
Radek Krejci8bc87f62015-09-02 16:19:05 +0200206 if (!last) {
207 /* first call */
208
209 /* get know where to start */
210 if (parent) {
211 /* schema subtree */
212 next = last = parent->child;
213 } else {
214 /* top level data */
215 assert(module);
216 next = last = module->data;
217 }
Radek Krejci972724f2016-08-12 15:24:40 +0200218 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
219 /* continue with uses content */
220 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200221 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200222 /* continue after the last returned value */
223 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200224 }
225
226repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200227 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200228 if (options & LYS_GETNEXT_WITHGROUPING) {
229 return next;
230 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200231 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200232 }
233
Radek Krejci972724f2016-08-12 15:24:40 +0200234 if (!next) { /* cover case when parent is augment */
235 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200236 /* no next element */
237 return NULL;
238 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200239 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200240 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200241 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200242 } else {
243 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200244 }
245
246 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200247 case LYS_INPUT:
248 case LYS_OUTPUT:
249 if (options & LYS_GETNEXT_WITHINOUT) {
250 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200251 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200252 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200253 } else {
254 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200255 }
Radek Krejci972724f2016-08-12 15:24:40 +0200256 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200257
Michal Vaskoa5835e92015-10-20 15:07:39 +0200258 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200259 if (options & LYS_GETNEXT_WITHCASE) {
260 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200261 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200262 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200263 } else {
264 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200265 }
Radek Krejci972724f2016-08-12 15:24:40 +0200266 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200267
Michal Vasko1dca6882015-10-22 14:29:42 +0200268 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200269 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200270 if (options & LYS_GETNEXT_WITHUSES) {
271 return next;
272 } else if (next->child) {
273 next = next->child;
274 } else {
275 next = next->next;
276 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200277 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200278
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200279 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200280 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200281 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200282 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200283 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200284 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200285 case LYS_LIST:
286 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200287 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200288
Radek Krejci972724f2016-08-12 15:24:40 +0200289 case LYS_CONTAINER:
290 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
291 if (next->child) {
292 /* go into */
293 next = next->child;
294 } else {
295 next = next->next;
296 }
297 goto repeat;
298 } else {
299 return next;
300 }
301
Radek Krejci8bc87f62015-09-02 16:19:05 +0200302 case LYS_CHOICE:
303 if (options & LYS_GETNEXT_WITHCHOICE) {
304 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200305 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200306 /* go into */
307 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200308 } else {
309 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200310 }
Radek Krejci972724f2016-08-12 15:24:40 +0200311 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200312
Radek Krejci7f40ce32015-08-12 20:38:46 +0200313 default:
314 /* we should not be here */
315 return NULL;
316 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200317
318
319}
320
Radek Krejcibf285832017-01-26 16:05:41 +0100321void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200322lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200323{
Radek Krejci76512572015-08-04 09:47:08 +0200324 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100325 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200327 if (!node) {
328 return;
329 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200331 /* unlink from data model if necessary */
332 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100333 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100334 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100335 if (main_module->data == node) {
336 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200337 }
338 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200340 /* store pointers to important nodes */
341 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200342 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200343 /* handle augments - first, unlink it from the augment parent ... */
344 if (parent->child == node) {
345 parent->child = node->next;
346 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100347
348 if (parent->flags & LYS_NOTAPPLIED) {
349 /* data are not connected in the target, so we cannot continue with the target as a parent */
350 parent = NULL;
351 } else {
352 /* data are connected in target, so we will continue with the target as a parent */
353 parent = ((struct lys_node_augment *)parent)->target;
354 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200355 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200357 /* unlink from parent */
358 if (parent) {
359 if (parent->child == node) {
360 parent->child = node->next;
361 }
362 node->parent = NULL;
363 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200365 /* unlink from siblings */
366 if (node->prev == node) {
367 /* there are no more siblings */
368 return;
369 }
370 if (node->next) {
371 node->next->prev = node->prev;
372 } else {
373 /* unlinking the last element */
374 if (parent) {
375 first = parent->child;
376 } else {
377 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200378 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200379 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200380 }
381 }
382 first->prev = node->prev;
383 }
384 if (node->prev->next) {
385 node->prev->next = node->next;
386 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200388 /* clean up the unlinked element */
389 node->next = NULL;
390 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200391}
392
Michal Vasko563ef092015-09-04 13:17:23 +0200393struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100394lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200395{
396 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200397
398 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200399 /* top-level augment, look into module (uses augment is handled correctly below) */
400 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
401 par_iter = par_iter->parent->module->data;
402 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200403 break;
404 }
405 }
406
Michal Vasko6f929da2015-10-02 16:23:25 +0200407 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200408 continue;
409 }
410
411 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
412 if (!stop) {
413 stop = par_iter;
414 } else if (iter == stop) {
415 break;
416 }
417 if (iter->nodetype != LYS_GROUPING) {
418 continue;
419 }
420
Radek Krejcif8426a72015-10-31 23:14:03 +0100421 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200422 return (struct lys_node_grp *)iter;
423 }
424 }
425 }
426
Michal Vasko563ef092015-09-04 13:17:23 +0200427 return NULL;
428}
429
Radek Krejci10c760e2015-08-14 14:45:43 +0200430/*
431 * get next grouping in the root's subtree, in the
432 * first call, tha last is NULL
433 */
434static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200435lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200436{
Radek Krejci10c760e2015-08-14 14:45:43 +0200437 struct lys_node *last = (struct lys_node *)lastgrp;
438 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200439
Radek Krejci10c760e2015-08-14 14:45:43 +0200440 assert(root);
441
442 if (!last) {
443 last = root;
444 }
445
446 while (1) {
447 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
448 next = last->child;
449 } else {
450 next = NULL;
451 }
452 if (!next) {
453 if (last == root) {
454 /* we are done */
455 return NULL;
456 }
457
458 /* no children, go to siblings */
459 next = last->next;
460 }
461 while (!next) {
462 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100463 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200464 /* we are done */
465 return NULL;
466 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200467 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100468 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200469 }
470
471 if (next->nodetype == LYS_GROUPING) {
472 return (struct lys_node_grp *)next;
473 }
474
475 last = next;
476 }
477}
478
Michal Vasko0d343d12015-08-24 14:57:36 +0200479/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200480int
Radek Krejci07911992015-08-14 15:13:31 +0200481lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
482{
Michal Vasko563ef092015-09-04 13:17:23 +0200483 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200484 struct lys_node_grp *grp;
485 int down;
486
487 assert(node);
488
489 if (!parent) {
490 assert(module);
491 } else {
492 module = parent->module;
493 }
494
495 switch (node->nodetype) {
496 case LYS_GROUPING:
497 /* 6.2.1, rule 6 */
498 if (parent) {
499 if (parent->child) {
500 down = 1;
501 start = parent->child;
502 } else {
503 down = 0;
504 start = parent;
505 }
506 } else {
507 down = 1;
508 start = module->data;
509 }
510 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100511 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100512 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200513 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200514 }
515 /* go down, because grouping can be defined after e.g. container in which is collision */
516 if (down) {
517 for (iter = start, stop = NULL; iter; iter = iter->prev) {
518 if (!stop) {
519 stop = start;
520 } else if (iter == stop) {
521 break;
522 }
523 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
524 continue;
525 }
526
527 grp = NULL;
528 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100529 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100530 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200531 return EXIT_FAILURE;
532 }
533 }
534 }
535 }
536 break;
537 case LYS_LEAF:
538 case LYS_LEAFLIST:
539 case LYS_LIST:
540 case LYS_CONTAINER:
541 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200542 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200543 /* 6.2.1, rule 7 */
544 if (parent) {
545 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200546 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
547 if (iter->nodetype == LYS_AUGMENT) {
548 if (((struct lys_node_augment *)iter)->target) {
549 /* augment is resolved, go up */
550 iter = ((struct lys_node_augment *)iter)->target;
551 continue;
552 }
553 /* augment is not resolved, this is the final parent */
554 break;
555 }
Radek Krejci07911992015-08-14 15:13:31 +0200556 iter = iter->parent;
557 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200558
Radek Krejci07911992015-08-14 15:13:31 +0200559 if (!iter) {
560 stop = NULL;
561 iter = module->data;
562 } else {
563 stop = iter;
564 iter = iter->child;
565 }
566 } else {
567 stop = NULL;
568 iter = module->data;
569 }
570 while (iter) {
571 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
572 iter = iter->child;
573 continue;
574 }
575
Radek Krejcibf2abff2016-08-23 15:51:52 +0200576 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100577 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100578 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200579 return EXIT_FAILURE;
580 }
581 }
582
583 /* special case for choice - we must check the choice's name as
584 * well as the names of nodes under the choice
585 */
586 if (iter->nodetype == LYS_CHOICE) {
587 iter = iter->child;
588 continue;
589 }
590
591 /* go to siblings */
592 if (!iter->next) {
593 /* no sibling, go to parent's sibling */
594 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200595 /* for parent LYS_AUGMENT */
596 if (iter->parent == stop) {
597 iter = stop;
598 break;
599 }
600 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200601 if (iter && iter->next) {
602 break;
603 }
604 } while (iter != stop);
605
606 if (iter == stop) {
607 break;
608 }
609 }
610 iter = iter->next;
611 }
612 break;
613 case LYS_CASE:
614 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100615 if (parent) {
616 start = parent->child;
617 } else {
618 start = module->data;
619 }
620
621 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200622 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200623 continue;
624 }
625
Radek Krejci749190d2016-02-18 16:26:25 +0100626 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100627 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200628 return EXIT_FAILURE;
629 }
630 }
631 break;
632 default:
633 /* no check needed */
634 break;
635 }
636
637 return EXIT_SUCCESS;
638}
639
Michal Vasko0d343d12015-08-24 14:57:36 +0200640/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200641int
Radek Krejci10c760e2015-08-14 14:45:43 +0200642lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
643{
Radek Krejci30bfcd22017-01-27 16:54:48 +0100644 struct lys_node *iter, *next;
Radek Krejci41a349b2016-10-24 19:21:59 +0200645 struct lys_node_inout *in, *out, *inout;
Radek Krejci07911992015-08-14 15:13:31 +0200646 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200648 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200649
Radek Krejci10c760e2015-08-14 14:45:43 +0200650 if (parent) {
651 type = parent->nodetype;
652 module = parent->module;
653 } else {
654 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100655 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200656 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200657 }
658
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200659 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200660 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200661 case LYS_CONTAINER:
662 case LYS_LIST:
663 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100664 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200665 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200666 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200667 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200668 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
669 return EXIT_FAILURE;
670 }
671 break;
Radek Krejci76512572015-08-04 09:47:08 +0200672 case LYS_INPUT:
673 case LYS_OUTPUT:
674 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200675 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200676 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200677 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100678 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200679 return EXIT_FAILURE;
680 }
681 break;
Radek Krejci76512572015-08-04 09:47:08 +0200682 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200683 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200684 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100685 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200686 return EXIT_FAILURE;
687 }
688 break;
Radek Krejci76512572015-08-04 09:47:08 +0200689 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200690 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200691 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100692 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200693 return EXIT_FAILURE;
694 }
695 break;
Radek Krejci76512572015-08-04 09:47:08 +0200696 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200697 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200698 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100699 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200700 return EXIT_FAILURE;
701 }
702 break;
Radek Krejci76512572015-08-04 09:47:08 +0200703 case LYS_LEAF:
704 case LYS_LEAFLIST:
705 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200706 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100707 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vasko51e5c582017-01-19 14:16:39 +0100708 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100709 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200710 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200711 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200712 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200713 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100714 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100715 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200716 return EXIT_FAILURE;
717 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200718 break;
719 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200720 /* top level */
721 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200722 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200723 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100724 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200725 return EXIT_FAILURE;
726 }
727
Radek Krejcic071c542016-01-27 14:57:51 +0100728 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200729 }
730
731 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200732 if (lys_check_id(child, parent, module)) {
733 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200734 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200736 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200737 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200738 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200739
Radek Krejci41a349b2016-10-24 19:21:59 +0200740 if (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
741 /* replace the implicit input/output node */
742 if (child->nodetype == LYS_OUTPUT) {
743 inout = (struct lys_node_inout *)parent->child->next;
744 } else { /* LYS_INPUT */
745 inout = (struct lys_node_inout *)parent->child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200746 parent->child = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200747 }
748 if (inout->next) {
749 child->next = inout->next;
750 inout->next->prev = child;
751 inout->next = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200752 } else {
Radek Krejci41a349b2016-10-24 19:21:59 +0200753 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200754 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200755 child->prev = inout->prev;
756 if (inout->prev->next) {
757 inout->prev->next = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200758 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200759 inout->prev = (struct lys_node *)inout;
760 child->parent = parent;
761 inout->parent = NULL;
762 lys_node_free((struct lys_node *)inout, NULL, 0);
763 } else {
764 /* connect the child correctly */
765 if (!parent) {
766 if (module->data) {
767 module->data->prev->next = child;
768 child->prev = module->data->prev;
769 module->data->prev = child;
770 } else {
771 module->data = child;
772 }
773 } else {
Radek Krejci30bfcd22017-01-27 16:54:48 +0100774 next = NULL;
Radek Krejci41a349b2016-10-24 19:21:59 +0200775 if (!parent->child) {
776 /* the only/first child of the parent */
777 parent->child = child;
778 child->parent = parent;
779 iter = child;
Radek Krejci30bfcd22017-01-27 16:54:48 +0100780 } else if (type == LYS_AUGMENT) {
781 /* add a new child as a last child of the augment (no matter if applied or not) */
782 for (iter = parent->child->prev; iter->parent != parent; iter = iter->prev);
783 next = iter->next;
784 iter->next = child;
785 child->prev = iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200786 } else {
787 /* add a new child at the end of parent's child list */
788 iter = parent->child->prev;
789 iter->next = child;
790 child->prev = iter;
791 }
792 while (iter->next) {
793 iter = iter->next;
794 iter->parent = parent;
795 }
Radek Krejci30bfcd22017-01-27 16:54:48 +0100796 if (next) {
797 /* we are in applied augment, its target has some additional nodes after the nodes from this augment */
798 iter->next = next;
799 next->prev = iter;
800 } else {
801 parent->child->prev = iter;
802 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200803 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200804 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200805
Michal Vaskoe022a562016-09-27 14:24:15 +0200806 /* check config value (but ignore them in groupings and augments) */
807 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT)); iter = iter->parent);
808 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200809 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
810 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
811 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +0100812 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200813 return EXIT_FAILURE;
814 }
815 }
816
Radek Krejci41771502016-04-14 17:52:32 +0200817 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200818 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200819 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200820 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200821 /* store it only into container or list - the only data inner nodes */
822 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
823 if (iter->flags & LYS_INCL_STATUS) {
824 /* done, someone else set it already from here */
825 break;
826 }
827 /* set flag about including status data */
828 iter->flags |= LYS_INCL_STATUS;
829 }
830 }
831 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200832
833 /* create implicit input/output nodes to have available them as possible target for augment */
834 if (child->nodetype & (LYS_RPC | LYS_ACTION)) {
835 in = calloc(1, sizeof *in);
836 in->nodetype = LYS_INPUT;
837 in->name = lydict_insert(child->module->ctx, "input", 5);
838 out = calloc(1, sizeof *out);
839 out->name = lydict_insert(child->module->ctx, "output", 6);
840 out->nodetype = LYS_OUTPUT;
841 in->module = out->module = child->module;
842 in->parent = out->parent = child;
843 in->flags = out->flags = LYS_IMPLICIT;
844 in->next = (struct lys_node *)out;
845 in->prev = (struct lys_node *)out;
846 out->prev = (struct lys_node *)in;
847 child->child = (struct lys_node *)in;
848 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200849 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200850}
851
Radek Krejcia1df1682016-04-11 14:56:59 +0200852static const struct lys_module *
853lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200854{
Radek Krejcia1df1682016-04-11 14:56:59 +0200855 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200856 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200857 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200858
Radek Krejci00a0e712016-10-26 10:24:46 +0200859 ly_err_clean(1);
Radek Krejcif347abc2016-06-22 10:18:47 +0200860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200861 if (!ctx || !data) {
862 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
863 return NULL;
864 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200865
Radek Krejcia1df1682016-04-11 14:56:59 +0200866 if (!internal && format == LYS_IN_YANG) {
867 /* enlarge data by 2 bytes for flex */
868 len = strlen(data);
869 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
870 if (!enlarged_data) {
871 LOGMEM;
872 return NULL;
873 }
874 memcpy(enlarged_data, data, len);
875 enlarged_data[len] = enlarged_data[len + 1] = '\0';
876 data = enlarged_data;
877 }
878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200879 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200880 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100881 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200882 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200883 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100884 mod = yang_read_module(ctx, data, 0, NULL, 1);
885 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200886 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200887 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200888 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200889 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200890
Radek Krejcia1df1682016-04-11 14:56:59 +0200891 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200892 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200893}
894
Radek Krejcia1df1682016-04-11 14:56:59 +0200895API const struct lys_module *
896lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
897{
898 return lys_parse_mem_(ctx, data, format, 0);
899}
900
Michal Vasko5a721fd2016-02-16 12:16:48 +0100901struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +0100902lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200903{
Michal Vasko5b998712017-01-26 10:34:06 +0100904 char *enlarged_data = NULL;
Michal Vasko5a721fd2016-02-16 12:16:48 +0100905 struct lys_submodule *submod = NULL;
Michal Vasko5b998712017-01-26 10:34:06 +0100906 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200907
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200908 assert(module);
909 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200910
Michal Vasko5b998712017-01-26 10:34:06 +0100911 if (format == LYS_IN_YANG) {
912 /* enlarge data by 2 bytes for flex */
913 len = strlen(data);
914 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
915 if (!enlarged_data) {
916 LOGMEM;
917 return NULL;
918 }
919 memcpy(enlarged_data, data, len);
920 enlarged_data[len] = enlarged_data[len + 1] = '\0';
921 data = enlarged_data;
922 }
923
Radek Krejcic071c542016-01-27 14:57:51 +0100924 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +0200925 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200926
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200927 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200928 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +0100929 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200930 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200931 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100932 submod = yang_read_submodule(module, data, 0, unres);
933 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200934 default:
Radek Krejci90a550a2016-04-13 16:00:58 +0200935 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200936 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200938
Michal Vasko5b998712017-01-26 10:34:06 +0100939 free(enlarged_data);
Michal Vasko5a721fd2016-02-16 12:16:48 +0100940 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200941}
942
Michal Vasko1e62a092015-12-01 12:27:20 +0100943API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +0100944lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
945{
946 int fd;
947 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +0200948 const char *rev, *dot, *filename;
949 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +0100950
951 if (!ctx || !path) {
952 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
953 return NULL;
954 }
955
956 fd = open(path, O_RDONLY);
957 if (fd == -1) {
958 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
959 return NULL;
960 }
961
962 ret = lys_parse_fd(ctx, fd, format);
963 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +0100964
Radek Krejcid80c8602016-10-25 11:56:03 +0200965 if (!ret) {
966 /* error */
967 return NULL;
968 }
969
970 /* check that name and revision match filename */
971 filename = strrchr(path, '/');
972 if (!filename) {
973 filename = path;
974 } else {
975 filename++;
976 }
977 rev = strchr(filename, '@');
978 dot = strrchr(filename, '.');
979
980 /* name */
981 len = strlen(ret->name);
982 if (strncmp(filename, ret->name, len) ||
983 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Radek Krejcic0c82302016-10-25 14:21:33 +0200984 LOGWRN("File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +0200985 }
986 if (rev) {
987 len = dot - ++rev;
988 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
989 LOGWRN("File name \"%s\" does not match module revision \"%s\".", filename,
990 ret->rev_size ? ret->rev[0].date : "none");
991 }
992 }
993
994 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +0100995 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +0100996 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +0100997 }
998
Michal Vasko662610a2015-12-07 11:25:45 +0100999 return ret;
1000}
1001
1002API const struct lys_module *
1003lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001004{
Michal Vasko1e62a092015-12-01 12:27:20 +01001005 const struct lys_module *module;
Radek Krejci0fb11502017-01-31 16:45:42 +01001006 size_t length;
Radek Krejci63a91a92015-07-29 13:31:04 +02001007 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001008 char buf[PATH_MAX];
1009 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001010
1011 if (!ctx || fd < 0) {
1012 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1013 return NULL;
1014 }
1015
Radek Krejci0fb11502017-01-31 16:45:42 +01001016 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001017 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001018 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001019 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001020 } else if (!addr) {
1021 LOGERR(LY_EINVAL, "Empty schema file.");
Pavol Vicane36ea262015-11-12 11:57:47 +01001022 return NULL;
1023 }
Radek Krejci0fb11502017-01-31 16:45:42 +01001024
Radek Krejcia1df1682016-04-11 14:56:59 +02001025 module = lys_parse_mem_(ctx, addr, format, 1);
Radek Krejci0fb11502017-01-31 16:45:42 +01001026 lyp_munmap(addr, length);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001027
Radek Krejcia77904e2016-02-25 16:23:45 +01001028 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001029 /* get URI if there is /proc */
1030 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001031 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1032 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1033 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1034 }
1035 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001036 }
Radek Krejcib051f722016-02-25 15:12:21 +01001037 }
1038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001039 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001040}
1041
Michal Vasko5a721fd2016-02-16 12:16:48 +01001042struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001043lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001044{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001045 struct lys_submodule *submodule;
Radek Krejci0fb11502017-01-31 16:45:42 +01001046 size_t length;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001047 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001049 assert(module);
1050 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001051
Radek Krejci0fb11502017-01-31 16:45:42 +01001052 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001053 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001054 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001055 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001056 } else if (!addr) {
1057 LOGERR(LY_EINVAL, "Empty submodule schema file.");
Michal Vasko2e7241e2016-02-15 16:06:34 +01001058 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001059 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001060
Michal Vasko5b998712017-01-26 10:34:06 +01001061 /* get the main module */
1062 module = lys_main_module(module);
1063
1064 switch (format) {
1065 case LYS_IN_YIN:
1066 submodule = yin_read_submodule(module, addr, unres);
1067 break;
1068 case LYS_IN_YANG:
1069 submodule = yang_read_submodule(module, addr, 0, unres);
1070 break;
1071 default:
1072 assert(0);
1073 break;
1074 }
1075
Radek Krejcic645a3a2017-01-31 16:59:00 +01001076 lyp_munmap(addr, length);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001077 return submodule;
1078
Radek Krejciefaeba32015-05-27 14:30:57 +02001079}
1080
Radek Krejcibf285832017-01-26 16:05:41 +01001081int
1082lys_ext_iter(struct lys_ext_instance **ext, uint8_t ext_size, uint8_t start, LYEXT_SUBSTMT substmt)
1083{
1084 unsigned int u;
1085
1086 for (u = start; u < ext_size; u++) {
1087 if (ext[u]->substmt == substmt) {
1088 return u;
1089 }
1090 }
1091
1092 return -1;
1093}
1094
Radek Krejcifdc0d702017-01-23 15:58:38 +01001095/*
1096 * duplicate extension instance
1097 */
1098int
Radek Krejci8d6b7422017-02-03 14:42:13 +01001099lys_ext_dup(struct lys_module *mod, struct lys_ext_instance **orig, uint8_t size,
Radek Krejcifdc0d702017-01-23 15:58:38 +01001100 void *parent, LYEXT_PAR parent_type, struct lys_ext_instance ***new, struct unres_schema *unres)
1101{
1102 int i;
1103 uint8_t u = 0;
1104 struct lys_ext_instance **result;
1105 struct unres_ext *info, *info_orig;
1106
1107 assert(new);
1108
1109 if (!size) {
1110 if (orig) {
1111 LOGINT;
1112 return EXIT_FAILURE;
1113 }
1114 (*new) = NULL;
1115 return EXIT_SUCCESS;
1116 }
1117
1118 (*new) = result = calloc(size, sizeof *result);
1119 for (u = 0; u < size; u++) {
Radek Krejci9722c6d2017-02-03 15:39:01 +01001120 /* TODO cover complex extension instances */
1121
Radek Krejcifdc0d702017-01-23 15:58:38 +01001122 if (orig[u]) {
1123 /* resolved extension instance, just duplicate it */
1124 switch(lys_ext_instance_type(orig[u])) {
1125 case LYEXT_FLAG:
1126 result[u] = malloc(sizeof(struct lys_ext_instance));
1127 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001128 case LYEXT_COMPLEX:
1129 result[u] = calloc(1, ((struct lyext_plugin_complex*)orig[u]->def->plugin)->instance_size);
Radek Krejci9722c6d2017-02-03 15:39:01 +01001130 ((struct lys_ext_instance_complex*)result[u])->module = mod;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001131 /* TODO duplicate data in extension instance content */
1132 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001133 case LYEXT_ERR:
1134 LOGINT;
1135 break;
1136 }
1137 /* generic part */
1138 result[u]->def = orig[u]->def;
1139 result[u]->flags = 0;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001140 result[u]->arg_value = lydict_insert(mod->ctx, orig[u]->arg_value, 0);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001141 result[u]->parent = parent;
1142 result[u]->parent_type = parent_type;
1143 result[u]->substmt = orig[u]->substmt;
1144 result[u]->substmt_index = orig[u]->substmt_index;
1145
1146 /* extensions */
1147 orig[u]->ext = NULL;
1148 result[u]->ext_size = orig[u]->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001149 if (lys_ext_dup(mod, orig[u]->ext, orig[u]->ext_size, result[u],
Radek Krejcif0bb3602017-01-25 17:05:08 +01001150 LYEXT_PAR_EXTINST, &result[u]->ext, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001151 goto error;
1152 }
1153 } else {
1154 /* original extension is not yet resolved, so duplicate it in unres */
1155 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1156 if (i == -1) {
1157 /* extension not found in unres */
1158 LOGINT;
1159 goto error;
1160 }
1161 info_orig = unres->str_snode[i];
1162 info = malloc(sizeof *info);
1163 info->datatype = info_orig->datatype;
1164 if (info->datatype == LYS_IN_YIN) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001165 info->data.yin = lyxml_dup_elem(mod->ctx, info_orig->data.yin, NULL, 1);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001166 } /* else TODO YANG */
1167 info->parent = parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001168 info->mod = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001169 info->parent_type = parent_type;
1170 info->ext_index = u;
1171 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1172 goto error;
1173 }
1174 }
1175 }
1176
1177 return EXIT_SUCCESS;
1178
1179error:
1180 (*new) = NULL;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001181 lys_extension_instances_free(mod->ctx, result, u);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001182 return EXIT_FAILURE;
1183}
1184
Radek Krejci1d82ef62015-08-07 14:44:40 +02001185static struct lys_restr *
Radek Krejci8d6b7422017-02-03 14:42:13 +01001186lys_restr_dup(struct lys_module *mod, struct lys_restr *old, int size, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001187{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001188 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001189 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001190
Radek Krejci3733a802015-06-19 13:43:21 +02001191 if (!size) {
1192 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001193 }
Radek Krejci3733a802015-06-19 13:43:21 +02001194
1195 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001196 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001197 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001198 return NULL;
1199 }
Radek Krejci3733a802015-06-19 13:43:21 +02001200 for (i = 0; i < size; i++) {
Radek Krejci77f22b22017-01-17 15:23:03 +01001201 result[i].ext_size = old[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001202 lys_ext_dup(mod, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_RESTR, &result[i].ext, unres);
1203 result[i].expr = lydict_insert(mod->ctx, old[i].expr, 0);
1204 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1205 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1206 result[i].eapptag = lydict_insert(mod->ctx, old[i].eapptag, 0);
1207 result[i].emsg = lydict_insert(mod->ctx, old[i].emsg, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001208 }
1209
1210 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001211}
1212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001213void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001214lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001215{
1216 assert(ctx);
1217 if (!restr) {
1218 return;
1219 }
1220
Radek Krejcifccd1442017-01-16 10:26:57 +01001221 lys_extension_instances_free(ctx, restr->ext, restr->ext_size);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001222 lydict_remove(ctx, restr->expr);
1223 lydict_remove(ctx, restr->dsc);
1224 lydict_remove(ctx, restr->ref);
1225 lydict_remove(ctx, restr->eapptag);
1226 lydict_remove(ctx, restr->emsg);
1227}
1228
Pavol Vican05810b62016-11-23 14:07:22 +01001229void
Radek Krejci5323b492017-01-16 15:40:11 +01001230lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size)
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001231{
1232 uint8_t i;
1233
1234 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci5323b492017-01-16 15:40:11 +01001235 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001236 free(iffeature[i].expr);
1237 free(iffeature[i].features);
1238 }
1239 free(iffeature);
1240}
1241
Michal Vaskob84f88a2015-09-24 13:16:10 +02001242static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001243type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001244 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001245{
1246 int i;
1247
1248 switch (base) {
1249 case LY_TYPE_BINARY:
1250 if (old->info.binary.length) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001251 new->info.binary.length = lys_restr_dup(mod, old->info.binary.length, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001252 }
1253 break;
1254
1255 case LY_TYPE_BITS:
1256 new->info.bits.count = old->info.bits.count;
1257 if (new->info.bits.count) {
1258 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1259 if (!new->info.bits.bit) {
1260 LOGMEM;
1261 return -1;
1262 }
1263 for (i = 0; i < new->info.bits.count; i++) {
1264 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1265 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1266 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1267 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1268 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001269 new->info.bits.bit[i].ext_size = old->info.bits.bit[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001270 if (lys_ext_dup(mod, old->info.bits.bit[i].ext, old->info.bits.bit[i].ext_size,
Radek Krejcif0bb3602017-01-25 17:05:08 +01001271 &new->info.bits.bit[i], LYEXT_PAR_TYPE_BIT,
1272 &new->info.bits.bit[i].ext, unres)) {
1273 return -1;
1274 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001275 }
1276 }
1277 break;
1278
1279 case LY_TYPE_DEC64:
1280 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001281 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001282 if (old->info.dec64.range) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001283 new->info.dec64.range = lys_restr_dup(mod, old->info.dec64.range, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001284 }
1285 break;
1286
1287 case LY_TYPE_ENUM:
1288 new->info.enums.count = old->info.enums.count;
1289 if (new->info.enums.count) {
1290 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1291 if (!new->info.enums.enm) {
1292 LOGMEM;
1293 return -1;
1294 }
1295 for (i = 0; i < new->info.enums.count; i++) {
1296 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1297 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1298 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1299 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1300 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001301 new->info.enums.enm[i].ext_size = old->info.enums.enm[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001302 if (lys_ext_dup(mod, old->info.enums.enm[i].ext, old->info.enums.enm[i].ext_size,
Radek Krejcif0bb3602017-01-25 17:05:08 +01001303 &new->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM,
1304 &new->info.enums.enm[i].ext, unres)) {
1305 return -1;
1306 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001307 }
1308 }
1309 break;
1310
1311 case LY_TYPE_IDENT:
Michal Vaskoaffc37f2016-10-10 18:05:03 +00001312 new->info.ident.count = old->info.ident.count;
Michal Vasko878e38d2016-09-05 12:17:53 +02001313 if (old->info.ident.count) {
1314 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1315 if (!new->info.ident.ref) {
1316 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001317 return -1;
1318 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001319 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1320 } else {
1321 /* there can be several unresolved base identities, duplicate them all */
1322 i = -1;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001323 do {
1324 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1325 if (i != -1) {
1326 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1327 return -1;
1328 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001329 }
1330 --i;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001331 } while (i > -1);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001332 }
1333 break;
1334
1335 case LY_TYPE_INST:
1336 new->info.inst.req = old->info.inst.req;
1337 break;
1338
1339 case LY_TYPE_INT8:
1340 case LY_TYPE_INT16:
1341 case LY_TYPE_INT32:
1342 case LY_TYPE_INT64:
1343 case LY_TYPE_UINT8:
1344 case LY_TYPE_UINT16:
1345 case LY_TYPE_UINT32:
1346 case LY_TYPE_UINT64:
1347 if (old->info.num.range) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001348 new->info.num.range = lys_restr_dup(mod, old->info.num.range, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001349 }
1350 break;
1351
1352 case LY_TYPE_LEAFREF:
1353 if (old->info.lref.path) {
1354 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001355 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001356 return -1;
1357 }
1358 }
1359 break;
1360
1361 case LY_TYPE_STRING:
1362 if (old->info.str.length) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001363 new->info.str.length = lys_restr_dup(mod, old->info.str.length, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001364 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01001365 new->info.str.patterns = lys_restr_dup(mod, old->info.str.patterns, old->info.str.pat_count, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001366 new->info.str.pat_count = old->info.str.pat_count;
1367 break;
1368
1369 case LY_TYPE_UNION:
1370 new->info.uni.count = old->info.uni.count;
1371 if (new->info.uni.count) {
1372 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1373 if (!new->info.uni.types) {
1374 LOGMEM;
1375 return -1;
1376 }
1377 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001378 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001379 return -1;
1380 }
1381 }
1382 }
1383 break;
1384
1385 default:
1386 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1387 break;
1388 }
1389 return EXIT_SUCCESS;
1390}
1391
1392struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001393lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1394 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001395{
1396 struct yang_type *new;
1397
1398 new = calloc(1, sizeof *new);
1399 if (!new) {
1400 LOGMEM;
1401 return NULL;
1402 }
1403 new->flags = old->flags;
1404 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001405 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001406 new->type = type;
1407 if (!new->name) {
1408 LOGMEM;
1409 goto error;
1410 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001411 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001412 new->type->base = new->base;
1413 lys_type_free(module->ctx, new->type);
1414 memset(&new->type->info, 0, sizeof new->type->info);
1415 goto error;
1416 }
1417 return new;
1418
1419 error:
1420 free(new);
1421 return NULL;
1422}
1423
Radek Krejci43ce4b72017-01-04 11:02:38 +01001424API const void *
1425lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1426{
1427 if (!ext) {
1428 return NULL;
1429 }
1430
1431 switch (ext->substmt) {
1432 case LYEXT_SUBSTMT_SELF:
1433 case LYEXT_SUBSTMT_MODIFIER:
1434 case LYEXT_SUBSTMT_VERSION:
1435 return NULL;
1436 case LYEXT_SUBSTMT_ARGUMENT:
1437 if (ext->parent_type == LYEXT_PAR_EXT) {
1438 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1439 }
1440 break;
1441 case LYEXT_SUBSTMT_BASE:
1442 if (ext->parent_type == LYEXT_PAR_TYPE) {
1443 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->substmt_index];
1444 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
1445 return ((struct lys_ident*)ext->parent)->base[ext->substmt_index];
1446 }
1447 break;
1448 case LYEXT_SUBSTMT_BELONGSTO:
1449 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1450 return ((struct lys_submodule*)ext->parent)->belongsto;
1451 }
1452 break;
1453 case LYEXT_SUBSTMT_CONFIG:
1454 case LYEXT_SUBSTMT_MANDATORY:
1455 if (ext->parent_type == LYEXT_PAR_NODE) {
1456 return &((struct lys_node*)ext->parent)->flags;
1457 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1458 return &((struct lys_deviate*)ext->parent)->flags;
1459 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1460 return &((struct lys_refine*)ext->parent)->flags;
1461 }
1462 break;
1463 case LYEXT_SUBSTMT_CONTACT:
1464 if (ext->parent_type == LYEXT_PAR_MODULE) {
1465 return ((struct lys_module*)ext->parent)->contact;
1466 }
1467 break;
1468 case LYEXT_SUBSTMT_DEFAULT:
1469 if (ext->parent_type == LYEXT_PAR_NODE) {
1470 switch (((struct lys_node*)ext->parent)->nodetype) {
1471 case LYS_LEAF:
1472 case LYS_LEAFLIST:
1473 /* in case of leaf, the index is supposed to be 0, so it will return the
1474 * correct pointer despite the leaf structure does not have dflt as array */
1475 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->substmt_index];
1476 case LYS_CHOICE:
1477 return ((struct lys_node_choice*)ext->parent)->dflt;
1478 default:
1479 /* internal error */
1480 break;
1481 }
1482 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1483 return ((struct lys_tpdf*)ext->parent)->dflt;
1484 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1485 return ((struct lys_deviate*)ext->parent)->dflt[ext->substmt_index];
1486 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1487 return &((struct lys_refine*)ext->parent)->dflt[ext->substmt_index];
1488 }
1489 break;
1490 case LYEXT_SUBSTMT_DESCRIPTION:
1491 switch (ext->parent_type) {
1492 case LYEXT_PAR_NODE:
1493 return ((struct lys_node*)ext->parent)->dsc;
1494 case LYEXT_PAR_MODULE:
1495 return ((struct lys_module*)ext->parent)->dsc;
1496 case LYEXT_PAR_IMPORT:
1497 return ((struct lys_import*)ext->parent)->dsc;
1498 case LYEXT_PAR_INCLUDE:
1499 return ((struct lys_include*)ext->parent)->dsc;
1500 case LYEXT_PAR_EXT:
1501 return ((struct lys_ext*)ext->parent)->dsc;
1502 case LYEXT_PAR_FEATURE:
1503 return ((struct lys_feature*)ext->parent)->dsc;
1504 case LYEXT_PAR_TPDF:
1505 return ((struct lys_tpdf*)ext->parent)->dsc;
1506 case LYEXT_PAR_TYPE_BIT:
1507 return ((struct lys_type_bit*)ext->parent)->dsc;
1508 case LYEXT_PAR_TYPE_ENUM:
1509 return ((struct lys_type_enum*)ext->parent)->dsc;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001510 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001511 return ((struct lys_restr*)ext->parent)->dsc;
1512 case LYEXT_PAR_WHEN:
1513 return ((struct lys_when*)ext->parent)->dsc;
1514 case LYEXT_PAR_IDENT:
1515 return ((struct lys_ident*)ext->parent)->dsc;
1516 case LYEXT_PAR_DEVIATION:
1517 return ((struct lys_deviation*)ext->parent)->dsc;
1518 case LYEXT_PAR_REVISION:
1519 return ((struct lys_revision*)ext->parent)->dsc;
1520 case LYEXT_PAR_REFINE:
1521 return ((struct lys_refine*)ext->parent)->dsc;
1522 default:
1523 break;
1524 }
1525 break;
1526 case LYEXT_SUBSTMT_ERRTAG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001527 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001528 return ((struct lys_restr*)ext->parent)->eapptag;
1529 }
1530 break;
1531 case LYEXT_SUBSTMT_ERRMSG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001532 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001533 return ((struct lys_restr*)ext->parent)->emsg;
1534 }
1535 break;
1536 case LYEXT_SUBSTMT_DIGITS:
1537 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
1538 return &((struct lys_type*)ext->parent)->info.dec64.dig;
1539 }
1540 break;
1541 case LYEXT_SUBSTMT_KEY:
1542 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1543 return ((struct lys_node_list*)ext->parent)->keys;
1544 }
1545 break;
1546 case LYEXT_SUBSTMT_MAX:
1547 if (ext->parent_type == LYEXT_PAR_NODE) {
1548 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1549 return &((struct lys_node_list*)ext->parent)->max;
1550 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1551 return &((struct lys_node_leaflist*)ext->parent)->max;
1552 }
1553 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1554 return &((struct lys_refine*)ext->parent)->mod.list.max;
1555 }
1556 break;
1557 case LYEXT_SUBSTMT_MIN:
1558 if (ext->parent_type == LYEXT_PAR_NODE) {
1559 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1560 return &((struct lys_node_list*)ext->parent)->min;
1561 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1562 return &((struct lys_node_leaflist*)ext->parent)->min;
1563 }
1564 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1565 return &((struct lys_refine*)ext->parent)->mod.list.min;
1566 }
1567 break;
1568 case LYEXT_SUBSTMT_NAMESPACE:
1569 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
1570 return ((struct lys_module*)ext->parent)->ns;
1571 }
1572 break;
1573 case LYEXT_SUBSTMT_ORDEREDBY:
1574 if (ext->parent_type == LYEXT_PAR_NODE &&
1575 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
1576 return &((struct lys_node_list*)ext->parent)->flags;
1577 }
1578 break;
1579 case LYEXT_SUBSTMT_ORGANIZATION:
1580 if (ext->parent_type == LYEXT_PAR_MODULE) {
1581 return ((struct lys_module*)ext->parent)->org;
1582 }
1583 break;
1584 case LYEXT_SUBSTMT_PATH:
1585 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1586 return ((struct lys_type*)ext->parent)->info.lref.path;
1587 }
1588 break;
1589 case LYEXT_SUBSTMT_POSITION:
1590 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
1591 return &((struct lys_type_bit*)ext->parent)->pos;
1592 }
1593 break;
1594 case LYEXT_SUBSTMT_PREFIX:
1595 if (ext->parent_type == LYEXT_PAR_MODULE) {
1596 /* covers also lys_submodule */
1597 return ((struct lys_module*)ext->parent)->prefix;
1598 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
1599 return ((struct lys_import*)ext->parent)->prefix;
1600 }
1601 break;
1602 case LYEXT_SUBSTMT_PRESENCE:
1603 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
1604 return ((struct lys_node_container*)ext->parent)->presence;
1605 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1606 return ((struct lys_refine*)ext->parent)->mod.presence;
1607 }
1608 break;
1609 case LYEXT_SUBSTMT_REFERENCE:
1610 switch (ext->parent_type) {
1611 case LYEXT_PAR_NODE:
1612 return ((struct lys_node*)ext->parent)->ref;
1613 case LYEXT_PAR_MODULE:
1614 return ((struct lys_module*)ext->parent)->ref;
1615 case LYEXT_PAR_IMPORT:
1616 return ((struct lys_import*)ext->parent)->ref;
1617 case LYEXT_PAR_INCLUDE:
1618 return ((struct lys_include*)ext->parent)->ref;
1619 case LYEXT_PAR_EXT:
1620 return ((struct lys_ext*)ext->parent)->ref;
1621 case LYEXT_PAR_FEATURE:
1622 return ((struct lys_feature*)ext->parent)->ref;
1623 case LYEXT_PAR_TPDF:
1624 return ((struct lys_tpdf*)ext->parent)->ref;
1625 case LYEXT_PAR_TYPE_BIT:
1626 return ((struct lys_type_bit*)ext->parent)->ref;
1627 case LYEXT_PAR_TYPE_ENUM:
1628 return ((struct lys_type_enum*)ext->parent)->ref;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001629 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001630 return ((struct lys_restr*)ext->parent)->ref;
1631 case LYEXT_PAR_WHEN:
1632 return ((struct lys_when*)ext->parent)->ref;
1633 case LYEXT_PAR_IDENT:
1634 return ((struct lys_ident*)ext->parent)->ref;
1635 case LYEXT_PAR_DEVIATION:
1636 return ((struct lys_deviation*)ext->parent)->ref;
1637 case LYEXT_PAR_REVISION:
1638 return ((struct lys_revision*)ext->parent)->ref;
1639 case LYEXT_PAR_REFINE:
1640 return ((struct lys_refine*)ext->parent)->ref;
1641 default:
1642 break;
1643 }
1644 break;
1645 case LYEXT_SUBSTMT_REQINST:
1646 if (ext->parent_type == LYEXT_PAR_TYPE) {
1647 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1648 return &((struct lys_type*)ext->parent)->info.lref.req;
1649 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
1650 return &((struct lys_type*)ext->parent)->info.inst.req;
1651 }
1652 }
1653 break;
1654 case LYEXT_SUBSTMT_REVISIONDATE:
1655 if (ext->parent_type == LYEXT_PAR_IMPORT) {
1656 return ((struct lys_import*)ext->parent)->rev;
1657 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
1658 return ((struct lys_include*)ext->parent)->rev;
1659 }
1660 break;
1661 case LYEXT_SUBSTMT_STATUS:
1662 switch (ext->parent_type) {
1663 case LYEXT_PAR_NODE:
1664 case LYEXT_PAR_IDENT:
1665 case LYEXT_PAR_TPDF:
1666 case LYEXT_PAR_EXT:
1667 case LYEXT_PAR_FEATURE:
1668 case LYEXT_PAR_TYPE_ENUM:
1669 case LYEXT_PAR_TYPE_BIT:
1670 /* in all structures the flags member is at the same offset */
1671 return &((struct lys_node*)ext->parent)->flags;
1672 default:
1673 break;
1674 }
1675 break;
1676 case LYEXT_SUBSTMT_UNIQUE:
1677 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1678 return &((struct lys_deviate*)ext->parent)->unique[ext->substmt_index];
1679 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1680 return &((struct lys_node_list*)ext->parent)->unique[ext->substmt_index];
1681 }
1682 break;
1683 case LYEXT_SUBSTMT_UNITS:
1684 if (ext->parent_type == LYEXT_PAR_NODE &&
1685 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1686 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
1687 return ((struct lys_node_leaf*)ext->parent)->units;
1688 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1689 return ((struct lys_tpdf*)ext->parent)->units;
1690 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1691 return ((struct lys_deviate*)ext->parent)->units;
1692 }
1693 break;
1694 case LYEXT_SUBSTMT_VALUE:
1695 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
1696 return &((struct lys_type_enum*)ext->parent)->value;
1697 }
1698 break;
1699 case LYEXT_SUBSTMT_YINELEM:
1700 if (ext->parent_type == LYEXT_PAR_EXT) {
1701 return &((struct lys_ext*)ext->parent)->flags;
1702 }
1703 break;
1704 }
1705 LOGINT;
1706 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01001707}
1708
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001709static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001710lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001711 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001712{
1713 int i;
1714
Michal Vasko1dca6882015-10-22 14:29:42 +02001715 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001716 new->base = old->base;
1717 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001718 new->parent = (struct lys_tpdf *)parent;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001719 new->ext_size = old->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001720 if (lys_ext_dup(mod, old->ext, old->ext_size, new, LYEXT_PAR_TYPE, &new->ext, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01001721 return -1;
Radek Krejcie534c132016-11-23 13:32:31 +01001722 }
Radek Krejci3733a802015-06-19 13:43:21 +02001723
Michal Vasko878e38d2016-09-05 12:17:53 +02001724 i = unres_schema_find(unres, -1, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001725 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001726 /* HACK (serious one) for unres */
1727 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001728 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001729 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, tpdftype, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001730 } else {
1731 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1732 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001733 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001734 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001735 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001736 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001737 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001738 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001739 }
1740
Radek Krejci3a5501d2016-07-18 22:03:34 +02001741 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001742}
1743
1744void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001745lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001746{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001747 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001749 assert(ctx);
1750 if (!type) {
1751 return;
1752 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001753
Michal Vasko1dca6882015-10-22 14:29:42 +02001754 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001755
Radek Krejcie534c132016-11-23 13:32:31 +01001756 lys_extension_instances_free(ctx, type->ext, type->ext_size);
1757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001759 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001760 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001761 free(type->info.binary.length);
1762 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001763 case LY_TYPE_BITS:
1764 for (i = 0; i < type->info.bits.count; i++) {
1765 lydict_remove(ctx, type->info.bits.bit[i].name);
1766 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1767 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001768 lys_iffeature_free(ctx, type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci9b15fea2017-01-23 11:31:43 +01001769 lys_extension_instances_free(ctx, type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001770 }
1771 free(type->info.bits.bit);
1772 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001773
1774 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001775 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001776 free(type->info.dec64.range);
1777 break;
1778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 case LY_TYPE_ENUM:
1780 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001781 lydict_remove(ctx, type->info.enums.enm[i].name);
1782 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1783 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001784 lys_iffeature_free(ctx, type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci9b15fea2017-01-23 11:31:43 +01001785 lys_extension_instances_free(ctx, type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001786 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001787 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001788 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001789
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001790 case LY_TYPE_INT8:
1791 case LY_TYPE_INT16:
1792 case LY_TYPE_INT32:
1793 case LY_TYPE_INT64:
1794 case LY_TYPE_UINT8:
1795 case LY_TYPE_UINT16:
1796 case LY_TYPE_UINT32:
1797 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001798 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001799 free(type->info.num.range);
1800 break;
1801
Radek Krejcidc4c1412015-06-19 15:39:54 +02001802 case LY_TYPE_LEAFREF:
1803 lydict_remove(ctx, type->info.lref.path);
1804 break;
1805
Radek Krejci3733a802015-06-19 13:43:21 +02001806 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001807 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001808 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001809 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001810 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001811 }
1812 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001813 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001814
Radek Krejcie4c366b2015-07-02 10:11:31 +02001815 case LY_TYPE_UNION:
1816 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001817 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001818 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001819 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001820 break;
1821
Michal Vaskod3282192016-09-05 11:27:57 +02001822 case LY_TYPE_IDENT:
1823 free(type->info.ident.ref);
1824 break;
1825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001826 default:
Michal Vaskod3282192016-09-05 11:27:57 +02001827 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001828 break;
1829 }
Radek Krejci5a065542015-05-22 15:02:07 +02001830}
1831
Radek Krejci1d82ef62015-08-07 14:44:40 +02001832static void
1833lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001834{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001835 assert(ctx);
1836 if (!tpdf) {
1837 return;
1838 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001840 lydict_remove(ctx, tpdf->name);
1841 lydict_remove(ctx, tpdf->dsc);
1842 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001843
Radek Krejci1d82ef62015-08-07 14:44:40 +02001844 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001846 lydict_remove(ctx, tpdf->units);
1847 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01001848
1849 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001850}
1851
Radek Krejci1d82ef62015-08-07 14:44:40 +02001852static struct lys_when *
Radek Krejci8d6b7422017-02-03 14:42:13 +01001853lys_when_dup(struct lys_module *mod, struct lys_when *old, struct unres_schema *unres)
Radek Krejci00768f42015-06-18 17:04:04 +02001854{
Radek Krejci76512572015-08-04 09:47:08 +02001855 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001856
1857 if (!old) {
1858 return NULL;
1859 }
1860
1861 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001862 if (!new) {
1863 LOGMEM;
1864 return NULL;
1865 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01001866 new->cond = lydict_insert(mod->ctx, old->cond, 0);
1867 new->dsc = lydict_insert(mod->ctx, old->dsc, 0);
1868 new->ref = lydict_insert(mod->ctx, old->ref, 0);
Radek Krejcif0bb3602017-01-25 17:05:08 +01001869 new->ext_size = old->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001870 lys_ext_dup(mod, old->ext, old->ext_size, new, LYEXT_PAR_WHEN, &new->ext, unres);
Radek Krejci00768f42015-06-18 17:04:04 +02001871
1872 return new;
1873}
1874
Michal Vasko0308dd62015-10-07 09:14:40 +02001875void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001876lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001877{
1878 if (!w) {
1879 return;
1880 }
1881
Radek Krejci5323b492017-01-16 15:40:11 +01001882 lys_extension_instances_free(ctx, w->ext, w->ext_size);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001883 lydict_remove(ctx, w->cond);
1884 lydict_remove(ctx, w->dsc);
1885 lydict_remove(ctx, w->ref);
1886
1887 free(w);
1888}
1889
Radek Krejcib7f5e412015-08-13 10:15:51 +02001890static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001891lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02001892{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001893 struct lys_node *next, *sub;
1894
Radek Krejcic071c542016-01-27 14:57:51 +01001895 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01001896 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001897 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001898 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001899 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001900 }
1901
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001902 lydict_remove(ctx, aug->target_name);
1903 lydict_remove(ctx, aug->dsc);
1904 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001905
Radek Krejci5323b492017-01-16 15:40:11 +01001906 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01001907 lys_extension_instances_free(ctx, aug->ext, aug->ext_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001908
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001909 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001910}
1911
Radek Krejci1d82ef62015-08-07 14:44:40 +02001912static void
1913lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001914{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001915 assert(ctx);
1916 if (!ident) {
1917 return;
1918 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001919
Radek Krejci018f1f52016-08-03 16:01:20 +02001920 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02001921 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001922 lydict_remove(ctx, ident->name);
1923 lydict_remove(ctx, ident->dsc);
1924 lydict_remove(ctx, ident->ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001925 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01001926 lys_extension_instances_free(ctx, ident->ext, ident->ext_size);
Radek Krejci6793db02015-05-22 17:49:54 +02001927
1928}
1929
Radek Krejci1d82ef62015-08-07 14:44:40 +02001930static void
1931lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001932{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001933 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001934
Radek Krejcid12f57b2015-08-06 10:43:39 +02001935 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001936 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001937 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001938 }
1939 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001940}
1941
Radek Krejci1d82ef62015-08-07 14:44:40 +02001942static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001943lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001944{
1945 int i;
1946
1947 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1948 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001949 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001950 }
1951 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02001952
1953 for (i = 0; i < io->must_size; i++) {
1954 lys_restr_free(ctx, &io->must[i]);
1955 }
1956 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001957}
1958
Radek Krejci1d82ef62015-08-07 14:44:40 +02001959static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02001960lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
1961{
1962 int i;
1963
1964 for (i = 0; i < notif->must_size; i++) {
1965 lys_restr_free(ctx, &notif->must[i]);
1966 }
1967 free(notif->must);
1968
1969 for (i = 0; i < notif->tpdf_size; i++) {
1970 lys_tpdf_free(ctx, &notif->tpdf[i]);
1971 }
1972 free(notif->tpdf);
1973}
1974static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02001975lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001976{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001977 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001979 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001980 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001981 }
1982 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001983
Radek Krejci1d82ef62015-08-07 14:44:40 +02001984 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001985}
1986
Radek Krejci1d82ef62015-08-07 14:44:40 +02001987static void
1988lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001989{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001991
Radek Krejci85a54be2016-10-20 12:39:56 +02001992 /* leafref backlinks */
1993 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001996 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001997 }
1998 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001999
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002001
Radek Krejci1d82ef62015-08-07 14:44:40 +02002002 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002003 lydict_remove(ctx, leaf->units);
2004 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002005}
2006
Radek Krejci1d82ef62015-08-07 14:44:40 +02002007static void
2008lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02002009{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002010 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002011
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002012 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002013 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002014 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002015 }
2016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002017 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002018 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002019 }
2020 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002021
Pavol Vican38321d02016-08-16 14:56:02 +02002022 for (i = 0; i < llist->dflt_size; i++) {
2023 lydict_remove(ctx, llist->dflt[i]);
2024 }
2025 free(llist->dflt);
2026
Radek Krejci1d82ef62015-08-07 14:44:40 +02002027 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002028
Radek Krejci1d82ef62015-08-07 14:44:40 +02002029 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002030 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002031}
2032
Radek Krejci1d82ef62015-08-07 14:44:40 +02002033static void
2034lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002035{
Radek Krejci581ce772015-11-10 17:22:40 +01002036 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 /* handle only specific parts for LY_NODE_LIST */
2039 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002040 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 }
2042 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002044 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002045 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002046 }
2047 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002048
Radek Krejci1d82ef62015-08-07 14:44:40 +02002049 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002051 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002052 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002053 lydict_remove(ctx, list->unique[i].expr[j]);
2054 }
2055 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 }
2057 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002060}
2061
Radek Krejci1d82ef62015-08-07 14:44:40 +02002062static void
2063lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002064{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067 /* handle only specific parts for LY_NODE_CONTAINER */
2068 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002071 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 }
2073 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002076 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002077 }
2078 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002079
Radek Krejci1d82ef62015-08-07 14:44:40 +02002080 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002081}
2082
Radek Krejci1d82ef62015-08-07 14:44:40 +02002083static void
2084lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02002085{
2086 lydict_remove(ctx, f->name);
2087 lydict_remove(ctx, f->dsc);
2088 lydict_remove(ctx, f->ref);
Radek Krejci5323b492017-01-16 15:40:11 +01002089 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size);
Radek Krejci9de2c042016-10-19 16:53:06 +02002090 ly_set_free(f->depfeatures);
Radek Krejcie534c132016-11-23 13:32:31 +01002091 lys_extension_instances_free(ctx, f->ext, f->ext_size);
2092}
2093
2094static void
2095lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e)
2096{
2097 lydict_remove(ctx, e->name);
2098 lydict_remove(ctx, e->dsc);
2099 lydict_remove(ctx, e->ref);
2100 lydict_remove(ctx, e->argument);
2101 lys_extension_instances_free(ctx, e->ext, e->ext_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002102}
2103
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104static void
Michal Vaskoff006c12016-02-17 11:15:19 +01002105lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02002106{
Radek Krejci581ce772015-11-10 17:22:40 +01002107 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002108 struct ly_ctx *ctx;
2109 struct lys_node *next, *elem;
2110
2111 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002112
2113 lydict_remove(ctx, dev->target_name);
2114 lydict_remove(ctx, dev->dsc);
2115 lydict_remove(ctx, dev->ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002116 lys_extension_instances_free(ctx, dev->ext, dev->ext_size);
Radek Krejcieb00f512015-07-01 16:44:58 +02002117
Pavol Vican64d0b762016-08-25 10:44:59 +02002118 if (!dev->deviate) {
2119 return ;
2120 }
2121
Michal Vaskoff006c12016-02-17 11:15:19 +01002122 /* the module was freed, but we only need the context from orig_node, use ours */
2123 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2124 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2125 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2126 elem->module = module;
2127
2128 LY_TREE_DFS_END(dev->orig_node, next, elem);
2129 }
2130 lys_node_free(dev->orig_node, NULL, 0);
2131 } else {
2132 /* it's just a shallow copy, freeing one node */
2133 dev->orig_node->module = module;
2134 lys_node_free(dev->orig_node, NULL, 1);
2135 }
2136
Radek Krejcieb00f512015-07-01 16:44:58 +02002137 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002138 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size);
2139
Radek Krejcid5a5c282016-08-15 15:38:08 +02002140 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002141 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002142 }
2143 free(dev->deviate[i].dflt);
2144
Radek Krejcieb00f512015-07-01 16:44:58 +02002145 lydict_remove(ctx, dev->deviate[i].units);
2146
2147 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2148 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002149 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002150 }
2151 free(dev->deviate[i].must);
2152
2153 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002154 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2155 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2156 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002157 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002158 }
2159 free(dev->deviate[i].unique);
2160 }
2161 }
2162 free(dev->deviate);
2163}
2164
Radek Krejci1d82ef62015-08-07 14:44:40 +02002165static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002166lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02002167{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002171 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 lydict_remove(ctx, uses->refine[i].dsc);
2173 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002174
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002175 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002176 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 }
2178 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002179
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002180 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002181 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002182 }
2183 free(uses->refine[i].dflt);
2184
Radek Krejcie534c132016-11-23 13:32:31 +01002185 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size);
2186
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002187 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002188 lydict_remove(ctx, uses->refine[i].mod.presence);
2189 }
2190 }
2191 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002194 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 }
2196 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002197
Radek Krejci1d82ef62015-08-07 14:44:40 +02002198 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002199}
2200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002202lys_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 +02002203{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002205 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 if (!node) {
2208 return;
2209 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002211 assert(node->module);
2212 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002215
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002216 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002217 if (node->priv && private_destructor) {
2218 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002219 }
2220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002222 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002223 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci5323b492017-01-16 15:40:11 +01002224 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002225 lydict_remove(ctx, node->dsc);
2226 lydict_remove(ctx, node->ref);
2227 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002228
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002229 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002230 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002231 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002232 }
2233 }
2234
Radek Krejcie534c132016-11-23 13:32:31 +01002235 lys_extension_instances_free(ctx, node->ext, node->ext_size);
2236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 /* specific part */
2238 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002239 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002240 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 break;
Radek Krejci76512572015-08-04 09:47:08 +02002242 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002243 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 break;
Radek Krejci76512572015-08-04 09:47:08 +02002245 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002246 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 break;
Radek Krejci76512572015-08-04 09:47:08 +02002248 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002249 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 break;
Radek Krejci76512572015-08-04 09:47:08 +02002251 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002252 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 break;
Radek Krejci76512572015-08-04 09:47:08 +02002254 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002255 case LYS_ANYDATA:
2256 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 break;
Radek Krejci76512572015-08-04 09:47:08 +02002258 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002259 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 break;
Radek Krejci76512572015-08-04 09:47:08 +02002261 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002262 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002263 break;
Radek Krejci76512572015-08-04 09:47:08 +02002264 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 /* do nothing */
2266 break;
Radek Krejci76512572015-08-04 09:47:08 +02002267 case LYS_GROUPING:
2268 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002269 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002270 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002272 case LYS_NOTIF:
2273 lys_notif_free(ctx, (struct lys_node_notif *)node);
2274 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002275 case LYS_INPUT:
2276 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02002277 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002278 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02002279 case LYS_UNKNOWN:
2280 LOGINT;
2281 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 }
Radek Krejci5a065542015-05-22 15:02:07 +02002283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002284 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002285 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002287}
2288
Radek Krejci2eee5c02016-12-06 19:18:05 +01002289API struct lys_module *
2290lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002291{
2292 struct ly_ctx *ctx;
2293 int i;
2294
2295 if (!mod || mod->implemented) {
2296 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002297 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002298 }
2299
2300 ctx = mod->ctx;
2301 for (i = 0; i < ctx->models.used; i++) {
2302 if (!ctx->models.list[i]->implemented) {
2303 continue;
2304 }
2305
2306 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2307 /* we have some revision of the module implemented */
2308 return ctx->models.list[i];
2309 }
2310 }
2311
2312 /* we have no revision of the module implemented, return the module itself,
2313 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002314 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002315}
2316
2317const struct lys_module *
Radek Krejcie534c132016-11-23 13:32:31 +01002318lys_get_import_module_ns(const struct lys_module *module, const char *ns)
2319{
2320 int i;
2321
2322 assert(module && ns);
2323
Radek Krejcic789d692017-01-11 11:31:14 +01002324 if (module->type) {
2325 /* the module is actually submodule and to get the namespace, we need the main module */
2326 if (ly_strequal(((struct lys_submodule *)module)->belongsto->ns, ns, 0)) {
2327 return ((struct lys_submodule *)module)->belongsto;
2328 }
2329 } else {
2330 /* modul's own namespace */
2331 if (ly_strequal(module->ns, ns, 0)) {
2332 return module;
2333 }
Radek Krejcie534c132016-11-23 13:32:31 +01002334 }
2335
2336 /* imported modules */
2337 for (i = 0; i < module->imp_size; ++i) {
2338 if (ly_strequal(module->imp[i].module->ns, ns, 0)) {
2339 return module->imp[i].module;
2340 }
2341 }
2342
2343 return NULL;
2344}
2345
2346const struct lys_module *
Michal Vasko1e62a092015-12-01 12:27:20 +01002347lys_get_import_module(const struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len)
Michal Vasko8ce24d72015-10-21 11:27:26 +02002348{
Radek Krejcic071c542016-01-27 14:57:51 +01002349 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02002350 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002351 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002352
Michal Vaskoa7789a82016-02-11 15:42:55 +01002353 assert(!prefix || !name);
2354
Michal Vaskob6729c62015-10-21 12:09:47 +02002355 if (prefix && !pref_len) {
2356 pref_len = strlen(prefix);
2357 }
2358 if (name && !name_len) {
2359 name_len = strlen(name);
2360 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002361
Radek Krejcic4283442016-04-22 09:19:27 +02002362 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002363
2364 /* module own prefix, submodule own prefix, (sub)module own name */
2365 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2366 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002367 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002368 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002369 }
2370
Michal Vasko89563fc2016-07-28 16:19:35 +02002371 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02002372 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002373 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2374 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002375 return module->imp[i].module;
2376 }
2377 }
2378
Michal Vasko89563fc2016-07-28 16:19:35 +02002379 /* module required by a foreign grouping, deviation, or submodule */
2380 if (name) {
2381 str = strndup(name, name_len);
2382 if (!str) {
2383 LOGMEM;
2384 return NULL;
2385 }
2386 main_module = ly_ctx_get_module(module->ctx, str, NULL);
2387 free(str);
2388 return main_module;
2389 }
2390
Michal Vasko8ce24d72015-10-21 11:27:26 +02002391 return NULL;
2392}
2393
Michal Vasko13b15832015-08-19 11:04:48 +02002394/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002396module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002397{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002399 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002400 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002402 assert(module->ctx);
2403 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002404
Michal Vaskob746fff2016-02-11 11:37:50 +01002405 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002406 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002407 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002408 lydict_remove(ctx, module->imp[i].dsc);
2409 lydict_remove(ctx, module->imp[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002410 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size);
Radek Krejci225376f2016-02-16 17:36:22 +01002411 }
Radek Krejcidce51452015-06-16 15:20:08 +02002412 free(module->imp);
2413
Radek Krejcic071c542016-01-27 14:57:51 +01002414 /* submodules don't have data tree, the data nodes
2415 * are placed in the main module altogether */
2416 if (!module->type) {
2417 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002418 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002419 }
Radek Krejci21181962015-06-30 14:11:00 +02002420 }
Radek Krejci5a065542015-05-22 15:02:07 +02002421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002422 lydict_remove(ctx, module->dsc);
2423 lydict_remove(ctx, module->ref);
2424 lydict_remove(ctx, module->org);
2425 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002426 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002427
Radek Krejcieb00f512015-07-01 16:44:58 +02002428 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002429 for (i = 0; i < module->rev_size; i++) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01002430 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 lydict_remove(ctx, module->rev[i].dsc);
2432 lydict_remove(ctx, module->rev[i].ref);
2433 }
2434 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002435
Radek Krejcieb00f512015-07-01 16:44:58 +02002436 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002438 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 }
2440 module->ident_size = 0;
2441 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002442
Radek Krejcieb00f512015-07-01 16:44:58 +02002443 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002444 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002445 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002446 }
2447 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002448
Radek Krejcie534c132016-11-23 13:32:31 +01002449 /* extension instances */
2450 lys_extension_instances_free(ctx, module->ext, module->ext_size);
2451
Radek Krejcieb00f512015-07-01 16:44:58 +02002452 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002453 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002454 lydict_remove(ctx, module->inc[i].dsc);
2455 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002456 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size);
Radek Krejcic071c542016-01-27 14:57:51 +01002457 /* complete submodule free is done only from main module since
2458 * submodules propagate their includes to the main module */
2459 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002460 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002461 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 }
2463 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002464
Radek Krejcieb00f512015-07-01 16:44:58 +02002465 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002466 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002467 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002468 }
2469 free(module->augment);
2470
Radek Krejcieb00f512015-07-01 16:44:58 +02002471 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002472 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002473 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002474 }
2475 free(module->features);
2476
Radek Krejcieb00f512015-07-01 16:44:58 +02002477 /* deviations */
2478 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002479 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002480 }
2481 free(module->deviation);
2482
Radek Krejcie534c132016-11-23 13:32:31 +01002483 /* extensions */
2484 for (i = 0; i < module->extensions_size; i++) {
2485 lys_extension_free(ctx, &module->extensions[i]);
2486 }
2487 free(module->extensions);
2488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002489 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002490 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002491}
2492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493void
Michal Vaskob746fff2016-02-11 11:37:50 +01002494lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002495{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 if (!submodule) {
2497 return;
2498 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002501 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002506}
2507
Radek Krejci3a5501d2016-07-18 22:03:34 +02002508static int
2509ingrouping(const struct lys_node *node)
2510{
2511 const struct lys_node *iter = node;
2512 assert(node);
2513
2514 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2515 if (!iter) {
2516 return 0;
2517 } else {
2518 return 1;
2519 }
2520}
2521
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002522/*
2523 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2524 */
2525static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002526lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002527 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002528{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002529 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002530 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002531 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002532 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002533 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002534 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002535
Michal Vaskoc07187d2015-08-13 15:20:57 +02002536 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002537 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002538 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002539 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002540 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002541 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002542 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002543 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002544 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002545 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002546 struct lys_node_anydata *any = NULL;
2547 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002548 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002549 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002550 struct lys_node_rpc_action *rpc = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002551 struct lys_node_inout *io = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002552 struct lys_node_rpc_action *ntf = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002553 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002554 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 /* we cannot just duplicate memory since the strings are stored in
2557 * dictionary and we need to update dictionary counters.
2558 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002559
Radek Krejci1d82ef62015-08-07 14:44:40 +02002560 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002561 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002562 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002563 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 break;
2565
Radek Krejci76512572015-08-04 09:47:08 +02002566 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002567 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002568 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002569 break;
2570
Radek Krejci76512572015-08-04 09:47:08 +02002571 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002572 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002573 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002574 break;
2575
Radek Krejci76512572015-08-04 09:47:08 +02002576 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002577 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002578 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002579 break;
2580
Radek Krejci76512572015-08-04 09:47:08 +02002581 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002582 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002583 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002584 break;
2585
Radek Krejci76512572015-08-04 09:47:08 +02002586 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002587 case LYS_ANYDATA:
2588 any = calloc(1, sizeof *any);
2589 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002590 break;
2591
Radek Krejci76512572015-08-04 09:47:08 +02002592 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002593 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002594 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002595 break;
2596
Radek Krejci76512572015-08-04 09:47:08 +02002597 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002598 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002599 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 break;
2601
Radek Krejci76512572015-08-04 09:47:08 +02002602 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002603 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002604 rpc = calloc(1, sizeof *rpc);
2605 retval = (struct lys_node *)rpc;
2606 break;
2607
Radek Krejci76512572015-08-04 09:47:08 +02002608 case LYS_INPUT:
2609 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002610 io = calloc(1, sizeof *io);
2611 retval = (struct lys_node *)io;
2612 break;
2613
Radek Krejci76512572015-08-04 09:47:08 +02002614 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002615 ntf = calloc(1, sizeof *ntf);
2616 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002617 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002619 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002620 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002621 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002622 }
Radek Krejcib388c152015-06-04 17:03:03 +02002623
Michal Vasko253035f2015-12-17 16:58:13 +01002624 if (!retval) {
2625 LOGMEM;
2626 return NULL;
2627 }
2628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002629 /*
2630 * duplicate generic part of the structure
2631 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002632 retval->name = lydict_insert(ctx, node->name, 0);
2633 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2634 retval->ref = lydict_insert(ctx, node->ref, 0);
2635 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002636
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002637 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002638 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002640 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002641
Radek Krejcif0bb3602017-01-25 17:05:08 +01002642 retval->ext_size = node->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002643 if (lys_ext_dup(module, node->ext, node->ext_size, retval, LYEXT_PAR_NODE, &retval->ext, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002644 goto error;
2645 }
2646
Radek Krejci06214042016-11-04 16:25:58 +01002647 if (node->iffeature_size) {
2648 retval->iffeature_size = node->iffeature_size;
2649 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2650 if (!retval->iffeature) {
2651 LOGMEM;
2652 goto error;
2653 }
Michal Vasko253035f2015-12-17 16:58:13 +01002654 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002655
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002656 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002657 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002658 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2659 if (size1) {
2660 /* there is something to duplicate */
2661
2662 /* duplicate compiled expression */
2663 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2664 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2665 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2666
2667 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002668 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002669 for (j = 0; (unsigned int)j < size2; j++) {
2670 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2671 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002672 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002673 /* feature is resolved in origin, so copy it
2674 * - duplication is used for instantiating groupings
2675 * and if-feature inside grouping is supposed to be
2676 * resolved inside the original grouping, so we want
2677 * to keep pointers to features from the grouping
2678 * context */
2679 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2680 } else if (rc == -1) {
2681 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002682 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002683 }
2684 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01002685
2686 /* duplicate if-feature's extensions */
2687 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002688 if (lys_ext_dup(module, node->iffeature[i].ext, node->iffeature[i].ext_size,
Radek Krejcif0bb3602017-01-25 17:05:08 +01002689 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, unres)) {
2690 goto error;
2691 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002692 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002693
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002694 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01002695 p = parent;
2696 do {
2697 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
2698 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002699 if (iter) {
2700 flags = iter->flags & LYS_CONFIG_MASK;
2701 } else {
2702 /* default */
2703 flags = LYS_CONFIG_W;
2704 }
2705
2706 switch (finalize) {
2707 case 1:
2708 /* inherit config flags */
2709 if (retval->flags & LYS_CONFIG_SET) {
2710 /* skip nodes with an explicit config value */
2711 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
2712 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +01002713 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002714 goto error;
2715 }
2716 break;
2717 }
2718
2719 if (retval->nodetype != LYS_USES) {
2720 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
2721 }
2722 break;
2723 case 2:
2724 /* erase config flags */
2725 retval->flags &= ~LYS_CONFIG_MASK;
2726 retval->flags &= ~LYS_CONFIG_SET;
2727 break;
2728 }
2729
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002730 /* connect it to the parent */
2731 if (lys_node_addchild(parent, retval->module, retval)) {
2732 goto error;
2733 }
Radek Krejcidce51452015-06-16 15:20:08 +02002734
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002735 /* go recursively */
2736 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002737 LY_TREE_FOR(node->child, iter) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002738 if (iter->nodetype & LYS_GROUPING) {
2739 /* do not instantiate groupings */
2740 continue;
2741 }
Radek Krejci6ff885d2017-01-03 14:06:22 +01002742 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002743 goto error;
2744 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 }
2746 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002747
2748 if (finalize == 1) {
2749 /* check that configuration lists have keys
2750 * - we really want to check keys_size in original node, because the keys are
2751 * not yet resolved here, it is done below in nodetype specific part */
2752 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
2753 && !((struct lys_node_list *)node)->keys_size) {
2754 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
2755 goto error;
2756 }
2757 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002758 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002759 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002760 }
2761
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002762 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002763 * duplicate specific part of the structure
2764 */
2765 switch (node->nodetype) {
2766 case LYS_CONTAINER:
2767 if (cont_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002768 cont->when = lys_when_dup(module, cont_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002769 }
2770 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002772 cont->must_size = cont_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002773 cont->must = lys_restr_dup(module, cont_orig->must, cont->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774
Radek Krejcif0bb3602017-01-25 17:05:08 +01002775 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
2776
2777 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002778 case LYS_CHOICE:
2779 if (choice_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002780 choice->when = lys_when_dup(module, choice_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002781 }
2782
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002783 if (!shallow) {
2784 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002785 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2786 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2787 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002788 if (rc) {
2789 if (rc == EXIT_FAILURE) {
2790 LOGINT;
2791 }
2792 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002793 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002794 } else {
2795 /* useless to check return value, we don't know whether
2796 * there really wasn't any default defined or it just hasn't
2797 * been resolved, we just hope for the best :)
2798 */
2799 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002800 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002802 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002803 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002804 break;
2805
2806 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002807 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002808 goto error;
2809 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002810 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2811
2812 if (leaf_orig->dflt) {
2813 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci51673202016-11-01 17:00:32 +01002814 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
2815 (struct lys_node *)(&leaf->dflt)) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002816 goto error;
2817 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002818 }
2819
2820 leaf->must_size = leaf_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002821 leaf->must = lys_restr_dup(module, leaf_orig->must, leaf->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002822
2823 if (leaf_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002824 leaf->when = lys_when_dup(module, leaf_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002825 }
2826 break;
2827
2828 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002829 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002830 goto error;
2831 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002832 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2833
2834 llist->min = llist_orig->min;
2835 llist->max = llist_orig->max;
2836
2837 llist->must_size = llist_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002838 llist->must = lys_restr_dup(module, llist_orig->must, llist->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002839
Radek Krejci51673202016-11-01 17:00:32 +01002840 llist->dflt_size = llist_orig->dflt_size;
2841 llist->dflt = malloc(llist->dflt_size * sizeof *llist->dflt);
2842 for (i = 0; i < llist->dflt_size; i++) {
2843 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
2844 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2845 (struct lys_node *)(&llist->dflt[i])) == -1) {
2846 goto error;
2847 }
2848 }
2849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002850 if (llist_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002851 llist->when = lys_when_dup(module, llist_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002852 }
2853 break;
2854
2855 case LYS_LIST:
2856 list->min = list_orig->min;
2857 list->max = list_orig->max;
2858
2859 list->must_size = list_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002860 list->must = lys_restr_dup(module, list_orig->must, list->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002861
Radek Krejcif0bb3602017-01-25 17:05:08 +01002862 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Michal Vasko38d01f72015-06-15 09:41:06 +02002863
Radek Krejci581ce772015-11-10 17:22:40 +01002864 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002865 if (list->keys_size) {
2866 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejci5c08a992016-11-02 13:30:04 +01002867 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Michal Vasko253035f2015-12-17 16:58:13 +01002868 if (!list->keys) {
2869 LOGMEM;
2870 goto error;
2871 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002872
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002873 if (!shallow) {
Radek Krejci5c08a992016-11-02 13:30:04 +01002874 /* the keys are going to be resolved only if the list is instantiated in data tree, not just
2875 * in another grouping */
2876 for (iter = parent; iter && iter->nodetype != LYS_GROUPING; iter = iter->parent);
2877 if (!iter && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
2878 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02002879 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002880 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002881 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002882 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002883 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884
Radek Krejci581ce772015-11-10 17:22:40 +01002885 list->unique_size = list_orig->unique_size;
2886 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002887 if (!list->unique) {
2888 LOGMEM;
2889 goto error;
2890 }
Radek Krejci581ce772015-11-10 17:22:40 +01002891 for (i = 0; i < list->unique_size; ++i) {
2892 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2893 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002894 if (!list->unique[i].expr) {
2895 LOGMEM;
2896 goto error;
2897 }
Radek Krejci581ce772015-11-10 17:22:40 +01002898 for (j = 0; j < list->unique[i].expr_size; j++) {
2899 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2900
2901 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02002902 unique_info = malloc(sizeof *unique_info);
2903 unique_info->list = (struct lys_node *)list;
2904 unique_info->expr = list->unique[i].expr[j];
2905 unique_info->trg_type = &list->unique[i].trg_type;
2906 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002907 }
2908 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002910 if (list_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002911 list->when = lys_when_dup(module, list_orig->when, unres);
Radek Krejciefaeba32015-05-27 14:30:57 +02002912 }
Radek Krejcidce51452015-06-16 15:20:08 +02002913 break;
2914
2915 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002916 case LYS_ANYDATA:
2917 any->must_size = any_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002918 any->must = lys_restr_dup(module, any_orig->must, any->must_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002919
Radek Krejcibf2abff2016-08-23 15:51:52 +02002920 if (any_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002921 any->when = lys_when_dup(module, any_orig->when, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002922 }
2923 break;
2924
2925 case LYS_USES:
2926 uses->grp = uses_orig->grp;
2927
2928 if (uses_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002929 uses->when = lys_when_dup(module, uses_orig->when, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002930 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002931 /* it is not needed to duplicate refine, nor augment. They are already applied to the uses children */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002932 break;
2933
2934 case LYS_CASE:
2935 if (cs_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002936 cs->when = lys_when_dup(module, cs_orig->when, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002937 }
2938 break;
2939
Radek Krejci96935402016-11-04 16:27:28 +01002940 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02002941 case LYS_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002942 case LYS_INPUT:
2943 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002944 case LYS_NOTIF:
Radek Krejcif0bb3602017-01-25 17:05:08 +01002945 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002946 break;
2947
2948 default:
2949 /* LY_NODE_AUGMENT */
2950 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002951 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002952 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002953
2954 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002955
2956error:
2957
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002958 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002959 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002960}
2961
Radek Krejcib3142312016-11-09 11:04:12 +01002962int
2963lys_has_xpath(const struct lys_node *node)
2964{
2965 assert(node);
2966
2967 switch (node->nodetype) {
2968 case LYS_AUGMENT:
2969 if (((struct lys_node_augment *)node)->when) {
2970 return 1;
2971 }
2972 break;
2973 case LYS_CASE:
2974 if (((struct lys_node_case *)node)->when) {
2975 return 1;
2976 }
2977 break;
2978 case LYS_CHOICE:
2979 if (((struct lys_node_choice *)node)->when) {
2980 return 1;
2981 }
2982 break;
2983 case LYS_ANYDATA:
2984 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
2985 return 1;
2986 }
2987 break;
2988 case LYS_LEAF:
2989 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
2990 return 1;
2991 }
2992 break;
2993 case LYS_LEAFLIST:
2994 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
2995 return 1;
2996 }
2997 break;
2998 case LYS_LIST:
2999 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3000 return 1;
3001 }
3002 break;
3003 case LYS_CONTAINER:
3004 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3005 return 1;
3006 }
3007 break;
3008 case LYS_INPUT:
3009 case LYS_OUTPUT:
3010 if (((struct lys_node_inout *)node)->must_size) {
3011 return 1;
3012 }
3013 break;
3014 case LYS_NOTIF:
3015 if (((struct lys_node_notif *)node)->must_size) {
3016 return 1;
3017 }
3018 break;
3019 case LYS_USES:
3020 if (((struct lys_node_uses *)node)->when) {
3021 return 1;
3022 }
3023 break;
3024 default:
3025 /* does not have XPath */
3026 break;
3027 }
3028
3029 return 0;
3030}
3031
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003032struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003033lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003034 struct unres_schema *unres, int shallow)
3035{
3036 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003037 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003038 struct lys_node *result, *iter, *next;
3039
3040 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003041 /* 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 +02003042 for (p = parent;
3043 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3044 p = lys_parent(p));
3045 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3046 }
3047
Radek Krejci6ff885d2017-01-03 14:06:22 +01003048 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003049 if (finalize) {
3050 /* check xpath expressions in the instantiated tree */
3051 for (iter = next = parent->child; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003052 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003053 /* invalid xpath */
3054 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003055 }
3056
3057 /* select next item */
3058 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3059 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3060 next = NULL;
3061 } else {
3062 next = iter->child;
3063 }
3064 if (!next) {
3065 /* no children, try siblings */
3066 next = iter->next;
3067 }
3068 while (!next) {
3069 /* parent is already processed, go to its sibling */
3070 iter = lys_parent(iter);
3071 if (iter == parent) {
3072 /* we are done, no next element to process */
3073 break;
3074 }
3075 next = iter->next;
3076 }
3077 }
3078 }
3079
3080 return result;
3081}
3082
Michal Vasko13b15832015-08-19 11:04:48 +02003083void
Michal Vaskoff006c12016-02-17 11:15:19 +01003084lys_node_switch(struct lys_node *dst, struct lys_node *src)
3085{
3086 struct lys_node *child;
3087
Michal Vaskob42b6972016-06-06 14:21:30 +02003088 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003089
3090 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02003091 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01003092 dst->prev->next = src;
3093 }
3094
3095 /* sibling prev */
3096 if (dst->next) {
3097 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02003098 } else {
3099 for (child = dst->prev; child->prev->next; child = child->prev);
3100 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003101 }
3102
3103 /* next */
3104 src->next = dst->next;
3105 dst->next = NULL;
3106
3107 /* prev */
3108 if (dst->prev != dst) {
3109 src->prev = dst->prev;
3110 }
3111 dst->prev = dst;
3112
3113 /* parent child */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003114 if (dst->parent) {
3115 if (dst->parent->child == dst) {
3116 dst->parent->child = src;
3117 }
3118 } else if (dst->module->data == dst) {
3119 dst->module->data = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003120 }
3121
3122 /* parent */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003123 src->parent = dst->parent; dst->parent = NULL;
3124
Michal Vaskoff006c12016-02-17 11:15:19 +01003125
3126 /* child parent */
3127 LY_TREE_FOR(dst->child, child) {
3128 if (child->parent == dst) {
3129 child->parent = src;
3130 }
3131 }
3132
3133 /* child */
3134 src->child = dst->child;
3135 dst->child = NULL;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003136
3137 /* node-specific data */
3138 switch (dst->nodetype) {
3139 case LYS_CONTAINER:
3140 ((struct lys_node_container *)src)->tpdf_size = ((struct lys_node_container *)dst)->tpdf_size;
3141 ((struct lys_node_container *)src)->tpdf = ((struct lys_node_container *)dst)->tpdf;
3142 ((struct lys_node_container *)dst)->tpdf_size = 0;
3143 ((struct lys_node_container *)dst)->tpdf = NULL;
3144 break;
3145 case LYS_LIST:
3146 ((struct lys_node_list *)src)->tpdf_size = ((struct lys_node_list *)dst)->tpdf_size;
3147 ((struct lys_node_list *)src)->tpdf = ((struct lys_node_list *)dst)->tpdf;
3148 ((struct lys_node_list *)dst)->tpdf_size = 0;
3149 ((struct lys_node_list *)dst)->tpdf = NULL;
3150 break;
3151 case LYS_RPC:
3152 case LYS_ACTION:
3153 ((struct lys_node_rpc_action *)src)->tpdf_size = ((struct lys_node_rpc_action *)dst)->tpdf_size;
3154 ((struct lys_node_rpc_action *)src)->tpdf = ((struct lys_node_rpc_action *)dst)->tpdf;
3155 ((struct lys_node_rpc_action *)dst)->tpdf_size = 0;
3156 ((struct lys_node_rpc_action *)dst)->tpdf = NULL;
3157 break;
3158 case LYS_NOTIF:
3159 ((struct lys_node_notif *)src)->tpdf_size = ((struct lys_node_notif *)dst)->tpdf_size;
3160 ((struct lys_node_notif *)src)->tpdf = ((struct lys_node_notif *)dst)->tpdf;
3161 ((struct lys_node_notif *)dst)->tpdf_size = 0;
3162 ((struct lys_node_notif *)dst)->tpdf = NULL;
3163 break;
3164 case LYS_INPUT:
3165 case LYS_OUTPUT:
3166 ((struct lys_node_inout *)src)->tpdf_size = ((struct lys_node_inout *)dst)->tpdf_size;
3167 ((struct lys_node_inout *)src)->tpdf = ((struct lys_node_inout *)dst)->tpdf;
3168 ((struct lys_node_inout *)dst)->tpdf_size = 0;
3169 ((struct lys_node_inout *)dst)->tpdf = NULL;
3170 break;
3171 default:
3172 /* nothing special */
3173 break;
3174 }
3175
Michal Vaskoff006c12016-02-17 11:15:19 +01003176}
3177
3178void
Michal Vasko627975a2016-02-11 11:39:03 +01003179lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int remove_from_ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003180{
3181 struct ly_ctx *ctx;
3182 int i;
3183
3184 if (!module) {
3185 return;
3186 }
3187
3188 /* remove schema from the context */
3189 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003190 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003191 for (i = 0; i < ctx->models.used; i++) {
3192 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003193 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003194 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003195 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 +02003196 ctx->models.list[ctx->models.used] = NULL;
3197 /* we are done */
3198 break;
3199 }
3200 }
3201 }
3202
3203 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003204 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003205
3206 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003207 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003208
3209 free(module);
3210}
Radek Krejci7e97c352015-06-19 16:26:34 +02003211
Radek Krejci9de2c042016-10-19 16:53:06 +02003212static void
3213lys_features_disable_recursive(struct lys_feature *f)
3214{
3215 unsigned int i;
3216 struct lys_feature *depf;
3217
3218 /* disable the feature */
3219 f->flags &= ~LYS_FENABLED;
3220
3221 /* by disabling feature we have to disable also all features that depends on this feature */
3222 if (f->depfeatures) {
3223 for (i = 0; i < f->depfeatures->number; i++) {
3224 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3225 if (depf->flags & LYS_FENABLED) {
3226 lys_features_disable_recursive(depf);
3227 }
3228 }
3229 }
3230}
3231
3232
Radek Krejci7e97c352015-06-19 16:26:34 +02003233/*
3234 * op: 1 - enable, 0 - disable
3235 */
3236static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003237lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003238{
3239 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003240 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003241 int progress, faili, failj, failk;
3242
3243 uint8_t fsize;
3244 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003245
3246 if (!module || !name || !strlen(name)) {
3247 return EXIT_FAILURE;
3248 }
3249
3250 if (!strcmp(name, "*")) {
3251 /* enable all */
3252 all = 1;
3253 }
3254
Radek Krejcia889c1f2016-10-19 15:50:11 +02003255 progress = failk = 1;
3256 while (progress && failk) {
3257 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3258 if (i == -1) {
3259 fsize = module->features_size;
3260 f = module->features;
3261 } else {
3262 fsize = module->inc[i].submodule->features_size;
3263 f = module->inc[i].submodule->features;
3264 }
3265
3266 for (j = 0; j < fsize; j++) {
3267 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003268 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3269 if (all) {
3270 /* skip already set features */
3271 continue;
3272 } else {
3273 /* feature already set correctly */
3274 return EXIT_SUCCESS;
3275 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003276 }
3277
3278 if (op) {
3279 /* check referenced features if they are enabled */
3280 for (k = 0; k < f[j].iffeature_size; k++) {
3281 if (!resolve_iffeature(&f[j].iffeature[k])) {
3282 if (all) {
3283 faili = i;
3284 failj = j;
3285 failk = k + 1;
3286 break;
3287 } else {
3288 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3289 f[j].name, k + 1);
3290 return EXIT_FAILURE;
3291 }
3292 }
3293 }
3294
3295 if (k == f[j].iffeature_size) {
3296 /* the last check passed, do the change */
3297 f[j].flags |= LYS_FENABLED;
3298 progress++;
3299 }
3300 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003301 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003302 progress++;
3303 }
3304 if (!all) {
3305 /* stop in case changing a single feature */
3306 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003307 }
3308 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003309 }
3310 }
3311 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003312 if (failk) {
3313 /* print info about the last failing feature */
3314 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3315 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3316 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003317 }
3318
3319 if (all) {
3320 return EXIT_SUCCESS;
3321 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003322 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003323 return EXIT_FAILURE;
3324 }
3325}
3326
3327API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003328lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003329{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003330 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003331}
3332
3333API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003334lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003335{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003336 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003337}
3338
3339API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003340lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003341{
3342 int i, j;
3343
3344 if (!module || !feature) {
3345 return -1;
3346 }
3347
3348 /* search for the specified feature */
3349 /* module itself */
3350 for (i = 0; i < module->features_size; i++) {
3351 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003352 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003353 return 1;
3354 } else {
3355 return 0;
3356 }
3357 }
3358 }
3359
3360 /* submodules */
3361 for (j = 0; j < module->inc_size; j++) {
3362 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3363 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003364 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003365 return 1;
3366 } else {
3367 return 0;
3368 }
3369 }
3370 }
3371 }
3372
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003373 /* feature definition not found */
3374 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003375}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003376
Radek Krejci96a10da2015-07-30 11:00:14 +02003377API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003378lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003379{
Radek Krejci96a10da2015-07-30 11:00:14 +02003380 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003381 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003382 unsigned int count;
3383
3384 if (!module) {
3385 return NULL;
3386 }
3387
3388 count = module->features_size;
3389 for (i = 0; i < module->inc_size; i++) {
3390 count += module->inc[i].submodule->features_size;
3391 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003392 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01003393 if (!result) {
3394 LOGMEM;
3395 return NULL;
3396 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003397 if (states) {
3398 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01003399 if (!(*states)) {
3400 LOGMEM;
3401 free(result);
3402 return NULL;
3403 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003404 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003405 count = 0;
3406
3407 /* module itself */
3408 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003409 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003410 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003411 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003412 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003413 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003414 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003415 }
3416 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003417 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003418 }
3419
3420 /* submodules */
3421 for (j = 0; j < module->inc_size; j++) {
3422 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003423 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003424 if (states) {
3425 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3426 (*states)[count] = 1;
3427 } else {
3428 (*states)[count] = 0;
3429 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003430 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003431 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003432 }
3433 }
3434
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003435 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003436 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003437
3438 return result;
3439}
Michal Vaskobaefb032015-09-24 14:52:10 +02003440
Radek Krejci6910a032016-04-13 10:06:21 +02003441API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003442lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003443{
Michal Vaskof53187d2017-01-13 13:23:14 +01003444 if (!node) {
3445 return NULL;
3446 }
3447
Radek Krejcic071c542016-01-27 14:57:51 +01003448 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3449}
3450
Radek Krejci6910a032016-04-13 10:06:21 +02003451API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003452lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003453{
Michal Vaskof53187d2017-01-13 13:23:14 +01003454 if (!module) {
3455 return NULL;
3456 }
3457
Michal Vasko320e8532016-02-15 13:11:57 +01003458 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3459}
3460
Michal Vaskobaefb032015-09-24 14:52:10 +02003461API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003462lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003463{
3464 if (!node || !node->parent) {
3465 return NULL;
3466 }
3467
3468 if (node->parent->nodetype == LYS_AUGMENT) {
3469 return ((struct lys_node_augment *)node->parent)->target;
3470 }
3471
3472 return node->parent;
3473}
Michal Vasko1b229152016-01-13 11:28:38 +01003474
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003475API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003476lys_set_private(const struct lys_node *node, void *priv)
3477{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003478 void *prev;
3479
Michal Vasko1b229152016-01-13 11:28:38 +01003480 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003481 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
3482 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003483 }
3484
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003485 prev = node->priv;
3486 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003487
3488 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003489}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003490
Michal Vasko01c6fd22016-05-20 11:43:05 +02003491int
3492lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3493{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003494 struct lys_node_leaf *iter = leafref_target;
3495
Michal Vasko48a573d2016-07-01 11:46:02 +02003496 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003497 LOGINT;
3498 return -1;
3499 }
3500
Pavol Vican93175152016-08-30 15:34:44 +02003501 /* check for config flag */
3502 if ((leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
3503 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
3504 "The %s is config but refers to a non-config %s.",
3505 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
3506 return -1;
3507 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003508 /* check for cycles */
3509 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3510 if ((void *)iter == (void *)leafref) {
3511 /* cycle detected */
3512 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3513 return -1;
3514 }
3515 iter = iter->type.info.lref.target;
3516 }
3517
3518 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003519 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02003520 if (!leafref_target->backlinks) {
3521 leafref_target->backlinks = (void*)ly_set_new();
3522 if (!leafref_target->backlinks) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003523 LOGMEM;
3524 return -1;
3525 }
3526 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003527 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003528
3529 return 0;
3530}
3531
Michal Vasko8548e082016-07-22 12:00:18 +02003532/* not needed currently */
3533#if 0
3534
Michal Vasko5b3492c2016-07-20 09:37:40 +02003535static const char *
3536lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3537{
3538 struct lys_module *prev_mod;
3539 uint32_t str_len, mod_len, buf_idx;
3540
Radek Krejcibf2abff2016-08-23 15:51:52 +02003541 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003542 LOGINT;
3543 return NULL;
3544 }
3545
3546 buf_idx = buf_len - 1;
3547 buf[buf_idx] = '\0';
3548
3549 while (node) {
3550 if (lys_parent(node)) {
3551 prev_mod = lys_node_module(lys_parent(node));
3552 } else {
3553 prev_mod = NULL;
3554 }
3555
Radek Krejcibf2abff2016-08-23 15:51:52 +02003556 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003557 str_len = strlen(node->name);
3558
3559 if (prev_mod != node->module) {
3560 mod_len = strlen(node->module->name);
3561 } else {
3562 mod_len = 0;
3563 }
3564
3565 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3566 LOGINT;
3567 return NULL;
3568 }
3569
3570 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3571
3572 buf[buf_idx] = '/';
3573 if (mod_len) {
3574 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3575 buf[buf_idx + 1 + mod_len] = ':';
3576 }
3577 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3578 }
3579
3580 node = lys_parent(node);
3581 }
3582
3583 return buf + buf_idx;
3584}
3585
Michal Vasko8548e082016-07-22 12:00:18 +02003586#endif
3587
3588API struct ly_set *
Michal Vasko2611e192017-01-23 10:33:21 +01003589lys_find_xpath(struct ly_ctx *ctx, const struct lys_node *node, const char *expr, int options)
Michal Vasko46a4bf92016-09-08 08:23:49 +02003590{
3591 struct lyxp_set set;
3592 struct ly_set *ret_set;
3593 uint32_t i;
Michal Vaskodb1da032016-09-08 10:07:38 +02003594 int opts;
Michal Vasko46a4bf92016-09-08 08:23:49 +02003595
Michal Vasko2611e192017-01-23 10:33:21 +01003596 if ((!ctx && !node) || !expr) {
Michal Vasko46a4bf92016-09-08 08:23:49 +02003597 ly_errno = LY_EINVAL;
3598 return NULL;
3599 }
3600
Michal Vasko2611e192017-01-23 10:33:21 +01003601 if (!node) {
3602 node = ly_ctx_get_node(ctx, NULL, "/ietf-yang-library:modules-state");
3603 if (!node) {
3604 ly_errno = LY_EINT;
3605 return NULL;
3606 }
3607 }
3608
Michal Vasko46a4bf92016-09-08 08:23:49 +02003609 memset(&set, 0, sizeof set);
3610
Michal Vaskodb1da032016-09-08 10:07:38 +02003611 opts = LYXP_SNODE;
3612 if (options & LYS_FIND_OUTPUT) {
3613 opts |= LYXP_SNODE_OUTPUT;
3614 }
3615
Michal Vaskodb1da032016-09-08 10:07:38 +02003616 if (lyxp_atomize(expr, node, LYXP_NODE_ELEM, &set, opts)) {
Michal Vaskoc90f3ff2017-01-23 13:51:58 +01003617 /* just find a relevant node to put in path, if it fails, use the original one */
3618 for (i = 0; i < set.used; ++i) {
3619 if (set.val.snodes[i].in_ctx == 1) {
3620 node = set.val.snodes[i].snode;
3621 break;
3622 }
3623 }
Michal Vasko46a4bf92016-09-08 08:23:49 +02003624 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003625 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko46a4bf92016-09-08 08:23:49 +02003626 return NULL;
3627 }
3628
3629 ret_set = ly_set_new();
3630
3631 for (i = 0; i < set.used; ++i) {
3632 if (!set.val.snodes[i].in_ctx) {
3633 continue;
3634 }
3635 assert(set.val.snodes[i].in_ctx == 1);
3636
3637 switch (set.val.snodes[i].type) {
3638 case LYXP_NODE_ELEM:
3639 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
3640 ly_set_free(ret_set);
3641 free(set.val.snodes);
3642 return NULL;
3643 }
3644 break;
3645 default:
3646 /* ignore roots, text and attr should not ever appear */
3647 break;
3648 }
3649 }
3650
3651 free(set.val.snodes);
3652 return ret_set;
3653}
3654
3655API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02003656lys_xpath_atomize(const struct lys_node *cur_snode, enum lyxp_node_type cur_snode_type, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02003657{
Michal Vasko508a50d2016-09-07 14:50:33 +02003658 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003659 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003660 uint32_t i;
3661
Michal Vaskob94a5e42016-09-08 14:01:56 +02003662 if (!cur_snode || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02003663 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003664 }
3665
Michal Vaskob94a5e42016-09-08 14:01:56 +02003666 /* adjust the root */
3667 if ((cur_snode_type == LYXP_NODE_ROOT) || (cur_snode_type == LYXP_NODE_ROOT_CONFIG)) {
3668 do {
3669 cur_snode = lys_getnext(NULL, NULL, lys_node_module(cur_snode), 0);
3670 } while ((cur_snode_type == LYXP_NODE_ROOT_CONFIG) && (cur_snode->flags & LYS_CONFIG_R));
3671 }
3672
Michal Vasko508a50d2016-09-07 14:50:33 +02003673 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003674
3675 if (options & LYXP_MUST) {
3676 options &= ~LYXP_MUST;
3677 options |= LYXP_SNODE_MUST;
3678 } else if (options & LYXP_WHEN) {
3679 options &= ~LYXP_WHEN;
3680 options |= LYXP_SNODE_WHEN;
3681 } else {
3682 options |= LYXP_SNODE;
3683 }
3684
Michal Vasko508a50d2016-09-07 14:50:33 +02003685 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
3686 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003687 LOGVAL(LYE_SPEC, LY_VLOG_LYS, cur_snode, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02003688 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003689 }
3690
Michal Vasko8548e082016-07-22 12:00:18 +02003691 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003692
Michal Vasko508a50d2016-09-07 14:50:33 +02003693 for (i = 0; i < set.used; ++i) {
3694 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003695 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003696 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003697 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003698 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003699 return NULL;
3700 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003701 break;
3702 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003703 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003704 break;
3705 }
3706 }
3707
Michal Vasko508a50d2016-09-07 14:50:33 +02003708 free(set.val.snodes);
3709 return ret_set;
3710}
3711
3712API struct ly_set *
3713lys_node_xpath_atomize(const struct lys_node *node, int options)
3714{
3715 const struct lys_node *next, *elem, *parent, *tmp;
3716 struct lyxp_set set;
3717 struct ly_set *ret_set;
3718 uint16_t i;
3719
3720 if (!node) {
3721 return NULL;
3722 }
3723
3724 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3725 if (!parent) {
3726 /* not in input, output, or notification */
3727 return NULL;
3728 }
3729
3730 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003731 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003732 return NULL;
3733 }
3734
3735 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003736 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_XPATH_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003737 /* elem has no dependencies from other subtrees and local nodes get discarded */
3738 goto next_iter;
3739 }
3740
Michal Vasko769f8032017-01-24 13:11:55 +01003741 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003742 ly_set_free(ret_set);
3743 free(set.val.snodes);
3744 return NULL;
3745 }
3746
3747 for (i = 0; i < set.used; ++i) {
3748 switch (set.val.snodes[i].type) {
3749 case LYXP_NODE_ELEM:
3750 if (options & LYXP_NO_LOCAL) {
3751 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3752 if (tmp) {
3753 /* in local subtree, discard */
3754 break;
3755 }
3756 }
3757 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3758 ly_set_free(ret_set);
3759 free(set.val.snodes);
3760 return NULL;
3761 }
3762 break;
3763 default:
3764 /* ignore roots, text and attr should not ever appear */
3765 break;
3766 }
3767 }
3768
3769 free(set.val.snodes);
3770 if (!(options & LYXP_RECURSIVE)) {
3771 break;
3772 }
3773next_iter:
3774 LY_TREE_DFS_END(node, next, elem);
3775 }
3776
Michal Vasko8548e082016-07-22 12:00:18 +02003777 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003778}
3779
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003780static void
Radek Krejci0ec51da2016-12-14 16:42:03 +01003781apply_aug(struct lys_node_augment *augment)
3782{
3783 struct lys_node *last;
3784
3785 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
3786
3787 /* reconnect augmenting data into the target - add them to the target child list */
3788 if (augment->target->child) {
3789 last = augment->target->child->prev;
3790 last->next = augment->child;
3791 augment->target->child->prev = augment->child->prev;
3792 augment->child->prev = last;
3793 } else {
3794 augment->target->child = augment->child;
3795 }
3796
3797 /* remove the flag about not applicability */
3798 augment->flags &= ~LYS_NOTAPPLIED;
3799}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003800
Radek Krejcib2541a32016-12-12 16:45:57 +01003801static void
3802remove_aug(struct lys_node_augment *augment)
3803{
3804 struct lys_node *last, *elem;
3805
3806 if (!augment->target) {
3807 /* skip not resolved augments */
3808 return;
3809 }
3810
3811 elem = augment->child;
3812 if (elem) {
3813 LY_TREE_FOR(elem, last) {
3814 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
3815 break;
3816 }
3817 }
3818 /* elem is first augment child, last is the last child */
3819
3820 /* parent child ptr */
3821 if (augment->target->child == elem) {
3822 augment->target->child = last->next;
3823 }
3824
3825 /* parent child next ptr */
3826 if (elem->prev->next) {
3827 elem->prev->next = last->next;
3828 }
3829
3830 /* parent child prev ptr */
3831 if (last->next) {
3832 last->next->prev = elem->prev;
3833 } else if (augment->target->child) {
3834 augment->target->child->prev = elem->prev;
3835 }
3836
3837 /* update augment children themselves */
3838 elem->prev = last;
3839 last->next = NULL;
3840 }
3841
Radek Krejci0ec51da2016-12-14 16:42:03 +01003842 /* augment->target still keeps the resolved target, but for lys_augment_free()
3843 * we have to keep information that this augment is not applied to free its data */
3844 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01003845}
3846
Radek Krejci30bfcd22017-01-27 16:54:48 +01003847/*
3848 * @param[in] module - the module where the deviation is defined
3849 */
3850static void
3851lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module)
3852{
3853 int ret;
3854 char *parent_path;
3855 struct lys_node *target = NULL, *parent;
3856
3857 if (!dev->deviate) {
3858 return ;
3859 }
3860
3861 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3862 if (dev->orig_node) {
3863 /* removing not-supported deviation ... */
3864 if (strrchr(dev->target_name, '/') != dev->target_name) {
3865 /* ... from a parent */
3866
3867 /* reconnect to its previous position */
3868 parent = dev->orig_node->parent;
3869 if (parent) {
3870 /* the original node was actually from augment, we have to get know if the augment is
3871 * applied (its module is enabled and implemented). If yes, the node will be connected
3872 * to the augment and the linkage with the target will be fixed if needed, otherwise
3873 * it will be connected only to the augment */
3874 /* first, connect it into the augment */
3875 lys_node_addchild(parent, NULL, dev->orig_node);
3876 if (!parent->module->disabled && parent->module->implemented) {
3877 /* augment is supposed to be applied, so fix pointers in target and the status of the original node */
3878 if (parent->child == dev->orig_node) {
3879 /* the only node in augment */
3880 dev->orig_node->flags |= LYS_NOTAPPLIED;
3881 apply_aug((struct lys_node_augment *)parent);
3882 } else {
3883 /* other nodes from augment applied, nothing more needed in target, everything was done
3884 * by lys_node_addchild() */
3885 dev->orig_node->flags |= parent->child->flags & LYS_NOTAPPLIED;
3886 }
3887 } else {
3888 /* augment is not supposed to be applied */
3889 dev->orig_node->flags |= LYS_NOTAPPLIED;
3890 }
3891 } else {
3892 /* non-augment, non-toplevel */
3893 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3894 ret = resolve_augment_schema_nodeid(parent_path, NULL, module, 1,
3895 (const struct lys_node **)&target);
3896 free(parent_path);
3897 if (ret || !target) {
3898 LOGINT;
3899 return;
3900 }
3901 lys_node_addchild(target, NULL, dev->orig_node);
3902 }
3903 } else {
3904 /* ... from top-level data */
3905 lys_node_addchild(NULL, (struct lys_module *)dev->orig_node->module, dev->orig_node);
3906 }
3907
3908 dev->orig_node = NULL;
3909 } else {
3910 /* adding not-supported deviation */
3911 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1,
3912 (const struct lys_node **)&target);
3913 if (ret || !target) {
3914 LOGINT;
3915 return;
3916 }
3917
3918 /* unlink and store the original node */
3919 parent = target->parent;
3920 lys_node_unlink(target);
3921 if (parent && parent->nodetype == LYS_AUGMENT) {
3922 /* hack for augment, because when the original will be sometime reconnected back, we actually need
3923 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
3924 * path), so we need to remember the augment as an addition */
3925 target->parent = parent;
3926 }
3927 dev->orig_node = target;
3928 }
3929 } else {
3930 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1,
3931 (const struct lys_node **)&target);
3932 if (ret || !target) {
3933 LOGINT;
3934 return;
3935 }
3936
3937 lys_node_switch(target, dev->orig_node);
3938 dev->orig_node = target;
3939 }
3940}
3941
3942/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3943void
3944lys_switch_deviations(struct lys_module *module)
3945{
3946 uint32_t i = 0, j;
3947 const struct lys_module *mod;
3948 const char *ptr;
3949
3950 if (module->deviated) {
3951 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3952 if (mod == module) {
3953 continue;
3954 }
3955
3956 for (j = 0; j < mod->deviation_size; ++j) {
3957 ptr = strstr(mod->deviation[j].target_name, module->name);
3958 if (ptr && ptr[strlen(module->name)] == ':') {
3959 lys_switch_deviation(&mod->deviation[j], mod);
3960 }
3961 }
3962 }
3963
3964 if (module->deviated == 2) {
3965 module->deviated = 1;
3966 } else {
3967 module->deviated = 2;
3968 }
3969 }
3970}
3971
3972static void
3973apply_dev(struct lys_deviation *dev, const struct lys_module *module)
3974{
3975 lys_switch_deviation(dev, module);
3976
3977 assert(dev->orig_node);
3978 lys_node_module(dev->orig_node)->deviated = 1;
3979}
3980
3981static void
3982remove_dev(struct lys_deviation *dev, const struct lys_module *module)
3983{
3984 uint32_t idx = 0, j;
3985 const struct lys_module *mod;
3986 struct lys_module *target_mod;
3987 const char *ptr;
3988
3989 if (dev->orig_node) {
3990 target_mod = lys_node_module(dev->orig_node);
3991 } else {
3992 LOGINT;
3993 return;
3994 }
3995 lys_switch_deviation(dev, module);
3996
3997 /* clear the deviation flag if possible */
3998 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
3999 if ((mod == module) || (mod == target_mod)) {
4000 continue;
4001 }
4002
4003 for (j = 0; j < mod->deviation_size; ++j) {
4004 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4005 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4006 /* some other module deviation targets the inspected module, flag remains */
4007 break;
4008 }
4009 }
4010
4011 if (j < mod->deviation_size) {
4012 break;
4013 }
4014 }
4015
4016 if (!mod) {
4017 target_mod->deviated = 0;
4018 }
4019}
4020
4021void
4022lys_sub_module_apply_devs_augs(struct lys_module *module)
4023{
4024 uint8_t u, v;
4025
4026 /* remove applied deviations */
4027 for (u = 0; u < module->deviation_size; ++u) {
4028 apply_dev(&module->deviation[u], module);
4029 }
4030 /* remove applied augments */
4031 for (u = 0; u < module->augment_size; ++u) {
4032 apply_aug(&module->augment[u]);
4033 }
4034
4035 /* remove deviation and augments defined in submodules */
4036 for (v = 0; v < module->inc_size; ++v) {
4037 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4038 apply_dev(&module->inc[v].submodule->deviation[u], module);
4039 }
4040
4041 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4042 apply_aug(&module->inc[v].submodule->augment[u]);
4043 }
4044 }
4045}
4046
Radek Krejcib2541a32016-12-12 16:45:57 +01004047void
4048lys_sub_module_remove_devs_augs(struct lys_module *module)
4049{
4050 uint8_t u, v;
4051
4052 /* remove applied deviations */
4053 for (u = 0; u < module->deviation_size; ++u) {
4054 remove_dev(&module->deviation[u], module);
4055 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004056 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004057 for (u = 0; u < module->augment_size; ++u) {
4058 remove_aug(&module->augment[u]);
4059 }
4060
4061 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004062 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01004063 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4064 remove_dev(&module->inc[v].submodule->deviation[u], module);
Radek Krejcidbc15262016-06-16 14:58:29 +02004065 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004066
Radek Krejcib2541a32016-12-12 16:45:57 +01004067 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4068 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004069 }
4070 }
4071}
4072
Radek Krejci27fe55e2016-09-13 17:13:35 +02004073static int
4074lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
4075{
4076 struct lys_node *root, *next, *node;
4077 uint8_t i;
4078
4079 for (i = 0; i < module->augment_size; i++) {
4080 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02004081 if (!module->augment[i].target
4082 && (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004083 return -1;
4084 }
4085 }
4086 LY_TREE_FOR(module->data, root) {
4087 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4088 LY_TREE_DFS_BEGIN(root, next, node) {
4089 if (node->nodetype == LYS_GROUPING) {
4090 goto nextsibling;
4091 }
4092 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4093 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4094 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4095 UNRES_TYPE_LEAFREF, node) == -1) {
4096 return EXIT_FAILURE;
4097 }
4098 }
4099 }
4100
4101 /* modified LY_TREE_DFS_END */
4102 next = node->child;
4103 /* child exception for leafs, leaflists and anyxml without children */
4104 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4105 next = NULL;
4106 }
4107 if (!next) {
4108nextsibling:
4109 /* no children */
4110 if (node == root) {
4111 /* we are done, root has no children */
4112 break;
4113 }
4114 /* try siblings */
4115 next = node->next;
4116 }
4117 while (!next) {
4118 /* parent is already processed, go to its sibling */
4119 node = lys_parent(node);
4120 /* no siblings, go back through parents */
4121 if (lys_parent(node) == lys_parent(root)) {
4122 /* we are done, no next element to process */
4123 break;
4124 }
4125 next = node->next;
4126 }
4127 }
4128 }
4129
4130 return EXIT_SUCCESS;
4131}
4132
4133API int
4134lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004135{
4136 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004137 struct unres_schema *unres;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004138 int i, j, disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004139
Radek Krejci27fe55e2016-09-13 17:13:35 +02004140 if (!module) {
4141 ly_errno = LY_EINVAL;
4142 return EXIT_FAILURE;
4143 }
4144
4145 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004146
4147 if (module->disabled) {
4148 disabled = 1;
4149 lys_set_enabled(module);
4150 }
4151
Michal Vasko26055752016-05-03 11:36:31 +02004152 if (module->implemented) {
4153 return EXIT_SUCCESS;
4154 }
4155
4156 ctx = module->ctx;
4157
4158 for (i = 0; i < ctx->models.used; ++i) {
4159 if (module == ctx->models.list[i]) {
4160 continue;
4161 }
4162
4163 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4164 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004165 if (disabled) {
4166 /* set it back disabled */
4167 lys_set_disabled(module);
4168 }
Michal Vasko26055752016-05-03 11:36:31 +02004169 return EXIT_FAILURE;
4170 }
4171 }
4172
Radek Krejci27fe55e2016-09-13 17:13:35 +02004173 unres = calloc(1, sizeof *unres);
4174 if (!unres) {
4175 LOGMEM;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004176 if (disabled) {
4177 /* set it back disabled */
4178 lys_set_disabled(module);
4179 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004180 return EXIT_FAILURE;
4181 }
4182 /* recursively make the module implemented */
4183 ((struct lys_module *)module)->implemented = 1;
4184 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
4185 goto error;
4186 }
4187 /* process augments in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004188 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004189 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
4190 /* apply augment */
Radek Krejcic8c22532016-11-09 15:11:24 +01004191 if (!module->inc[i].submodule->augment[j].target
4192 && (unres_schema_add_node((struct lys_module *)module->inc[j].submodule, unres,
4193 &module->inc[i].submodule->augment[j], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01004194
Radek Krejci27fe55e2016-09-13 17:13:35 +02004195 goto error;
4196 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004197 }
4198 }
Radek Krejcidf46e222016-11-08 11:57:37 +01004199 /* try again resolve augments in other modules possibly augmenting this one,
4200 * since we have just enabled it
4201 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004202 /* resolve rest of unres items */
4203 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4204 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004205 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004206 unres_schema_free((struct lys_module *)module, &unres);
Michal Vasko26055752016-05-03 11:36:31 +02004207
4208 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004209
4210error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004211
4212 if (disabled) {
4213 /* set it back disabled */
4214 lys_set_disabled(module);
4215 }
4216
Radek Krejci27fe55e2016-09-13 17:13:35 +02004217 ((struct lys_module *)module)->implemented = 0;
4218 unres_schema_free((struct lys_module *)module, &unres);
4219 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004220}
4221
4222void
4223lys_submodule_module_data_free(struct lys_submodule *submodule)
4224{
4225 struct lys_node *next, *elem;
4226
4227 /* remove parsed data */
4228 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4229 if (elem->module == (struct lys_module *)submodule) {
4230 lys_node_free(elem, NULL, 0);
4231 }
4232 }
4233}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004234
4235int
4236lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
4237{
4238 uint8_t i;
4239
4240 for (i = 0; i < list->keys_size; i++) {
4241 if (list->keys[i] == leaf) {
4242 return i + 1;
4243 }
4244 }
4245
4246 return 0;
4247}
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004248
4249API char *
4250lys_path(const struct lys_node *node)
4251{
4252 char *buf_backup = NULL, *buf = ly_buf(), *result = NULL;
4253 uint16_t index = LY_BUF_SIZE - 1;
4254
4255 if (!node) {
4256 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
4257 return NULL;
4258 }
4259
4260 /* backup the shared internal buffer */
4261 if (ly_buf_used && buf[0]) {
4262 buf_backup = strndup(buf, LY_BUF_SIZE - 1);
4263 }
4264 ly_buf_used++;
4265
4266 /* build the path */
4267 buf[index] = '\0';
Michal Vasko5efa25c2017-01-10 11:34:30 +01004268 ly_vlog_build_path_reverse(LY_VLOG_LYS, node, buf, &index, 0);
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004269 result = strdup(&buf[index]);
4270
4271 /* restore the shared internal buffer */
4272 if (buf_backup) {
4273 strcpy(buf, buf_backup);
4274 free(buf_backup);
4275 }
4276 ly_buf_used--;
4277
4278 return result;
4279}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004280
Radek Krejci8d6b7422017-02-03 14:42:13 +01004281static void
4282lys_extcomplex_free_str(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext, LY_STMT stmt)
4283{
4284 struct lyext_substmt *info;
4285 const char **str;
4286 int c;
4287
4288 str = lys_ext_complex_get_substmt(stmt, ext, &info);
4289 if (!str || !(*str)) {
4290 return;
4291 }
4292 if (info->cardinality >= LY_STMT_CARD_SOME) {
4293 /* we have array */
4294 for (str = (const char **)(*str), c = 0; *str; str++, c++) {
4295 lydict_remove(ctx, *str);
4296 }
4297 free(str);
4298 } else {
4299 lydict_remove(ctx, *str);
4300 }
4301}
4302void
4303lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size)
4304{
4305 unsigned int i, j;
4306 struct lyext_substmt *substmt;
4307 struct lyext_substmt *info;
4308 void **pp, **start;
4309
4310#define EXTCOMPLEX_FREE_STRUCT(STMT, TYPE, FUNC, FREE, ARGS...) \
4311 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)e[i], &info); \
4312 if (!pp || !(*pp)) { break; } \
4313 if (info->cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
4314 for (start = pp = *pp; *pp; pp++) { \
4315 FUNC(ctx, (TYPE *)(*pp), ##ARGS); \
4316 if (FREE) { free(*pp); } \
4317 } \
4318 free(start); \
4319 } else { /* single item */ \
4320 FUNC(ctx, (TYPE *)(*pp), ##ARGS); \
4321 if (FREE) { free(*pp); } \
4322 }
4323
4324 if (!size || !e || !(*e)) {
4325 return;
4326 }
4327
4328 for (i = 0; i < size; i++) {
4329 if (!e[i]) {
4330 continue;
4331 }
4332
4333 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
4334 /* no free, this is just a shadow copy of the original extension instance */
4335 } else {
4336 if (e[i]->flags & (LYEXT_OPT_YANG)) {
4337 free(e[i]->def); /* remove name of instance extension */
4338 free(e[i]->parent); /* remove backup part of yang file */
4339 }
4340 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size);
4341 lydict_remove(ctx, e[i]->arg_value);
4342 }
4343
4344 if (e[i]->def && e[i]->def->plugin && e[i]->def->plugin->type == LYEXT_COMPLEX) {
4345 substmt = ((struct lyext_plugin_complex *)e[i]->def->plugin)->substmt;
4346 for (j = 0; substmt[j].stmt; j++) {
4347 switch(substmt[j].stmt) {
4348 case LY_STMT_DESCRIPTION:
4349 case LY_STMT_REFERENCE:
4350 case LY_STMT_UNITS:
4351 lys_extcomplex_free_str(ctx, (struct lys_ext_instance_complex *)e[i], substmt[j].stmt);
4352 break;
4353 case LY_STMT_TYPE:
4354 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPE, struct lys_type, lys_type_free, 1);
4355 break;
4356 case LY_STMT_IFFEATURE:
4357 EXTCOMPLEX_FREE_STRUCT(LY_STMT_IFFEATURE, struct lys_iffeature, lys_iffeature_free, 0, 1);
4358 break;
4359 case LY_STMT_STATUS:
4360 /* nothing to free */
4361 break;
4362 default:
4363 /* TODO */
4364 break;
4365 }
4366 }
4367 }
4368
4369 free(e[i]);
4370 }
4371 free(e);
4372
4373#undef EXTCOMPLEX_FREE_STRUCT
4374}