blob: 0f0e77cdff4f5fda9bc69ee95d112b924ddf0a5d [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;
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100141 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
Radek Krejcic071c542016-01-27 14:57:51 +0100142 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 Vasko0f99d3e2017-01-10 10:50:40 +0100163lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, int nam_len,
164 LYS_NODE type, 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 */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100190 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
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 Krejcifdc0d702017-01-23 15:58:38 +0100336 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
Radek Krejci80056d52017-01-05 13:13:33 +0100337 /* 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 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100373
374 if (parent->flags & LYS_NOTAPPLIED) {
375 /* data are not connected in the target, so we cannot continue with the target as a parent */
376 parent = NULL;
377 } else {
378 /* data are connected in target, so we will continue with the target as a parent */
379 parent = ((struct lys_node_augment *)parent)->target;
380 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200381 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200383 /* unlink from parent */
384 if (parent) {
385 if (parent->child == node) {
386 parent->child = node->next;
387 }
388 node->parent = NULL;
389 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200391 /* unlink from siblings */
392 if (node->prev == node) {
393 /* there are no more siblings */
394 return;
395 }
396 if (node->next) {
397 node->next->prev = node->prev;
398 } else {
399 /* unlinking the last element */
400 if (parent) {
401 first = parent->child;
402 } else {
403 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200404 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200405 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200406 }
407 }
408 first->prev = node->prev;
409 }
410 if (node->prev->next) {
411 node->prev->next = node->next;
412 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200414 /* clean up the unlinked element */
415 node->next = NULL;
416 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200417}
418
Michal Vasko563ef092015-09-04 13:17:23 +0200419struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100420lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200421{
422 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200423
424 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200425 /* top-level augment, look into module (uses augment is handled correctly below) */
426 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
427 par_iter = par_iter->parent->module->data;
428 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200429 break;
430 }
431 }
432
Michal Vasko6f929da2015-10-02 16:23:25 +0200433 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200434 continue;
435 }
436
437 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
438 if (!stop) {
439 stop = par_iter;
440 } else if (iter == stop) {
441 break;
442 }
443 if (iter->nodetype != LYS_GROUPING) {
444 continue;
445 }
446
Radek Krejcif8426a72015-10-31 23:14:03 +0100447 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200448 return (struct lys_node_grp *)iter;
449 }
450 }
451 }
452
Michal Vasko563ef092015-09-04 13:17:23 +0200453 return NULL;
454}
455
Radek Krejci10c760e2015-08-14 14:45:43 +0200456/*
457 * get next grouping in the root's subtree, in the
458 * first call, tha last is NULL
459 */
460static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200461lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200462{
Radek Krejci10c760e2015-08-14 14:45:43 +0200463 struct lys_node *last = (struct lys_node *)lastgrp;
464 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200465
Radek Krejci10c760e2015-08-14 14:45:43 +0200466 assert(root);
467
468 if (!last) {
469 last = root;
470 }
471
472 while (1) {
473 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
474 next = last->child;
475 } else {
476 next = NULL;
477 }
478 if (!next) {
479 if (last == root) {
480 /* we are done */
481 return NULL;
482 }
483
484 /* no children, go to siblings */
485 next = last->next;
486 }
487 while (!next) {
488 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100489 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200490 /* we are done */
491 return NULL;
492 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200493 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100494 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200495 }
496
497 if (next->nodetype == LYS_GROUPING) {
498 return (struct lys_node_grp *)next;
499 }
500
501 last = next;
502 }
503}
504
Michal Vasko0d343d12015-08-24 14:57:36 +0200505/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200506int
Radek Krejci07911992015-08-14 15:13:31 +0200507lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
508{
Michal Vasko563ef092015-09-04 13:17:23 +0200509 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200510 struct lys_node_grp *grp;
511 int down;
512
513 assert(node);
514
515 if (!parent) {
516 assert(module);
517 } else {
518 module = parent->module;
519 }
520
521 switch (node->nodetype) {
522 case LYS_GROUPING:
523 /* 6.2.1, rule 6 */
524 if (parent) {
525 if (parent->child) {
526 down = 1;
527 start = parent->child;
528 } else {
529 down = 0;
530 start = parent;
531 }
532 } else {
533 down = 1;
534 start = module->data;
535 }
536 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100537 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100538 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200539 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200540 }
541 /* go down, because grouping can be defined after e.g. container in which is collision */
542 if (down) {
543 for (iter = start, stop = NULL; iter; iter = iter->prev) {
544 if (!stop) {
545 stop = start;
546 } else if (iter == stop) {
547 break;
548 }
549 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
550 continue;
551 }
552
553 grp = NULL;
554 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100555 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100556 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200557 return EXIT_FAILURE;
558 }
559 }
560 }
561 }
562 break;
563 case LYS_LEAF:
564 case LYS_LEAFLIST:
565 case LYS_LIST:
566 case LYS_CONTAINER:
567 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200568 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200569 /* 6.2.1, rule 7 */
570 if (parent) {
571 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200572 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
573 if (iter->nodetype == LYS_AUGMENT) {
574 if (((struct lys_node_augment *)iter)->target) {
575 /* augment is resolved, go up */
576 iter = ((struct lys_node_augment *)iter)->target;
577 continue;
578 }
579 /* augment is not resolved, this is the final parent */
580 break;
581 }
Radek Krejci07911992015-08-14 15:13:31 +0200582 iter = iter->parent;
583 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200584
Radek Krejci07911992015-08-14 15:13:31 +0200585 if (!iter) {
586 stop = NULL;
587 iter = module->data;
588 } else {
589 stop = iter;
590 iter = iter->child;
591 }
592 } else {
593 stop = NULL;
594 iter = module->data;
595 }
596 while (iter) {
597 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
598 iter = iter->child;
599 continue;
600 }
601
Radek Krejcibf2abff2016-08-23 15:51:52 +0200602 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100603 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100604 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200605 return EXIT_FAILURE;
606 }
607 }
608
609 /* special case for choice - we must check the choice's name as
610 * well as the names of nodes under the choice
611 */
612 if (iter->nodetype == LYS_CHOICE) {
613 iter = iter->child;
614 continue;
615 }
616
617 /* go to siblings */
618 if (!iter->next) {
619 /* no sibling, go to parent's sibling */
620 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200621 /* for parent LYS_AUGMENT */
622 if (iter->parent == stop) {
623 iter = stop;
624 break;
625 }
626 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200627 if (iter && iter->next) {
628 break;
629 }
630 } while (iter != stop);
631
632 if (iter == stop) {
633 break;
634 }
635 }
636 iter = iter->next;
637 }
638 break;
639 case LYS_CASE:
640 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100641 if (parent) {
642 start = parent->child;
643 } else {
644 start = module->data;
645 }
646
647 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200648 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200649 continue;
650 }
651
Radek Krejci749190d2016-02-18 16:26:25 +0100652 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100653 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200654 return EXIT_FAILURE;
655 }
656 }
657 break;
658 default:
659 /* no check needed */
660 break;
661 }
662
663 return EXIT_SUCCESS;
664}
665
Michal Vasko0d343d12015-08-24 14:57:36 +0200666/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200667int
Radek Krejci10c760e2015-08-14 14:45:43 +0200668lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
669{
Radek Krejci92720552015-10-05 15:28:27 +0200670 struct lys_node *iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200671 struct lys_node_inout *in, *out, *inout;
Radek Krejci07911992015-08-14 15:13:31 +0200672 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200675
Radek Krejci10c760e2015-08-14 14:45:43 +0200676 if (parent) {
677 type = parent->nodetype;
678 module = parent->module;
679 } else {
680 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100681 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200682 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200683 }
684
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200685 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200686 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200687 case LYS_CONTAINER:
688 case LYS_LIST:
689 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100690 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200691 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200692 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200693 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200694 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
695 return EXIT_FAILURE;
696 }
697 break;
Radek Krejci76512572015-08-04 09:47:08 +0200698 case LYS_INPUT:
699 case LYS_OUTPUT:
700 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200701 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200702 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200703 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100704 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200705 return EXIT_FAILURE;
706 }
707 break;
Radek Krejci76512572015-08-04 09:47:08 +0200708 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200709 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200710 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100711 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200712 return EXIT_FAILURE;
713 }
714 break;
Radek Krejci76512572015-08-04 09:47:08 +0200715 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200716 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200717 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100718 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200719 return EXIT_FAILURE;
720 }
721 break;
Radek Krejci76512572015-08-04 09:47:08 +0200722 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200723 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200724 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100725 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200726 return EXIT_FAILURE;
727 }
728 break;
Radek Krejci76512572015-08-04 09:47:08 +0200729 case LYS_LEAF:
730 case LYS_LEAFLIST:
731 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200732 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100733 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vasko51e5c582017-01-19 14:16:39 +0100734 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100735 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200736 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200737 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200738 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200739 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100740 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100741 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200742 return EXIT_FAILURE;
743 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200744 break;
745 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200746 /* top level */
747 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200748 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200749 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100750 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200751 return EXIT_FAILURE;
752 }
753
Radek Krejcic071c542016-01-27 14:57:51 +0100754 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200755 }
756
757 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200758 if (lys_check_id(child, parent, module)) {
759 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200760 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200762 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200763 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200764 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200765
Radek Krejci41a349b2016-10-24 19:21:59 +0200766 if (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
767 /* replace the implicit input/output node */
768 if (child->nodetype == LYS_OUTPUT) {
769 inout = (struct lys_node_inout *)parent->child->next;
770 } else { /* LYS_INPUT */
771 inout = (struct lys_node_inout *)parent->child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200772 parent->child = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200773 }
774 if (inout->next) {
775 child->next = inout->next;
776 inout->next->prev = child;
777 inout->next = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200778 } else {
Radek Krejci41a349b2016-10-24 19:21:59 +0200779 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200780 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200781 child->prev = inout->prev;
782 if (inout->prev->next) {
783 inout->prev->next = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200784 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200785 inout->prev = (struct lys_node *)inout;
786 child->parent = parent;
787 inout->parent = NULL;
788 lys_node_free((struct lys_node *)inout, NULL, 0);
789 } else {
790 /* connect the child correctly */
791 if (!parent) {
792 if (module->data) {
793 module->data->prev->next = child;
794 child->prev = module->data->prev;
795 module->data->prev = child;
796 } else {
797 module->data = child;
798 }
799 } else {
800 if (!parent->child) {
801 /* the only/first child of the parent */
802 parent->child = child;
803 child->parent = parent;
804 iter = child;
805 } else {
806 /* add a new child at the end of parent's child list */
807 iter = parent->child->prev;
808 iter->next = child;
809 child->prev = iter;
810 }
811 while (iter->next) {
812 iter = iter->next;
813 iter->parent = parent;
814 }
815 parent->child->prev = iter;
816 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200818
Michal Vaskoe022a562016-09-27 14:24:15 +0200819 /* check config value (but ignore them in groupings and augments) */
820 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT)); iter = iter->parent);
821 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200822 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
823 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
824 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +0100825 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200826 return EXIT_FAILURE;
827 }
828 }
829
Radek Krejci41771502016-04-14 17:52:32 +0200830 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200831 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200832 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200833 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200834 /* store it only into container or list - the only data inner nodes */
835 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
836 if (iter->flags & LYS_INCL_STATUS) {
837 /* done, someone else set it already from here */
838 break;
839 }
840 /* set flag about including status data */
841 iter->flags |= LYS_INCL_STATUS;
842 }
843 }
844 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200845
846 /* create implicit input/output nodes to have available them as possible target for augment */
847 if (child->nodetype & (LYS_RPC | LYS_ACTION)) {
848 in = calloc(1, sizeof *in);
849 in->nodetype = LYS_INPUT;
850 in->name = lydict_insert(child->module->ctx, "input", 5);
851 out = calloc(1, sizeof *out);
852 out->name = lydict_insert(child->module->ctx, "output", 6);
853 out->nodetype = LYS_OUTPUT;
854 in->module = out->module = child->module;
855 in->parent = out->parent = child;
856 in->flags = out->flags = LYS_IMPLICIT;
857 in->next = (struct lys_node *)out;
858 in->prev = (struct lys_node *)out;
859 out->prev = (struct lys_node *)in;
860 child->child = (struct lys_node *)in;
861 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200862 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200863}
864
Radek Krejcia1df1682016-04-11 14:56:59 +0200865static const struct lys_module *
866lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200867{
Radek Krejcia1df1682016-04-11 14:56:59 +0200868 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200869 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200870 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200871
Radek Krejci00a0e712016-10-26 10:24:46 +0200872 ly_err_clean(1);
Radek Krejcif347abc2016-06-22 10:18:47 +0200873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200874 if (!ctx || !data) {
875 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
876 return NULL;
877 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200878
Radek Krejcia1df1682016-04-11 14:56:59 +0200879 if (!internal && format == LYS_IN_YANG) {
880 /* enlarge data by 2 bytes for flex */
881 len = strlen(data);
882 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
883 if (!enlarged_data) {
884 LOGMEM;
885 return NULL;
886 }
887 memcpy(enlarged_data, data, len);
888 enlarged_data[len] = enlarged_data[len + 1] = '\0';
889 data = enlarged_data;
890 }
891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200892 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200893 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100894 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200895 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200896 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100897 mod = yang_read_module(ctx, data, 0, NULL, 1);
898 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200899 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200900 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200901 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200902 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200903
Radek Krejcia1df1682016-04-11 14:56:59 +0200904 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200905 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200906}
907
Radek Krejcia1df1682016-04-11 14:56:59 +0200908API const struct lys_module *
909lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
910{
911 return lys_parse_mem_(ctx, data, format, 0);
912}
913
Michal Vasko5a721fd2016-02-16 12:16:48 +0100914struct lys_submodule *
915lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200916{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100917 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200919 assert(module);
920 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200921
Radek Krejcic071c542016-01-27 14:57:51 +0100922 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +0200923 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200925 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200926 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +0100927 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200928 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200929 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100930 submod = yang_read_submodule(module, data, 0, unres);
931 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200932 default:
Radek Krejci90a550a2016-04-13 16:00:58 +0200933 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200934 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200935 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200936
Michal Vasko5a721fd2016-02-16 12:16:48 +0100937 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200938}
939
Michal Vasko1e62a092015-12-01 12:27:20 +0100940API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +0100941lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
942{
943 int fd;
944 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +0200945 const char *rev, *dot, *filename;
946 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +0100947
948 if (!ctx || !path) {
949 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
950 return NULL;
951 }
952
953 fd = open(path, O_RDONLY);
954 if (fd == -1) {
955 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
956 return NULL;
957 }
958
959 ret = lys_parse_fd(ctx, fd, format);
960 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +0100961
Radek Krejcid80c8602016-10-25 11:56:03 +0200962 if (!ret) {
963 /* error */
964 return NULL;
965 }
966
967 /* check that name and revision match filename */
968 filename = strrchr(path, '/');
969 if (!filename) {
970 filename = path;
971 } else {
972 filename++;
973 }
974 rev = strchr(filename, '@');
975 dot = strrchr(filename, '.');
976
977 /* name */
978 len = strlen(ret->name);
979 if (strncmp(filename, ret->name, len) ||
980 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Radek Krejcic0c82302016-10-25 14:21:33 +0200981 LOGWRN("File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +0200982 }
983 if (rev) {
984 len = dot - ++rev;
985 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
986 LOGWRN("File name \"%s\" does not match module revision \"%s\".", filename,
987 ret->rev_size ? ret->rev[0].date : "none");
988 }
989 }
990
991 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +0100992 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +0100993 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +0100994 }
995
Michal Vasko662610a2015-12-07 11:25:45 +0100996 return ret;
997}
998
999API const struct lys_module *
1000lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001001{
Michal Vasko1e62a092015-12-01 12:27:20 +01001002 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001003 struct stat sb;
1004 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001005 char buf[PATH_MAX];
1006 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001007
1008 if (!ctx || fd < 0) {
1009 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1010 return NULL;
1011 }
1012
Radek Krejci10a833c2015-12-16 15:28:37 +01001013 if (fstat(fd, &sb) == -1) {
1014 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1015 return NULL;
1016 }
Radek Krejcib051f722016-02-25 15:12:21 +01001017 if (!S_ISREG(sb.st_mode)) {
1018 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1019 return NULL;
1020 }
1021
Michal Vasko164d9012016-04-01 10:16:59 +02001022 if (!sb.st_size) {
1023 LOGERR(LY_EINVAL, "File empty.");
1024 return NULL;
1025 }
1026
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001027 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001028 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001029 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001030 return NULL;
1031 }
Radek Krejcia1df1682016-04-11 14:56:59 +02001032 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001033 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001034
Radek Krejcia77904e2016-02-25 16:23:45 +01001035 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001036 /* get URI if there is /proc */
1037 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001038 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1039 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1040 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1041 }
1042 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001043 }
Radek Krejcib051f722016-02-25 15:12:21 +01001044 }
1045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001046 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001047}
1048
Michal Vasko5a721fd2016-02-16 12:16:48 +01001049struct lys_submodule *
1050lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001051{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001052 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001053 struct stat sb;
1054 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001056 assert(module);
1057 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001058
Radek Krejci10a833c2015-12-16 15:28:37 +01001059 if (fstat(fd, &sb) == -1) {
1060 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001061 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001062 }
Michal Vasko164d9012016-04-01 10:16:59 +02001063
1064 if (!sb.st_size) {
1065 LOGERR(LY_EINVAL, "File empty.");
1066 return NULL;
1067 }
1068
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001069 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001070 if (addr == MAP_FAILED) {
1071 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001072 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001073 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001074 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001075 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +02001076
Michal Vasko5a721fd2016-02-16 12:16:48 +01001077 return submodule;
1078
Radek Krejciefaeba32015-05-27 14:30:57 +02001079}
1080
Radek Krejcifdc0d702017-01-23 15:58:38 +01001081/*
1082 * duplicate extension instance
1083 */
1084int
1085lys_ext_dup(struct ly_ctx *ctx, struct lys_ext_instance **orig, uint8_t size,
1086 void *parent, LYEXT_PAR parent_type, struct lys_ext_instance ***new, struct unres_schema *unres)
1087{
1088 int i;
1089 uint8_t u = 0;
1090 struct lys_ext_instance **result;
1091 struct unres_ext *info, *info_orig;
1092
1093 assert(new);
1094
1095 if (!size) {
1096 if (orig) {
1097 LOGINT;
1098 return EXIT_FAILURE;
1099 }
1100 (*new) = NULL;
1101 return EXIT_SUCCESS;
1102 }
1103
1104 (*new) = result = calloc(size, sizeof *result);
1105 for (u = 0; u < size; u++) {
1106 if (orig[u]) {
1107 /* resolved extension instance, just duplicate it */
1108 switch(lys_ext_instance_type(orig[u])) {
1109 case LYEXT_FLAG:
1110 result[u] = malloc(sizeof(struct lys_ext_instance));
1111 break;
1112 case LYEXT_ERR:
1113 LOGINT;
1114 break;
1115 }
1116 /* generic part */
1117 result[u]->def = orig[u]->def;
1118 result[u]->flags = 0;
1119 result[u]->arg_value = lydict_insert(ctx, orig[u]->arg_value, 0);
1120 result[u]->parent = parent;
1121 result[u]->parent_type = parent_type;
1122 result[u]->substmt = orig[u]->substmt;
1123 result[u]->substmt_index = orig[u]->substmt_index;
1124
1125 /* extensions */
1126 orig[u]->ext = NULL;
1127 result[u]->ext_size = orig[u]->ext_size;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001128 if (lys_ext_dup(ctx, orig[u]->ext, orig[u]->ext_size, result[u],
1129 LYEXT_PAR_EXTINST, &result[u]->ext, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001130 goto error;
1131 }
1132 } else {
1133 /* original extension is not yet resolved, so duplicate it in unres */
1134 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1135 if (i == -1) {
1136 /* extension not found in unres */
1137 LOGINT;
1138 goto error;
1139 }
1140 info_orig = unres->str_snode[i];
1141 info = malloc(sizeof *info);
1142 info->datatype = info_orig->datatype;
1143 if (info->datatype == LYS_IN_YIN) {
1144 info->data.yin = lyxml_dup_elem(ctx, info_orig->data.yin, NULL, 1);
1145 } /* else TODO YANG */
1146 info->parent = parent;
1147 info->mod = info_orig->mod;
1148 info->parent_type = parent_type;
1149 info->ext_index = u;
1150 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1151 goto error;
1152 }
1153 }
1154 }
1155
1156 return EXIT_SUCCESS;
1157
1158error:
1159 (*new) = NULL;
1160 lys_extension_instances_free(ctx, result, u);
1161 return EXIT_FAILURE;
1162}
1163
Radek Krejci1d82ef62015-08-07 14:44:40 +02001164static struct lys_restr *
Radek Krejcifdc0d702017-01-23 15:58:38 +01001165lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001166{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001167 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001168 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001169
Radek Krejci3733a802015-06-19 13:43:21 +02001170 if (!size) {
1171 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001172 }
Radek Krejci3733a802015-06-19 13:43:21 +02001173
1174 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001175 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001176 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001177 return NULL;
1178 }
Radek Krejci3733a802015-06-19 13:43:21 +02001179 for (i = 0; i < size; i++) {
Radek Krejci77f22b22017-01-17 15:23:03 +01001180 result[i].ext_size = old[i].ext_size;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001181 lys_ext_dup(ctx, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_RESTR, &result[i].ext, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001182 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1183 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1184 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1185 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1186 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1187 }
1188
1189 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001190}
1191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001192void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001193lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001194{
1195 assert(ctx);
1196 if (!restr) {
1197 return;
1198 }
1199
Radek Krejcifccd1442017-01-16 10:26:57 +01001200 lys_extension_instances_free(ctx, restr->ext, restr->ext_size);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001201 lydict_remove(ctx, restr->expr);
1202 lydict_remove(ctx, restr->dsc);
1203 lydict_remove(ctx, restr->ref);
1204 lydict_remove(ctx, restr->eapptag);
1205 lydict_remove(ctx, restr->emsg);
1206}
1207
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001208static void
Radek Krejci5323b492017-01-16 15:40:11 +01001209lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size)
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001210{
1211 uint8_t i;
1212
1213 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci5323b492017-01-16 15:40:11 +01001214 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001215 free(iffeature[i].expr);
1216 free(iffeature[i].features);
1217 }
1218 free(iffeature);
1219}
1220
Michal Vaskob84f88a2015-09-24 13:16:10 +02001221static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001222type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001223 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001224{
1225 int i;
1226
1227 switch (base) {
1228 case LY_TYPE_BINARY:
1229 if (old->info.binary.length) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001230 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001231 }
1232 break;
1233
1234 case LY_TYPE_BITS:
1235 new->info.bits.count = old->info.bits.count;
1236 if (new->info.bits.count) {
1237 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1238 if (!new->info.bits.bit) {
1239 LOGMEM;
1240 return -1;
1241 }
1242 for (i = 0; i < new->info.bits.count; i++) {
1243 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1244 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1245 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1246 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1247 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001248 new->info.bits.bit[i].ext_size = old->info.bits.bit[i].ext_size;
1249 if (lys_ext_dup(mod->ctx, old->info.bits.bit[i].ext, old->info.bits.bit[i].ext_size,
1250 &new->info.bits.bit[i], LYEXT_PAR_TYPE_BIT,
1251 &new->info.bits.bit[i].ext, unres)) {
1252 return -1;
1253 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001254 }
1255 }
1256 break;
1257
1258 case LY_TYPE_DEC64:
1259 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001260 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001261 if (old->info.dec64.range) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001262 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001263 }
1264 break;
1265
1266 case LY_TYPE_ENUM:
1267 new->info.enums.count = old->info.enums.count;
1268 if (new->info.enums.count) {
1269 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1270 if (!new->info.enums.enm) {
1271 LOGMEM;
1272 return -1;
1273 }
1274 for (i = 0; i < new->info.enums.count; i++) {
1275 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1276 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1277 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1278 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1279 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001280 new->info.enums.enm[i].ext_size = old->info.enums.enm[i].ext_size;
1281 if (lys_ext_dup(mod->ctx, old->info.enums.enm[i].ext, old->info.enums.enm[i].ext_size,
1282 &new->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM,
1283 &new->info.enums.enm[i].ext, unres)) {
1284 return -1;
1285 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001286 }
1287 }
1288 break;
1289
1290 case LY_TYPE_IDENT:
Michal Vaskoaffc37f2016-10-10 18:05:03 +00001291 new->info.ident.count = old->info.ident.count;
Michal Vasko878e38d2016-09-05 12:17:53 +02001292 if (old->info.ident.count) {
1293 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1294 if (!new->info.ident.ref) {
1295 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001296 return -1;
1297 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001298 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1299 } else {
1300 /* there can be several unresolved base identities, duplicate them all */
1301 i = -1;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001302 do {
1303 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1304 if (i != -1) {
1305 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1306 return -1;
1307 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001308 }
1309 --i;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001310 } while (i > -1);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001311 }
1312 break;
1313
1314 case LY_TYPE_INST:
1315 new->info.inst.req = old->info.inst.req;
1316 break;
1317
1318 case LY_TYPE_INT8:
1319 case LY_TYPE_INT16:
1320 case LY_TYPE_INT32:
1321 case LY_TYPE_INT64:
1322 case LY_TYPE_UINT8:
1323 case LY_TYPE_UINT16:
1324 case LY_TYPE_UINT32:
1325 case LY_TYPE_UINT64:
1326 if (old->info.num.range) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001327 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001328 }
1329 break;
1330
1331 case LY_TYPE_LEAFREF:
1332 if (old->info.lref.path) {
1333 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001334 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001335 return -1;
1336 }
1337 }
1338 break;
1339
1340 case LY_TYPE_STRING:
1341 if (old->info.str.length) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001342 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001343 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01001344 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001345 new->info.str.pat_count = old->info.str.pat_count;
1346 break;
1347
1348 case LY_TYPE_UNION:
1349 new->info.uni.count = old->info.uni.count;
1350 if (new->info.uni.count) {
1351 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1352 if (!new->info.uni.types) {
1353 LOGMEM;
1354 return -1;
1355 }
1356 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001357 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 +02001358 return -1;
1359 }
1360 }
1361 }
1362 break;
1363
1364 default:
1365 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1366 break;
1367 }
1368 return EXIT_SUCCESS;
1369}
1370
1371struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001372lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1373 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001374{
1375 struct yang_type *new;
1376
1377 new = calloc(1, sizeof *new);
1378 if (!new) {
1379 LOGMEM;
1380 return NULL;
1381 }
1382 new->flags = old->flags;
1383 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001384 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001385 new->type = type;
1386 if (!new->name) {
1387 LOGMEM;
1388 goto error;
1389 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001390 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001391 new->type->base = new->base;
1392 lys_type_free(module->ctx, new->type);
1393 memset(&new->type->info, 0, sizeof new->type->info);
1394 goto error;
1395 }
1396 return new;
1397
1398 error:
1399 free(new);
1400 return NULL;
1401}
1402
Radek Krejci43ce4b72017-01-04 11:02:38 +01001403API const void *
1404lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1405{
1406 if (!ext) {
1407 return NULL;
1408 }
1409
1410 switch (ext->substmt) {
1411 case LYEXT_SUBSTMT_SELF:
1412 case LYEXT_SUBSTMT_MODIFIER:
1413 case LYEXT_SUBSTMT_VERSION:
1414 return NULL;
1415 case LYEXT_SUBSTMT_ARGUMENT:
1416 if (ext->parent_type == LYEXT_PAR_EXT) {
1417 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1418 }
1419 break;
1420 case LYEXT_SUBSTMT_BASE:
1421 if (ext->parent_type == LYEXT_PAR_TYPE) {
1422 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->substmt_index];
1423 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
1424 return ((struct lys_ident*)ext->parent)->base[ext->substmt_index];
1425 }
1426 break;
1427 case LYEXT_SUBSTMT_BELONGSTO:
1428 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1429 return ((struct lys_submodule*)ext->parent)->belongsto;
1430 }
1431 break;
1432 case LYEXT_SUBSTMT_CONFIG:
1433 case LYEXT_SUBSTMT_MANDATORY:
1434 if (ext->parent_type == LYEXT_PAR_NODE) {
1435 return &((struct lys_node*)ext->parent)->flags;
1436 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1437 return &((struct lys_deviate*)ext->parent)->flags;
1438 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1439 return &((struct lys_refine*)ext->parent)->flags;
1440 }
1441 break;
1442 case LYEXT_SUBSTMT_CONTACT:
1443 if (ext->parent_type == LYEXT_PAR_MODULE) {
1444 return ((struct lys_module*)ext->parent)->contact;
1445 }
1446 break;
1447 case LYEXT_SUBSTMT_DEFAULT:
1448 if (ext->parent_type == LYEXT_PAR_NODE) {
1449 switch (((struct lys_node*)ext->parent)->nodetype) {
1450 case LYS_LEAF:
1451 case LYS_LEAFLIST:
1452 /* in case of leaf, the index is supposed to be 0, so it will return the
1453 * correct pointer despite the leaf structure does not have dflt as array */
1454 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->substmt_index];
1455 case LYS_CHOICE:
1456 return ((struct lys_node_choice*)ext->parent)->dflt;
1457 default:
1458 /* internal error */
1459 break;
1460 }
1461 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1462 return ((struct lys_tpdf*)ext->parent)->dflt;
1463 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1464 return ((struct lys_deviate*)ext->parent)->dflt[ext->substmt_index];
1465 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1466 return &((struct lys_refine*)ext->parent)->dflt[ext->substmt_index];
1467 }
1468 break;
1469 case LYEXT_SUBSTMT_DESCRIPTION:
1470 switch (ext->parent_type) {
1471 case LYEXT_PAR_NODE:
1472 return ((struct lys_node*)ext->parent)->dsc;
1473 case LYEXT_PAR_MODULE:
1474 return ((struct lys_module*)ext->parent)->dsc;
1475 case LYEXT_PAR_IMPORT:
1476 return ((struct lys_import*)ext->parent)->dsc;
1477 case LYEXT_PAR_INCLUDE:
1478 return ((struct lys_include*)ext->parent)->dsc;
1479 case LYEXT_PAR_EXT:
1480 return ((struct lys_ext*)ext->parent)->dsc;
1481 case LYEXT_PAR_FEATURE:
1482 return ((struct lys_feature*)ext->parent)->dsc;
1483 case LYEXT_PAR_TPDF:
1484 return ((struct lys_tpdf*)ext->parent)->dsc;
1485 case LYEXT_PAR_TYPE_BIT:
1486 return ((struct lys_type_bit*)ext->parent)->dsc;
1487 case LYEXT_PAR_TYPE_ENUM:
1488 return ((struct lys_type_enum*)ext->parent)->dsc;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001489 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001490 return ((struct lys_restr*)ext->parent)->dsc;
1491 case LYEXT_PAR_WHEN:
1492 return ((struct lys_when*)ext->parent)->dsc;
1493 case LYEXT_PAR_IDENT:
1494 return ((struct lys_ident*)ext->parent)->dsc;
1495 case LYEXT_PAR_DEVIATION:
1496 return ((struct lys_deviation*)ext->parent)->dsc;
1497 case LYEXT_PAR_REVISION:
1498 return ((struct lys_revision*)ext->parent)->dsc;
1499 case LYEXT_PAR_REFINE:
1500 return ((struct lys_refine*)ext->parent)->dsc;
1501 default:
1502 break;
1503 }
1504 break;
1505 case LYEXT_SUBSTMT_ERRTAG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001506 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001507 return ((struct lys_restr*)ext->parent)->eapptag;
1508 }
1509 break;
1510 case LYEXT_SUBSTMT_ERRMSG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001511 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001512 return ((struct lys_restr*)ext->parent)->emsg;
1513 }
1514 break;
1515 case LYEXT_SUBSTMT_DIGITS:
1516 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
1517 return &((struct lys_type*)ext->parent)->info.dec64.dig;
1518 }
1519 break;
1520 case LYEXT_SUBSTMT_KEY:
1521 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1522 return ((struct lys_node_list*)ext->parent)->keys;
1523 }
1524 break;
1525 case LYEXT_SUBSTMT_MAX:
1526 if (ext->parent_type == LYEXT_PAR_NODE) {
1527 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1528 return &((struct lys_node_list*)ext->parent)->max;
1529 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1530 return &((struct lys_node_leaflist*)ext->parent)->max;
1531 }
1532 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1533 return &((struct lys_refine*)ext->parent)->mod.list.max;
1534 }
1535 break;
1536 case LYEXT_SUBSTMT_MIN:
1537 if (ext->parent_type == LYEXT_PAR_NODE) {
1538 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1539 return &((struct lys_node_list*)ext->parent)->min;
1540 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1541 return &((struct lys_node_leaflist*)ext->parent)->min;
1542 }
1543 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1544 return &((struct lys_refine*)ext->parent)->mod.list.min;
1545 }
1546 break;
1547 case LYEXT_SUBSTMT_NAMESPACE:
1548 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
1549 return ((struct lys_module*)ext->parent)->ns;
1550 }
1551 break;
1552 case LYEXT_SUBSTMT_ORDEREDBY:
1553 if (ext->parent_type == LYEXT_PAR_NODE &&
1554 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
1555 return &((struct lys_node_list*)ext->parent)->flags;
1556 }
1557 break;
1558 case LYEXT_SUBSTMT_ORGANIZATION:
1559 if (ext->parent_type == LYEXT_PAR_MODULE) {
1560 return ((struct lys_module*)ext->parent)->org;
1561 }
1562 break;
1563 case LYEXT_SUBSTMT_PATH:
1564 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1565 return ((struct lys_type*)ext->parent)->info.lref.path;
1566 }
1567 break;
1568 case LYEXT_SUBSTMT_POSITION:
1569 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
1570 return &((struct lys_type_bit*)ext->parent)->pos;
1571 }
1572 break;
1573 case LYEXT_SUBSTMT_PREFIX:
1574 if (ext->parent_type == LYEXT_PAR_MODULE) {
1575 /* covers also lys_submodule */
1576 return ((struct lys_module*)ext->parent)->prefix;
1577 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
1578 return ((struct lys_import*)ext->parent)->prefix;
1579 }
1580 break;
1581 case LYEXT_SUBSTMT_PRESENCE:
1582 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
1583 return ((struct lys_node_container*)ext->parent)->presence;
1584 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1585 return ((struct lys_refine*)ext->parent)->mod.presence;
1586 }
1587 break;
1588 case LYEXT_SUBSTMT_REFERENCE:
1589 switch (ext->parent_type) {
1590 case LYEXT_PAR_NODE:
1591 return ((struct lys_node*)ext->parent)->ref;
1592 case LYEXT_PAR_MODULE:
1593 return ((struct lys_module*)ext->parent)->ref;
1594 case LYEXT_PAR_IMPORT:
1595 return ((struct lys_import*)ext->parent)->ref;
1596 case LYEXT_PAR_INCLUDE:
1597 return ((struct lys_include*)ext->parent)->ref;
1598 case LYEXT_PAR_EXT:
1599 return ((struct lys_ext*)ext->parent)->ref;
1600 case LYEXT_PAR_FEATURE:
1601 return ((struct lys_feature*)ext->parent)->ref;
1602 case LYEXT_PAR_TPDF:
1603 return ((struct lys_tpdf*)ext->parent)->ref;
1604 case LYEXT_PAR_TYPE_BIT:
1605 return ((struct lys_type_bit*)ext->parent)->ref;
1606 case LYEXT_PAR_TYPE_ENUM:
1607 return ((struct lys_type_enum*)ext->parent)->ref;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001608 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001609 return ((struct lys_restr*)ext->parent)->ref;
1610 case LYEXT_PAR_WHEN:
1611 return ((struct lys_when*)ext->parent)->ref;
1612 case LYEXT_PAR_IDENT:
1613 return ((struct lys_ident*)ext->parent)->ref;
1614 case LYEXT_PAR_DEVIATION:
1615 return ((struct lys_deviation*)ext->parent)->ref;
1616 case LYEXT_PAR_REVISION:
1617 return ((struct lys_revision*)ext->parent)->ref;
1618 case LYEXT_PAR_REFINE:
1619 return ((struct lys_refine*)ext->parent)->ref;
1620 default:
1621 break;
1622 }
1623 break;
1624 case LYEXT_SUBSTMT_REQINST:
1625 if (ext->parent_type == LYEXT_PAR_TYPE) {
1626 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1627 return &((struct lys_type*)ext->parent)->info.lref.req;
1628 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
1629 return &((struct lys_type*)ext->parent)->info.inst.req;
1630 }
1631 }
1632 break;
1633 case LYEXT_SUBSTMT_REVISIONDATE:
1634 if (ext->parent_type == LYEXT_PAR_IMPORT) {
1635 return ((struct lys_import*)ext->parent)->rev;
1636 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
1637 return ((struct lys_include*)ext->parent)->rev;
1638 }
1639 break;
1640 case LYEXT_SUBSTMT_STATUS:
1641 switch (ext->parent_type) {
1642 case LYEXT_PAR_NODE:
1643 case LYEXT_PAR_IDENT:
1644 case LYEXT_PAR_TPDF:
1645 case LYEXT_PAR_EXT:
1646 case LYEXT_PAR_FEATURE:
1647 case LYEXT_PAR_TYPE_ENUM:
1648 case LYEXT_PAR_TYPE_BIT:
1649 /* in all structures the flags member is at the same offset */
1650 return &((struct lys_node*)ext->parent)->flags;
1651 default:
1652 break;
1653 }
1654 break;
1655 case LYEXT_SUBSTMT_UNIQUE:
1656 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1657 return &((struct lys_deviate*)ext->parent)->unique[ext->substmt_index];
1658 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1659 return &((struct lys_node_list*)ext->parent)->unique[ext->substmt_index];
1660 }
1661 break;
1662 case LYEXT_SUBSTMT_UNITS:
1663 if (ext->parent_type == LYEXT_PAR_NODE &&
1664 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1665 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
1666 return ((struct lys_node_leaf*)ext->parent)->units;
1667 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1668 return ((struct lys_tpdf*)ext->parent)->units;
1669 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1670 return ((struct lys_deviate*)ext->parent)->units;
1671 }
1672 break;
1673 case LYEXT_SUBSTMT_VALUE:
1674 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
1675 return &((struct lys_type_enum*)ext->parent)->value;
1676 }
1677 break;
1678 case LYEXT_SUBSTMT_YINELEM:
1679 if (ext->parent_type == LYEXT_PAR_EXT) {
1680 return &((struct lys_ext*)ext->parent)->flags;
1681 }
1682 break;
1683 }
1684 LOGINT;
1685 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01001686}
1687
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001688static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001689lys_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 +02001690 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001691{
1692 int i;
1693
Michal Vasko1dca6882015-10-22 14:29:42 +02001694 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001695 new->base = old->base;
1696 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001697 new->parent = (struct lys_tpdf *)parent;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001698 new->ext_size = old->ext_size;
1699 if (lys_ext_dup(mod->ctx, old->ext, old->ext_size, new, LYEXT_PAR_TYPE, &new->ext, unres)) {
1700 return -1;
Radek Krejcie534c132016-11-23 13:32:31 +01001701 }
Radek Krejci3733a802015-06-19 13:43:21 +02001702
Michal Vasko878e38d2016-09-05 12:17:53 +02001703 i = unres_schema_find(unres, -1, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001704 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001705 /* HACK (serious one) for unres */
1706 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001707 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001708 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 +02001709 } else {
1710 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1711 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001712 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001713 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001714 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001715 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001716 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001717 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001718 }
1719
Radek Krejci3a5501d2016-07-18 22:03:34 +02001720 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001721}
1722
1723void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001724lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001725{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001726 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001728 assert(ctx);
1729 if (!type) {
1730 return;
1731 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001732
Michal Vasko1dca6882015-10-22 14:29:42 +02001733 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001734
Radek Krejcie534c132016-11-23 13:32:31 +01001735 lys_extension_instances_free(ctx, type->ext, type->ext_size);
1736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001737 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001738 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001739 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001740 free(type->info.binary.length);
1741 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001742 case LY_TYPE_BITS:
1743 for (i = 0; i < type->info.bits.count; i++) {
1744 lydict_remove(ctx, type->info.bits.bit[i].name);
1745 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1746 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001747 lys_iffeature_free(ctx, type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci9b15fea2017-01-23 11:31:43 +01001748 lys_extension_instances_free(ctx, type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001749 }
1750 free(type->info.bits.bit);
1751 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001752
1753 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001754 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001755 free(type->info.dec64.range);
1756 break;
1757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 case LY_TYPE_ENUM:
1759 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001760 lydict_remove(ctx, type->info.enums.enm[i].name);
1761 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1762 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001763 lys_iffeature_free(ctx, type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci9b15fea2017-01-23 11:31:43 +01001764 lys_extension_instances_free(ctx, type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001766 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001767 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001768
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001769 case LY_TYPE_INT8:
1770 case LY_TYPE_INT16:
1771 case LY_TYPE_INT32:
1772 case LY_TYPE_INT64:
1773 case LY_TYPE_UINT8:
1774 case LY_TYPE_UINT16:
1775 case LY_TYPE_UINT32:
1776 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001777 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001778 free(type->info.num.range);
1779 break;
1780
Radek Krejcidc4c1412015-06-19 15:39:54 +02001781 case LY_TYPE_LEAFREF:
1782 lydict_remove(ctx, type->info.lref.path);
1783 break;
1784
Radek Krejci3733a802015-06-19 13:43:21 +02001785 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001786 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001787 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001788 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001789 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001790 }
1791 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001792 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001793
Radek Krejcie4c366b2015-07-02 10:11:31 +02001794 case LY_TYPE_UNION:
1795 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001796 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001797 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001798 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001799 break;
1800
Michal Vaskod3282192016-09-05 11:27:57 +02001801 case LY_TYPE_IDENT:
1802 free(type->info.ident.ref);
1803 break;
1804
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001805 default:
Michal Vaskod3282192016-09-05 11:27:57 +02001806 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001807 break;
1808 }
Radek Krejci5a065542015-05-22 15:02:07 +02001809}
1810
Radek Krejci1d82ef62015-08-07 14:44:40 +02001811static void
1812lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001813{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001814 assert(ctx);
1815 if (!tpdf) {
1816 return;
1817 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001819 lydict_remove(ctx, tpdf->name);
1820 lydict_remove(ctx, tpdf->dsc);
1821 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001822
Radek Krejci1d82ef62015-08-07 14:44:40 +02001823 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001824
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001825 lydict_remove(ctx, tpdf->units);
1826 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01001827
1828 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001829}
1830
Radek Krejci1d82ef62015-08-07 14:44:40 +02001831static struct lys_when *
Radek Krejcif0bb3602017-01-25 17:05:08 +01001832lys_when_dup(struct ly_ctx *ctx, struct lys_when *old, struct unres_schema *unres)
Radek Krejci00768f42015-06-18 17:04:04 +02001833{
Radek Krejci76512572015-08-04 09:47:08 +02001834 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001835
1836 if (!old) {
1837 return NULL;
1838 }
1839
1840 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001841 if (!new) {
1842 LOGMEM;
1843 return NULL;
1844 }
Radek Krejci00768f42015-06-18 17:04:04 +02001845 new->cond = lydict_insert(ctx, old->cond, 0);
1846 new->dsc = lydict_insert(ctx, old->dsc, 0);
1847 new->ref = lydict_insert(ctx, old->ref, 0);
Radek Krejcif0bb3602017-01-25 17:05:08 +01001848 new->ext_size = old->ext_size;
1849 lys_ext_dup(ctx, old->ext, old->ext_size, new, LYEXT_PAR_WHEN, &new->ext, unres);
Radek Krejci00768f42015-06-18 17:04:04 +02001850
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
Radek Krejci5323b492017-01-16 15:40:11 +01001861 lys_extension_instances_free(ctx, w->ext, w->ext_size);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001862 lydict_remove(ctx, w->cond);
1863 lydict_remove(ctx, w->dsc);
1864 lydict_remove(ctx, w->ref);
1865
1866 free(w);
1867}
1868
Radek Krejcib7f5e412015-08-13 10:15:51 +02001869static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001870lys_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 +02001871{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001872 struct lys_node *next, *sub;
1873
Radek Krejcic071c542016-01-27 14:57:51 +01001874 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01001875 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001876 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001877 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001878 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001879 }
1880
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001881 lydict_remove(ctx, aug->target_name);
1882 lydict_remove(ctx, aug->dsc);
1883 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001884
Radek Krejci5323b492017-01-16 15:40:11 +01001885 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01001886 lys_extension_instances_free(ctx, aug->ext, aug->ext_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001887
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001888 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001889}
1890
Radek Krejci76512572015-08-04 09:47:08 +02001891static struct lys_node_augment *
Radek Krejcif0bb3602017-01-25 17:05:08 +01001892lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size,
1893 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001894{
Radek Krejci76512572015-08-04 09:47:08 +02001895 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001896 struct lys_node *old_child, *new_child;
1897 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 if (!size) {
1900 return NULL;
1901 }
Radek Krejci106efc02015-06-10 14:36:27 +02001902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001903 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001904 if (!new) {
1905 LOGMEM;
1906 return NULL;
1907 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001908 for (i = 0; i < size; i++) {
1909 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1910 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1911 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1912 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001913 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001914 new[i].nodetype = old[i].nodetype;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001915 new[i].ext_size = old[i].ext_size;
1916 lys_ext_dup(module->ctx, old[i].ext, old[i].ext_size, &new[i], LYEXT_PAR_REFINE, &new[i].ext, unres);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001917
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001918 /* this must succeed, it was already resolved once */
Radek Krejcidf46e222016-11-08 11:57:37 +01001919 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL, 1,
Michal Vasko3edeaf72016-02-11 13:17:43 +01001920 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001921 LOGINT;
1922 free(new);
1923 return NULL;
1924 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001926
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001927 /* Correct the augment nodes.
1928 * This function can only be called from lys_node_dup() with uses
1929 * being the node duplicated, so we must have a case of grouping
1930 * with a uses with augments. The augmented nodes have already been
1931 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001932 * (it was set to their actual data parent, not an augment), and
1933 * the new augment does not have child pointer to its augment nodes,
1934 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001935 */
1936 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001937 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001938 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001939 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001940 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001941 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001942 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001943 LY_TREE_FOR(old[i].child, old_child) {
1944 /* all augment nodes were connected as siblings, there can be no more after this */
1945 if (old_child->parent != (struct lys_node *)&old[i]) {
1946 break;
1947 }
1948
Radek Krejci749190d2016-02-18 16:26:25 +01001949 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001950
1951 new_child->parent = (struct lys_node *)&new[i];
1952 new_child = new_child->next;
1953 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001954 }
Radek Krejci106efc02015-06-10 14:36:27 +02001955
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001956 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001957}
1958
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001959static const char **
1960lys_dflt_dup(struct ly_ctx *ctx, const char **old, int size)
1961{
1962 int i;
1963 const char **result;
1964
1965 if (!size) {
1966 return NULL;
1967 }
1968
1969 result = calloc(size, sizeof *result);
1970 if (!result) {
1971 LOGMEM;
1972 return NULL;
1973 }
1974
1975 for (i = 0; i < size; i++) {
1976 result[i] = lydict_insert(ctx, old[i], 0);
1977 }
1978 return result;
1979}
1980
Radek Krejci76512572015-08-04 09:47:08 +02001981static struct lys_refine *
Radek Krejcifdc0d702017-01-23 15:58:38 +01001982lys_refine_dup(struct ly_ctx *ctx, struct lys_refine *old, int size, struct unres_schema *unres)
Michal Vasko1982cad2015-06-08 15:49:30 +02001983{
Radek Krejci76512572015-08-04 09:47:08 +02001984 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001985 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001987 if (!size) {
1988 return NULL;
1989 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001991 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001992 if (!result) {
1993 LOGMEM;
1994 return NULL;
1995 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001996 for (i = 0; i < size; i++) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001997 result[i].target_name = lydict_insert(ctx, old[i].target_name, 0);
1998 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1999 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002000 result[i].flags = old[i].flags;
2001 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002003 result[i].must_size = old[i].must_size;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002004 result[i].must = lys_restr_dup(ctx, old[i].must, old[i].must_size, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002005
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002006 result[i].dflt_size = old[i].dflt_size;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002007 result[i].dflt = lys_dflt_dup(ctx, old[i].dflt, old[i].dflt_size);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002008
2009 if (result[i].target_type == LYS_CONTAINER) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01002010 result[i].mod.presence = lydict_insert(ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02002011 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002012 result[i].mod.list = old[i].mod.list;
2013 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01002014 result[i].ext_size = old[i].ext_size;
2015 lys_ext_dup(ctx, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_REFINE, &result[i].ext, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002016 }
Michal Vasko1982cad2015-06-08 15:49:30 +02002017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02002019}
2020
Radek Krejci1d82ef62015-08-07 14:44:40 +02002021static void
2022lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02002023{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002024 assert(ctx);
2025 if (!ident) {
2026 return;
2027 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002028
Radek Krejci018f1f52016-08-03 16:01:20 +02002029 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02002030 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002031 lydict_remove(ctx, ident->name);
2032 lydict_remove(ctx, ident->dsc);
2033 lydict_remove(ctx, ident->ref);
Radek Krejci5323b492017-01-16 15:40:11 +01002034 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01002035 lys_extension_instances_free(ctx, ident->ext, ident->ext_size);
Radek Krejci6793db02015-05-22 17:49:54 +02002036
2037}
2038
Radek Krejci1d82ef62015-08-07 14:44:40 +02002039static void
2040lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002041{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002042 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002043
Radek Krejcid12f57b2015-08-06 10:43:39 +02002044 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002045 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002046 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 }
2048 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002049}
2050
Radek Krejci1d82ef62015-08-07 14:44:40 +02002051static void
Michal Vasko44fb6382016-06-29 11:12:27 +02002052lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02002053{
2054 int i;
2055
2056 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
2057 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002058 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002059 }
2060 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002061
2062 for (i = 0; i < io->must_size; i++) {
2063 lys_restr_free(ctx, &io->must[i]);
2064 }
2065 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002066}
2067
Radek Krejci1d82ef62015-08-07 14:44:40 +02002068static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02002069lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
2070{
2071 int i;
2072
2073 for (i = 0; i < notif->must_size; i++) {
2074 lys_restr_free(ctx, &notif->must[i]);
2075 }
2076 free(notif->must);
2077
2078 for (i = 0; i < notif->tpdf_size; i++) {
2079 lys_tpdf_free(ctx, &notif->tpdf[i]);
2080 }
2081 free(notif->tpdf);
2082}
2083static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02002084lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02002085{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002088 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002089 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 }
2091 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002092
Radek Krejci1d82ef62015-08-07 14:44:40 +02002093 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002094}
2095
Radek Krejci1d82ef62015-08-07 14:44:40 +02002096static void
2097lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02002098{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002100
Radek Krejci85a54be2016-10-20 12:39:56 +02002101 /* leafref backlinks */
2102 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002105 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 }
2107 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002108
Radek Krejci1d82ef62015-08-07 14:44:40 +02002109 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002110
Radek Krejci1d82ef62015-08-07 14:44:40 +02002111 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 lydict_remove(ctx, leaf->units);
2113 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002114}
2115
Radek Krejci1d82ef62015-08-07 14:44:40 +02002116static void
2117lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02002118{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002120
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002121 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002122 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002123 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002124 }
2125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002127 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 }
2129 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002130
Pavol Vican38321d02016-08-16 14:56:02 +02002131 for (i = 0; i < llist->dflt_size; i++) {
2132 lydict_remove(ctx, llist->dflt[i]);
2133 }
2134 free(llist->dflt);
2135
Radek Krejci1d82ef62015-08-07 14:44:40 +02002136 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002137
Radek Krejci1d82ef62015-08-07 14:44:40 +02002138 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002140}
2141
Radek Krejci1d82ef62015-08-07 14:44:40 +02002142static void
2143lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002144{
Radek Krejci581ce772015-11-10 17:22:40 +01002145 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 /* handle only specific parts for LY_NODE_LIST */
2148 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002149 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 }
2151 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002154 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002155 }
2156 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002157
Radek Krejci1d82ef62015-08-07 14:44:40 +02002158 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002161 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002162 lydict_remove(ctx, list->unique[i].expr[j]);
2163 }
2164 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002165 }
2166 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002169}
2170
Radek Krejci1d82ef62015-08-07 14:44:40 +02002171static void
2172lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002173{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002174 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 /* handle only specific parts for LY_NODE_CONTAINER */
2177 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002180 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002181 }
2182 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002185 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 }
2187 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002188
Radek Krejci1d82ef62015-08-07 14:44:40 +02002189 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002190}
2191
Radek Krejci1d82ef62015-08-07 14:44:40 +02002192static void
2193lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02002194{
2195 lydict_remove(ctx, f->name);
2196 lydict_remove(ctx, f->dsc);
2197 lydict_remove(ctx, f->ref);
Radek Krejci5323b492017-01-16 15:40:11 +01002198 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size);
Radek Krejci9de2c042016-10-19 16:53:06 +02002199 ly_set_free(f->depfeatures);
Radek Krejcie534c132016-11-23 13:32:31 +01002200 lys_extension_instances_free(ctx, f->ext, f->ext_size);
2201}
2202
2203static void
2204lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e)
2205{
2206 lydict_remove(ctx, e->name);
2207 lydict_remove(ctx, e->dsc);
2208 lydict_remove(ctx, e->ref);
2209 lydict_remove(ctx, e->argument);
2210 lys_extension_instances_free(ctx, e->ext, e->ext_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002211}
2212
Radek Krejci1d82ef62015-08-07 14:44:40 +02002213static void
Michal Vaskoff006c12016-02-17 11:15:19 +01002214lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02002215{
Radek Krejci581ce772015-11-10 17:22:40 +01002216 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002217 struct ly_ctx *ctx;
2218 struct lys_node *next, *elem;
2219
2220 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002221
2222 lydict_remove(ctx, dev->target_name);
2223 lydict_remove(ctx, dev->dsc);
2224 lydict_remove(ctx, dev->ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002225 lys_extension_instances_free(ctx, dev->ext, dev->ext_size);
Radek Krejcieb00f512015-07-01 16:44:58 +02002226
Pavol Vican64d0b762016-08-25 10:44:59 +02002227 if (!dev->deviate) {
2228 return ;
2229 }
2230
Michal Vaskoff006c12016-02-17 11:15:19 +01002231 /* the module was freed, but we only need the context from orig_node, use ours */
2232 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2233 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2234 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2235 elem->module = module;
2236
2237 LY_TREE_DFS_END(dev->orig_node, next, elem);
2238 }
2239 lys_node_free(dev->orig_node, NULL, 0);
2240 } else {
2241 /* it's just a shallow copy, freeing one node */
2242 dev->orig_node->module = module;
2243 lys_node_free(dev->orig_node, NULL, 1);
2244 }
2245
Radek Krejcieb00f512015-07-01 16:44:58 +02002246 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002247 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size);
2248
Radek Krejcid5a5c282016-08-15 15:38:08 +02002249 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002250 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002251 }
2252 free(dev->deviate[i].dflt);
2253
Radek Krejcieb00f512015-07-01 16:44:58 +02002254 lydict_remove(ctx, dev->deviate[i].units);
2255
2256 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2257 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002258 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002259 }
2260 free(dev->deviate[i].must);
2261
2262 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002263 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2264 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2265 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002266 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002267 }
2268 free(dev->deviate[i].unique);
2269 }
2270 }
2271 free(dev->deviate);
2272}
2273
Radek Krejci1d82ef62015-08-07 14:44:40 +02002274static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002275lys_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 +02002276{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002278
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002280 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 lydict_remove(ctx, uses->refine[i].dsc);
2282 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002283
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002284 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002285 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286 }
2287 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002288
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002289 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002290 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002291 }
2292 free(uses->refine[i].dflt);
2293
Radek Krejcie534c132016-11-23 13:32:31 +01002294 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size);
2295
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002296 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 lydict_remove(ctx, uses->refine[i].mod.presence);
2298 }
2299 }
2300 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002303 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 }
2305 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002306
Radek Krejci1d82ef62015-08-07 14:44:40 +02002307 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002308}
2309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002311lys_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 +02002312{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002313 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002314 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 if (!node) {
2317 return;
2318 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 assert(node->module);
2321 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002324
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002325 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002326 if (node->priv && private_destructor) {
2327 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002328 }
2329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002331 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002332 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci5323b492017-01-16 15:40:11 +01002333 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002334 lydict_remove(ctx, node->dsc);
2335 lydict_remove(ctx, node->ref);
2336 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002337
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002338 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002339 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002340 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002341 }
2342 }
2343
Radek Krejcie534c132016-11-23 13:32:31 +01002344 lys_extension_instances_free(ctx, node->ext, node->ext_size);
2345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 /* specific part */
2347 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002348 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002349 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002350 break;
Radek Krejci76512572015-08-04 09:47:08 +02002351 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002352 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002353 break;
Radek Krejci76512572015-08-04 09:47:08 +02002354 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002355 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 break;
Radek Krejci76512572015-08-04 09:47:08 +02002357 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002358 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002359 break;
Radek Krejci76512572015-08-04 09:47:08 +02002360 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002361 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002362 break;
Radek Krejci76512572015-08-04 09:47:08 +02002363 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002364 case LYS_ANYDATA:
2365 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002366 break;
Radek Krejci76512572015-08-04 09:47:08 +02002367 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002368 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002369 break;
Radek Krejci76512572015-08-04 09:47:08 +02002370 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002371 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002372 break;
Radek Krejci76512572015-08-04 09:47:08 +02002373 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 /* do nothing */
2375 break;
Radek Krejci76512572015-08-04 09:47:08 +02002376 case LYS_GROUPING:
2377 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002378 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002379 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002381 case LYS_NOTIF:
2382 lys_notif_free(ctx, (struct lys_node_notif *)node);
2383 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002384 case LYS_INPUT:
2385 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02002386 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002387 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02002388 case LYS_UNKNOWN:
2389 LOGINT;
2390 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002391 }
Radek Krejci5a065542015-05-22 15:02:07 +02002392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002393 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002394 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002396}
2397
Radek Krejci2eee5c02016-12-06 19:18:05 +01002398API struct lys_module *
2399lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002400{
2401 struct ly_ctx *ctx;
2402 int i;
2403
2404 if (!mod || mod->implemented) {
2405 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002406 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002407 }
2408
2409 ctx = mod->ctx;
2410 for (i = 0; i < ctx->models.used; i++) {
2411 if (!ctx->models.list[i]->implemented) {
2412 continue;
2413 }
2414
2415 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2416 /* we have some revision of the module implemented */
2417 return ctx->models.list[i];
2418 }
2419 }
2420
2421 /* we have no revision of the module implemented, return the module itself,
2422 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002423 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002424}
2425
2426const struct lys_module *
Radek Krejcie534c132016-11-23 13:32:31 +01002427lys_get_import_module_ns(const struct lys_module *module, const char *ns)
2428{
2429 int i;
2430
2431 assert(module && ns);
2432
Radek Krejcic789d692017-01-11 11:31:14 +01002433 if (module->type) {
2434 /* the module is actually submodule and to get the namespace, we need the main module */
2435 if (ly_strequal(((struct lys_submodule *)module)->belongsto->ns, ns, 0)) {
2436 return ((struct lys_submodule *)module)->belongsto;
2437 }
2438 } else {
2439 /* modul's own namespace */
2440 if (ly_strequal(module->ns, ns, 0)) {
2441 return module;
2442 }
Radek Krejcie534c132016-11-23 13:32:31 +01002443 }
2444
2445 /* imported modules */
2446 for (i = 0; i < module->imp_size; ++i) {
2447 if (ly_strequal(module->imp[i].module->ns, ns, 0)) {
2448 return module->imp[i].module;
2449 }
2450 }
2451
2452 return NULL;
2453}
2454
2455const struct lys_module *
Michal Vasko1e62a092015-12-01 12:27:20 +01002456lys_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 +02002457{
Radek Krejcic071c542016-01-27 14:57:51 +01002458 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02002459 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002460 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002461
Michal Vaskoa7789a82016-02-11 15:42:55 +01002462 assert(!prefix || !name);
2463
Michal Vaskob6729c62015-10-21 12:09:47 +02002464 if (prefix && !pref_len) {
2465 pref_len = strlen(prefix);
2466 }
2467 if (name && !name_len) {
2468 name_len = strlen(name);
2469 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002470
Radek Krejcic4283442016-04-22 09:19:27 +02002471 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002472
2473 /* module own prefix, submodule own prefix, (sub)module own name */
2474 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2475 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002476 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002477 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002478 }
2479
Michal Vasko89563fc2016-07-28 16:19:35 +02002480 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02002481 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002482 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2483 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002484 return module->imp[i].module;
2485 }
2486 }
2487
Michal Vasko89563fc2016-07-28 16:19:35 +02002488 /* module required by a foreign grouping, deviation, or submodule */
2489 if (name) {
2490 str = strndup(name, name_len);
2491 if (!str) {
2492 LOGMEM;
2493 return NULL;
2494 }
2495 main_module = ly_ctx_get_module(module->ctx, str, NULL);
2496 free(str);
2497 return main_module;
2498 }
2499
Michal Vasko8ce24d72015-10-21 11:27:26 +02002500 return NULL;
2501}
2502
Michal Vasko13b15832015-08-19 11:04:48 +02002503/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002504static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002505module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002506{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002507 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002508 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002509 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002511 assert(module->ctx);
2512 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002513
Michal Vaskob746fff2016-02-11 11:37:50 +01002514 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002515 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002516 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002517 lydict_remove(ctx, module->imp[i].dsc);
2518 lydict_remove(ctx, module->imp[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002519 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size);
Radek Krejci225376f2016-02-16 17:36:22 +01002520 }
Radek Krejcidce51452015-06-16 15:20:08 +02002521 free(module->imp);
2522
Radek Krejcic071c542016-01-27 14:57:51 +01002523 /* submodules don't have data tree, the data nodes
2524 * are placed in the main module altogether */
2525 if (!module->type) {
2526 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002527 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002528 }
Radek Krejci21181962015-06-30 14:11:00 +02002529 }
Radek Krejci5a065542015-05-22 15:02:07 +02002530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 lydict_remove(ctx, module->dsc);
2532 lydict_remove(ctx, module->ref);
2533 lydict_remove(ctx, module->org);
2534 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002535 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002536
Radek Krejcieb00f512015-07-01 16:44:58 +02002537 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538 for (i = 0; i < module->rev_size; i++) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01002539 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002540 lydict_remove(ctx, module->rev[i].dsc);
2541 lydict_remove(ctx, module->rev[i].ref);
2542 }
2543 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002544
Radek Krejcieb00f512015-07-01 16:44:58 +02002545 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002547 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002548 }
2549 module->ident_size = 0;
2550 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002551
Radek Krejcieb00f512015-07-01 16:44:58 +02002552 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002553 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002554 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 }
2556 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002557
Radek Krejcie534c132016-11-23 13:32:31 +01002558 /* extension instances */
2559 lys_extension_instances_free(ctx, module->ext, module->ext_size);
2560
Radek Krejcieb00f512015-07-01 16:44:58 +02002561 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002562 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002563 lydict_remove(ctx, module->inc[i].dsc);
2564 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002565 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size);
Radek Krejcic071c542016-01-27 14:57:51 +01002566 /* complete submodule free is done only from main module since
2567 * submodules propagate their includes to the main module */
2568 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002569 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002570 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 }
2572 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002573
Radek Krejcieb00f512015-07-01 16:44:58 +02002574 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002575 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002576 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002577 }
2578 free(module->augment);
2579
Radek Krejcieb00f512015-07-01 16:44:58 +02002580 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002581 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002582 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002583 }
2584 free(module->features);
2585
Radek Krejcieb00f512015-07-01 16:44:58 +02002586 /* deviations */
2587 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002588 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002589 }
2590 free(module->deviation);
2591
Radek Krejcie534c132016-11-23 13:32:31 +01002592 /* extensions */
2593 for (i = 0; i < module->extensions_size; i++) {
2594 lys_extension_free(ctx, &module->extensions[i]);
2595 }
2596 free(module->extensions);
2597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002598 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002599 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002600}
2601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002602void
Michal Vaskob746fff2016-02-11 11:37:50 +01002603lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002604{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002605 if (!submodule) {
2606 return;
2607 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002609 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002610 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002612 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002614 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002615}
2616
Radek Krejci3a5501d2016-07-18 22:03:34 +02002617static int
2618ingrouping(const struct lys_node *node)
2619{
2620 const struct lys_node *iter = node;
2621 assert(node);
2622
2623 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2624 if (!iter) {
2625 return 0;
2626 } else {
2627 return 1;
2628 }
2629}
2630
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002631/*
2632 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2633 */
2634static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002635lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002636 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002637{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002638 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002639 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002640 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002641 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002642 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002643 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002644
Michal Vaskoc07187d2015-08-13 15:20:57 +02002645 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002646 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002647 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002648 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002649 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002650 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002651 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002652 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002653 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002654 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002655 struct lys_node_anydata *any = NULL;
2656 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002657 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002658 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002659 struct lys_node_rpc_action *rpc = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002660 struct lys_node_inout *io = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002661 struct lys_node_rpc_action *ntf = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002662 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002663 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002665 /* we cannot just duplicate memory since the strings are stored in
2666 * dictionary and we need to update dictionary counters.
2667 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002668
Radek Krejci1d82ef62015-08-07 14:44:40 +02002669 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002670 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002671 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002672 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002673 break;
2674
Radek Krejci76512572015-08-04 09:47:08 +02002675 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002676 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002677 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002678 break;
2679
Radek Krejci76512572015-08-04 09:47:08 +02002680 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002681 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002682 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002683 break;
2684
Radek Krejci76512572015-08-04 09:47:08 +02002685 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002686 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002687 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002688 break;
2689
Radek Krejci76512572015-08-04 09:47:08 +02002690 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002691 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002692 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002693 break;
2694
Radek Krejci76512572015-08-04 09:47:08 +02002695 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002696 case LYS_ANYDATA:
2697 any = calloc(1, sizeof *any);
2698 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002699 break;
2700
Radek Krejci76512572015-08-04 09:47:08 +02002701 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002702 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002703 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002704 break;
2705
Radek Krejci76512572015-08-04 09:47:08 +02002706 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002707 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002708 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002709 break;
2710
Radek Krejci76512572015-08-04 09:47:08 +02002711 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002712 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002713 rpc = calloc(1, sizeof *rpc);
2714 retval = (struct lys_node *)rpc;
2715 break;
2716
Radek Krejci76512572015-08-04 09:47:08 +02002717 case LYS_INPUT:
2718 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002719 io = calloc(1, sizeof *io);
2720 retval = (struct lys_node *)io;
2721 break;
2722
Radek Krejci76512572015-08-04 09:47:08 +02002723 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002724 ntf = calloc(1, sizeof *ntf);
2725 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002726 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002728 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002729 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002730 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 }
Radek Krejcib388c152015-06-04 17:03:03 +02002732
Michal Vasko253035f2015-12-17 16:58:13 +01002733 if (!retval) {
2734 LOGMEM;
2735 return NULL;
2736 }
2737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 /*
2739 * duplicate generic part of the structure
2740 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002741 retval->name = lydict_insert(ctx, node->name, 0);
2742 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2743 retval->ref = lydict_insert(ctx, node->ref, 0);
2744 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002746 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002747 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002749 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002750
Radek Krejcif0bb3602017-01-25 17:05:08 +01002751 retval->ext_size = node->ext_size;
2752 if (lys_ext_dup(ctx, node->ext, node->ext_size, retval, LYEXT_PAR_NODE, &retval->ext, unres)) {
2753 goto error;
2754 }
2755
Radek Krejci06214042016-11-04 16:25:58 +01002756 if (node->iffeature_size) {
2757 retval->iffeature_size = node->iffeature_size;
2758 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2759 if (!retval->iffeature) {
2760 LOGMEM;
2761 goto error;
2762 }
Michal Vasko253035f2015-12-17 16:58:13 +01002763 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002764
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002765 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002766 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002767 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2768 if (size1) {
2769 /* there is something to duplicate */
2770
2771 /* duplicate compiled expression */
2772 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2773 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2774 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2775
2776 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002777 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002778 for (j = 0; (unsigned int)j < size2; j++) {
2779 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2780 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002781 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002782 /* feature is resolved in origin, so copy it
2783 * - duplication is used for instantiating groupings
2784 * and if-feature inside grouping is supposed to be
2785 * resolved inside the original grouping, so we want
2786 * to keep pointers to features from the grouping
2787 * context */
2788 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2789 } else if (rc == -1) {
2790 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002791 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002792 }
2793 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01002794
2795 /* duplicate if-feature's extensions */
2796 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
2797 if (lys_ext_dup(ctx, node->iffeature[i].ext, node->iffeature[i].ext_size,
2798 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, unres)) {
2799 goto error;
2800 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002802
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002803 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01002804 p = parent;
2805 do {
2806 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
2807 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002808 if (iter) {
2809 flags = iter->flags & LYS_CONFIG_MASK;
2810 } else {
2811 /* default */
2812 flags = LYS_CONFIG_W;
2813 }
2814
2815 switch (finalize) {
2816 case 1:
2817 /* inherit config flags */
2818 if (retval->flags & LYS_CONFIG_SET) {
2819 /* skip nodes with an explicit config value */
2820 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
2821 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +01002822 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002823 goto error;
2824 }
2825 break;
2826 }
2827
2828 if (retval->nodetype != LYS_USES) {
2829 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
2830 }
2831 break;
2832 case 2:
2833 /* erase config flags */
2834 retval->flags &= ~LYS_CONFIG_MASK;
2835 retval->flags &= ~LYS_CONFIG_SET;
2836 break;
2837 }
2838
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002839 /* connect it to the parent */
2840 if (lys_node_addchild(parent, retval->module, retval)) {
2841 goto error;
2842 }
Radek Krejcidce51452015-06-16 15:20:08 +02002843
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002844 /* go recursively */
2845 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002846 LY_TREE_FOR(node->child, iter) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002847 if (iter->nodetype & LYS_GROUPING) {
2848 /* do not instantiate groupings */
2849 continue;
2850 }
Radek Krejci6ff885d2017-01-03 14:06:22 +01002851 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002852 goto error;
2853 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002854 }
2855 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002856
2857 if (finalize == 1) {
2858 /* check that configuration lists have keys
2859 * - we really want to check keys_size in original node, because the keys are
2860 * not yet resolved here, it is done below in nodetype specific part */
2861 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
2862 && !((struct lys_node_list *)node)->keys_size) {
2863 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
2864 goto error;
2865 }
2866 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002867 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002868 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002869 }
2870
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002871 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002872 * duplicate specific part of the structure
2873 */
2874 switch (node->nodetype) {
2875 case LYS_CONTAINER:
2876 if (cont_orig->when) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002877 cont->when = lys_when_dup(ctx, cont_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002878 }
2879 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002881 cont->must_size = cont_orig->must_size;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002882 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883
Radek Krejcif0bb3602017-01-25 17:05:08 +01002884 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
2885
2886 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002887 case LYS_CHOICE:
2888 if (choice_orig->when) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002889 choice->when = lys_when_dup(ctx, choice_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002890 }
2891
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002892 if (!shallow) {
2893 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002894 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2895 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2896 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002897 if (rc) {
2898 if (rc == EXIT_FAILURE) {
2899 LOGINT;
2900 }
2901 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002902 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002903 } else {
2904 /* useless to check return value, we don't know whether
2905 * there really wasn't any default defined or it just hasn't
2906 * been resolved, we just hope for the best :)
2907 */
2908 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002909 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002910 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002911 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002912 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002913 break;
2914
2915 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002916 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002917 goto error;
2918 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002919 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2920
2921 if (leaf_orig->dflt) {
2922 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci51673202016-11-01 17:00:32 +01002923 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
2924 (struct lys_node *)(&leaf->dflt)) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002925 goto error;
2926 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002927 }
2928
2929 leaf->must_size = leaf_orig->must_size;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002930 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002931
2932 if (leaf_orig->when) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002933 leaf->when = lys_when_dup(ctx, leaf_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002934 }
2935 break;
2936
2937 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002938 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002939 goto error;
2940 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002941 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2942
2943 llist->min = llist_orig->min;
2944 llist->max = llist_orig->max;
2945
2946 llist->must_size = llist_orig->must_size;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002947 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002948
Radek Krejci51673202016-11-01 17:00:32 +01002949 llist->dflt_size = llist_orig->dflt_size;
2950 llist->dflt = malloc(llist->dflt_size * sizeof *llist->dflt);
2951 for (i = 0; i < llist->dflt_size; i++) {
2952 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
2953 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2954 (struct lys_node *)(&llist->dflt[i])) == -1) {
2955 goto error;
2956 }
2957 }
2958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 if (llist_orig->when) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002960 llist->when = lys_when_dup(ctx, llist_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002961 }
2962 break;
2963
2964 case LYS_LIST:
2965 list->min = list_orig->min;
2966 list->max = list_orig->max;
2967
2968 list->must_size = list_orig->must_size;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002969 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002970
Radek Krejcif0bb3602017-01-25 17:05:08 +01002971 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Michal Vasko38d01f72015-06-15 09:41:06 +02002972
Radek Krejci581ce772015-11-10 17:22:40 +01002973 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002974 if (list->keys_size) {
2975 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejci5c08a992016-11-02 13:30:04 +01002976 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Michal Vasko253035f2015-12-17 16:58:13 +01002977 if (!list->keys) {
2978 LOGMEM;
2979 goto error;
2980 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002981
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002982 if (!shallow) {
Radek Krejci5c08a992016-11-02 13:30:04 +01002983 /* the keys are going to be resolved only if the list is instantiated in data tree, not just
2984 * in another grouping */
2985 for (iter = parent; iter && iter->nodetype != LYS_GROUPING; iter = iter->parent);
2986 if (!iter && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
2987 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02002988 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002989 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002990 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002991 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002992 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002993
Radek Krejci581ce772015-11-10 17:22:40 +01002994 list->unique_size = list_orig->unique_size;
2995 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002996 if (!list->unique) {
2997 LOGMEM;
2998 goto error;
2999 }
Radek Krejci581ce772015-11-10 17:22:40 +01003000 for (i = 0; i < list->unique_size; ++i) {
3001 list->unique[i].expr_size = list_orig->unique[i].expr_size;
3002 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01003003 if (!list->unique[i].expr) {
3004 LOGMEM;
3005 goto error;
3006 }
Radek Krejci581ce772015-11-10 17:22:40 +01003007 for (j = 0; j < list->unique[i].expr_size; j++) {
3008 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
3009
3010 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02003011 unique_info = malloc(sizeof *unique_info);
3012 unique_info->list = (struct lys_node *)list;
3013 unique_info->expr = list->unique[i].expr[j];
3014 unique_info->trg_type = &list->unique[i].trg_type;
3015 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 }
3017 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 if (list_orig->when) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003020 list->when = lys_when_dup(ctx, list_orig->when, unres);
Radek Krejciefaeba32015-05-27 14:30:57 +02003021 }
Radek Krejcidce51452015-06-16 15:20:08 +02003022 break;
3023
3024 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003025 case LYS_ANYDATA:
3026 any->must_size = any_orig->must_size;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003027 any->must = lys_restr_dup(ctx, any_orig->must, any->must_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003028
Radek Krejcibf2abff2016-08-23 15:51:52 +02003029 if (any_orig->when) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003030 any->when = lys_when_dup(ctx, any_orig->when, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003031 }
3032 break;
3033
3034 case LYS_USES:
3035 uses->grp = uses_orig->grp;
3036
3037 if (uses_orig->when) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003038 uses->when = lys_when_dup(ctx, uses_orig->when, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003039 }
3040
3041 uses->refine_size = uses_orig->refine_size;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003042 uses->refine = lys_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003043 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003044 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003045 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment,
3046 uses_orig->augment_size, unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01003047#if __BYTE_ORDER == __LITTLE_ENDIAN
3048 if (!uses->grp || ((uint8_t*)&uses->grp->flags)[1]) {
3049#else
3050 if (!uses->grp || ((uint8_t*)&uses->grp->flags)[0]) {
3051#endif
Michal Vaskocda51712016-05-19 15:22:11 +02003052 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01003053 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003054 goto error;
3055 }
Michal Vasko49168a22015-08-17 16:35:41 +02003056 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003057 } else {
3058 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003059 }
3060 break;
3061
Radek Krejcidce51452015-06-16 15:20:08 +02003062 case LYS_CASE:
3063 if (cs_orig->when) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003064 cs->when = lys_when_dup(ctx, cs_orig->when, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02003065 }
3066 break;
3067
Radek Krejci96935402016-11-04 16:27:28 +01003068 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02003069 case LYS_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 case LYS_INPUT:
3071 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02003072 case LYS_NOTIF:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003073 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003074 break;
3075
3076 default:
3077 /* LY_NODE_AUGMENT */
3078 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02003079 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003080 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003081
3082 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02003083
3084error:
3085
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003086 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02003087 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003088}
3089
Radek Krejcib3142312016-11-09 11:04:12 +01003090int
3091lys_has_xpath(const struct lys_node *node)
3092{
3093 assert(node);
3094
3095 switch (node->nodetype) {
3096 case LYS_AUGMENT:
3097 if (((struct lys_node_augment *)node)->when) {
3098 return 1;
3099 }
3100 break;
3101 case LYS_CASE:
3102 if (((struct lys_node_case *)node)->when) {
3103 return 1;
3104 }
3105 break;
3106 case LYS_CHOICE:
3107 if (((struct lys_node_choice *)node)->when) {
3108 return 1;
3109 }
3110 break;
3111 case LYS_ANYDATA:
3112 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3113 return 1;
3114 }
3115 break;
3116 case LYS_LEAF:
3117 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3118 return 1;
3119 }
3120 break;
3121 case LYS_LEAFLIST:
3122 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3123 return 1;
3124 }
3125 break;
3126 case LYS_LIST:
3127 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3128 return 1;
3129 }
3130 break;
3131 case LYS_CONTAINER:
3132 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3133 return 1;
3134 }
3135 break;
3136 case LYS_INPUT:
3137 case LYS_OUTPUT:
3138 if (((struct lys_node_inout *)node)->must_size) {
3139 return 1;
3140 }
3141 break;
3142 case LYS_NOTIF:
3143 if (((struct lys_node_notif *)node)->must_size) {
3144 return 1;
3145 }
3146 break;
3147 case LYS_USES:
3148 if (((struct lys_node_uses *)node)->when) {
3149 return 1;
3150 }
3151 break;
3152 default:
3153 /* does not have XPath */
3154 break;
3155 }
3156
3157 return 0;
3158}
3159
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003160struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003161lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003162 struct unres_schema *unres, int shallow)
3163{
3164 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003165 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003166 struct lys_node *result, *iter, *next;
3167
3168 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003169 /* get know where in schema tree we are to know what should be done during instantiation of the grouping */
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003170 for (p = parent;
3171 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3172 p = lys_parent(p));
3173 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3174 }
3175
Radek Krejci6ff885d2017-01-03 14:06:22 +01003176 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003177 if (finalize) {
3178 /* check xpath expressions in the instantiated tree */
3179 for (iter = next = parent->child; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003180 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003181 /* invalid xpath */
3182 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003183 }
3184
3185 /* select next item */
3186 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3187 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3188 next = NULL;
3189 } else {
3190 next = iter->child;
3191 }
3192 if (!next) {
3193 /* no children, try siblings */
3194 next = iter->next;
3195 }
3196 while (!next) {
3197 /* parent is already processed, go to its sibling */
3198 iter = lys_parent(iter);
3199 if (iter == parent) {
3200 /* we are done, no next element to process */
3201 break;
3202 }
3203 next = iter->next;
3204 }
3205 }
3206 }
3207
3208 return result;
3209}
3210
Michal Vasko13b15832015-08-19 11:04:48 +02003211void
Michal Vaskoff006c12016-02-17 11:15:19 +01003212lys_node_switch(struct lys_node *dst, struct lys_node *src)
3213{
3214 struct lys_node *child;
3215
Michal Vaskob42b6972016-06-06 14:21:30 +02003216 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003217
3218 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02003219 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01003220 dst->prev->next = src;
3221 }
3222
3223 /* sibling prev */
3224 if (dst->next) {
3225 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02003226 } else {
3227 for (child = dst->prev; child->prev->next; child = child->prev);
3228 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003229 }
3230
3231 /* next */
3232 src->next = dst->next;
3233 dst->next = NULL;
3234
3235 /* prev */
3236 if (dst->prev != dst) {
3237 src->prev = dst->prev;
3238 }
3239 dst->prev = dst;
3240
3241 /* parent child */
3242 if (dst->parent && (dst->parent->child == dst)) {
3243 dst->parent->child = src;
3244 }
3245
3246 /* parent */
3247 src->parent = dst->parent;
3248 dst->parent = NULL;
3249
3250 /* child parent */
3251 LY_TREE_FOR(dst->child, child) {
3252 if (child->parent == dst) {
3253 child->parent = src;
3254 }
3255 }
3256
3257 /* child */
3258 src->child = dst->child;
3259 dst->child = NULL;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003260
3261 /* node-specific data */
3262 switch (dst->nodetype) {
3263 case LYS_CONTAINER:
3264 ((struct lys_node_container *)src)->tpdf_size = ((struct lys_node_container *)dst)->tpdf_size;
3265 ((struct lys_node_container *)src)->tpdf = ((struct lys_node_container *)dst)->tpdf;
3266 ((struct lys_node_container *)dst)->tpdf_size = 0;
3267 ((struct lys_node_container *)dst)->tpdf = NULL;
3268 break;
3269 case LYS_LIST:
3270 ((struct lys_node_list *)src)->tpdf_size = ((struct lys_node_list *)dst)->tpdf_size;
3271 ((struct lys_node_list *)src)->tpdf = ((struct lys_node_list *)dst)->tpdf;
3272 ((struct lys_node_list *)dst)->tpdf_size = 0;
3273 ((struct lys_node_list *)dst)->tpdf = NULL;
3274 break;
3275 case LYS_RPC:
3276 case LYS_ACTION:
3277 ((struct lys_node_rpc_action *)src)->tpdf_size = ((struct lys_node_rpc_action *)dst)->tpdf_size;
3278 ((struct lys_node_rpc_action *)src)->tpdf = ((struct lys_node_rpc_action *)dst)->tpdf;
3279 ((struct lys_node_rpc_action *)dst)->tpdf_size = 0;
3280 ((struct lys_node_rpc_action *)dst)->tpdf = NULL;
3281 break;
3282 case LYS_NOTIF:
3283 ((struct lys_node_notif *)src)->tpdf_size = ((struct lys_node_notif *)dst)->tpdf_size;
3284 ((struct lys_node_notif *)src)->tpdf = ((struct lys_node_notif *)dst)->tpdf;
3285 ((struct lys_node_notif *)dst)->tpdf_size = 0;
3286 ((struct lys_node_notif *)dst)->tpdf = NULL;
3287 break;
3288 case LYS_INPUT:
3289 case LYS_OUTPUT:
3290 ((struct lys_node_inout *)src)->tpdf_size = ((struct lys_node_inout *)dst)->tpdf_size;
3291 ((struct lys_node_inout *)src)->tpdf = ((struct lys_node_inout *)dst)->tpdf;
3292 ((struct lys_node_inout *)dst)->tpdf_size = 0;
3293 ((struct lys_node_inout *)dst)->tpdf = NULL;
3294 break;
3295 default:
3296 /* nothing special */
3297 break;
3298 }
3299
Michal Vaskoff006c12016-02-17 11:15:19 +01003300}
3301
3302void
Michal Vasko627975a2016-02-11 11:39:03 +01003303lys_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 +02003304{
3305 struct ly_ctx *ctx;
3306 int i;
3307
3308 if (!module) {
3309 return;
3310 }
3311
3312 /* remove schema from the context */
3313 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003314 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003315 for (i = 0; i < ctx->models.used; i++) {
3316 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003317 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003318 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003319 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 +02003320 ctx->models.list[ctx->models.used] = NULL;
3321 /* we are done */
3322 break;
3323 }
3324 }
3325 }
3326
3327 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003328 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003329
3330 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003331 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003332
3333 free(module);
3334}
Radek Krejci7e97c352015-06-19 16:26:34 +02003335
Radek Krejci9de2c042016-10-19 16:53:06 +02003336static void
3337lys_features_disable_recursive(struct lys_feature *f)
3338{
3339 unsigned int i;
3340 struct lys_feature *depf;
3341
3342 /* disable the feature */
3343 f->flags &= ~LYS_FENABLED;
3344
3345 /* by disabling feature we have to disable also all features that depends on this feature */
3346 if (f->depfeatures) {
3347 for (i = 0; i < f->depfeatures->number; i++) {
3348 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3349 if (depf->flags & LYS_FENABLED) {
3350 lys_features_disable_recursive(depf);
3351 }
3352 }
3353 }
3354}
3355
3356
Radek Krejci7e97c352015-06-19 16:26:34 +02003357/*
3358 * op: 1 - enable, 0 - disable
3359 */
3360static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003361lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003362{
3363 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003364 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003365 int progress, faili, failj, failk;
3366
3367 uint8_t fsize;
3368 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003369
3370 if (!module || !name || !strlen(name)) {
3371 return EXIT_FAILURE;
3372 }
3373
3374 if (!strcmp(name, "*")) {
3375 /* enable all */
3376 all = 1;
3377 }
3378
Radek Krejcia889c1f2016-10-19 15:50:11 +02003379 progress = failk = 1;
3380 while (progress && failk) {
3381 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3382 if (i == -1) {
3383 fsize = module->features_size;
3384 f = module->features;
3385 } else {
3386 fsize = module->inc[i].submodule->features_size;
3387 f = module->inc[i].submodule->features;
3388 }
3389
3390 for (j = 0; j < fsize; j++) {
3391 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003392 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3393 if (all) {
3394 /* skip already set features */
3395 continue;
3396 } else {
3397 /* feature already set correctly */
3398 return EXIT_SUCCESS;
3399 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003400 }
3401
3402 if (op) {
3403 /* check referenced features if they are enabled */
3404 for (k = 0; k < f[j].iffeature_size; k++) {
3405 if (!resolve_iffeature(&f[j].iffeature[k])) {
3406 if (all) {
3407 faili = i;
3408 failj = j;
3409 failk = k + 1;
3410 break;
3411 } else {
3412 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3413 f[j].name, k + 1);
3414 return EXIT_FAILURE;
3415 }
3416 }
3417 }
3418
3419 if (k == f[j].iffeature_size) {
3420 /* the last check passed, do the change */
3421 f[j].flags |= LYS_FENABLED;
3422 progress++;
3423 }
3424 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003425 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003426 progress++;
3427 }
3428 if (!all) {
3429 /* stop in case changing a single feature */
3430 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003431 }
3432 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003433 }
3434 }
3435 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003436 if (failk) {
3437 /* print info about the last failing feature */
3438 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3439 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3440 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003441 }
3442
3443 if (all) {
3444 return EXIT_SUCCESS;
3445 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003446 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003447 return EXIT_FAILURE;
3448 }
3449}
3450
3451API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003452lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003453{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003454 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003455}
3456
3457API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003458lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003459{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003460 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003461}
3462
3463API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003464lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003465{
3466 int i, j;
3467
3468 if (!module || !feature) {
3469 return -1;
3470 }
3471
3472 /* search for the specified feature */
3473 /* module itself */
3474 for (i = 0; i < module->features_size; i++) {
3475 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003476 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003477 return 1;
3478 } else {
3479 return 0;
3480 }
3481 }
3482 }
3483
3484 /* submodules */
3485 for (j = 0; j < module->inc_size; j++) {
3486 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3487 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003488 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003489 return 1;
3490 } else {
3491 return 0;
3492 }
3493 }
3494 }
3495 }
3496
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003497 /* feature definition not found */
3498 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003499}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003500
Radek Krejci96a10da2015-07-30 11:00:14 +02003501API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003502lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003503{
Radek Krejci96a10da2015-07-30 11:00:14 +02003504 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003505 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003506 unsigned int count;
3507
3508 if (!module) {
3509 return NULL;
3510 }
3511
3512 count = module->features_size;
3513 for (i = 0; i < module->inc_size; i++) {
3514 count += module->inc[i].submodule->features_size;
3515 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003516 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01003517 if (!result) {
3518 LOGMEM;
3519 return NULL;
3520 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003521 if (states) {
3522 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01003523 if (!(*states)) {
3524 LOGMEM;
3525 free(result);
3526 return NULL;
3527 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003528 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003529 count = 0;
3530
3531 /* module itself */
3532 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003533 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003534 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003535 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003536 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003537 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003538 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003539 }
3540 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003541 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003542 }
3543
3544 /* submodules */
3545 for (j = 0; j < module->inc_size; j++) {
3546 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003547 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003548 if (states) {
3549 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3550 (*states)[count] = 1;
3551 } else {
3552 (*states)[count] = 0;
3553 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003554 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003555 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003556 }
3557 }
3558
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003559 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003560 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003561
3562 return result;
3563}
Michal Vaskobaefb032015-09-24 14:52:10 +02003564
Radek Krejci6910a032016-04-13 10:06:21 +02003565API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003566lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003567{
Michal Vaskof53187d2017-01-13 13:23:14 +01003568 if (!node) {
3569 return NULL;
3570 }
3571
Radek Krejcic071c542016-01-27 14:57:51 +01003572 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3573}
3574
Radek Krejci6910a032016-04-13 10:06:21 +02003575API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003576lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003577{
Michal Vaskof53187d2017-01-13 13:23:14 +01003578 if (!module) {
3579 return NULL;
3580 }
3581
Michal Vasko320e8532016-02-15 13:11:57 +01003582 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3583}
3584
Michal Vaskobaefb032015-09-24 14:52:10 +02003585API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003586lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003587{
3588 if (!node || !node->parent) {
3589 return NULL;
3590 }
3591
3592 if (node->parent->nodetype == LYS_AUGMENT) {
3593 return ((struct lys_node_augment *)node->parent)->target;
3594 }
3595
3596 return node->parent;
3597}
Michal Vasko1b229152016-01-13 11:28:38 +01003598
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003599API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003600lys_set_private(const struct lys_node *node, void *priv)
3601{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003602 void *prev;
3603
Michal Vasko1b229152016-01-13 11:28:38 +01003604 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003605 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
3606 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003607 }
3608
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003609 prev = node->priv;
3610 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003611
3612 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003613}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003614
Michal Vasko01c6fd22016-05-20 11:43:05 +02003615int
3616lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3617{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003618 struct lys_node_leaf *iter = leafref_target;
3619
Michal Vasko48a573d2016-07-01 11:46:02 +02003620 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003621 LOGINT;
3622 return -1;
3623 }
3624
Pavol Vican93175152016-08-30 15:34:44 +02003625 /* check for config flag */
3626 if ((leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
3627 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
3628 "The %s is config but refers to a non-config %s.",
3629 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
3630 return -1;
3631 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003632 /* check for cycles */
3633 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3634 if ((void *)iter == (void *)leafref) {
3635 /* cycle detected */
3636 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3637 return -1;
3638 }
3639 iter = iter->type.info.lref.target;
3640 }
3641
3642 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003643 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02003644 if (!leafref_target->backlinks) {
3645 leafref_target->backlinks = (void*)ly_set_new();
3646 if (!leafref_target->backlinks) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003647 LOGMEM;
3648 return -1;
3649 }
3650 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003651 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003652
3653 return 0;
3654}
3655
Michal Vasko8548e082016-07-22 12:00:18 +02003656/* not needed currently */
3657#if 0
3658
Michal Vasko5b3492c2016-07-20 09:37:40 +02003659static const char *
3660lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3661{
3662 struct lys_module *prev_mod;
3663 uint32_t str_len, mod_len, buf_idx;
3664
Radek Krejcibf2abff2016-08-23 15:51:52 +02003665 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003666 LOGINT;
3667 return NULL;
3668 }
3669
3670 buf_idx = buf_len - 1;
3671 buf[buf_idx] = '\0';
3672
3673 while (node) {
3674 if (lys_parent(node)) {
3675 prev_mod = lys_node_module(lys_parent(node));
3676 } else {
3677 prev_mod = NULL;
3678 }
3679
Radek Krejcibf2abff2016-08-23 15:51:52 +02003680 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003681 str_len = strlen(node->name);
3682
3683 if (prev_mod != node->module) {
3684 mod_len = strlen(node->module->name);
3685 } else {
3686 mod_len = 0;
3687 }
3688
3689 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3690 LOGINT;
3691 return NULL;
3692 }
3693
3694 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3695
3696 buf[buf_idx] = '/';
3697 if (mod_len) {
3698 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3699 buf[buf_idx + 1 + mod_len] = ':';
3700 }
3701 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3702 }
3703
3704 node = lys_parent(node);
3705 }
3706
3707 return buf + buf_idx;
3708}
3709
Michal Vasko8548e082016-07-22 12:00:18 +02003710#endif
3711
3712API struct ly_set *
Michal Vasko2611e192017-01-23 10:33:21 +01003713lys_find_xpath(struct ly_ctx *ctx, const struct lys_node *node, const char *expr, int options)
Michal Vasko46a4bf92016-09-08 08:23:49 +02003714{
3715 struct lyxp_set set;
3716 struct ly_set *ret_set;
3717 uint32_t i;
Michal Vaskodb1da032016-09-08 10:07:38 +02003718 int opts;
Michal Vasko46a4bf92016-09-08 08:23:49 +02003719
Michal Vasko2611e192017-01-23 10:33:21 +01003720 if ((!ctx && !node) || !expr) {
Michal Vasko46a4bf92016-09-08 08:23:49 +02003721 ly_errno = LY_EINVAL;
3722 return NULL;
3723 }
3724
Michal Vasko2611e192017-01-23 10:33:21 +01003725 if (!node) {
3726 node = ly_ctx_get_node(ctx, NULL, "/ietf-yang-library:modules-state");
3727 if (!node) {
3728 ly_errno = LY_EINT;
3729 return NULL;
3730 }
3731 }
3732
Michal Vasko46a4bf92016-09-08 08:23:49 +02003733 memset(&set, 0, sizeof set);
3734
Michal Vaskodb1da032016-09-08 10:07:38 +02003735 opts = LYXP_SNODE;
3736 if (options & LYS_FIND_OUTPUT) {
3737 opts |= LYXP_SNODE_OUTPUT;
3738 }
3739
Michal Vaskodb1da032016-09-08 10:07:38 +02003740 if (lyxp_atomize(expr, node, LYXP_NODE_ELEM, &set, opts)) {
Michal Vaskoc90f3ff2017-01-23 13:51:58 +01003741 /* just find a relevant node to put in path, if it fails, use the original one */
3742 for (i = 0; i < set.used; ++i) {
3743 if (set.val.snodes[i].in_ctx == 1) {
3744 node = set.val.snodes[i].snode;
3745 break;
3746 }
3747 }
Michal Vasko46a4bf92016-09-08 08:23:49 +02003748 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003749 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko46a4bf92016-09-08 08:23:49 +02003750 return NULL;
3751 }
3752
3753 ret_set = ly_set_new();
3754
3755 for (i = 0; i < set.used; ++i) {
3756 if (!set.val.snodes[i].in_ctx) {
3757 continue;
3758 }
3759 assert(set.val.snodes[i].in_ctx == 1);
3760
3761 switch (set.val.snodes[i].type) {
3762 case LYXP_NODE_ELEM:
3763 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
3764 ly_set_free(ret_set);
3765 free(set.val.snodes);
3766 return NULL;
3767 }
3768 break;
3769 default:
3770 /* ignore roots, text and attr should not ever appear */
3771 break;
3772 }
3773 }
3774
3775 free(set.val.snodes);
3776 return ret_set;
3777}
3778
3779API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02003780lys_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 +02003781{
Michal Vasko508a50d2016-09-07 14:50:33 +02003782 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003783 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003784 uint32_t i;
3785
Michal Vaskob94a5e42016-09-08 14:01:56 +02003786 if (!cur_snode || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02003787 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003788 }
3789
Michal Vaskob94a5e42016-09-08 14:01:56 +02003790 /* adjust the root */
3791 if ((cur_snode_type == LYXP_NODE_ROOT) || (cur_snode_type == LYXP_NODE_ROOT_CONFIG)) {
3792 do {
3793 cur_snode = lys_getnext(NULL, NULL, lys_node_module(cur_snode), 0);
3794 } while ((cur_snode_type == LYXP_NODE_ROOT_CONFIG) && (cur_snode->flags & LYS_CONFIG_R));
3795 }
3796
Michal Vasko508a50d2016-09-07 14:50:33 +02003797 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003798
3799 if (options & LYXP_MUST) {
3800 options &= ~LYXP_MUST;
3801 options |= LYXP_SNODE_MUST;
3802 } else if (options & LYXP_WHEN) {
3803 options &= ~LYXP_WHEN;
3804 options |= LYXP_SNODE_WHEN;
3805 } else {
3806 options |= LYXP_SNODE;
3807 }
3808
Michal Vasko508a50d2016-09-07 14:50:33 +02003809 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
3810 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003811 LOGVAL(LYE_SPEC, LY_VLOG_LYS, cur_snode, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02003812 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003813 }
3814
Michal Vasko8548e082016-07-22 12:00:18 +02003815 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003816
Michal Vasko508a50d2016-09-07 14:50:33 +02003817 for (i = 0; i < set.used; ++i) {
3818 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003819 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003820 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003821 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003822 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003823 return NULL;
3824 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003825 break;
3826 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003827 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003828 break;
3829 }
3830 }
3831
Michal Vasko508a50d2016-09-07 14:50:33 +02003832 free(set.val.snodes);
3833 return ret_set;
3834}
3835
3836API struct ly_set *
3837lys_node_xpath_atomize(const struct lys_node *node, int options)
3838{
3839 const struct lys_node *next, *elem, *parent, *tmp;
3840 struct lyxp_set set;
3841 struct ly_set *ret_set;
3842 uint16_t i;
3843
3844 if (!node) {
3845 return NULL;
3846 }
3847
3848 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3849 if (!parent) {
3850 /* not in input, output, or notification */
3851 return NULL;
3852 }
3853
3854 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003855 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003856 return NULL;
3857 }
3858
3859 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003860 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_XPATH_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003861 /* elem has no dependencies from other subtrees and local nodes get discarded */
3862 goto next_iter;
3863 }
3864
Michal Vasko769f8032017-01-24 13:11:55 +01003865 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003866 ly_set_free(ret_set);
3867 free(set.val.snodes);
3868 return NULL;
3869 }
3870
3871 for (i = 0; i < set.used; ++i) {
3872 switch (set.val.snodes[i].type) {
3873 case LYXP_NODE_ELEM:
3874 if (options & LYXP_NO_LOCAL) {
3875 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3876 if (tmp) {
3877 /* in local subtree, discard */
3878 break;
3879 }
3880 }
3881 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3882 ly_set_free(ret_set);
3883 free(set.val.snodes);
3884 return NULL;
3885 }
3886 break;
3887 default:
3888 /* ignore roots, text and attr should not ever appear */
3889 break;
3890 }
3891 }
3892
3893 free(set.val.snodes);
3894 if (!(options & LYXP_RECURSIVE)) {
3895 break;
3896 }
3897next_iter:
3898 LY_TREE_DFS_END(node, next, elem);
3899 }
3900
Michal Vasko8548e082016-07-22 12:00:18 +02003901 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003902}
3903
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003904static void
Michal Vasko89563fc2016-07-28 16:19:35 +02003905lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003906{
3907 int ret;
3908 char *parent_path;
3909 struct lys_node *target;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003910
Pavol Vican64d0b762016-08-25 10:44:59 +02003911 if (!dev->deviate) {
3912 return ;
3913 }
3914
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003915 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3916 if (dev->orig_node) {
3917 /* removing not-supported deviation ... */
3918 if (strrchr(dev->target_name, '/') != dev->target_name) {
3919 /* ... from a parent */
3920 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3921
3922 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003923 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, 1,
3924 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003925 free(parent_path);
3926 if (ret || !target) {
3927 LOGINT;
3928 return;
3929 }
3930
3931 lys_node_addchild(target, NULL, dev->orig_node);
3932 } else {
3933 /* ... from top-level data */
3934 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3935 }
3936
3937 dev->orig_node = NULL;
3938 } else {
3939 /* adding not-supported deviation */
3940 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003941 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
3942 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003943 if (ret || !target) {
3944 LOGINT;
3945 return;
3946 }
3947
3948 lys_node_unlink(target);
3949 dev->orig_node = target;
3950 }
3951 } else {
3952 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003953 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
3954 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003955 if (ret || !target) {
3956 LOGINT;
3957 return;
3958 }
3959
3960 lys_node_switch(target, dev->orig_node);
3961 dev->orig_node = target;
3962 }
3963}
3964
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003965/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3966void
3967lys_switch_deviations(struct lys_module *module)
3968{
Michal Vasko89563fc2016-07-28 16:19:35 +02003969 uint32_t i = 0, j;
3970 const struct lys_module *mod;
3971 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003972
Michal Vasko89563fc2016-07-28 16:19:35 +02003973 if (module->deviated) {
3974 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3975 if (mod == module) {
3976 continue;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003977 }
3978
Michal Vasko89563fc2016-07-28 16:19:35 +02003979 for (j = 0; j < mod->deviation_size; ++j) {
3980 ptr = strstr(mod->deviation[j].target_name, module->name);
3981 if (ptr && ptr[strlen(module->name)] == ':') {
3982 lys_switch_deviation(&mod->deviation[j], module);
3983 }
3984 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003985 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003986
Michal Vasko89563fc2016-07-28 16:19:35 +02003987 if (module->deviated == 2) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003988 module->deviated = 1;
Michal Vasko89563fc2016-07-28 16:19:35 +02003989 } else {
3990 module->deviated = 2;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003991 }
3992 }
3993}
3994
Radek Krejci0ec51da2016-12-14 16:42:03 +01003995static void
3996apply_dev(struct lys_deviation *dev, const struct lys_module *module)
3997{
3998 lys_switch_deviation(dev, module);
3999
4000 assert(dev->orig_node);
4001 lys_node_module(dev->orig_node)->deviated = 1;
4002}
4003
4004static void
4005apply_aug(struct lys_node_augment *augment)
4006{
4007 struct lys_node *last;
4008
4009 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
4010
4011 /* reconnect augmenting data into the target - add them to the target child list */
4012 if (augment->target->child) {
4013 last = augment->target->child->prev;
4014 last->next = augment->child;
4015 augment->target->child->prev = augment->child->prev;
4016 augment->child->prev = last;
4017 } else {
4018 augment->target->child = augment->child;
4019 }
4020
4021 /* remove the flag about not applicability */
4022 augment->flags &= ~LYS_NOTAPPLIED;
4023}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004024
4025void
4026lys_sub_module_apply_devs_augs(struct lys_module *module)
4027{
Radek Krejci0ec51da2016-12-14 16:42:03 +01004028 uint8_t u, v;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004029
Radek Krejci0ec51da2016-12-14 16:42:03 +01004030 /* remove applied deviations */
4031 for (u = 0; u < module->deviation_size; ++u) {
4032 apply_dev(&module->deviation[u], module);
4033 }
4034 /* remove applied augments */
4035 for (u = 0; u < module->augment_size; ++u) {
4036 apply_aug(&module->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004037 }
4038
Radek Krejci0ec51da2016-12-14 16:42:03 +01004039 /* remove deviation and augments defined in submodules */
4040 for (v = 0; v < module->inc_size; ++v) {
4041 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4042 apply_dev(&module->inc[v].submodule->deviation[u], module);
4043 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004044
Radek Krejci0ec51da2016-12-14 16:42:03 +01004045 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4046 apply_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004047 }
4048 }
4049}
4050
Radek Krejcib2541a32016-12-12 16:45:57 +01004051static void
4052remove_dev(struct lys_deviation *dev, const struct lys_module *module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004053{
Radek Krejcib2541a32016-12-12 16:45:57 +01004054 uint32_t idx = 0, j;
Michal Vasko89563fc2016-07-28 16:19:35 +02004055 const struct lys_module *mod;
4056 struct lys_module *target_mod;
4057 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004058
Radek Krejcib2541a32016-12-12 16:45:57 +01004059 if (dev->orig_node) {
4060 target_mod = lys_node_module(dev->orig_node);
4061 } else {
Radek Krejci0ec51da2016-12-14 16:42:03 +01004062 LOGINT;
4063 return;
Radek Krejcib2541a32016-12-12 16:45:57 +01004064 }
4065 lys_switch_deviation(dev, module);
4066
4067 /* clear the deviation flag if possible */
4068 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4069 if ((mod == module) || (mod == target_mod)) {
4070 continue;
Pavol Vican64d0b762016-08-25 10:44:59 +02004071 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004072
Radek Krejcib2541a32016-12-12 16:45:57 +01004073 for (j = 0; j < mod->deviation_size; ++j) {
4074 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4075 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4076 /* some other module deviation targets the inspected module, flag remains */
Michal Vasko89563fc2016-07-28 16:19:35 +02004077 break;
4078 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004079 }
Michal Vasko89563fc2016-07-28 16:19:35 +02004080
Radek Krejcib2541a32016-12-12 16:45:57 +01004081 if (j < mod->deviation_size) {
4082 break;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004083 }
4084 }
4085
Radek Krejcib2541a32016-12-12 16:45:57 +01004086 if (!mod) {
4087 target_mod->deviated = 0;
4088 }
4089}
4090
4091static void
4092remove_aug(struct lys_node_augment *augment)
4093{
4094 struct lys_node *last, *elem;
4095
4096 if (!augment->target) {
4097 /* skip not resolved augments */
4098 return;
4099 }
4100
4101 elem = augment->child;
4102 if (elem) {
4103 LY_TREE_FOR(elem, last) {
4104 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
4105 break;
4106 }
4107 }
4108 /* elem is first augment child, last is the last child */
4109
4110 /* parent child ptr */
4111 if (augment->target->child == elem) {
4112 augment->target->child = last->next;
4113 }
4114
4115 /* parent child next ptr */
4116 if (elem->prev->next) {
4117 elem->prev->next = last->next;
4118 }
4119
4120 /* parent child prev ptr */
4121 if (last->next) {
4122 last->next->prev = elem->prev;
4123 } else if (augment->target->child) {
4124 augment->target->child->prev = elem->prev;
4125 }
4126
4127 /* update augment children themselves */
4128 elem->prev = last;
4129 last->next = NULL;
4130 }
4131
Radek Krejci0ec51da2016-12-14 16:42:03 +01004132 /* augment->target still keeps the resolved target, but for lys_augment_free()
4133 * we have to keep information that this augment is not applied to free its data */
4134 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01004135}
4136
4137void
4138lys_sub_module_remove_devs_augs(struct lys_module *module)
4139{
4140 uint8_t u, v;
4141
4142 /* remove applied deviations */
4143 for (u = 0; u < module->deviation_size; ++u) {
4144 remove_dev(&module->deviation[u], module);
4145 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004146 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004147 for (u = 0; u < module->augment_size; ++u) {
4148 remove_aug(&module->augment[u]);
4149 }
4150
4151 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004152 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01004153 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4154 remove_dev(&module->inc[v].submodule->deviation[u], module);
Radek Krejcidbc15262016-06-16 14:58:29 +02004155 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004156
Radek Krejcib2541a32016-12-12 16:45:57 +01004157 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4158 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004159 }
4160 }
4161}
4162
Radek Krejci27fe55e2016-09-13 17:13:35 +02004163static int
4164lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
4165{
4166 struct lys_node *root, *next, *node;
4167 uint8_t i;
4168
4169 for (i = 0; i < module->augment_size; i++) {
4170 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02004171 if (!module->augment[i].target
4172 && (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004173 return -1;
4174 }
4175 }
4176 LY_TREE_FOR(module->data, root) {
4177 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4178 LY_TREE_DFS_BEGIN(root, next, node) {
4179 if (node->nodetype == LYS_GROUPING) {
4180 goto nextsibling;
4181 }
4182 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4183 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4184 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4185 UNRES_TYPE_LEAFREF, node) == -1) {
4186 return EXIT_FAILURE;
4187 }
4188 }
4189 }
4190
4191 /* modified LY_TREE_DFS_END */
4192 next = node->child;
4193 /* child exception for leafs, leaflists and anyxml without children */
4194 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4195 next = NULL;
4196 }
4197 if (!next) {
4198nextsibling:
4199 /* no children */
4200 if (node == root) {
4201 /* we are done, root has no children */
4202 break;
4203 }
4204 /* try siblings */
4205 next = node->next;
4206 }
4207 while (!next) {
4208 /* parent is already processed, go to its sibling */
4209 node = lys_parent(node);
4210 /* no siblings, go back through parents */
4211 if (lys_parent(node) == lys_parent(root)) {
4212 /* we are done, no next element to process */
4213 break;
4214 }
4215 next = node->next;
4216 }
4217 }
4218 }
4219
4220 return EXIT_SUCCESS;
4221}
4222
4223API int
4224lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004225{
4226 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004227 struct unres_schema *unres;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004228 int i, j, disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004229
Radek Krejci27fe55e2016-09-13 17:13:35 +02004230 if (!module) {
4231 ly_errno = LY_EINVAL;
4232 return EXIT_FAILURE;
4233 }
4234
4235 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004236
4237 if (module->disabled) {
4238 disabled = 1;
4239 lys_set_enabled(module);
4240 }
4241
Michal Vasko26055752016-05-03 11:36:31 +02004242 if (module->implemented) {
4243 return EXIT_SUCCESS;
4244 }
4245
4246 ctx = module->ctx;
4247
4248 for (i = 0; i < ctx->models.used; ++i) {
4249 if (module == ctx->models.list[i]) {
4250 continue;
4251 }
4252
4253 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4254 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004255 if (disabled) {
4256 /* set it back disabled */
4257 lys_set_disabled(module);
4258 }
Michal Vasko26055752016-05-03 11:36:31 +02004259 return EXIT_FAILURE;
4260 }
4261 }
4262
Radek Krejci27fe55e2016-09-13 17:13:35 +02004263 unres = calloc(1, sizeof *unres);
4264 if (!unres) {
4265 LOGMEM;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004266 if (disabled) {
4267 /* set it back disabled */
4268 lys_set_disabled(module);
4269 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004270 return EXIT_FAILURE;
4271 }
4272 /* recursively make the module implemented */
4273 ((struct lys_module *)module)->implemented = 1;
4274 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
4275 goto error;
4276 }
4277 /* process augments in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004278 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004279 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
4280 /* apply augment */
Radek Krejcic8c22532016-11-09 15:11:24 +01004281 if (!module->inc[i].submodule->augment[j].target
4282 && (unres_schema_add_node((struct lys_module *)module->inc[j].submodule, unres,
4283 &module->inc[i].submodule->augment[j], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01004284
Radek Krejci27fe55e2016-09-13 17:13:35 +02004285 goto error;
4286 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004287 }
4288 }
Radek Krejcidf46e222016-11-08 11:57:37 +01004289 /* try again resolve augments in other modules possibly augmenting this one,
4290 * since we have just enabled it
4291 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004292 /* resolve rest of unres items */
4293 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4294 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004295 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004296 unres_schema_free((struct lys_module *)module, &unres);
Michal Vasko26055752016-05-03 11:36:31 +02004297
4298 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004299
4300error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004301
4302 if (disabled) {
4303 /* set it back disabled */
4304 lys_set_disabled(module);
4305 }
4306
Radek Krejci27fe55e2016-09-13 17:13:35 +02004307 ((struct lys_module *)module)->implemented = 0;
4308 unres_schema_free((struct lys_module *)module, &unres);
4309 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004310}
4311
4312void
4313lys_submodule_module_data_free(struct lys_submodule *submodule)
4314{
4315 struct lys_node *next, *elem;
4316
4317 /* remove parsed data */
4318 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4319 if (elem->module == (struct lys_module *)submodule) {
4320 lys_node_free(elem, NULL, 0);
4321 }
4322 }
4323}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004324
4325int
4326lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
4327{
4328 uint8_t i;
4329
4330 for (i = 0; i < list->keys_size; i++) {
4331 if (list->keys[i] == leaf) {
4332 return i + 1;
4333 }
4334 }
4335
4336 return 0;
4337}
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004338
4339API char *
4340lys_path(const struct lys_node *node)
4341{
4342 char *buf_backup = NULL, *buf = ly_buf(), *result = NULL;
4343 uint16_t index = LY_BUF_SIZE - 1;
4344
4345 if (!node) {
4346 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
4347 return NULL;
4348 }
4349
4350 /* backup the shared internal buffer */
4351 if (ly_buf_used && buf[0]) {
4352 buf_backup = strndup(buf, LY_BUF_SIZE - 1);
4353 }
4354 ly_buf_used++;
4355
4356 /* build the path */
4357 buf[index] = '\0';
Michal Vasko5efa25c2017-01-10 11:34:30 +01004358 ly_vlog_build_path_reverse(LY_VLOG_LYS, node, buf, &index, 0);
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004359 result = strdup(&buf[index]);
4360
4361 /* restore the shared internal buffer */
4362 if (buf_backup) {
4363 strcpy(buf, buf_backup);
4364 free(buf_backup);
4365 }
4366 ly_buf_used--;
4367
4368 return result;
4369}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004370