blob: 248aa445e273dc503a7d5ed67d1666d60ee0986d [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
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020040static int
41lys_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 +020042 int tpdftype, struct unres_schema *unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020043
Radek Krejci9ff0a922016-07-14 13:08:05 +020044API const struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010045lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020046{
Radek Krejci9ff0a922016-07-14 13:08:05 +020047 int i;
Radek Krejci48061fb2015-08-05 15:41:07 +020048
Radek Krejci27fe55e2016-09-13 17:13:35 +020049 if (!node) {
50 return NULL;
51 }
52
Radek Krejci48061fb2015-08-05 15:41:07 +020053check:
54 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
55 /* input/output does not have if-feature, so skip them */
56
57 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020058 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci69b8d922016-07-27 13:13:41 +020059 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020060 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020061 }
62 }
63 }
64
65 if (!recursive) {
66 return NULL;
67 }
68
69 /* go through parents */
70 if (node->nodetype == LYS_AUGMENT) {
71 /* go to parent actually means go to the target node */
72 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 } else if (node->parent) {
74 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020075 } else {
76 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020077 }
78
Radek Krejci074bf852015-08-19 14:22:16 +020079 if (recursive == 2) {
80 /* continue only if the node cannot have a data instance */
81 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
82 return NULL;
83 }
84 }
85 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020086}
87
Michal Vasko1dca6882015-10-22 14:29:42 +020088int
Michal Vasko36cbaa42015-12-14 13:15:48 +010089lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
90 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020091{
Radek Krejcic071c542016-01-27 14:57:51 +010092 const struct lys_node *node, *parent = NULL;
93 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010094 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020095
Michal Vasko36cbaa42015-12-14 13:15:48 +010096 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020097 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020098
Michal Vasko36cbaa42015-12-14 13:15:48 +010099 /* fill the lengths in case the caller is so indifferent */
100 if (!mod_name_len) {
101 mod_name_len = strlen(mod_name);
102 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200103 if (!nam_len) {
104 nam_len = strlen(name);
105 }
106
Michal Vasko9e635ac2016-10-17 11:44:09 +0200107 while (siblings && (siblings->nodetype == LYS_USES)) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200108 siblings = siblings->child;
109 }
Michal Vasko9e635ac2016-10-17 11:44:09 +0200110 if (!siblings) {
111 /* unresolved uses */
112 return EXIT_FAILURE;
113 }
114
Michal Vasko680f8b42016-10-17 10:27:37 +0200115 if (siblings->nodetype == LYS_GROUPING) {
116 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
117 if (node->nodetype == LYS_GROUPING) {
118 /* we went through all the siblings, only groupings there - no valid sibling */
119 return EXIT_FAILURE;
120 }
121 /* update siblings to be valid */
122 siblings = node;
123 }
124
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200125 /* set parent correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100126 parent = lys_parent(siblings);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200127
Michal Vasko680f8b42016-10-17 10:27:37 +0200128 /* go up all uses */
129 while (parent && (parent->nodetype == LYS_USES)) {
130 parent = lys_parent(parent);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200131 }
132
Radek Krejcic071c542016-01-27 14:57:51 +0100133 if (!parent) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200134 /* handle situation when there is a top-level uses referencing a foreign grouping */
135 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
136 mod = lys_node_module(node);
Michal Vasko1dca6882015-10-22 14:29:42 +0200137 }
138
Radek Krejcic071c542016-01-27 14:57:51 +0100139 /* try to find the node */
140 node = NULL;
141 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
142 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100143 /* module name comparison */
144 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200145 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 +0100146 continue;
147 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200148
Radek Krejcic071c542016-01-27 14:57:51 +0100149 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200150 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100151 if (ret) {
152 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200153 }
Radek Krejcic071c542016-01-27 14:57:51 +0100154 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200155 }
156 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200157 }
158
159 return EXIT_FAILURE;
160}
161
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200162int
Michal Vasko1e62a092015-12-01 12:27:20 +0100163lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
164 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200165{
Michal Vasko1e62a092015-12-01 12:27:20 +0100166 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200167
168 assert(siblings && name);
169 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
170
171 /* find the beginning */
172 while (siblings->prev->next) {
173 siblings = siblings->prev;
174 }
175
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200176 if (!mod) {
177 mod = siblings->module;
178 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200179
Michal Vasko4f0dad02016-02-15 14:08:23 +0100180 /* try to find the node */
181 node = NULL;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200182 while ((node = lys_getnext(node, lys_parent(siblings), mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100183 if (!type || (node->nodetype & type)) {
184 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200185 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100186 continue;
187 }
188
Michal Vasko4f0dad02016-02-15 14:08:23 +0100189 /* direct name check */
Radek Krejci749190d2016-02-18 16:26:25 +0100190 if (ly_strequal(node->name, name, 0)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100191 if (ret) {
192 *ret = node;
193 }
194 return EXIT_SUCCESS;
195 }
Radek Krejcic071c542016-01-27 14:57:51 +0100196 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200197 }
198
199 return EXIT_FAILURE;
200}
201
Michal Vasko1e62a092015-12-01 12:27:20 +0100202API const struct lys_node *
203lys_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 +0200204{
Michal Vasko1e62a092015-12-01 12:27:20 +0100205 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200206
Radek Krejci8bc87f62015-09-02 16:19:05 +0200207 if (!last) {
208 /* first call */
209
210 /* get know where to start */
211 if (parent) {
212 /* schema subtree */
213 next = last = parent->child;
214 } else {
215 /* top level data */
216 assert(module);
217 next = last = module->data;
218 }
Radek Krejci972724f2016-08-12 15:24:40 +0200219 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
220 /* continue with uses content */
221 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200222 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200223 /* continue after the last returned value */
224 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200225 }
226
227repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200228 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200229 if (options & LYS_GETNEXT_WITHGROUPING) {
230 return next;
231 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200232 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200233 }
234
Radek Krejci972724f2016-08-12 15:24:40 +0200235 if (!next) { /* cover case when parent is augment */
236 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200237 /* no next element */
238 return NULL;
239 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200240 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200241 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200242 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200243 } else {
244 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200245 }
246
247 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200248 case LYS_INPUT:
249 case LYS_OUTPUT:
250 if (options & LYS_GETNEXT_WITHINOUT) {
251 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200252 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200253 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200254 } else {
255 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200256 }
Radek Krejci972724f2016-08-12 15:24:40 +0200257 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200258
Michal Vaskoa5835e92015-10-20 15:07:39 +0200259 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200260 if (options & LYS_GETNEXT_WITHCASE) {
261 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200262 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200263 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200264 } else {
265 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200266 }
Radek Krejci972724f2016-08-12 15:24:40 +0200267 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200268
Michal Vasko1dca6882015-10-22 14:29:42 +0200269 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200270 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200271 if (options & LYS_GETNEXT_WITHUSES) {
272 return next;
273 } else if (next->child) {
274 next = next->child;
275 } else {
276 next = next->next;
277 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200278 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200279
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200280 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200281 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200282 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200283 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200284 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200285 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200286 case LYS_LIST:
287 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200288 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200289
Radek Krejci972724f2016-08-12 15:24:40 +0200290 case LYS_CONTAINER:
291 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
292 if (next->child) {
293 /* go into */
294 next = next->child;
295 } else {
296 next = next->next;
297 }
298 goto repeat;
299 } else {
300 return next;
301 }
302
Radek Krejci8bc87f62015-09-02 16:19:05 +0200303 case LYS_CHOICE:
304 if (options & LYS_GETNEXT_WITHCHOICE) {
305 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200306 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200307 /* go into */
308 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200309 } else {
310 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200311 }
Radek Krejci972724f2016-08-12 15:24:40 +0200312 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200313
Radek Krejci7f40ce32015-08-12 20:38:46 +0200314 default:
315 /* we should not be here */
316 return NULL;
317 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200318
319
320}
321
Radek Krejcie534c132016-11-23 13:32:31 +0100322static void
323lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size)
324{
325 unsigned int i;
326
327 if (!size || !e || !(*e)) {
328 return;
329 }
330
331 for (i = 0; i < size; i++) {
332 if (!e[i]) {
333 continue;
334 }
335
Radek Krejci80056d52017-01-05 13:13:33 +0100336 if (e[i]->flags & LYEXT_OPT_INHERIT) {
337 /* no free, this is just a shadow copy of the original extension instance */
338 } else {
339 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size);
340 lydict_remove(ctx, e[i]->arg_value);
Radek Krejcie534c132016-11-23 13:32:31 +0100341 }
342 free(e[i]);
343 }
344 free(e);
345}
346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200347void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200348lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200349{
Radek Krejci76512572015-08-04 09:47:08 +0200350 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100351 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 if (!node) {
354 return;
355 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200357 /* unlink from data model if necessary */
358 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100359 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100360 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100361 if (main_module->data == node) {
362 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200363 }
364 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200366 /* store pointers to important nodes */
367 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200368 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200369 /* handle augments - first, unlink it from the augment parent ... */
370 if (parent->child == node) {
371 parent->child = node->next;
372 }
373 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200374 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200375 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200377 /* unlink from parent */
378 if (parent) {
379 if (parent->child == node) {
380 parent->child = node->next;
381 }
382 node->parent = NULL;
383 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200385 /* unlink from siblings */
386 if (node->prev == node) {
387 /* there are no more siblings */
388 return;
389 }
390 if (node->next) {
391 node->next->prev = node->prev;
392 } else {
393 /* unlinking the last element */
394 if (parent) {
395 first = parent->child;
396 } else {
397 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200398 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200399 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200400 }
401 }
402 first->prev = node->prev;
403 }
404 if (node->prev->next) {
405 node->prev->next = node->next;
406 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200408 /* clean up the unlinked element */
409 node->next = NULL;
410 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200411}
412
Michal Vasko563ef092015-09-04 13:17:23 +0200413struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100414lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200415{
416 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200417
418 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200419 /* top-level augment, look into module (uses augment is handled correctly below) */
420 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
421 par_iter = par_iter->parent->module->data;
422 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200423 break;
424 }
425 }
426
Michal Vasko6f929da2015-10-02 16:23:25 +0200427 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200428 continue;
429 }
430
431 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
432 if (!stop) {
433 stop = par_iter;
434 } else if (iter == stop) {
435 break;
436 }
437 if (iter->nodetype != LYS_GROUPING) {
438 continue;
439 }
440
Radek Krejcif8426a72015-10-31 23:14:03 +0100441 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200442 return (struct lys_node_grp *)iter;
443 }
444 }
445 }
446
Michal Vasko563ef092015-09-04 13:17:23 +0200447 return NULL;
448}
449
Radek Krejci10c760e2015-08-14 14:45:43 +0200450/*
451 * get next grouping in the root's subtree, in the
452 * first call, tha last is NULL
453 */
454static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200455lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200456{
Radek Krejci10c760e2015-08-14 14:45:43 +0200457 struct lys_node *last = (struct lys_node *)lastgrp;
458 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200459
Radek Krejci10c760e2015-08-14 14:45:43 +0200460 assert(root);
461
462 if (!last) {
463 last = root;
464 }
465
466 while (1) {
467 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
468 next = last->child;
469 } else {
470 next = NULL;
471 }
472 if (!next) {
473 if (last == root) {
474 /* we are done */
475 return NULL;
476 }
477
478 /* no children, go to siblings */
479 next = last->next;
480 }
481 while (!next) {
482 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100483 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200484 /* we are done */
485 return NULL;
486 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200487 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100488 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200489 }
490
491 if (next->nodetype == LYS_GROUPING) {
492 return (struct lys_node_grp *)next;
493 }
494
495 last = next;
496 }
497}
498
Michal Vasko0d343d12015-08-24 14:57:36 +0200499/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200500int
Radek Krejci07911992015-08-14 15:13:31 +0200501lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
502{
Michal Vasko563ef092015-09-04 13:17:23 +0200503 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200504 struct lys_node_grp *grp;
505 int down;
506
507 assert(node);
508
509 if (!parent) {
510 assert(module);
511 } else {
512 module = parent->module;
513 }
514
515 switch (node->nodetype) {
516 case LYS_GROUPING:
517 /* 6.2.1, rule 6 */
518 if (parent) {
519 if (parent->child) {
520 down = 1;
521 start = parent->child;
522 } else {
523 down = 0;
524 start = parent;
525 }
526 } else {
527 down = 1;
528 start = module->data;
529 }
530 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100531 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100532 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200533 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200534 }
535 /* go down, because grouping can be defined after e.g. container in which is collision */
536 if (down) {
537 for (iter = start, stop = NULL; iter; iter = iter->prev) {
538 if (!stop) {
539 stop = start;
540 } else if (iter == stop) {
541 break;
542 }
543 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
544 continue;
545 }
546
547 grp = NULL;
548 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100549 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100550 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200551 return EXIT_FAILURE;
552 }
553 }
554 }
555 }
556 break;
557 case LYS_LEAF:
558 case LYS_LEAFLIST:
559 case LYS_LIST:
560 case LYS_CONTAINER:
561 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200562 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200563 /* 6.2.1, rule 7 */
564 if (parent) {
565 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200566 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
567 if (iter->nodetype == LYS_AUGMENT) {
568 if (((struct lys_node_augment *)iter)->target) {
569 /* augment is resolved, go up */
570 iter = ((struct lys_node_augment *)iter)->target;
571 continue;
572 }
573 /* augment is not resolved, this is the final parent */
574 break;
575 }
Radek Krejci07911992015-08-14 15:13:31 +0200576 iter = iter->parent;
577 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200578
Radek Krejci07911992015-08-14 15:13:31 +0200579 if (!iter) {
580 stop = NULL;
581 iter = module->data;
582 } else {
583 stop = iter;
584 iter = iter->child;
585 }
586 } else {
587 stop = NULL;
588 iter = module->data;
589 }
590 while (iter) {
591 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
592 iter = iter->child;
593 continue;
594 }
595
Radek Krejcibf2abff2016-08-23 15:51:52 +0200596 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100597 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100598 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200599 return EXIT_FAILURE;
600 }
601 }
602
603 /* special case for choice - we must check the choice's name as
604 * well as the names of nodes under the choice
605 */
606 if (iter->nodetype == LYS_CHOICE) {
607 iter = iter->child;
608 continue;
609 }
610
611 /* go to siblings */
612 if (!iter->next) {
613 /* no sibling, go to parent's sibling */
614 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200615 /* for parent LYS_AUGMENT */
616 if (iter->parent == stop) {
617 iter = stop;
618 break;
619 }
620 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200621 if (iter && iter->next) {
622 break;
623 }
624 } while (iter != stop);
625
626 if (iter == stop) {
627 break;
628 }
629 }
630 iter = iter->next;
631 }
632 break;
633 case LYS_CASE:
634 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100635 if (parent) {
636 start = parent->child;
637 } else {
638 start = module->data;
639 }
640
641 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200642 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200643 continue;
644 }
645
Radek Krejci749190d2016-02-18 16:26:25 +0100646 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100647 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200648 return EXIT_FAILURE;
649 }
650 }
651 break;
652 default:
653 /* no check needed */
654 break;
655 }
656
657 return EXIT_SUCCESS;
658}
659
Michal Vasko0d343d12015-08-24 14:57:36 +0200660/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200661int
Radek Krejci10c760e2015-08-14 14:45:43 +0200662lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
663{
Radek Krejci92720552015-10-05 15:28:27 +0200664 struct lys_node *iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200665 struct lys_node_inout *in, *out, *inout;
Radek Krejci07911992015-08-14 15:13:31 +0200666 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200668 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200669
Radek Krejci10c760e2015-08-14 14:45:43 +0200670 if (parent) {
671 type = parent->nodetype;
672 module = parent->module;
673 } else {
674 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100675 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200676 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200677 }
678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200679 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200680 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200681 case LYS_CONTAINER:
682 case LYS_LIST:
683 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100684 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200685 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200686 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200687 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200688 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
689 return EXIT_FAILURE;
690 }
691 break;
Radek Krejci76512572015-08-04 09:47:08 +0200692 case LYS_INPUT:
693 case LYS_OUTPUT:
694 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200695 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200696 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200697 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100698 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200699 return EXIT_FAILURE;
700 }
701 break;
Radek Krejci76512572015-08-04 09:47:08 +0200702 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200703 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200704 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100705 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200706 return EXIT_FAILURE;
707 }
708 break;
Radek Krejci76512572015-08-04 09:47:08 +0200709 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200710 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200711 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100712 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200713 return EXIT_FAILURE;
714 }
715 break;
Radek Krejci76512572015-08-04 09:47:08 +0200716 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200717 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200718 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100719 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200720 return EXIT_FAILURE;
721 }
722 break;
Radek Krejci76512572015-08-04 09:47:08 +0200723 case LYS_LEAF:
724 case LYS_LEAFLIST:
725 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200726 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100727 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
728 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100729 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200730 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200731 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200732 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200733 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200734 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100735 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200736 return EXIT_FAILURE;
737 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200738 break;
739 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200740 /* top level */
741 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200742 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200743 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100744 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200745 return EXIT_FAILURE;
746 }
747
Radek Krejcic071c542016-01-27 14:57:51 +0100748 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200749 }
750
751 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200752 if (lys_check_id(child, parent, module)) {
753 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200754 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200756 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200757 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200758 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200759
Radek Krejci41a349b2016-10-24 19:21:59 +0200760 if (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
761 /* replace the implicit input/output node */
762 if (child->nodetype == LYS_OUTPUT) {
763 inout = (struct lys_node_inout *)parent->child->next;
764 } else { /* LYS_INPUT */
765 inout = (struct lys_node_inout *)parent->child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200766 parent->child = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200767 }
768 if (inout->next) {
769 child->next = inout->next;
770 inout->next->prev = child;
771 inout->next = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200772 } else {
Radek Krejci41a349b2016-10-24 19:21:59 +0200773 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200774 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200775 child->prev = inout->prev;
776 if (inout->prev->next) {
777 inout->prev->next = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200778 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200779 inout->prev = (struct lys_node *)inout;
780 child->parent = parent;
781 inout->parent = NULL;
782 lys_node_free((struct lys_node *)inout, NULL, 0);
783 } else {
784 /* connect the child correctly */
785 if (!parent) {
786 if (module->data) {
787 module->data->prev->next = child;
788 child->prev = module->data->prev;
789 module->data->prev = child;
790 } else {
791 module->data = child;
792 }
793 } else {
794 if (!parent->child) {
795 /* the only/first child of the parent */
796 parent->child = child;
797 child->parent = parent;
798 iter = child;
799 } else {
800 /* add a new child at the end of parent's child list */
801 iter = parent->child->prev;
802 iter->next = child;
803 child->prev = iter;
804 }
805 while (iter->next) {
806 iter = iter->next;
807 iter->parent = parent;
808 }
809 parent->child->prev = iter;
810 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200812
Michal Vaskoe022a562016-09-27 14:24:15 +0200813 /* check config value (but ignore them in groupings and augments) */
814 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT)); iter = iter->parent);
815 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200816 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
817 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
818 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
819 LOGVAL(LYE_SPEC, LY_VLOG_LYS, child, "State nodes cannot have configuration nodes as children.");
820 return EXIT_FAILURE;
821 }
822 }
823
Radek Krejci41771502016-04-14 17:52:32 +0200824 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200825 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200826 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200827 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200828 /* store it only into container or list - the only data inner nodes */
829 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
830 if (iter->flags & LYS_INCL_STATUS) {
831 /* done, someone else set it already from here */
832 break;
833 }
834 /* set flag about including status data */
835 iter->flags |= LYS_INCL_STATUS;
836 }
837 }
838 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200839
840 /* create implicit input/output nodes to have available them as possible target for augment */
841 if (child->nodetype & (LYS_RPC | LYS_ACTION)) {
842 in = calloc(1, sizeof *in);
843 in->nodetype = LYS_INPUT;
844 in->name = lydict_insert(child->module->ctx, "input", 5);
845 out = calloc(1, sizeof *out);
846 out->name = lydict_insert(child->module->ctx, "output", 6);
847 out->nodetype = LYS_OUTPUT;
848 in->module = out->module = child->module;
849 in->parent = out->parent = child;
850 in->flags = out->flags = LYS_IMPLICIT;
851 in->next = (struct lys_node *)out;
852 in->prev = (struct lys_node *)out;
853 out->prev = (struct lys_node *)in;
854 child->child = (struct lys_node *)in;
855 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200856 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200857}
858
Radek Krejcia1df1682016-04-11 14:56:59 +0200859static const struct lys_module *
860lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200861{
Radek Krejcia1df1682016-04-11 14:56:59 +0200862 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200863 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200864 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200865
Radek Krejci00a0e712016-10-26 10:24:46 +0200866 ly_err_clean(1);
Radek Krejcif347abc2016-06-22 10:18:47 +0200867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200868 if (!ctx || !data) {
869 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
870 return NULL;
871 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200872
Radek Krejcia1df1682016-04-11 14:56:59 +0200873 if (!internal && format == LYS_IN_YANG) {
874 /* enlarge data by 2 bytes for flex */
875 len = strlen(data);
876 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
877 if (!enlarged_data) {
878 LOGMEM;
879 return NULL;
880 }
881 memcpy(enlarged_data, data, len);
882 enlarged_data[len] = enlarged_data[len + 1] = '\0';
883 data = enlarged_data;
884 }
885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200886 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200887 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100888 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200889 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200890 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100891 mod = yang_read_module(ctx, data, 0, NULL, 1);
892 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200893 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200894 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200895 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200896 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200897
Radek Krejcia1df1682016-04-11 14:56:59 +0200898 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200899 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200900}
901
Radek Krejcia1df1682016-04-11 14:56:59 +0200902API const struct lys_module *
903lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
904{
905 return lys_parse_mem_(ctx, data, format, 0);
906}
907
Michal Vasko5a721fd2016-02-16 12:16:48 +0100908struct lys_submodule *
909lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200910{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100911 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200913 assert(module);
914 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200915
Radek Krejcic071c542016-01-27 14:57:51 +0100916 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +0200917 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200919 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200920 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +0100921 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200922 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200923 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100924 submod = yang_read_submodule(module, data, 0, unres);
925 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200926 default:
Radek Krejci90a550a2016-04-13 16:00:58 +0200927 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200928 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200929 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200930
Michal Vasko5a721fd2016-02-16 12:16:48 +0100931 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200932}
933
Michal Vasko1e62a092015-12-01 12:27:20 +0100934API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +0100935lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
936{
937 int fd;
938 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +0200939 const char *rev, *dot, *filename;
940 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +0100941
942 if (!ctx || !path) {
943 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
944 return NULL;
945 }
946
947 fd = open(path, O_RDONLY);
948 if (fd == -1) {
949 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
950 return NULL;
951 }
952
953 ret = lys_parse_fd(ctx, fd, format);
954 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +0100955
Radek Krejcid80c8602016-10-25 11:56:03 +0200956 if (!ret) {
957 /* error */
958 return NULL;
959 }
960
961 /* check that name and revision match filename */
962 filename = strrchr(path, '/');
963 if (!filename) {
964 filename = path;
965 } else {
966 filename++;
967 }
968 rev = strchr(filename, '@');
969 dot = strrchr(filename, '.');
970
971 /* name */
972 len = strlen(ret->name);
973 if (strncmp(filename, ret->name, len) ||
974 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Radek Krejcic0c82302016-10-25 14:21:33 +0200975 LOGWRN("File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +0200976 }
977 if (rev) {
978 len = dot - ++rev;
979 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
980 LOGWRN("File name \"%s\" does not match module revision \"%s\".", filename,
981 ret->rev_size ? ret->rev[0].date : "none");
982 }
983 }
984
985 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +0100986 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +0100987 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +0100988 }
989
Michal Vasko662610a2015-12-07 11:25:45 +0100990 return ret;
991}
992
993API const struct lys_module *
994lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200995{
Michal Vasko1e62a092015-12-01 12:27:20 +0100996 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200997 struct stat sb;
998 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +0100999 char buf[PATH_MAX];
1000 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001001
1002 if (!ctx || fd < 0) {
1003 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1004 return NULL;
1005 }
1006
Radek Krejci10a833c2015-12-16 15:28:37 +01001007 if (fstat(fd, &sb) == -1) {
1008 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1009 return NULL;
1010 }
Radek Krejcib051f722016-02-25 15:12:21 +01001011 if (!S_ISREG(sb.st_mode)) {
1012 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1013 return NULL;
1014 }
1015
Michal Vasko164d9012016-04-01 10:16:59 +02001016 if (!sb.st_size) {
1017 LOGERR(LY_EINVAL, "File empty.");
1018 return NULL;
1019 }
1020
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001021 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001022 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001023 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001024 return NULL;
1025 }
Radek Krejcia1df1682016-04-11 14:56:59 +02001026 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001027 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001028
Radek Krejcia77904e2016-02-25 16:23:45 +01001029 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001030 /* get URI if there is /proc */
1031 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001032 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1033 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1034 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1035 }
1036 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001037 }
Radek Krejcib051f722016-02-25 15:12:21 +01001038 }
1039
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001040 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001041}
1042
Michal Vasko5a721fd2016-02-16 12:16:48 +01001043struct lys_submodule *
1044lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001045{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001046 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001047 struct stat sb;
1048 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001050 assert(module);
1051 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001052
Radek Krejci10a833c2015-12-16 15:28:37 +01001053 if (fstat(fd, &sb) == -1) {
1054 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001055 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001056 }
Michal Vasko164d9012016-04-01 10:16:59 +02001057
1058 if (!sb.st_size) {
1059 LOGERR(LY_EINVAL, "File empty.");
1060 return NULL;
1061 }
1062
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001063 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001064 if (addr == MAP_FAILED) {
1065 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001066 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001067 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001068 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001069 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +02001070
Michal Vasko5a721fd2016-02-16 12:16:48 +01001071 return submodule;
1072
Radek Krejciefaeba32015-05-27 14:30:57 +02001073}
1074
Radek Krejci1d82ef62015-08-07 14:44:40 +02001075static struct lys_restr *
1076lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001077{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001078 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001079 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001080
Radek Krejci3733a802015-06-19 13:43:21 +02001081 if (!size) {
1082 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001083 }
Radek Krejci3733a802015-06-19 13:43:21 +02001084
1085 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001086 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001087 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001088 return NULL;
1089 }
Radek Krejci3733a802015-06-19 13:43:21 +02001090 for (i = 0; i < size; i++) {
1091 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1092 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1093 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1094 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1095 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1096 }
1097
1098 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001099}
1100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001101void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001102lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001103{
1104 assert(ctx);
1105 if (!restr) {
1106 return;
1107 }
1108
1109 lydict_remove(ctx, restr->expr);
1110 lydict_remove(ctx, restr->dsc);
1111 lydict_remove(ctx, restr->ref);
1112 lydict_remove(ctx, restr->eapptag);
1113 lydict_remove(ctx, restr->emsg);
1114}
1115
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001116static void
1117lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
1118{
1119 uint8_t i;
1120
1121 for (i = 0; i < iffeature_size; ++i) {
1122 free(iffeature[i].expr);
1123 free(iffeature[i].features);
1124 }
1125 free(iffeature);
1126}
1127
Michal Vaskob84f88a2015-09-24 13:16:10 +02001128static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001129type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001130 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001131{
1132 int i;
1133
1134 switch (base) {
1135 case LY_TYPE_BINARY:
1136 if (old->info.binary.length) {
1137 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1138 }
1139 break;
1140
1141 case LY_TYPE_BITS:
1142 new->info.bits.count = old->info.bits.count;
1143 if (new->info.bits.count) {
1144 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1145 if (!new->info.bits.bit) {
1146 LOGMEM;
1147 return -1;
1148 }
1149 for (i = 0; i < new->info.bits.count; i++) {
1150 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1151 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1152 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1153 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1154 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1155 }
1156 }
1157 break;
1158
1159 case LY_TYPE_DEC64:
1160 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001161 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001162 if (old->info.dec64.range) {
1163 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1164 }
1165 break;
1166
1167 case LY_TYPE_ENUM:
1168 new->info.enums.count = old->info.enums.count;
1169 if (new->info.enums.count) {
1170 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1171 if (!new->info.enums.enm) {
1172 LOGMEM;
1173 return -1;
1174 }
1175 for (i = 0; i < new->info.enums.count; i++) {
1176 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1177 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1178 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1179 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1180 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1181 }
1182 }
1183 break;
1184
1185 case LY_TYPE_IDENT:
Michal Vaskoaffc37f2016-10-10 18:05:03 +00001186 new->info.ident.count = old->info.ident.count;
Michal Vasko878e38d2016-09-05 12:17:53 +02001187 if (old->info.ident.count) {
1188 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1189 if (!new->info.ident.ref) {
1190 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001191 return -1;
1192 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001193 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1194 } else {
1195 /* there can be several unresolved base identities, duplicate them all */
1196 i = -1;
1197 while ((i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF)) != -1) {
1198 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1199 return -1;
1200 }
1201 --i;
1202 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001203 }
1204 break;
1205
1206 case LY_TYPE_INST:
1207 new->info.inst.req = old->info.inst.req;
1208 break;
1209
1210 case LY_TYPE_INT8:
1211 case LY_TYPE_INT16:
1212 case LY_TYPE_INT32:
1213 case LY_TYPE_INT64:
1214 case LY_TYPE_UINT8:
1215 case LY_TYPE_UINT16:
1216 case LY_TYPE_UINT32:
1217 case LY_TYPE_UINT64:
1218 if (old->info.num.range) {
1219 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1220 }
1221 break;
1222
1223 case LY_TYPE_LEAFREF:
1224 if (old->info.lref.path) {
1225 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001226 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001227 return -1;
1228 }
1229 }
1230 break;
1231
1232 case LY_TYPE_STRING:
1233 if (old->info.str.length) {
1234 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1235 }
1236 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1237 new->info.str.pat_count = old->info.str.pat_count;
1238 break;
1239
1240 case LY_TYPE_UNION:
1241 new->info.uni.count = old->info.uni.count;
1242 if (new->info.uni.count) {
1243 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1244 if (!new->info.uni.types) {
1245 LOGMEM;
1246 return -1;
1247 }
1248 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001249 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 +02001250 return -1;
1251 }
1252 }
1253 }
1254 break;
1255
1256 default:
1257 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1258 break;
1259 }
1260 return EXIT_SUCCESS;
1261}
1262
1263struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001264lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1265 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001266{
1267 struct yang_type *new;
1268
1269 new = calloc(1, sizeof *new);
1270 if (!new) {
1271 LOGMEM;
1272 return NULL;
1273 }
1274 new->flags = old->flags;
1275 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001276 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001277 new->type = type;
1278 if (!new->name) {
1279 LOGMEM;
1280 goto error;
1281 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001282 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001283 new->type->base = new->base;
1284 lys_type_free(module->ctx, new->type);
1285 memset(&new->type->info, 0, sizeof new->type->info);
1286 goto error;
1287 }
1288 return new;
1289
1290 error:
1291 free(new);
1292 return NULL;
1293}
1294
Radek Krejcie534c132016-11-23 13:32:31 +01001295/*
1296 * duplicate extension instance
1297 */
1298static struct lys_ext_instance **
Radek Krejci43ce4b72017-01-04 11:02:38 +01001299lys_ext_dup(struct lys_module *mod, struct lys_ext_instance **orig, unsigned int size,
1300 void *parent, LYEXT_PAR parent_type, struct unres_schema *unres)
Radek Krejcie534c132016-11-23 13:32:31 +01001301{
1302 int i;
Radek Krejci43ce4b72017-01-04 11:02:38 +01001303 unsigned int u = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01001304 struct lys_ext_instance **result;
Radek Krejcie534c132016-11-23 13:32:31 +01001305 struct unres_ext *info, *info_orig;
1306
1307 assert(size);
1308 assert(!orig);
1309 assert(!(*orig));
1310
1311 result = calloc(size, sizeof *result);
1312 for (u = 0; u < size; u++) {
1313 if (orig[u]) {
1314 /* resolved extension instance, just duplicate it */
1315 result[u]->def = orig[u]->def;
Radek Krejci0aa821a2016-12-08 11:21:35 +01001316 switch(lys_ext_instance_type(orig[u])) {
1317 case LYEXT_FLAG:
1318 result[u] = malloc(sizeof(struct lys_ext_instance));
1319 break;
1320 case LYEXT_ERR:
1321 LOGINT;
1322 break;
Radek Krejcie534c132016-11-23 13:32:31 +01001323 }
Radek Krejci0aa821a2016-12-08 11:21:35 +01001324 /* generic part */
1325 result[u]->arg_value = lydict_insert(mod->ctx, orig[u]->arg_value, 0);
Radek Krejci43ce4b72017-01-04 11:02:38 +01001326 result[u]->parent = parent;
1327 result[u]->parent_type = parent_type;
Radek Krejci80c6b442017-01-04 16:21:13 +01001328 result[u]->substmt = orig[u]->substmt;
1329 result[u]->substmt_index = orig[u]->substmt_index;
Radek Krejcie534c132016-11-23 13:32:31 +01001330 } else {
1331 /* original extension is not yet resolved, so duplicate it in unres */
1332 i = unres_schema_find(unres, -1, orig, UNRES_EXT);
1333 if (i == -1) {
1334 /* extension not found in unres */
1335 LOGINT;
Radek Krejci43ce4b72017-01-04 11:02:38 +01001336 goto error;
Radek Krejcie534c132016-11-23 13:32:31 +01001337 }
1338 info_orig = unres->str_snode[i];
1339 info = malloc(sizeof *info);
1340 info->datatype = info_orig->datatype;
1341 if (info->datatype == LYS_IN_YIN) {
1342 info->data.yin = lyxml_dup_elem(mod->ctx, info_orig->data.yin, NULL, 1);
1343 } /* else TODO YANG */
Radek Krejci43ce4b72017-01-04 11:02:38 +01001344 info->parent = parent;
1345 info->parent_type = parent_type;
Radek Krejcie534c132016-11-23 13:32:31 +01001346 if (unres_schema_add_node(mod, unres, &result[u], UNRES_EXT, (struct lys_node *)info) == -1) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001347 goto error;
Radek Krejcie534c132016-11-23 13:32:31 +01001348 }
1349 }
1350 }
1351
1352 return result;
Radek Krejci43ce4b72017-01-04 11:02:38 +01001353
1354error:
1355 lys_extension_instances_free(mod->ctx, result, u);
1356 return NULL;
1357}
1358
1359API const void *
1360lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1361{
1362 if (!ext) {
1363 return NULL;
1364 }
1365
1366 switch (ext->substmt) {
1367 case LYEXT_SUBSTMT_SELF:
1368 case LYEXT_SUBSTMT_MODIFIER:
1369 case LYEXT_SUBSTMT_VERSION:
1370 return NULL;
1371 case LYEXT_SUBSTMT_ARGUMENT:
1372 if (ext->parent_type == LYEXT_PAR_EXT) {
1373 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1374 }
1375 break;
1376 case LYEXT_SUBSTMT_BASE:
1377 if (ext->parent_type == LYEXT_PAR_TYPE) {
1378 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->substmt_index];
1379 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
1380 return ((struct lys_ident*)ext->parent)->base[ext->substmt_index];
1381 }
1382 break;
1383 case LYEXT_SUBSTMT_BELONGSTO:
1384 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1385 return ((struct lys_submodule*)ext->parent)->belongsto;
1386 }
1387 break;
1388 case LYEXT_SUBSTMT_CONFIG:
1389 case LYEXT_SUBSTMT_MANDATORY:
1390 if (ext->parent_type == LYEXT_PAR_NODE) {
1391 return &((struct lys_node*)ext->parent)->flags;
1392 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1393 return &((struct lys_deviate*)ext->parent)->flags;
1394 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1395 return &((struct lys_refine*)ext->parent)->flags;
1396 }
1397 break;
1398 case LYEXT_SUBSTMT_CONTACT:
1399 if (ext->parent_type == LYEXT_PAR_MODULE) {
1400 return ((struct lys_module*)ext->parent)->contact;
1401 }
1402 break;
1403 case LYEXT_SUBSTMT_DEFAULT:
1404 if (ext->parent_type == LYEXT_PAR_NODE) {
1405 switch (((struct lys_node*)ext->parent)->nodetype) {
1406 case LYS_LEAF:
1407 case LYS_LEAFLIST:
1408 /* in case of leaf, the index is supposed to be 0, so it will return the
1409 * correct pointer despite the leaf structure does not have dflt as array */
1410 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->substmt_index];
1411 case LYS_CHOICE:
1412 return ((struct lys_node_choice*)ext->parent)->dflt;
1413 default:
1414 /* internal error */
1415 break;
1416 }
1417 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1418 return ((struct lys_tpdf*)ext->parent)->dflt;
1419 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1420 return ((struct lys_deviate*)ext->parent)->dflt[ext->substmt_index];
1421 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1422 return &((struct lys_refine*)ext->parent)->dflt[ext->substmt_index];
1423 }
1424 break;
1425 case LYEXT_SUBSTMT_DESCRIPTION:
1426 switch (ext->parent_type) {
1427 case LYEXT_PAR_NODE:
1428 return ((struct lys_node*)ext->parent)->dsc;
1429 case LYEXT_PAR_MODULE:
1430 return ((struct lys_module*)ext->parent)->dsc;
1431 case LYEXT_PAR_IMPORT:
1432 return ((struct lys_import*)ext->parent)->dsc;
1433 case LYEXT_PAR_INCLUDE:
1434 return ((struct lys_include*)ext->parent)->dsc;
1435 case LYEXT_PAR_EXT:
1436 return ((struct lys_ext*)ext->parent)->dsc;
1437 case LYEXT_PAR_FEATURE:
1438 return ((struct lys_feature*)ext->parent)->dsc;
1439 case LYEXT_PAR_TPDF:
1440 return ((struct lys_tpdf*)ext->parent)->dsc;
1441 case LYEXT_PAR_TYPE_BIT:
1442 return ((struct lys_type_bit*)ext->parent)->dsc;
1443 case LYEXT_PAR_TYPE_ENUM:
1444 return ((struct lys_type_enum*)ext->parent)->dsc;
1445 case LYEXT_PAR_MUST:
1446 case LYEXT_PAR_RANGE:
1447 case LYEXT_PAR_LENGTH:
1448 case LYEXT_PAR_PATTERN:
1449 return ((struct lys_restr*)ext->parent)->dsc;
1450 case LYEXT_PAR_WHEN:
1451 return ((struct lys_when*)ext->parent)->dsc;
1452 case LYEXT_PAR_IDENT:
1453 return ((struct lys_ident*)ext->parent)->dsc;
1454 case LYEXT_PAR_DEVIATION:
1455 return ((struct lys_deviation*)ext->parent)->dsc;
1456 case LYEXT_PAR_REVISION:
1457 return ((struct lys_revision*)ext->parent)->dsc;
1458 case LYEXT_PAR_REFINE:
1459 return ((struct lys_refine*)ext->parent)->dsc;
1460 default:
1461 break;
1462 }
1463 break;
1464 case LYEXT_SUBSTMT_ERRTAG:
1465 if (ext->parent_type == LYEXT_PAR_MUST || ext->parent_type == LYEXT_PAR_RANGE ||
1466 ext->parent_type == LYEXT_PAR_LENGTH || ext->parent_type == LYEXT_PAR_PATTERN) {
1467 return ((struct lys_restr*)ext->parent)->eapptag;
1468 }
1469 break;
1470 case LYEXT_SUBSTMT_ERRMSG:
1471 if (ext->parent_type == LYEXT_PAR_MUST || ext->parent_type == LYEXT_PAR_RANGE ||
1472 ext->parent_type == LYEXT_PAR_LENGTH || ext->parent_type == LYEXT_PAR_PATTERN) {
1473 return ((struct lys_restr*)ext->parent)->emsg;
1474 }
1475 break;
1476 case LYEXT_SUBSTMT_DIGITS:
1477 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
1478 return &((struct lys_type*)ext->parent)->info.dec64.dig;
1479 }
1480 break;
1481 case LYEXT_SUBSTMT_KEY:
1482 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1483 return ((struct lys_node_list*)ext->parent)->keys;
1484 }
1485 break;
1486 case LYEXT_SUBSTMT_MAX:
1487 if (ext->parent_type == LYEXT_PAR_NODE) {
1488 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1489 return &((struct lys_node_list*)ext->parent)->max;
1490 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1491 return &((struct lys_node_leaflist*)ext->parent)->max;
1492 }
1493 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1494 return &((struct lys_refine*)ext->parent)->mod.list.max;
1495 }
1496 break;
1497 case LYEXT_SUBSTMT_MIN:
1498 if (ext->parent_type == LYEXT_PAR_NODE) {
1499 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1500 return &((struct lys_node_list*)ext->parent)->min;
1501 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1502 return &((struct lys_node_leaflist*)ext->parent)->min;
1503 }
1504 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1505 return &((struct lys_refine*)ext->parent)->mod.list.min;
1506 }
1507 break;
1508 case LYEXT_SUBSTMT_NAMESPACE:
1509 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
1510 return ((struct lys_module*)ext->parent)->ns;
1511 }
1512 break;
1513 case LYEXT_SUBSTMT_ORDEREDBY:
1514 if (ext->parent_type == LYEXT_PAR_NODE &&
1515 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
1516 return &((struct lys_node_list*)ext->parent)->flags;
1517 }
1518 break;
1519 case LYEXT_SUBSTMT_ORGANIZATION:
1520 if (ext->parent_type == LYEXT_PAR_MODULE) {
1521 return ((struct lys_module*)ext->parent)->org;
1522 }
1523 break;
1524 case LYEXT_SUBSTMT_PATH:
1525 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1526 return ((struct lys_type*)ext->parent)->info.lref.path;
1527 }
1528 break;
1529 case LYEXT_SUBSTMT_POSITION:
1530 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
1531 return &((struct lys_type_bit*)ext->parent)->pos;
1532 }
1533 break;
1534 case LYEXT_SUBSTMT_PREFIX:
1535 if (ext->parent_type == LYEXT_PAR_MODULE) {
1536 /* covers also lys_submodule */
1537 return ((struct lys_module*)ext->parent)->prefix;
1538 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
1539 return ((struct lys_import*)ext->parent)->prefix;
1540 }
1541 break;
1542 case LYEXT_SUBSTMT_PRESENCE:
1543 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
1544 return ((struct lys_node_container*)ext->parent)->presence;
1545 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1546 return ((struct lys_refine*)ext->parent)->mod.presence;
1547 }
1548 break;
1549 case LYEXT_SUBSTMT_REFERENCE:
1550 switch (ext->parent_type) {
1551 case LYEXT_PAR_NODE:
1552 return ((struct lys_node*)ext->parent)->ref;
1553 case LYEXT_PAR_MODULE:
1554 return ((struct lys_module*)ext->parent)->ref;
1555 case LYEXT_PAR_IMPORT:
1556 return ((struct lys_import*)ext->parent)->ref;
1557 case LYEXT_PAR_INCLUDE:
1558 return ((struct lys_include*)ext->parent)->ref;
1559 case LYEXT_PAR_EXT:
1560 return ((struct lys_ext*)ext->parent)->ref;
1561 case LYEXT_PAR_FEATURE:
1562 return ((struct lys_feature*)ext->parent)->ref;
1563 case LYEXT_PAR_TPDF:
1564 return ((struct lys_tpdf*)ext->parent)->ref;
1565 case LYEXT_PAR_TYPE_BIT:
1566 return ((struct lys_type_bit*)ext->parent)->ref;
1567 case LYEXT_PAR_TYPE_ENUM:
1568 return ((struct lys_type_enum*)ext->parent)->ref;
1569 case LYEXT_PAR_MUST:
1570 case LYEXT_PAR_RANGE:
1571 case LYEXT_PAR_LENGTH:
1572 case LYEXT_PAR_PATTERN:
1573 return ((struct lys_restr*)ext->parent)->ref;
1574 case LYEXT_PAR_WHEN:
1575 return ((struct lys_when*)ext->parent)->ref;
1576 case LYEXT_PAR_IDENT:
1577 return ((struct lys_ident*)ext->parent)->ref;
1578 case LYEXT_PAR_DEVIATION:
1579 return ((struct lys_deviation*)ext->parent)->ref;
1580 case LYEXT_PAR_REVISION:
1581 return ((struct lys_revision*)ext->parent)->ref;
1582 case LYEXT_PAR_REFINE:
1583 return ((struct lys_refine*)ext->parent)->ref;
1584 default:
1585 break;
1586 }
1587 break;
1588 case LYEXT_SUBSTMT_REQINST:
1589 if (ext->parent_type == LYEXT_PAR_TYPE) {
1590 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1591 return &((struct lys_type*)ext->parent)->info.lref.req;
1592 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
1593 return &((struct lys_type*)ext->parent)->info.inst.req;
1594 }
1595 }
1596 break;
1597 case LYEXT_SUBSTMT_REVISIONDATE:
1598 if (ext->parent_type == LYEXT_PAR_IMPORT) {
1599 return ((struct lys_import*)ext->parent)->rev;
1600 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
1601 return ((struct lys_include*)ext->parent)->rev;
1602 }
1603 break;
1604 case LYEXT_SUBSTMT_STATUS:
1605 switch (ext->parent_type) {
1606 case LYEXT_PAR_NODE:
1607 case LYEXT_PAR_IDENT:
1608 case LYEXT_PAR_TPDF:
1609 case LYEXT_PAR_EXT:
1610 case LYEXT_PAR_FEATURE:
1611 case LYEXT_PAR_TYPE_ENUM:
1612 case LYEXT_PAR_TYPE_BIT:
1613 /* in all structures the flags member is at the same offset */
1614 return &((struct lys_node*)ext->parent)->flags;
1615 default:
1616 break;
1617 }
1618 break;
1619 case LYEXT_SUBSTMT_UNIQUE:
1620 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1621 return &((struct lys_deviate*)ext->parent)->unique[ext->substmt_index];
1622 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1623 return &((struct lys_node_list*)ext->parent)->unique[ext->substmt_index];
1624 }
1625 break;
1626 case LYEXT_SUBSTMT_UNITS:
1627 if (ext->parent_type == LYEXT_PAR_NODE &&
1628 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1629 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
1630 return ((struct lys_node_leaf*)ext->parent)->units;
1631 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1632 return ((struct lys_tpdf*)ext->parent)->units;
1633 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1634 return ((struct lys_deviate*)ext->parent)->units;
1635 }
1636 break;
1637 case LYEXT_SUBSTMT_VALUE:
1638 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
1639 return &((struct lys_type_enum*)ext->parent)->value;
1640 }
1641 break;
1642 case LYEXT_SUBSTMT_YINELEM:
1643 if (ext->parent_type == LYEXT_PAR_EXT) {
1644 return &((struct lys_ext*)ext->parent)->flags;
1645 }
1646 break;
1647 }
1648 LOGINT;
1649 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01001650}
1651
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001652static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001653lys_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 +02001654 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001655{
1656 int i;
1657
Michal Vasko1dca6882015-10-22 14:29:42 +02001658 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001659 new->base = old->base;
1660 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001661 new->parent = (struct lys_tpdf *)parent;
Radek Krejcie534c132016-11-23 13:32:31 +01001662 if (old->ext_size) {
1663 new->ext_size = old->ext_size;
Radek Krejci43ce4b72017-01-04 11:02:38 +01001664 new->ext = lys_ext_dup(mod, old->ext, old->ext_size, new->parent, LYEXT_PAR_TPDF, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001665 if (!new->ext) {
1666 return -1;
1667 }
1668 }
Radek Krejci3733a802015-06-19 13:43:21 +02001669
Michal Vasko878e38d2016-09-05 12:17:53 +02001670 i = unres_schema_find(unres, -1, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001671 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001672 /* HACK (serious one) for unres */
1673 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001674 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001675 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 +02001676 } else {
1677 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1678 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001679 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001680 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001681 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001682 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001683 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001684 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001685 }
1686
Radek Krejci3a5501d2016-07-18 22:03:34 +02001687 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001688}
1689
1690void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001691lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001692{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001693 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001695 assert(ctx);
1696 if (!type) {
1697 return;
1698 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001699
Michal Vasko1dca6882015-10-22 14:29:42 +02001700 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001701
Radek Krejcie534c132016-11-23 13:32:31 +01001702 lys_extension_instances_free(ctx, type->ext, type->ext_size);
1703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001704 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001705 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001706 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001707 free(type->info.binary.length);
1708 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001709 case LY_TYPE_BITS:
1710 for (i = 0; i < type->info.bits.count; i++) {
1711 lydict_remove(ctx, type->info.bits.bit[i].name);
1712 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1713 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001714 lys_iffeature_free(type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001715 }
1716 free(type->info.bits.bit);
1717 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001718
1719 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001720 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001721 free(type->info.dec64.range);
1722 break;
1723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001724 case LY_TYPE_ENUM:
1725 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001726 lydict_remove(ctx, type->info.enums.enm[i].name);
1727 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1728 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001729 lys_iffeature_free(type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001730 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001731 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001732 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001733
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001734 case LY_TYPE_INT8:
1735 case LY_TYPE_INT16:
1736 case LY_TYPE_INT32:
1737 case LY_TYPE_INT64:
1738 case LY_TYPE_UINT8:
1739 case LY_TYPE_UINT16:
1740 case LY_TYPE_UINT32:
1741 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001742 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001743 free(type->info.num.range);
1744 break;
1745
Radek Krejcidc4c1412015-06-19 15:39:54 +02001746 case LY_TYPE_LEAFREF:
1747 lydict_remove(ctx, type->info.lref.path);
1748 break;
1749
Radek Krejci3733a802015-06-19 13:43:21 +02001750 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001751 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001752 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001753 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001754 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001755 }
1756 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001757 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001758
Radek Krejcie4c366b2015-07-02 10:11:31 +02001759 case LY_TYPE_UNION:
1760 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001761 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001762 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001763 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001764 break;
1765
Michal Vaskod3282192016-09-05 11:27:57 +02001766 case LY_TYPE_IDENT:
1767 free(type->info.ident.ref);
1768 break;
1769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001770 default:
Michal Vaskod3282192016-09-05 11:27:57 +02001771 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001772 break;
1773 }
Radek Krejci5a065542015-05-22 15:02:07 +02001774}
1775
Radek Krejci1d82ef62015-08-07 14:44:40 +02001776static void
1777lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001778{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 assert(ctx);
1780 if (!tpdf) {
1781 return;
1782 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001784 lydict_remove(ctx, tpdf->name);
1785 lydict_remove(ctx, tpdf->dsc);
1786 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001787
Radek Krejci1d82ef62015-08-07 14:44:40 +02001788 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001789
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001790 lydict_remove(ctx, tpdf->units);
1791 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01001792
1793 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001794}
1795
Michal Vaskob84f88a2015-09-24 13:16:10 +02001796static struct lys_tpdf *
1797lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1798{
1799 struct lys_tpdf *result;
1800 int i, j;
1801
1802 if (!size) {
1803 return NULL;
1804 }
1805
1806 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001807 if (!result) {
1808 LOGMEM;
1809 return NULL;
1810 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001811 for (i = 0; i < size; i++) {
1812 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1813 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1814 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1815 result[i].flags = old[i].flags;
1816 result[i].module = old[i].module;
1817
Radek Krejci3a5501d2016-07-18 22:03:34 +02001818 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), 1, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001819 for (j = 0; j <= i; ++j) {
1820 lys_tpdf_free(mod->ctx, &result[j]);
1821 }
1822 free(result);
1823 return NULL;
1824 }
1825
1826 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1827 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1828 }
1829
1830 return result;
1831}
1832
Radek Krejci1d82ef62015-08-07 14:44:40 +02001833static struct lys_when *
1834lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001835{
Radek Krejci76512572015-08-04 09:47:08 +02001836 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001837
1838 if (!old) {
1839 return NULL;
1840 }
1841
1842 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001843 if (!new) {
1844 LOGMEM;
1845 return NULL;
1846 }
Radek Krejci00768f42015-06-18 17:04:04 +02001847 new->cond = lydict_insert(ctx, old->cond, 0);
1848 new->dsc = lydict_insert(ctx, old->dsc, 0);
1849 new->ref = lydict_insert(ctx, old->ref, 0);
1850
1851 return new;
1852}
1853
Michal Vasko0308dd62015-10-07 09:14:40 +02001854void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001855lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001856{
1857 if (!w) {
1858 return;
1859 }
1860
1861 lydict_remove(ctx, w->cond);
1862 lydict_remove(ctx, w->dsc);
1863 lydict_remove(ctx, w->ref);
1864
1865 free(w);
1866}
1867
Radek Krejcib7f5e412015-08-13 10:15:51 +02001868static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001869lys_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 +02001870{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001871 struct lys_node *next, *sub;
1872
Radek Krejcic071c542016-01-27 14:57:51 +01001873 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01001874 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001875 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001876 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001877 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001878 }
1879
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001880 lydict_remove(ctx, aug->target_name);
1881 lydict_remove(ctx, aug->dsc);
1882 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001883
Radek Krejci9ff0a922016-07-14 13:08:05 +02001884 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01001885 lys_extension_instances_free(ctx, aug->ext, aug->ext_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001886
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001887 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001888}
1889
Radek Krejci76512572015-08-04 09:47:08 +02001890static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001891lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001892{
Radek Krejci76512572015-08-04 09:47:08 +02001893 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001894 struct lys_node *old_child, *new_child;
1895 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001897 if (!size) {
1898 return NULL;
1899 }
Radek Krejci106efc02015-06-10 14:36:27 +02001900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001901 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001902 if (!new) {
1903 LOGMEM;
1904 return NULL;
1905 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001906 for (i = 0; i < size; i++) {
1907 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1908 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1909 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1910 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001911 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001912 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001913
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001914 /* this must succeed, it was already resolved once */
Radek Krejcidf46e222016-11-08 11:57:37 +01001915 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL, 1,
Michal Vasko3edeaf72016-02-11 13:17:43 +01001916 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001917 LOGINT;
1918 free(new);
1919 return NULL;
1920 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001921 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001922
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001923 /* Correct the augment nodes.
1924 * This function can only be called from lys_node_dup() with uses
1925 * being the node duplicated, so we must have a case of grouping
1926 * with a uses with augments. The augmented nodes have already been
1927 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001928 * (it was set to their actual data parent, not an augment), and
1929 * the new augment does not have child pointer to its augment nodes,
1930 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001931 */
1932 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001933 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001934 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001935 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001936 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001937 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001938 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001939 LY_TREE_FOR(old[i].child, old_child) {
1940 /* all augment nodes were connected as siblings, there can be no more after this */
1941 if (old_child->parent != (struct lys_node *)&old[i]) {
1942 break;
1943 }
1944
Radek Krejci749190d2016-02-18 16:26:25 +01001945 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001946
1947 new_child->parent = (struct lys_node *)&new[i];
1948 new_child = new_child->next;
1949 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001950 }
Radek Krejci106efc02015-06-10 14:36:27 +02001951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001952 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001953}
1954
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001955static const char **
1956lys_dflt_dup(struct ly_ctx *ctx, const char **old, int size)
1957{
1958 int i;
1959 const char **result;
1960
1961 if (!size) {
1962 return NULL;
1963 }
1964
1965 result = calloc(size, sizeof *result);
1966 if (!result) {
1967 LOGMEM;
1968 return NULL;
1969 }
1970
1971 for (i = 0; i < size; i++) {
1972 result[i] = lydict_insert(ctx, old[i], 0);
1973 }
1974 return result;
1975}
1976
Radek Krejci76512572015-08-04 09:47:08 +02001977static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001978lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001979{
Radek Krejci76512572015-08-04 09:47:08 +02001980 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001981 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001983 if (!size) {
1984 return NULL;
1985 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001987 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001988 if (!result) {
1989 LOGMEM;
1990 return NULL;
1991 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001992 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001993 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001994 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1995 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001996 result[i].flags = old[i].flags;
1997 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001999 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002001
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002002 result[i].dflt_size = old[i].dflt_size;
2003 result[i].dflt = lys_dflt_dup(mod->ctx, old[i].dflt, old[i].dflt_size);
2004
2005 if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02002007 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002008 result[i].mod.list = old[i].mod.list;
2009 }
2010 }
Michal Vasko1982cad2015-06-08 15:49:30 +02002011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002012 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02002013}
2014
Radek Krejci1d82ef62015-08-07 14:44:40 +02002015static void
2016lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02002017{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 assert(ctx);
2019 if (!ident) {
2020 return;
2021 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002022
Radek Krejci018f1f52016-08-03 16:01:20 +02002023 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02002024 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002025 lydict_remove(ctx, ident->name);
2026 lydict_remove(ctx, ident->dsc);
2027 lydict_remove(ctx, ident->ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02002028 lys_iffeature_free(ident->iffeature, ident->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01002029 lys_extension_instances_free(ctx, ident->ext, ident->ext_size);
Radek Krejci6793db02015-05-22 17:49:54 +02002030
2031}
2032
Radek Krejci1d82ef62015-08-07 14:44:40 +02002033static void
2034lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002035{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002037
Radek Krejcid12f57b2015-08-06 10:43:39 +02002038 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002040 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 }
2042 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002043}
2044
Radek Krejci1d82ef62015-08-07 14:44:40 +02002045static void
Michal Vasko44fb6382016-06-29 11:12:27 +02002046lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02002047{
2048 int i;
2049
2050 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
2051 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002052 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002053 }
2054 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002055
2056 for (i = 0; i < io->must_size; i++) {
2057 lys_restr_free(ctx, &io->must[i]);
2058 }
2059 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002060}
2061
Radek Krejci1d82ef62015-08-07 14:44:40 +02002062static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02002063lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
2064{
2065 int i;
2066
2067 for (i = 0; i < notif->must_size; i++) {
2068 lys_restr_free(ctx, &notif->must[i]);
2069 }
2070 free(notif->must);
2071
2072 for (i = 0; i < notif->tpdf_size; i++) {
2073 lys_tpdf_free(ctx, &notif->tpdf[i]);
2074 }
2075 free(notif->tpdf);
2076}
2077static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02002078lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02002079{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002080 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002083 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002084 }
2085 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002086
Radek Krejci1d82ef62015-08-07 14:44:40 +02002087 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002088}
2089
Radek Krejci1d82ef62015-08-07 14:44:40 +02002090static void
2091lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02002092{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002094
Radek Krejci85a54be2016-10-20 12:39:56 +02002095 /* leafref backlinks */
2096 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002099 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 }
2101 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002102
Radek Krejci1d82ef62015-08-07 14:44:40 +02002103 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002104
Radek Krejci1d82ef62015-08-07 14:44:40 +02002105 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 lydict_remove(ctx, leaf->units);
2107 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002108}
2109
Radek Krejci1d82ef62015-08-07 14:44:40 +02002110static void
2111lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02002112{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002114
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002115 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002116 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002117 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002118 }
2119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002121 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 }
2123 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002124
Pavol Vican38321d02016-08-16 14:56:02 +02002125 for (i = 0; i < llist->dflt_size; i++) {
2126 lydict_remove(ctx, llist->dflt[i]);
2127 }
2128 free(llist->dflt);
2129
Radek Krejci1d82ef62015-08-07 14:44:40 +02002130 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002131
Radek Krejci1d82ef62015-08-07 14:44:40 +02002132 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002134}
2135
Radek Krejci1d82ef62015-08-07 14:44:40 +02002136static void
2137lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002138{
Radek Krejci581ce772015-11-10 17:22:40 +01002139 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 /* handle only specific parts for LY_NODE_LIST */
2142 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002143 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 }
2145 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002148 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 }
2150 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002151
Radek Krejci1d82ef62015-08-07 14:44:40 +02002152 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002155 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002156 lydict_remove(ctx, list->unique[i].expr[j]);
2157 }
2158 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 }
2160 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002163}
2164
Radek Krejci1d82ef62015-08-07 14:44:40 +02002165static void
2166lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002167{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 /* handle only specific parts for LY_NODE_CONTAINER */
2171 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002174 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175 }
2176 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002179 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 }
2181 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002182
Radek Krejci1d82ef62015-08-07 14:44:40 +02002183 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002184}
2185
Radek Krejci1d82ef62015-08-07 14:44:40 +02002186static void
2187lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02002188{
2189 lydict_remove(ctx, f->name);
2190 lydict_remove(ctx, f->dsc);
2191 lydict_remove(ctx, f->ref);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002192 lys_iffeature_free(f->iffeature, f->iffeature_size);
Radek Krejci9de2c042016-10-19 16:53:06 +02002193 ly_set_free(f->depfeatures);
Radek Krejcie534c132016-11-23 13:32:31 +01002194 lys_extension_instances_free(ctx, f->ext, f->ext_size);
2195}
2196
2197static void
2198lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e)
2199{
2200 lydict_remove(ctx, e->name);
2201 lydict_remove(ctx, e->dsc);
2202 lydict_remove(ctx, e->ref);
2203 lydict_remove(ctx, e->argument);
2204 lys_extension_instances_free(ctx, e->ext, e->ext_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002205}
2206
Radek Krejci1d82ef62015-08-07 14:44:40 +02002207static void
Michal Vaskoff006c12016-02-17 11:15:19 +01002208lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02002209{
Radek Krejci581ce772015-11-10 17:22:40 +01002210 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002211 struct ly_ctx *ctx;
2212 struct lys_node *next, *elem;
2213
2214 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002215
2216 lydict_remove(ctx, dev->target_name);
2217 lydict_remove(ctx, dev->dsc);
2218 lydict_remove(ctx, dev->ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002219 lys_extension_instances_free(ctx, dev->ext, dev->ext_size);
Radek Krejcieb00f512015-07-01 16:44:58 +02002220
Pavol Vican64d0b762016-08-25 10:44:59 +02002221 if (!dev->deviate) {
2222 return ;
2223 }
2224
Michal Vaskoff006c12016-02-17 11:15:19 +01002225 /* the module was freed, but we only need the context from orig_node, use ours */
2226 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2227 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2228 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2229 elem->module = module;
2230
2231 LY_TREE_DFS_END(dev->orig_node, next, elem);
2232 }
2233 lys_node_free(dev->orig_node, NULL, 0);
2234 } else {
2235 /* it's just a shallow copy, freeing one node */
2236 dev->orig_node->module = module;
2237 lys_node_free(dev->orig_node, NULL, 1);
2238 }
2239
Radek Krejcieb00f512015-07-01 16:44:58 +02002240 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002241 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002242 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002243 }
2244 free(dev->deviate[i].dflt);
2245
Radek Krejcieb00f512015-07-01 16:44:58 +02002246 lydict_remove(ctx, dev->deviate[i].units);
2247
2248 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2249 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002250 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002251 }
2252 free(dev->deviate[i].must);
2253
2254 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002255 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2256 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2257 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002258 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002259 }
2260 free(dev->deviate[i].unique);
2261 }
2262 }
2263 free(dev->deviate);
2264}
2265
Radek Krejci1d82ef62015-08-07 14:44:40 +02002266static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002267lys_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 +02002268{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002272 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 lydict_remove(ctx, uses->refine[i].dsc);
2274 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002275
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002276 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002277 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 }
2279 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002280
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002281 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002282 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002283 }
2284 free(uses->refine[i].dflt);
2285
Radek Krejcie534c132016-11-23 13:32:31 +01002286 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size);
2287
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002288 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289 lydict_remove(ctx, uses->refine[i].mod.presence);
2290 }
2291 }
2292 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002295 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 }
2297 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002298
Radek Krejci1d82ef62015-08-07 14:44:40 +02002299 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002300}
2301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002303lys_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 +02002304{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002306 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 if (!node) {
2309 return;
2310 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002312 assert(node->module);
2313 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002315 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002316
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002317 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002318 if (node->priv && private_destructor) {
2319 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002320 }
2321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002323 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002324 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002325 lys_iffeature_free(node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002326 lydict_remove(ctx, node->dsc);
2327 lydict_remove(ctx, node->ref);
2328 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002329
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002330 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002331 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002332 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002333 }
2334 }
2335
Radek Krejcie534c132016-11-23 13:32:31 +01002336 lys_extension_instances_free(ctx, node->ext, node->ext_size);
2337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 /* specific part */
2339 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002340 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002341 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 break;
Radek Krejci76512572015-08-04 09:47:08 +02002343 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002344 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002345 break;
Radek Krejci76512572015-08-04 09:47:08 +02002346 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002347 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002348 break;
Radek Krejci76512572015-08-04 09:47:08 +02002349 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002350 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 break;
Radek Krejci76512572015-08-04 09:47:08 +02002352 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002353 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354 break;
Radek Krejci76512572015-08-04 09:47:08 +02002355 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002356 case LYS_ANYDATA:
2357 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002358 break;
Radek Krejci76512572015-08-04 09:47:08 +02002359 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002360 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002361 break;
Radek Krejci76512572015-08-04 09:47:08 +02002362 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002363 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002364 break;
Radek Krejci76512572015-08-04 09:47:08 +02002365 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002366 /* do nothing */
2367 break;
Radek Krejci76512572015-08-04 09:47:08 +02002368 case LYS_GROUPING:
2369 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002370 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002371 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002372 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002373 case LYS_NOTIF:
2374 lys_notif_free(ctx, (struct lys_node_notif *)node);
2375 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002376 case LYS_INPUT:
2377 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02002378 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002379 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02002380 case LYS_UNKNOWN:
2381 LOGINT;
2382 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 }
Radek Krejci5a065542015-05-22 15:02:07 +02002384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002385 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002386 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002387 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002388}
2389
Radek Krejci2eee5c02016-12-06 19:18:05 +01002390API struct lys_module *
2391lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002392{
2393 struct ly_ctx *ctx;
2394 int i;
2395
2396 if (!mod || mod->implemented) {
2397 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002398 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002399 }
2400
2401 ctx = mod->ctx;
2402 for (i = 0; i < ctx->models.used; i++) {
2403 if (!ctx->models.list[i]->implemented) {
2404 continue;
2405 }
2406
2407 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2408 /* we have some revision of the module implemented */
2409 return ctx->models.list[i];
2410 }
2411 }
2412
2413 /* we have no revision of the module implemented, return the module itself,
2414 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002415 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002416}
2417
2418const struct lys_module *
Radek Krejcie534c132016-11-23 13:32:31 +01002419lys_get_import_module_ns(const struct lys_module *module, const char *ns)
2420{
2421 int i;
2422
2423 assert(module && ns);
2424
2425 module = lys_main_module(module);
2426
2427 /* modul's own namespace */
2428 if (ly_strequal(module->ns, ns, 0)) {
2429 return module;
2430 }
2431
2432 /* imported modules */
2433 for (i = 0; i < module->imp_size; ++i) {
2434 if (ly_strequal(module->imp[i].module->ns, ns, 0)) {
2435 return module->imp[i].module;
2436 }
2437 }
2438
2439 return NULL;
2440}
2441
2442const struct lys_module *
Michal Vasko1e62a092015-12-01 12:27:20 +01002443lys_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 +02002444{
Radek Krejcic071c542016-01-27 14:57:51 +01002445 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02002446 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002447 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002448
Michal Vaskoa7789a82016-02-11 15:42:55 +01002449 assert(!prefix || !name);
2450
Michal Vaskob6729c62015-10-21 12:09:47 +02002451 if (prefix && !pref_len) {
2452 pref_len = strlen(prefix);
2453 }
2454 if (name && !name_len) {
2455 name_len = strlen(name);
2456 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002457
Radek Krejcic4283442016-04-22 09:19:27 +02002458 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002459
2460 /* module own prefix, submodule own prefix, (sub)module own name */
2461 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2462 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002463 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002464 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002465 }
2466
Michal Vasko89563fc2016-07-28 16:19:35 +02002467 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02002468 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002469 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2470 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002471 return module->imp[i].module;
2472 }
2473 }
2474
Michal Vasko89563fc2016-07-28 16:19:35 +02002475 /* module required by a foreign grouping, deviation, or submodule */
2476 if (name) {
2477 str = strndup(name, name_len);
2478 if (!str) {
2479 LOGMEM;
2480 return NULL;
2481 }
2482 main_module = ly_ctx_get_module(module->ctx, str, NULL);
2483 free(str);
2484 return main_module;
2485 }
2486
Michal Vasko8ce24d72015-10-21 11:27:26 +02002487 return NULL;
2488}
2489
Michal Vasko13b15832015-08-19 11:04:48 +02002490/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002492module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002493{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002495 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002498 assert(module->ctx);
2499 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002500
Michal Vaskob746fff2016-02-11 11:37:50 +01002501 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002502 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002503 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002504 lydict_remove(ctx, module->imp[i].dsc);
2505 lydict_remove(ctx, module->imp[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002506 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size);
Radek Krejci225376f2016-02-16 17:36:22 +01002507 }
Radek Krejcidce51452015-06-16 15:20:08 +02002508 free(module->imp);
2509
Radek Krejcic071c542016-01-27 14:57:51 +01002510 /* submodules don't have data tree, the data nodes
2511 * are placed in the main module altogether */
2512 if (!module->type) {
2513 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002514 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002515 }
Radek Krejci21181962015-06-30 14:11:00 +02002516 }
Radek Krejci5a065542015-05-22 15:02:07 +02002517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002518 lydict_remove(ctx, module->dsc);
2519 lydict_remove(ctx, module->ref);
2520 lydict_remove(ctx, module->org);
2521 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002522 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002523
Radek Krejcieb00f512015-07-01 16:44:58 +02002524 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002525 for (i = 0; i < module->rev_size; i++) {
2526 lydict_remove(ctx, module->rev[i].dsc);
2527 lydict_remove(ctx, module->rev[i].ref);
2528 }
2529 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002530
Radek Krejcieb00f512015-07-01 16:44:58 +02002531 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002532 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002533 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002534 }
2535 module->ident_size = 0;
2536 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002537
Radek Krejcieb00f512015-07-01 16:44:58 +02002538 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002539 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002540 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 }
2542 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002543
Radek Krejcie534c132016-11-23 13:32:31 +01002544 /* extension instances */
2545 lys_extension_instances_free(ctx, module->ext, module->ext_size);
2546
Radek Krejcieb00f512015-07-01 16:44:58 +02002547 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002548 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002549 lydict_remove(ctx, module->inc[i].dsc);
2550 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002551 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size);
Radek Krejcic071c542016-01-27 14:57:51 +01002552 /* complete submodule free is done only from main module since
2553 * submodules propagate their includes to the main module */
2554 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002555 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002556 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002557 }
2558 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002559
Radek Krejcieb00f512015-07-01 16:44:58 +02002560 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002561 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002562 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002563 }
2564 free(module->augment);
2565
Radek Krejcieb00f512015-07-01 16:44:58 +02002566 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002567 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002568 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002569 }
2570 free(module->features);
2571
Radek Krejcieb00f512015-07-01 16:44:58 +02002572 /* deviations */
2573 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002574 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002575 }
2576 free(module->deviation);
2577
Radek Krejcie534c132016-11-23 13:32:31 +01002578 /* extensions */
2579 for (i = 0; i < module->extensions_size; i++) {
2580 lys_extension_free(ctx, &module->extensions[i]);
2581 }
2582 free(module->extensions);
2583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002584 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002585 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002586}
2587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002588void
Michal Vaskob746fff2016-02-11 11:37:50 +01002589lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002590{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002591 if (!submodule) {
2592 return;
2593 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002595 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002596 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002598 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002601}
2602
Radek Krejci3a5501d2016-07-18 22:03:34 +02002603static int
2604ingrouping(const struct lys_node *node)
2605{
2606 const struct lys_node *iter = node;
2607 assert(node);
2608
2609 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2610 if (!iter) {
2611 return 0;
2612 } else {
2613 return 1;
2614 }
2615}
2616
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002617/*
2618 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2619 */
2620static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002621lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002622 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002623{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002624 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002625 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002626 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002627 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002628 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002629 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002630
Michal Vaskoc07187d2015-08-13 15:20:57 +02002631 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002632 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002633 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002634 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002635 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002636 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002637 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002638 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002639 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002640 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002641 struct lys_node_anydata *any = NULL;
2642 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002643 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002644 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002645 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002646 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002647 struct lys_node_rpc_action *rpc = NULL;
2648 struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
2649 struct lys_node_inout *io = NULL;
2650 struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
2651 struct lys_node_rpc_action *ntf = NULL;
2652 struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002653 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002654 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002656 /* we cannot just duplicate memory since the strings are stored in
2657 * dictionary and we need to update dictionary counters.
2658 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002659
Radek Krejci1d82ef62015-08-07 14:44:40 +02002660 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002661 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002662 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002663 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002664 break;
2665
Radek Krejci76512572015-08-04 09:47:08 +02002666 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002667 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002668 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002669 break;
2670
Radek Krejci76512572015-08-04 09:47:08 +02002671 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002672 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002673 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002674 break;
2675
Radek Krejci76512572015-08-04 09:47:08 +02002676 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002677 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002678 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002679 break;
2680
Radek Krejci76512572015-08-04 09:47:08 +02002681 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002682 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002683 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002684 break;
2685
Radek Krejci76512572015-08-04 09:47:08 +02002686 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002687 case LYS_ANYDATA:
2688 any = calloc(1, sizeof *any);
2689 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002690 break;
2691
Radek Krejci76512572015-08-04 09:47:08 +02002692 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002693 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002694 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002695 break;
2696
Radek Krejci76512572015-08-04 09:47:08 +02002697 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002698 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002699 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002700 break;
2701
Radek Krejci76512572015-08-04 09:47:08 +02002702 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002703 grp = calloc(1, sizeof *grp);
2704 retval = (struct lys_node *)grp;
2705 break;
2706
Radek Krejci76512572015-08-04 09:47:08 +02002707 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002708 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002709 rpc = calloc(1, sizeof *rpc);
2710 retval = (struct lys_node *)rpc;
2711 break;
2712
Radek Krejci76512572015-08-04 09:47:08 +02002713 case LYS_INPUT:
2714 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002715 io = calloc(1, sizeof *io);
2716 retval = (struct lys_node *)io;
2717 break;
2718
Radek Krejci76512572015-08-04 09:47:08 +02002719 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002720 ntf = calloc(1, sizeof *ntf);
2721 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002722 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002724 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002725 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002726 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 }
Radek Krejcib388c152015-06-04 17:03:03 +02002728
Michal Vasko253035f2015-12-17 16:58:13 +01002729 if (!retval) {
2730 LOGMEM;
2731 return NULL;
2732 }
2733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002734 /*
2735 * duplicate generic part of the structure
2736 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002737 retval->name = lydict_insert(ctx, node->name, 0);
2738 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2739 retval->ref = lydict_insert(ctx, node->ref, 0);
2740 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002742 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002743 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002746
Radek Krejci06214042016-11-04 16:25:58 +01002747 if (node->iffeature_size) {
2748 retval->iffeature_size = node->iffeature_size;
2749 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2750 if (!retval->iffeature) {
2751 LOGMEM;
2752 goto error;
2753 }
Michal Vasko253035f2015-12-17 16:58:13 +01002754 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002755
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002756 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002757 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002758 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2759 if (size1) {
2760 /* there is something to duplicate */
2761
2762 /* duplicate compiled expression */
2763 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2764 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2765 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2766
2767 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002768 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002769 for (j = 0; (unsigned int)j < size2; j++) {
2770 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2771 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002772 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002773 /* feature is resolved in origin, so copy it
2774 * - duplication is used for instantiating groupings
2775 * and if-feature inside grouping is supposed to be
2776 * resolved inside the original grouping, so we want
2777 * to keep pointers to features from the grouping
2778 * context */
2779 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2780 } else if (rc == -1) {
2781 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002782 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002783 }
2784 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002786
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002787 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01002788 p = parent;
2789 do {
2790 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
2791 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002792 if (iter) {
2793 flags = iter->flags & LYS_CONFIG_MASK;
2794 } else {
2795 /* default */
2796 flags = LYS_CONFIG_W;
2797 }
2798
2799 switch (finalize) {
2800 case 1:
2801 /* inherit config flags */
2802 if (retval->flags & LYS_CONFIG_SET) {
2803 /* skip nodes with an explicit config value */
2804 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
2805 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
2806 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "State nodes cannot have configuration nodes as children.");
2807 goto error;
2808 }
2809 break;
2810 }
2811
2812 if (retval->nodetype != LYS_USES) {
2813 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
2814 }
2815 break;
2816 case 2:
2817 /* erase config flags */
2818 retval->flags &= ~LYS_CONFIG_MASK;
2819 retval->flags &= ~LYS_CONFIG_SET;
2820 break;
2821 }
2822
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002823 /* connect it to the parent */
2824 if (lys_node_addchild(parent, retval->module, retval)) {
2825 goto error;
2826 }
Radek Krejcidce51452015-06-16 15:20:08 +02002827
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002828 /* go recursively */
2829 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002830 LY_TREE_FOR(node->child, iter) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01002831 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002832 goto error;
2833 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002834 }
2835 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002836
2837 if (finalize == 1) {
2838 /* check that configuration lists have keys
2839 * - we really want to check keys_size in original node, because the keys are
2840 * not yet resolved here, it is done below in nodetype specific part */
2841 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
2842 && !((struct lys_node_list *)node)->keys_size) {
2843 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
2844 goto error;
2845 }
2846 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002847 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002848 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 }
2850
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002851 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002852 * duplicate specific part of the structure
2853 */
2854 switch (node->nodetype) {
2855 case LYS_CONTAINER:
2856 if (cont_orig->when) {
2857 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002858 }
2859 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002861 cont->must_size = cont_orig->must_size;
2862 cont->tpdf_size = cont_orig->tpdf_size;
2863
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002864 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002865 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002866 break;
2867
2868 case LYS_CHOICE:
2869 if (choice_orig->when) {
2870 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002871 }
2872
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002873 if (!shallow) {
2874 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002875 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2876 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2877 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002878 if (rc) {
2879 if (rc == EXIT_FAILURE) {
2880 LOGINT;
2881 }
2882 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002883 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002884 } else {
2885 /* useless to check return value, we don't know whether
2886 * there really wasn't any default defined or it just hasn't
2887 * been resolved, we just hope for the best :)
2888 */
2889 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002890 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002891 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002892 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002893 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002894 break;
2895
2896 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002897 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002898 goto error;
2899 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002900 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2901
2902 if (leaf_orig->dflt) {
2903 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci51673202016-11-01 17:00:32 +01002904 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
2905 (struct lys_node *)(&leaf->dflt)) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002906 goto error;
2907 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002908 }
2909
2910 leaf->must_size = leaf_orig->must_size;
2911 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002912
2913 if (leaf_orig->when) {
2914 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 }
2916 break;
2917
2918 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002919 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002920 goto error;
2921 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002922 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2923
2924 llist->min = llist_orig->min;
2925 llist->max = llist_orig->max;
2926
2927 llist->must_size = llist_orig->must_size;
2928 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929
Radek Krejci51673202016-11-01 17:00:32 +01002930 llist->dflt_size = llist_orig->dflt_size;
2931 llist->dflt = malloc(llist->dflt_size * sizeof *llist->dflt);
2932 for (i = 0; i < llist->dflt_size; i++) {
2933 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
2934 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2935 (struct lys_node *)(&llist->dflt[i])) == -1) {
2936 goto error;
2937 }
2938 }
2939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002940 if (llist_orig->when) {
2941 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002942 }
2943 break;
2944
2945 case LYS_LIST:
2946 list->min = list_orig->min;
2947 list->max = list_orig->max;
2948
2949 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002950 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002951
Radek Krejci581ce772015-11-10 17:22:40 +01002952 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002953 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002954
Radek Krejci581ce772015-11-10 17:22:40 +01002955 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002956 if (list->keys_size) {
2957 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejci5c08a992016-11-02 13:30:04 +01002958 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Michal Vasko253035f2015-12-17 16:58:13 +01002959 if (!list->keys) {
2960 LOGMEM;
2961 goto error;
2962 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002963
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002964 if (!shallow) {
Radek Krejci5c08a992016-11-02 13:30:04 +01002965 /* the keys are going to be resolved only if the list is instantiated in data tree, not just
2966 * in another grouping */
2967 for (iter = parent; iter && iter->nodetype != LYS_GROUPING; iter = iter->parent);
2968 if (!iter && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
2969 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02002970 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002971 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002972 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002973 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002974 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002975
Radek Krejci581ce772015-11-10 17:22:40 +01002976 list->unique_size = list_orig->unique_size;
2977 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002978 if (!list->unique) {
2979 LOGMEM;
2980 goto error;
2981 }
Radek Krejci581ce772015-11-10 17:22:40 +01002982 for (i = 0; i < list->unique_size; ++i) {
2983 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2984 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002985 if (!list->unique[i].expr) {
2986 LOGMEM;
2987 goto error;
2988 }
Radek Krejci581ce772015-11-10 17:22:40 +01002989 for (j = 0; j < list->unique[i].expr_size; j++) {
2990 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2991
2992 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02002993 unique_info = malloc(sizeof *unique_info);
2994 unique_info->list = (struct lys_node *)list;
2995 unique_info->expr = list->unique[i].expr[j];
2996 unique_info->trg_type = &list->unique[i].trg_type;
2997 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002998 }
2999 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003001 if (list_orig->when) {
3002 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02003003 }
Radek Krejcidce51452015-06-16 15:20:08 +02003004 break;
3005
3006 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003007 case LYS_ANYDATA:
3008 any->must_size = any_orig->must_size;
3009 any->must = lys_restr_dup(ctx, any_orig->must, any->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003010
Radek Krejcibf2abff2016-08-23 15:51:52 +02003011 if (any_orig->when) {
3012 any->when = lys_when_dup(ctx, any_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003013 }
3014 break;
3015
3016 case LYS_USES:
3017 uses->grp = uses_orig->grp;
3018
3019 if (uses_orig->when) {
3020 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003021 }
3022
3023 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02003024 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003025 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003026 if (!shallow) {
3027 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Radek Krejci6ff885d2017-01-03 14:06:22 +01003028#if __BYTE_ORDER == __LITTLE_ENDIAN
3029 if (!uses->grp || ((uint8_t*)&uses->grp->flags)[1]) {
3030#else
3031 if (!uses->grp || ((uint8_t*)&uses->grp->flags)[0]) {
3032#endif
Michal Vaskocda51712016-05-19 15:22:11 +02003033 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01003034 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003035 goto error;
3036 }
Michal Vasko49168a22015-08-17 16:35:41 +02003037 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003038 } else {
3039 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003040 }
3041 break;
3042
Radek Krejcidce51452015-06-16 15:20:08 +02003043 case LYS_CASE:
3044 if (cs_orig->when) {
3045 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02003046 }
3047 break;
3048
3049 case LYS_GROUPING:
3050 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02003051 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02003052 break;
3053
Radek Krejci96935402016-11-04 16:27:28 +01003054 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02003055 case LYS_RPC:
3056 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02003057 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02003058 break;
3059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 case LYS_INPUT:
3061 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02003062 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02003063 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 break;
3065
Radek Krejcida04f4a2015-05-21 12:54:09 +02003066 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003067 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02003068 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003069 break;
3070
Radek Krejci96935402016-11-04 16:27:28 +01003071
Radek Krejcida04f4a2015-05-21 12:54:09 +02003072 default:
3073 /* LY_NODE_AUGMENT */
3074 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02003075 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003076 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003077
3078 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02003079
3080error:
3081
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003082 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02003083 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003084}
3085
Radek Krejcib3142312016-11-09 11:04:12 +01003086int
3087lys_has_xpath(const struct lys_node *node)
3088{
3089 assert(node);
3090
3091 switch (node->nodetype) {
3092 case LYS_AUGMENT:
3093 if (((struct lys_node_augment *)node)->when) {
3094 return 1;
3095 }
3096 break;
3097 case LYS_CASE:
3098 if (((struct lys_node_case *)node)->when) {
3099 return 1;
3100 }
3101 break;
3102 case LYS_CHOICE:
3103 if (((struct lys_node_choice *)node)->when) {
3104 return 1;
3105 }
3106 break;
3107 case LYS_ANYDATA:
3108 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3109 return 1;
3110 }
3111 break;
3112 case LYS_LEAF:
3113 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3114 return 1;
3115 }
3116 break;
3117 case LYS_LEAFLIST:
3118 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3119 return 1;
3120 }
3121 break;
3122 case LYS_LIST:
3123 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3124 return 1;
3125 }
3126 break;
3127 case LYS_CONTAINER:
3128 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3129 return 1;
3130 }
3131 break;
3132 case LYS_INPUT:
3133 case LYS_OUTPUT:
3134 if (((struct lys_node_inout *)node)->must_size) {
3135 return 1;
3136 }
3137 break;
3138 case LYS_NOTIF:
3139 if (((struct lys_node_notif *)node)->must_size) {
3140 return 1;
3141 }
3142 break;
3143 case LYS_USES:
3144 if (((struct lys_node_uses *)node)->when) {
3145 return 1;
3146 }
3147 break;
3148 default:
3149 /* does not have XPath */
3150 break;
3151 }
3152
3153 return 0;
3154}
3155
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003156struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003157lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003158 struct unres_schema *unres, int shallow)
3159{
3160 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003161 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003162 struct lys_node *result, *iter, *next;
3163
3164 if (!shallow) {
3165 /* get know where in schema tre we are to know what should be done during instantiation of the grouping */
3166 for (p = parent;
3167 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3168 p = lys_parent(p));
3169 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3170 }
3171
Radek Krejci6ff885d2017-01-03 14:06:22 +01003172 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003173 if (finalize) {
3174 /* check xpath expressions in the instantiated tree */
3175 for (iter = next = parent->child; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003176 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003177 /* invalid xpath */
3178 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003179 }
3180
3181 /* select next item */
3182 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3183 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3184 next = NULL;
3185 } else {
3186 next = iter->child;
3187 }
3188 if (!next) {
3189 /* no children, try siblings */
3190 next = iter->next;
3191 }
3192 while (!next) {
3193 /* parent is already processed, go to its sibling */
3194 iter = lys_parent(iter);
3195 if (iter == parent) {
3196 /* we are done, no next element to process */
3197 break;
3198 }
3199 next = iter->next;
3200 }
3201 }
3202 }
3203
3204 return result;
3205}
3206
Michal Vasko13b15832015-08-19 11:04:48 +02003207void
Michal Vaskoff006c12016-02-17 11:15:19 +01003208lys_node_switch(struct lys_node *dst, struct lys_node *src)
3209{
3210 struct lys_node *child;
3211
Michal Vaskob42b6972016-06-06 14:21:30 +02003212 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003213
3214 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02003215 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01003216 dst->prev->next = src;
3217 }
3218
3219 /* sibling prev */
3220 if (dst->next) {
3221 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02003222 } else {
3223 for (child = dst->prev; child->prev->next; child = child->prev);
3224 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003225 }
3226
3227 /* next */
3228 src->next = dst->next;
3229 dst->next = NULL;
3230
3231 /* prev */
3232 if (dst->prev != dst) {
3233 src->prev = dst->prev;
3234 }
3235 dst->prev = dst;
3236
3237 /* parent child */
3238 if (dst->parent && (dst->parent->child == dst)) {
3239 dst->parent->child = src;
3240 }
3241
3242 /* parent */
3243 src->parent = dst->parent;
3244 dst->parent = NULL;
3245
3246 /* child parent */
3247 LY_TREE_FOR(dst->child, child) {
3248 if (child->parent == dst) {
3249 child->parent = src;
3250 }
3251 }
3252
3253 /* child */
3254 src->child = dst->child;
3255 dst->child = NULL;
3256}
3257
3258void
Michal Vasko627975a2016-02-11 11:39:03 +01003259lys_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 +02003260{
3261 struct ly_ctx *ctx;
3262 int i;
3263
3264 if (!module) {
3265 return;
3266 }
3267
3268 /* remove schema from the context */
3269 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003270 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003271 for (i = 0; i < ctx->models.used; i++) {
3272 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003273 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003274 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003275 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 +02003276 ctx->models.list[ctx->models.used] = NULL;
3277 /* we are done */
3278 break;
3279 }
3280 }
3281 }
3282
3283 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003284 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003285
3286 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003287 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003288
3289 free(module);
3290}
Radek Krejci7e97c352015-06-19 16:26:34 +02003291
Radek Krejci9de2c042016-10-19 16:53:06 +02003292static void
3293lys_features_disable_recursive(struct lys_feature *f)
3294{
3295 unsigned int i;
3296 struct lys_feature *depf;
3297
3298 /* disable the feature */
3299 f->flags &= ~LYS_FENABLED;
3300
3301 /* by disabling feature we have to disable also all features that depends on this feature */
3302 if (f->depfeatures) {
3303 for (i = 0; i < f->depfeatures->number; i++) {
3304 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3305 if (depf->flags & LYS_FENABLED) {
3306 lys_features_disable_recursive(depf);
3307 }
3308 }
3309 }
3310}
3311
3312
Radek Krejci7e97c352015-06-19 16:26:34 +02003313/*
3314 * op: 1 - enable, 0 - disable
3315 */
3316static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003317lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003318{
3319 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003320 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003321 int progress, faili, failj, failk;
3322
3323 uint8_t fsize;
3324 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003325
3326 if (!module || !name || !strlen(name)) {
3327 return EXIT_FAILURE;
3328 }
3329
3330 if (!strcmp(name, "*")) {
3331 /* enable all */
3332 all = 1;
3333 }
3334
Radek Krejcia889c1f2016-10-19 15:50:11 +02003335 progress = failk = 1;
3336 while (progress && failk) {
3337 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3338 if (i == -1) {
3339 fsize = module->features_size;
3340 f = module->features;
3341 } else {
3342 fsize = module->inc[i].submodule->features_size;
3343 f = module->inc[i].submodule->features;
3344 }
3345
3346 for (j = 0; j < fsize; j++) {
3347 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003348 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3349 if (all) {
3350 /* skip already set features */
3351 continue;
3352 } else {
3353 /* feature already set correctly */
3354 return EXIT_SUCCESS;
3355 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003356 }
3357
3358 if (op) {
3359 /* check referenced features if they are enabled */
3360 for (k = 0; k < f[j].iffeature_size; k++) {
3361 if (!resolve_iffeature(&f[j].iffeature[k])) {
3362 if (all) {
3363 faili = i;
3364 failj = j;
3365 failk = k + 1;
3366 break;
3367 } else {
3368 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3369 f[j].name, k + 1);
3370 return EXIT_FAILURE;
3371 }
3372 }
3373 }
3374
3375 if (k == f[j].iffeature_size) {
3376 /* the last check passed, do the change */
3377 f[j].flags |= LYS_FENABLED;
3378 progress++;
3379 }
3380 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003381 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003382 progress++;
3383 }
3384 if (!all) {
3385 /* stop in case changing a single feature */
3386 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003387 }
3388 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003389 }
3390 }
3391 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003392 if (failk) {
3393 /* print info about the last failing feature */
3394 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3395 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3396 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003397 }
3398
3399 if (all) {
3400 return EXIT_SUCCESS;
3401 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003402 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003403 return EXIT_FAILURE;
3404 }
3405}
3406
3407API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003408lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003409{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003410 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003411}
3412
3413API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003414lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003415{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003416 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003417}
3418
3419API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003420lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003421{
3422 int i, j;
3423
3424 if (!module || !feature) {
3425 return -1;
3426 }
3427
3428 /* search for the specified feature */
3429 /* module itself */
3430 for (i = 0; i < module->features_size; i++) {
3431 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003432 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003433 return 1;
3434 } else {
3435 return 0;
3436 }
3437 }
3438 }
3439
3440 /* submodules */
3441 for (j = 0; j < module->inc_size; j++) {
3442 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3443 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003444 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003445 return 1;
3446 } else {
3447 return 0;
3448 }
3449 }
3450 }
3451 }
3452
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003453 /* feature definition not found */
3454 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003455}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003456
Radek Krejci96a10da2015-07-30 11:00:14 +02003457API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003458lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003459{
Radek Krejci96a10da2015-07-30 11:00:14 +02003460 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003461 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003462 unsigned int count;
3463
3464 if (!module) {
3465 return NULL;
3466 }
3467
3468 count = module->features_size;
3469 for (i = 0; i < module->inc_size; i++) {
3470 count += module->inc[i].submodule->features_size;
3471 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003472 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01003473 if (!result) {
3474 LOGMEM;
3475 return NULL;
3476 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003477 if (states) {
3478 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01003479 if (!(*states)) {
3480 LOGMEM;
3481 free(result);
3482 return NULL;
3483 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003484 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003485 count = 0;
3486
3487 /* module itself */
3488 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003489 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003490 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003491 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003492 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003493 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003494 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003495 }
3496 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003497 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003498 }
3499
3500 /* submodules */
3501 for (j = 0; j < module->inc_size; j++) {
3502 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003503 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003504 if (states) {
3505 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3506 (*states)[count] = 1;
3507 } else {
3508 (*states)[count] = 0;
3509 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003510 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003511 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003512 }
3513 }
3514
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003515 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003516 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003517
3518 return result;
3519}
Michal Vaskobaefb032015-09-24 14:52:10 +02003520
Radek Krejci6910a032016-04-13 10:06:21 +02003521API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003522lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003523{
3524 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3525}
3526
Radek Krejci6910a032016-04-13 10:06:21 +02003527API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003528lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003529{
3530 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3531}
3532
Michal Vaskobaefb032015-09-24 14:52:10 +02003533API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003534lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003535{
3536 if (!node || !node->parent) {
3537 return NULL;
3538 }
3539
3540 if (node->parent->nodetype == LYS_AUGMENT) {
3541 return ((struct lys_node_augment *)node->parent)->target;
3542 }
3543
3544 return node->parent;
3545}
Michal Vasko1b229152016-01-13 11:28:38 +01003546
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003547API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003548lys_set_private(const struct lys_node *node, void *priv)
3549{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003550 void *prev;
3551
Michal Vasko1b229152016-01-13 11:28:38 +01003552 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003553 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
3554 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003555 }
3556
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003557 prev = node->priv;
3558 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003559
3560 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003561}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003562
Michal Vasko01c6fd22016-05-20 11:43:05 +02003563int
3564lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3565{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003566 struct lys_node_leaf *iter = leafref_target;
3567
Michal Vasko48a573d2016-07-01 11:46:02 +02003568 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003569 LOGINT;
3570 return -1;
3571 }
3572
Pavol Vican93175152016-08-30 15:34:44 +02003573 /* check for config flag */
3574 if ((leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
3575 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
3576 "The %s is config but refers to a non-config %s.",
3577 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
3578 return -1;
3579 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003580 /* check for cycles */
3581 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3582 if ((void *)iter == (void *)leafref) {
3583 /* cycle detected */
3584 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3585 return -1;
3586 }
3587 iter = iter->type.info.lref.target;
3588 }
3589
3590 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003591 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02003592 if (!leafref_target->backlinks) {
3593 leafref_target->backlinks = (void*)ly_set_new();
3594 if (!leafref_target->backlinks) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003595 LOGMEM;
3596 return -1;
3597 }
3598 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003599 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003600
3601 return 0;
3602}
3603
Michal Vasko8548e082016-07-22 12:00:18 +02003604/* not needed currently */
3605#if 0
3606
Michal Vasko5b3492c2016-07-20 09:37:40 +02003607static const char *
3608lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3609{
3610 struct lys_module *prev_mod;
3611 uint32_t str_len, mod_len, buf_idx;
3612
Radek Krejcibf2abff2016-08-23 15:51:52 +02003613 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003614 LOGINT;
3615 return NULL;
3616 }
3617
3618 buf_idx = buf_len - 1;
3619 buf[buf_idx] = '\0';
3620
3621 while (node) {
3622 if (lys_parent(node)) {
3623 prev_mod = lys_node_module(lys_parent(node));
3624 } else {
3625 prev_mod = NULL;
3626 }
3627
Radek Krejcibf2abff2016-08-23 15:51:52 +02003628 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003629 str_len = strlen(node->name);
3630
3631 if (prev_mod != node->module) {
3632 mod_len = strlen(node->module->name);
3633 } else {
3634 mod_len = 0;
3635 }
3636
3637 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3638 LOGINT;
3639 return NULL;
3640 }
3641
3642 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3643
3644 buf[buf_idx] = '/';
3645 if (mod_len) {
3646 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3647 buf[buf_idx + 1 + mod_len] = ':';
3648 }
3649 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3650 }
3651
3652 node = lys_parent(node);
3653 }
3654
3655 return buf + buf_idx;
3656}
3657
Michal Vasko8548e082016-07-22 12:00:18 +02003658#endif
3659
3660API struct ly_set *
Michal Vaskof06fb5b2016-09-08 10:05:56 +02003661lys_find_xpath(const struct lys_node *node, const char *expr, int options)
Michal Vasko46a4bf92016-09-08 08:23:49 +02003662{
3663 struct lyxp_set set;
3664 struct ly_set *ret_set;
3665 uint32_t i;
Michal Vaskodb1da032016-09-08 10:07:38 +02003666 int opts;
Michal Vasko46a4bf92016-09-08 08:23:49 +02003667
3668 if (!node || !expr) {
3669 ly_errno = LY_EINVAL;
3670 return NULL;
3671 }
3672
3673 memset(&set, 0, sizeof set);
3674
Michal Vaskodb1da032016-09-08 10:07:38 +02003675 opts = LYXP_SNODE;
3676 if (options & LYS_FIND_OUTPUT) {
3677 opts |= LYXP_SNODE_OUTPUT;
3678 }
3679
Michal Vasko46a4bf92016-09-08 08:23:49 +02003680 /* node and nodetype won't matter at all since it is absolute */
Michal Vaskodb1da032016-09-08 10:07:38 +02003681 if (lyxp_atomize(expr, node, LYXP_NODE_ELEM, &set, opts)) {
Michal Vasko46a4bf92016-09-08 08:23:49 +02003682 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003683 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko46a4bf92016-09-08 08:23:49 +02003684 return NULL;
3685 }
3686
3687 ret_set = ly_set_new();
3688
3689 for (i = 0; i < set.used; ++i) {
3690 if (!set.val.snodes[i].in_ctx) {
3691 continue;
3692 }
3693 assert(set.val.snodes[i].in_ctx == 1);
3694
3695 switch (set.val.snodes[i].type) {
3696 case LYXP_NODE_ELEM:
3697 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
3698 ly_set_free(ret_set);
3699 free(set.val.snodes);
3700 return NULL;
3701 }
3702 break;
3703 default:
3704 /* ignore roots, text and attr should not ever appear */
3705 break;
3706 }
3707 }
3708
3709 free(set.val.snodes);
3710 return ret_set;
3711}
3712
3713API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02003714lys_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 +02003715{
Michal Vasko508a50d2016-09-07 14:50:33 +02003716 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003717 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003718 uint32_t i;
3719
Michal Vaskob94a5e42016-09-08 14:01:56 +02003720 if (!cur_snode || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02003721 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003722 }
3723
Michal Vaskob94a5e42016-09-08 14:01:56 +02003724 /* adjust the root */
3725 if ((cur_snode_type == LYXP_NODE_ROOT) || (cur_snode_type == LYXP_NODE_ROOT_CONFIG)) {
3726 do {
3727 cur_snode = lys_getnext(NULL, NULL, lys_node_module(cur_snode), 0);
3728 } while ((cur_snode_type == LYXP_NODE_ROOT_CONFIG) && (cur_snode->flags & LYS_CONFIG_R));
3729 }
3730
Michal Vasko508a50d2016-09-07 14:50:33 +02003731 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003732
3733 if (options & LYXP_MUST) {
3734 options &= ~LYXP_MUST;
3735 options |= LYXP_SNODE_MUST;
3736 } else if (options & LYXP_WHEN) {
3737 options &= ~LYXP_WHEN;
3738 options |= LYXP_SNODE_WHEN;
3739 } else {
3740 options |= LYXP_SNODE;
3741 }
3742
Michal Vasko508a50d2016-09-07 14:50:33 +02003743 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
3744 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003745 LOGVAL(LYE_SPEC, LY_VLOG_LYS, cur_snode, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02003746 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003747 }
3748
Michal Vasko8548e082016-07-22 12:00:18 +02003749 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003750
Michal Vasko508a50d2016-09-07 14:50:33 +02003751 for (i = 0; i < set.used; ++i) {
3752 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003753 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003754 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003755 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003756 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003757 return NULL;
3758 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003759 break;
3760 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003761 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003762 break;
3763 }
3764 }
3765
Michal Vasko508a50d2016-09-07 14:50:33 +02003766 free(set.val.snodes);
3767 return ret_set;
3768}
3769
3770API struct ly_set *
3771lys_node_xpath_atomize(const struct lys_node *node, int options)
3772{
3773 const struct lys_node *next, *elem, *parent, *tmp;
3774 struct lyxp_set set;
3775 struct ly_set *ret_set;
3776 uint16_t i;
3777
3778 if (!node) {
3779 return NULL;
3780 }
3781
3782 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3783 if (!parent) {
3784 /* not in input, output, or notification */
3785 return NULL;
3786 }
3787
3788 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003789 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003790 return NULL;
3791 }
3792
3793 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003794 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_XPATH_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003795 /* elem has no dependencies from other subtrees and local nodes get discarded */
3796 goto next_iter;
3797 }
3798
3799 if (lyxp_node_atomize(elem, &set)) {
3800 ly_set_free(ret_set);
3801 free(set.val.snodes);
3802 return NULL;
3803 }
3804
3805 for (i = 0; i < set.used; ++i) {
3806 switch (set.val.snodes[i].type) {
3807 case LYXP_NODE_ELEM:
3808 if (options & LYXP_NO_LOCAL) {
3809 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3810 if (tmp) {
3811 /* in local subtree, discard */
3812 break;
3813 }
3814 }
3815 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3816 ly_set_free(ret_set);
3817 free(set.val.snodes);
3818 return NULL;
3819 }
3820 break;
3821 default:
3822 /* ignore roots, text and attr should not ever appear */
3823 break;
3824 }
3825 }
3826
3827 free(set.val.snodes);
3828 if (!(options & LYXP_RECURSIVE)) {
3829 break;
3830 }
3831next_iter:
3832 LY_TREE_DFS_END(node, next, elem);
3833 }
3834
Michal Vasko8548e082016-07-22 12:00:18 +02003835 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003836}
3837
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003838static void
Michal Vasko89563fc2016-07-28 16:19:35 +02003839lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003840{
3841 int ret;
3842 char *parent_path;
3843 struct lys_node *target;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003844
Pavol Vican64d0b762016-08-25 10:44:59 +02003845 if (!dev->deviate) {
3846 return ;
3847 }
3848
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003849 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3850 if (dev->orig_node) {
3851 /* removing not-supported deviation ... */
3852 if (strrchr(dev->target_name, '/') != dev->target_name) {
3853 /* ... from a parent */
3854 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3855
3856 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003857 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, 1,
3858 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003859 free(parent_path);
3860 if (ret || !target) {
3861 LOGINT;
3862 return;
3863 }
3864
3865 lys_node_addchild(target, NULL, dev->orig_node);
3866 } else {
3867 /* ... from top-level data */
3868 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3869 }
3870
3871 dev->orig_node = NULL;
3872 } else {
3873 /* adding not-supported deviation */
3874 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003875 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
3876 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003877 if (ret || !target) {
3878 LOGINT;
3879 return;
3880 }
3881
3882 lys_node_unlink(target);
3883 dev->orig_node = target;
3884 }
3885 } else {
3886 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003887 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
3888 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003889 if (ret || !target) {
3890 LOGINT;
3891 return;
3892 }
3893
3894 lys_node_switch(target, dev->orig_node);
3895 dev->orig_node = target;
3896 }
3897}
3898
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003899/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3900void
3901lys_switch_deviations(struct lys_module *module)
3902{
Michal Vasko89563fc2016-07-28 16:19:35 +02003903 uint32_t i = 0, j;
3904 const struct lys_module *mod;
3905 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003906
Michal Vasko89563fc2016-07-28 16:19:35 +02003907 if (module->deviated) {
3908 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3909 if (mod == module) {
3910 continue;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003911 }
3912
Michal Vasko89563fc2016-07-28 16:19:35 +02003913 for (j = 0; j < mod->deviation_size; ++j) {
3914 ptr = strstr(mod->deviation[j].target_name, module->name);
3915 if (ptr && ptr[strlen(module->name)] == ':') {
3916 lys_switch_deviation(&mod->deviation[j], module);
3917 }
3918 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003919 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003920
Michal Vasko89563fc2016-07-28 16:19:35 +02003921 if (module->deviated == 2) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003922 module->deviated = 1;
Michal Vasko89563fc2016-07-28 16:19:35 +02003923 } else {
3924 module->deviated = 2;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003925 }
3926 }
3927}
3928
Radek Krejci0ec51da2016-12-14 16:42:03 +01003929static void
3930apply_dev(struct lys_deviation *dev, const struct lys_module *module)
3931{
3932 lys_switch_deviation(dev, module);
3933
3934 assert(dev->orig_node);
3935 lys_node_module(dev->orig_node)->deviated = 1;
3936}
3937
3938static void
3939apply_aug(struct lys_node_augment *augment)
3940{
3941 struct lys_node *last;
3942
3943 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
3944
3945 /* reconnect augmenting data into the target - add them to the target child list */
3946 if (augment->target->child) {
3947 last = augment->target->child->prev;
3948 last->next = augment->child;
3949 augment->target->child->prev = augment->child->prev;
3950 augment->child->prev = last;
3951 } else {
3952 augment->target->child = augment->child;
3953 }
3954
3955 /* remove the flag about not applicability */
3956 augment->flags &= ~LYS_NOTAPPLIED;
3957}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003958
3959void
3960lys_sub_module_apply_devs_augs(struct lys_module *module)
3961{
Radek Krejci0ec51da2016-12-14 16:42:03 +01003962 uint8_t u, v;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003963
Radek Krejci0ec51da2016-12-14 16:42:03 +01003964 /* remove applied deviations */
3965 for (u = 0; u < module->deviation_size; ++u) {
3966 apply_dev(&module->deviation[u], module);
3967 }
3968 /* remove applied augments */
3969 for (u = 0; u < module->augment_size; ++u) {
3970 apply_aug(&module->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003971 }
3972
Radek Krejci0ec51da2016-12-14 16:42:03 +01003973 /* remove deviation and augments defined in submodules */
3974 for (v = 0; v < module->inc_size; ++v) {
3975 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
3976 apply_dev(&module->inc[v].submodule->deviation[u], module);
3977 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003978
Radek Krejci0ec51da2016-12-14 16:42:03 +01003979 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
3980 apply_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003981 }
3982 }
3983}
3984
Radek Krejcib2541a32016-12-12 16:45:57 +01003985static void
3986remove_dev(struct lys_deviation *dev, const struct lys_module *module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003987{
Radek Krejcib2541a32016-12-12 16:45:57 +01003988 uint32_t idx = 0, j;
Michal Vasko89563fc2016-07-28 16:19:35 +02003989 const struct lys_module *mod;
3990 struct lys_module *target_mod;
3991 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003992
Radek Krejcib2541a32016-12-12 16:45:57 +01003993 if (dev->orig_node) {
3994 target_mod = lys_node_module(dev->orig_node);
3995 } else {
Radek Krejci0ec51da2016-12-14 16:42:03 +01003996 LOGINT;
3997 return;
Radek Krejcib2541a32016-12-12 16:45:57 +01003998 }
3999 lys_switch_deviation(dev, module);
4000
4001 /* clear the deviation flag if possible */
4002 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4003 if ((mod == module) || (mod == target_mod)) {
4004 continue;
Pavol Vican64d0b762016-08-25 10:44:59 +02004005 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004006
Radek Krejcib2541a32016-12-12 16:45:57 +01004007 for (j = 0; j < mod->deviation_size; ++j) {
4008 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4009 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4010 /* some other module deviation targets the inspected module, flag remains */
Michal Vasko89563fc2016-07-28 16:19:35 +02004011 break;
4012 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004013 }
Michal Vasko89563fc2016-07-28 16:19:35 +02004014
Radek Krejcib2541a32016-12-12 16:45:57 +01004015 if (j < mod->deviation_size) {
4016 break;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004017 }
4018 }
4019
Radek Krejcib2541a32016-12-12 16:45:57 +01004020 if (!mod) {
4021 target_mod->deviated = 0;
4022 }
4023}
4024
4025static void
4026remove_aug(struct lys_node_augment *augment)
4027{
4028 struct lys_node *last, *elem;
4029
4030 if (!augment->target) {
4031 /* skip not resolved augments */
4032 return;
4033 }
4034
4035 elem = augment->child;
4036 if (elem) {
4037 LY_TREE_FOR(elem, last) {
4038 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
4039 break;
4040 }
4041 }
4042 /* elem is first augment child, last is the last child */
4043
4044 /* parent child ptr */
4045 if (augment->target->child == elem) {
4046 augment->target->child = last->next;
4047 }
4048
4049 /* parent child next ptr */
4050 if (elem->prev->next) {
4051 elem->prev->next = last->next;
4052 }
4053
4054 /* parent child prev ptr */
4055 if (last->next) {
4056 last->next->prev = elem->prev;
4057 } else if (augment->target->child) {
4058 augment->target->child->prev = elem->prev;
4059 }
4060
4061 /* update augment children themselves */
4062 elem->prev = last;
4063 last->next = NULL;
4064 }
4065
Radek Krejci0ec51da2016-12-14 16:42:03 +01004066 /* augment->target still keeps the resolved target, but for lys_augment_free()
4067 * we have to keep information that this augment is not applied to free its data */
4068 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01004069}
4070
4071void
4072lys_sub_module_remove_devs_augs(struct lys_module *module)
4073{
4074 uint8_t u, v;
4075
4076 /* remove applied deviations */
4077 for (u = 0; u < module->deviation_size; ++u) {
4078 remove_dev(&module->deviation[u], module);
4079 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004080 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004081 for (u = 0; u < module->augment_size; ++u) {
4082 remove_aug(&module->augment[u]);
4083 }
4084
4085 /* remove deviation and augments defined in submodules */
4086 for (v = 0; v < module->inc_size; ++v) {
4087 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4088 remove_dev(&module->inc[v].submodule->deviation[u], module);
Radek Krejcidbc15262016-06-16 14:58:29 +02004089 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004090
Radek Krejcib2541a32016-12-12 16:45:57 +01004091 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4092 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004093 }
4094 }
4095}
4096
Radek Krejci27fe55e2016-09-13 17:13:35 +02004097static int
4098lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
4099{
4100 struct lys_node *root, *next, *node;
4101 uint8_t i;
4102
4103 for (i = 0; i < module->augment_size; i++) {
4104 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02004105 if (!module->augment[i].target
4106 && (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004107 return -1;
4108 }
4109 }
4110 LY_TREE_FOR(module->data, root) {
4111 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4112 LY_TREE_DFS_BEGIN(root, next, node) {
4113 if (node->nodetype == LYS_GROUPING) {
4114 goto nextsibling;
4115 }
4116 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4117 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4118 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4119 UNRES_TYPE_LEAFREF, node) == -1) {
4120 return EXIT_FAILURE;
4121 }
4122 }
4123 }
4124
4125 /* modified LY_TREE_DFS_END */
4126 next = node->child;
4127 /* child exception for leafs, leaflists and anyxml without children */
4128 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4129 next = NULL;
4130 }
4131 if (!next) {
4132nextsibling:
4133 /* no children */
4134 if (node == root) {
4135 /* we are done, root has no children */
4136 break;
4137 }
4138 /* try siblings */
4139 next = node->next;
4140 }
4141 while (!next) {
4142 /* parent is already processed, go to its sibling */
4143 node = lys_parent(node);
4144 /* no siblings, go back through parents */
4145 if (lys_parent(node) == lys_parent(root)) {
4146 /* we are done, no next element to process */
4147 break;
4148 }
4149 next = node->next;
4150 }
4151 }
4152 }
4153
4154 return EXIT_SUCCESS;
4155}
4156
4157API int
4158lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004159{
4160 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004161 struct unres_schema *unres;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004162 int i, j, disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004163
Radek Krejci27fe55e2016-09-13 17:13:35 +02004164 if (!module) {
4165 ly_errno = LY_EINVAL;
4166 return EXIT_FAILURE;
4167 }
4168
4169 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004170
4171 if (module->disabled) {
4172 disabled = 1;
4173 lys_set_enabled(module);
4174 }
4175
Michal Vasko26055752016-05-03 11:36:31 +02004176 if (module->implemented) {
4177 return EXIT_SUCCESS;
4178 }
4179
4180 ctx = module->ctx;
4181
4182 for (i = 0; i < ctx->models.used; ++i) {
4183 if (module == ctx->models.list[i]) {
4184 continue;
4185 }
4186
4187 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4188 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004189 if (disabled) {
4190 /* set it back disabled */
4191 lys_set_disabled(module);
4192 }
Michal Vasko26055752016-05-03 11:36:31 +02004193 return EXIT_FAILURE;
4194 }
4195 }
4196
Radek Krejci27fe55e2016-09-13 17:13:35 +02004197 unres = calloc(1, sizeof *unres);
4198 if (!unres) {
4199 LOGMEM;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004200 if (disabled) {
4201 /* set it back disabled */
4202 lys_set_disabled(module);
4203 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004204 return EXIT_FAILURE;
4205 }
4206 /* recursively make the module implemented */
4207 ((struct lys_module *)module)->implemented = 1;
4208 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
4209 goto error;
4210 }
4211 /* process augments in submodules */
4212 for (i = 0; i < module->inc_size; ++i) {
4213 if (!module->inc[i].submodule) {
4214 continue;
4215 }
4216 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
4217 /* apply augment */
Radek Krejcic8c22532016-11-09 15:11:24 +01004218 if (!module->inc[i].submodule->augment[j].target
4219 && (unres_schema_add_node((struct lys_module *)module->inc[j].submodule, unres,
4220 &module->inc[i].submodule->augment[j], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01004221
Radek Krejci27fe55e2016-09-13 17:13:35 +02004222 goto error;
4223 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004224 }
4225 }
Radek Krejcidf46e222016-11-08 11:57:37 +01004226 /* try again resolve augments in other modules possibly augmenting this one,
4227 * since we have just enabled it
4228 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004229 /* resolve rest of unres items */
4230 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4231 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004232 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004233 unres_schema_free((struct lys_module *)module, &unres);
Michal Vasko26055752016-05-03 11:36:31 +02004234
4235 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004236
4237error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004238
4239 if (disabled) {
4240 /* set it back disabled */
4241 lys_set_disabled(module);
4242 }
4243
Radek Krejci27fe55e2016-09-13 17:13:35 +02004244 ((struct lys_module *)module)->implemented = 0;
4245 unres_schema_free((struct lys_module *)module, &unres);
4246 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004247}
4248
4249void
4250lys_submodule_module_data_free(struct lys_submodule *submodule)
4251{
4252 struct lys_node *next, *elem;
4253
4254 /* remove parsed data */
4255 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4256 if (elem->module == (struct lys_module *)submodule) {
4257 lys_node_free(elem, NULL, 0);
4258 }
4259 }
4260}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004261
4262int
4263lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
4264{
4265 uint8_t i;
4266
4267 for (i = 0; i < list->keys_size; i++) {
4268 if (list->keys[i] == leaf) {
4269 return i + 1;
4270 }
4271 }
4272
4273 return 0;
4274}
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004275
4276API char *
4277lys_path(const struct lys_node *node)
4278{
4279 char *buf_backup = NULL, *buf = ly_buf(), *result = NULL;
4280 uint16_t index = LY_BUF_SIZE - 1;
4281
4282 if (!node) {
4283 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
4284 return NULL;
4285 }
4286
4287 /* backup the shared internal buffer */
4288 if (ly_buf_used && buf[0]) {
4289 buf_backup = strndup(buf, LY_BUF_SIZE - 1);
4290 }
4291 ly_buf_used++;
4292
4293 /* build the path */
4294 buf[index] = '\0';
4295 ly_vlog_build_path_reverse(LY_VLOG_LYS, node, buf, &index);
4296 result = strdup(&buf[index]);
4297
4298 /* restore the shared internal buffer */
4299 if (buf_backup) {
4300 strcpy(buf, buf_backup);
4301 free(buf_backup);
4302 }
4303 ly_buf_used--;
4304
4305 return result;
4306}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004307