blob: 37c128fdf066cfe3a49d6444e9c4461e64ab6cc9 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
Michal Vasko2d162e12015-09-24 14:33:29 +02002 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02004 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02005 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
Radek Krejci54f6fb32016-02-24 12:56:39 +010014
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020015#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020016
Radek Krejci812b10a2015-05-28 16:48:25 +020017#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020018#include <ctype.h>
Radek Krejcib051f722016-02-25 15:12:21 +010019#include <limits.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010022#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010024#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020025#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010026#include <unistd.h>
27#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020028
29#include "common.h"
30#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020031#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020032#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010033#include "xml.h"
Michal Vasko5b3492c2016-07-20 09:37:40 +020034#include "xpath.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020035#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020037#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010038#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020039
Radek Krejci8d6b7422017-02-03 14:42:13 +010040static int lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
41 int tpdftype, struct unres_schema *unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020042
Radek Krejci9ff0a922016-07-14 13:08:05 +020043API const struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010044lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020045{
Radek Krejci9ff0a922016-07-14 13:08:05 +020046 int i;
Radek Krejci48061fb2015-08-05 15:41:07 +020047
Radek Krejci27fe55e2016-09-13 17:13:35 +020048 if (!node) {
49 return NULL;
50 }
51
Radek Krejci48061fb2015-08-05 15:41:07 +020052check:
53 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
54 /* input/output does not have if-feature, so skip them */
55
56 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020057 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci69b8d922016-07-27 13:13:41 +020058 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020059 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020060 }
61 }
62 }
63
64 if (!recursive) {
65 return NULL;
66 }
67
68 /* go through parents */
69 if (node->nodetype == LYS_AUGMENT) {
70 /* go to parent actually means go to the target node */
71 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020072 } else if (node->parent) {
73 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020074 } else {
75 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020076 }
77
Radek Krejci074bf852015-08-19 14:22:16 +020078 if (recursive == 2) {
79 /* continue only if the node cannot have a data instance */
80 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
81 return NULL;
82 }
83 }
84 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020085}
86
Michal Vasko1dca6882015-10-22 14:29:42 +020087int
Michal Vasko36cbaa42015-12-14 13:15:48 +010088lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
89 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020090{
Radek Krejcic071c542016-01-27 14:57:51 +010091 const struct lys_node *node, *parent = NULL;
92 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010093 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020094
Michal Vasko36cbaa42015-12-14 13:15:48 +010095 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020096 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020097
Michal Vasko36cbaa42015-12-14 13:15:48 +010098 /* fill the lengths in case the caller is so indifferent */
99 if (!mod_name_len) {
100 mod_name_len = strlen(mod_name);
101 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200102 if (!nam_len) {
103 nam_len = strlen(name);
104 }
105
Michal Vasko9e635ac2016-10-17 11:44:09 +0200106 while (siblings && (siblings->nodetype == LYS_USES)) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200107 siblings = siblings->child;
108 }
Michal Vasko9e635ac2016-10-17 11:44:09 +0200109 if (!siblings) {
110 /* unresolved uses */
111 return EXIT_FAILURE;
112 }
113
Michal Vasko680f8b42016-10-17 10:27:37 +0200114 if (siblings->nodetype == LYS_GROUPING) {
115 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
116 if (node->nodetype == LYS_GROUPING) {
117 /* we went through all the siblings, only groupings there - no valid sibling */
118 return EXIT_FAILURE;
119 }
120 /* update siblings to be valid */
121 siblings = node;
122 }
123
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200124 /* set parent correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100125 parent = lys_parent(siblings);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200126
Michal Vasko680f8b42016-10-17 10:27:37 +0200127 /* go up all uses */
128 while (parent && (parent->nodetype == LYS_USES)) {
129 parent = lys_parent(parent);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200130 }
131
Radek Krejcic071c542016-01-27 14:57:51 +0100132 if (!parent) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200133 /* handle situation when there is a top-level uses referencing a foreign grouping */
134 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
135 mod = lys_node_module(node);
Michal Vasko1dca6882015-10-22 14:29:42 +0200136 }
137
Radek Krejcic071c542016-01-27 14:57:51 +0100138 /* try to find the node */
139 node = NULL;
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100140 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
Radek Krejcic071c542016-01-27 14:57:51 +0100141 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100142 /* module name comparison */
143 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200144 if (!ly_strequal(node_mod_name, mod_name, 1) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100145 continue;
146 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200147
Radek Krejcic071c542016-01-27 14:57:51 +0100148 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200149 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100150 if (ret) {
151 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200152 }
Radek Krejcic071c542016-01-27 14:57:51 +0100153 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200154 }
155 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200156 }
157
158 return EXIT_FAILURE;
159}
160
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200161int
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100162lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, int nam_len,
163 LYS_NODE type, const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200164{
Michal Vasko1e62a092015-12-01 12:27:20 +0100165 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200166
167 assert(siblings && name);
168 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
169
170 /* find the beginning */
171 while (siblings->prev->next) {
172 siblings = siblings->prev;
173 }
174
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200175 if (!mod) {
176 mod = siblings->module;
177 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200178
Michal Vasko4f0dad02016-02-15 14:08:23 +0100179 /* try to find the node */
180 node = NULL;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200181 while ((node = lys_getnext(node, lys_parent(siblings), mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100182 if (!type || (node->nodetype & type)) {
183 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200184 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100185 continue;
186 }
187
Michal Vasko4f0dad02016-02-15 14:08:23 +0100188 /* direct name check */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100189 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100190 if (ret) {
191 *ret = node;
192 }
193 return EXIT_SUCCESS;
194 }
Radek Krejcic071c542016-01-27 14:57:51 +0100195 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200196 }
197
198 return EXIT_FAILURE;
199}
200
Michal Vasko1e62a092015-12-01 12:27:20 +0100201API const struct lys_node *
202lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200203{
Michal Vasko1e62a092015-12-01 12:27:20 +0100204 const struct lys_node *next;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100205 struct lys_node **snode;
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 */
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100213 snode = lys_child(parent, LYS_UNKNOWN);
214 if (!snode) {
215 return NULL;
216 }
217 next = last = *snode;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200218 } else {
219 /* top level data */
220 assert(module);
221 next = last = module->data;
222 }
Radek Krejci972724f2016-08-12 15:24:40 +0200223 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
224 /* continue with uses content */
225 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200226 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200227 /* continue after the last returned value */
228 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200229 }
230
231repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200232 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200233 if (options & LYS_GETNEXT_WITHGROUPING) {
234 return next;
235 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200236 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200237 }
238
Radek Krejci972724f2016-08-12 15:24:40 +0200239 if (!next) { /* cover case when parent is augment */
240 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200241 /* no next element */
242 return NULL;
243 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200244 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200245 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200246 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200247 } else {
248 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200249 }
250
251 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200252 case LYS_INPUT:
253 case LYS_OUTPUT:
254 if (options & LYS_GETNEXT_WITHINOUT) {
255 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200256 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200257 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200258 } else {
259 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200260 }
Radek Krejci972724f2016-08-12 15:24:40 +0200261 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200262
Michal Vaskoa5835e92015-10-20 15:07:39 +0200263 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200264 if (options & LYS_GETNEXT_WITHCASE) {
265 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200266 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200267 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200268 } else {
269 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200270 }
Radek Krejci972724f2016-08-12 15:24:40 +0200271 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200272
Michal Vasko1dca6882015-10-22 14:29:42 +0200273 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200274 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200275 if (options & LYS_GETNEXT_WITHUSES) {
276 return next;
277 } else if (next->child) {
278 next = next->child;
279 } else {
280 next = next->next;
281 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200282 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200283
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200284 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200285 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200286 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200287 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200288 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200289 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200290 case LYS_LIST:
291 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200292 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200293
Radek Krejci972724f2016-08-12 15:24:40 +0200294 case LYS_CONTAINER:
295 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
296 if (next->child) {
297 /* go into */
298 next = next->child;
299 } else {
300 next = next->next;
301 }
302 goto repeat;
303 } else {
304 return next;
305 }
306
Radek Krejci8bc87f62015-09-02 16:19:05 +0200307 case LYS_CHOICE:
308 if (options & LYS_GETNEXT_WITHCHOICE) {
309 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200310 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200311 /* go into */
312 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200313 } else {
314 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200315 }
Radek Krejci972724f2016-08-12 15:24:40 +0200316 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200317
Radek Krejci7f40ce32015-08-12 20:38:46 +0200318 default:
319 /* we should not be here */
320 return NULL;
321 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200322}
323
Radek Krejcibf285832017-01-26 16:05:41 +0100324void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200325lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200326{
Radek Krejcif95b6292017-02-13 15:57:37 +0100327 struct lys_node *parent, *first, **pp;
Radek Krejcic071c542016-01-27 14:57:51 +0100328 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200330 if (!node) {
331 return;
332 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200334 /* unlink from data model if necessary */
335 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100336 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100337 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100338 if (main_module->data == node) {
339 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200340 }
341 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200342
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200343 /* store pointers to important nodes */
344 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200345 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200346 /* handle augments - first, unlink it from the augment parent ... */
347 if (parent->child == node) {
348 parent->child = node->next;
349 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100350
351 if (parent->flags & LYS_NOTAPPLIED) {
352 /* data are not connected in the target, so we cannot continue with the target as a parent */
353 parent = NULL;
354 } else {
355 /* data are connected in target, so we will continue with the target as a parent */
356 parent = ((struct lys_node_augment *)parent)->target;
357 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200358 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200360 /* unlink from parent */
361 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100362 if (parent->nodetype == LYS_EXT) {
363 pp = (struct lys_node **)lys_ext_complex_get_substmt(lys_snode2stmt(node->nodetype),
364 (struct lys_ext_instance_complex*)parent, NULL);
365 if (*pp == node) {
366 *pp = node->next;
367 }
368 } else if (parent->child == node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200369 parent->child = node->next;
370 }
371 node->parent = NULL;
372 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200374 /* unlink from siblings */
375 if (node->prev == node) {
376 /* there are no more siblings */
377 return;
378 }
379 if (node->next) {
380 node->next->prev = node->prev;
381 } else {
382 /* unlinking the last element */
383 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100384 if (parent->nodetype == LYS_EXT) {
385 first = *(struct lys_node **)pp;
386 } else {
387 first = parent->child;
388 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200389 } else {
390 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200391 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200392 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200393 }
394 }
395 first->prev = node->prev;
396 }
397 if (node->prev->next) {
398 node->prev->next = node->next;
399 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200401 /* clean up the unlinked element */
402 node->next = NULL;
403 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200404}
405
Michal Vasko563ef092015-09-04 13:17:23 +0200406struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100407lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200408{
409 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200410
411 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200412 /* top-level augment, look into module (uses augment is handled correctly below) */
413 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
414 par_iter = par_iter->parent->module->data;
415 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200416 break;
417 }
418 }
419
Michal Vasko6f929da2015-10-02 16:23:25 +0200420 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200421 continue;
422 }
423
424 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
425 if (!stop) {
426 stop = par_iter;
427 } else if (iter == stop) {
428 break;
429 }
430 if (iter->nodetype != LYS_GROUPING) {
431 continue;
432 }
433
Radek Krejcif8426a72015-10-31 23:14:03 +0100434 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200435 return (struct lys_node_grp *)iter;
436 }
437 }
438 }
439
Michal Vasko563ef092015-09-04 13:17:23 +0200440 return NULL;
441}
442
Radek Krejci10c760e2015-08-14 14:45:43 +0200443/*
444 * get next grouping in the root's subtree, in the
445 * first call, tha last is NULL
446 */
447static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200448lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200449{
Radek Krejci10c760e2015-08-14 14:45:43 +0200450 struct lys_node *last = (struct lys_node *)lastgrp;
451 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200452
Radek Krejci10c760e2015-08-14 14:45:43 +0200453 assert(root);
454
455 if (!last) {
456 last = root;
457 }
458
459 while (1) {
460 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
461 next = last->child;
462 } else {
463 next = NULL;
464 }
465 if (!next) {
466 if (last == root) {
467 /* we are done */
468 return NULL;
469 }
470
471 /* no children, go to siblings */
472 next = last->next;
473 }
474 while (!next) {
475 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100476 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200477 /* we are done */
478 return NULL;
479 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200480 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100481 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200482 }
483
484 if (next->nodetype == LYS_GROUPING) {
485 return (struct lys_node_grp *)next;
486 }
487
488 last = next;
489 }
490}
491
Michal Vasko0d343d12015-08-24 14:57:36 +0200492/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200493int
Radek Krejci07911992015-08-14 15:13:31 +0200494lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
495{
Michal Vasko563ef092015-09-04 13:17:23 +0200496 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200497 struct lys_node_grp *grp;
Radek Krejcif95b6292017-02-13 15:57:37 +0100498 int down, up;
Radek Krejci07911992015-08-14 15:13:31 +0200499
500 assert(node);
501
502 if (!parent) {
503 assert(module);
504 } else {
505 module = parent->module;
506 }
507
508 switch (node->nodetype) {
509 case LYS_GROUPING:
510 /* 6.2.1, rule 6 */
511 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100512 start = *lys_child(parent, LYS_GROUPING);
513 if (!start) {
Radek Krejci07911992015-08-14 15:13:31 +0200514 down = 0;
515 start = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100516 } else {
517 down = 1;
518 }
519 if (parent->nodetype == LYS_EXT) {
520 up = 0;
521 } else {
522 up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200523 }
524 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100525 down = up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200526 start = module->data;
527 }
528 /* go up */
Radek Krejcif95b6292017-02-13 15:57:37 +0100529 if (up && lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100530 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200531 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200532 }
533 /* go down, because grouping can be defined after e.g. container in which is collision */
534 if (down) {
535 for (iter = start, stop = NULL; iter; iter = iter->prev) {
536 if (!stop) {
537 stop = start;
538 } else if (iter == stop) {
539 break;
540 }
541 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
542 continue;
543 }
544
545 grp = NULL;
546 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100547 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100548 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200549 return EXIT_FAILURE;
550 }
551 }
552 }
553 }
554 break;
555 case LYS_LEAF:
556 case LYS_LEAFLIST:
557 case LYS_LIST:
558 case LYS_CONTAINER:
559 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200560 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200561 /* 6.2.1, rule 7 */
562 if (parent) {
563 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200564 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
565 if (iter->nodetype == LYS_AUGMENT) {
566 if (((struct lys_node_augment *)iter)->target) {
567 /* augment is resolved, go up */
568 iter = ((struct lys_node_augment *)iter)->target;
569 continue;
570 }
571 /* augment is not resolved, this is the final parent */
572 break;
573 }
Radek Krejci07911992015-08-14 15:13:31 +0200574 iter = iter->parent;
575 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200576
Radek Krejci07911992015-08-14 15:13:31 +0200577 if (!iter) {
578 stop = NULL;
579 iter = module->data;
Radek Krejcif95b6292017-02-13 15:57:37 +0100580 } else if (iter->nodetype == LYS_EXT) {
581 stop = iter;
582 iter = *lys_child(iter, node->nodetype);
Radek Krejci07911992015-08-14 15:13:31 +0200583 } else {
584 stop = iter;
585 iter = iter->child;
586 }
587 } else {
588 stop = NULL;
589 iter = module->data;
590 }
591 while (iter) {
592 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
593 iter = iter->child;
594 continue;
595 }
596
Radek Krejcibf2abff2016-08-23 15:51:52 +0200597 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100598 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100599 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200600 return EXIT_FAILURE;
601 }
602 }
603
604 /* special case for choice - we must check the choice's name as
605 * well as the names of nodes under the choice
606 */
607 if (iter->nodetype == LYS_CHOICE) {
608 iter = iter->child;
609 continue;
610 }
611
612 /* go to siblings */
613 if (!iter->next) {
614 /* no sibling, go to parent's sibling */
615 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200616 /* for parent LYS_AUGMENT */
617 if (iter->parent == stop) {
618 iter = stop;
619 break;
620 }
621 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200622 if (iter && iter->next) {
623 break;
624 }
625 } while (iter != stop);
626
627 if (iter == stop) {
628 break;
629 }
630 }
631 iter = iter->next;
632 }
633 break;
634 case LYS_CASE:
635 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100636 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100637 start = *lys_child(parent, LYS_CASE);
Radek Krejcic071c542016-01-27 14:57:51 +0100638 } else {
639 start = module->data;
640 }
641
642 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200643 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200644 continue;
645 }
646
Radek Krejci749190d2016-02-18 16:26:25 +0100647 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100648 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200649 return EXIT_FAILURE;
650 }
651 }
652 break;
653 default:
654 /* no check needed */
655 break;
656 }
657
658 return EXIT_SUCCESS;
659}
660
Michal Vasko0d343d12015-08-24 14:57:36 +0200661/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200662int
Radek Krejci10c760e2015-08-14 14:45:43 +0200663lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
664{
Radek Krejcif95b6292017-02-13 15:57:37 +0100665 struct lys_node *iter, *next, **pchild;
Radek Krejci41a349b2016-10-24 19:21:59 +0200666 struct lys_node_inout *in, *out, *inout;
Radek Krejci07911992015-08-14 15:13:31 +0200667 int type;
Radek Krejcif95b6292017-02-13 15:57:37 +0100668 void *p;
669 struct lyext_substmt *info = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200671 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200672
Radek Krejci10c760e2015-08-14 14:45:43 +0200673 if (parent) {
674 type = parent->nodetype;
675 module = parent->module;
676 } else {
677 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100678 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200679 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200680 }
681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200682 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200683 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200684 case LYS_CONTAINER:
685 case LYS_LIST:
686 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100687 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200688 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200689 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200690 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200691 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
692 return EXIT_FAILURE;
693 }
694 break;
Radek Krejci76512572015-08-04 09:47:08 +0200695 case LYS_INPUT:
696 case LYS_OUTPUT:
697 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200698 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200699 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200700 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100701 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200702 return EXIT_FAILURE;
703 }
704 break;
Radek Krejci76512572015-08-04 09:47:08 +0200705 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200706 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200707 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100708 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200709 return EXIT_FAILURE;
710 }
711 break;
Radek Krejci76512572015-08-04 09:47:08 +0200712 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200713 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200714 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100715 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200716 return EXIT_FAILURE;
717 }
718 break;
Radek Krejci76512572015-08-04 09:47:08 +0200719 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200720 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200721 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100722 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200723 return EXIT_FAILURE;
724 }
725 break;
Radek Krejci76512572015-08-04 09:47:08 +0200726 case LYS_LEAF:
727 case LYS_LEAFLIST:
728 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200729 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100730 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vasko51e5c582017-01-19 14:16:39 +0100731 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100732 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200734 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200735 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200736 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100737 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100738 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200739 return EXIT_FAILURE;
740 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200741 break;
742 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200743 /* top level */
744 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200745 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200746 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100747 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200748 return EXIT_FAILURE;
749 }
Radek Krejcif95b6292017-02-13 15:57:37 +0100750 break;
751 case LYS_EXT:
752 /* plugin-defined */
753 p = lys_ext_complex_get_substmt(lys_snode2stmt(child->nodetype), (struct lys_ext_instance_complex*)parent, &info);
754 if (!p) {
755 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype),
756 ((struct lys_ext_instance_complex*)parent)->def->name);
757 return EXIT_FAILURE;
758 }
759 /* TODO check cardinality */
Radek Krejcic071c542016-01-27 14:57:51 +0100760 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200761 }
762
763 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200764 if (lys_check_id(child, parent, module)) {
765 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200766 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200768 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200769 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200770 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200771
Radek Krejcif95b6292017-02-13 15:57:37 +0100772 if ((child->nodetype & (LYS_INPUT | LYS_OUTPUT)) && parent->nodetype != LYS_EXT) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200773 /* replace the implicit input/output node */
774 if (child->nodetype == LYS_OUTPUT) {
775 inout = (struct lys_node_inout *)parent->child->next;
776 } else { /* LYS_INPUT */
777 inout = (struct lys_node_inout *)parent->child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200778 parent->child = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200779 }
780 if (inout->next) {
781 child->next = inout->next;
782 inout->next->prev = child;
783 inout->next = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200784 } else {
Radek Krejci41a349b2016-10-24 19:21:59 +0200785 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200786 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200787 child->prev = inout->prev;
788 if (inout->prev->next) {
789 inout->prev->next = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200790 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200791 inout->prev = (struct lys_node *)inout;
792 child->parent = parent;
793 inout->parent = NULL;
794 lys_node_free((struct lys_node *)inout, NULL, 0);
795 } else {
796 /* connect the child correctly */
797 if (!parent) {
798 if (module->data) {
799 module->data->prev->next = child;
800 child->prev = module->data->prev;
801 module->data->prev = child;
802 } else {
803 module->data = child;
804 }
805 } else {
Radek Krejci30bfcd22017-01-27 16:54:48 +0100806 next = NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +0100807 pchild = lys_child(parent, child->nodetype);
808 assert(pchild);
809
810 if (!(*pchild)) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200811 /* the only/first child of the parent */
Radek Krejcif95b6292017-02-13 15:57:37 +0100812 *pchild = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200813 child->parent = parent;
814 iter = child;
Radek Krejci30bfcd22017-01-27 16:54:48 +0100815 } else if (type == LYS_AUGMENT) {
816 /* add a new child as a last child of the augment (no matter if applied or not) */
Radek Krejcif95b6292017-02-13 15:57:37 +0100817 for (iter = (*pchild)->prev; iter->parent != parent; iter = iter->prev);
Radek Krejci30bfcd22017-01-27 16:54:48 +0100818 next = iter->next;
819 iter->next = child;
820 child->prev = iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200821 } else {
822 /* add a new child at the end of parent's child list */
Radek Krejcif95b6292017-02-13 15:57:37 +0100823 iter = (*pchild)->prev;
Radek Krejci41a349b2016-10-24 19:21:59 +0200824 iter->next = child;
825 child->prev = iter;
826 }
827 while (iter->next) {
828 iter = iter->next;
829 iter->parent = parent;
830 }
Radek Krejci30bfcd22017-01-27 16:54:48 +0100831 if (next) {
832 /* we are in applied augment, its target has some additional nodes after the nodes from this augment */
833 iter->next = next;
834 next->prev = iter;
835 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100836 (*pchild)->prev = iter;
Radek Krejci30bfcd22017-01-27 16:54:48 +0100837 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200838 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200839 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200840
Michal Vaskoe022a562016-09-27 14:24:15 +0200841 /* check config value (but ignore them in groupings and augments) */
Radek Krejcif95b6292017-02-13 15:57:37 +0100842 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); iter = iter->parent);
Michal Vaskoe022a562016-09-27 14:24:15 +0200843 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200844 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
845 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
846 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +0100847 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200848 return EXIT_FAILURE;
849 }
850 }
851
Radek Krejci41771502016-04-14 17:52:32 +0200852 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200853 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200854 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200855 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200856 /* store it only into container or list - the only data inner nodes */
857 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
858 if (iter->flags & LYS_INCL_STATUS) {
859 /* done, someone else set it already from here */
860 break;
861 }
862 /* set flag about including status data */
863 iter->flags |= LYS_INCL_STATUS;
864 }
865 }
866 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200867
868 /* create implicit input/output nodes to have available them as possible target for augment */
869 if (child->nodetype & (LYS_RPC | LYS_ACTION)) {
870 in = calloc(1, sizeof *in);
871 in->nodetype = LYS_INPUT;
872 in->name = lydict_insert(child->module->ctx, "input", 5);
873 out = calloc(1, sizeof *out);
874 out->name = lydict_insert(child->module->ctx, "output", 6);
875 out->nodetype = LYS_OUTPUT;
876 in->module = out->module = child->module;
877 in->parent = out->parent = child;
878 in->flags = out->flags = LYS_IMPLICIT;
879 in->next = (struct lys_node *)out;
880 in->prev = (struct lys_node *)out;
881 out->prev = (struct lys_node *)in;
882 child->child = (struct lys_node *)in;
883 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200884 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200885}
886
Radek Krejcia1df1682016-04-11 14:56:59 +0200887static const struct lys_module *
888lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200889{
Radek Krejcia1df1682016-04-11 14:56:59 +0200890 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200891 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200892 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200893
Radek Krejci00a0e712016-10-26 10:24:46 +0200894 ly_err_clean(1);
Radek Krejcif347abc2016-06-22 10:18:47 +0200895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200896 if (!ctx || !data) {
897 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
898 return NULL;
899 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200900
Radek Krejcia1df1682016-04-11 14:56:59 +0200901 if (!internal && format == LYS_IN_YANG) {
902 /* enlarge data by 2 bytes for flex */
903 len = strlen(data);
904 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
905 if (!enlarged_data) {
906 LOGMEM;
907 return NULL;
908 }
909 memcpy(enlarged_data, data, len);
910 enlarged_data[len] = enlarged_data[len + 1] = '\0';
911 data = enlarged_data;
912 }
913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200914 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200915 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100916 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200917 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200918 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100919 mod = yang_read_module(ctx, data, 0, NULL, 1);
920 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200921 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200922 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200923 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200924 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200925
Radek Krejcia1df1682016-04-11 14:56:59 +0200926 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200927 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200928}
929
Radek Krejcia1df1682016-04-11 14:56:59 +0200930API const struct lys_module *
931lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
932{
933 return lys_parse_mem_(ctx, data, format, 0);
934}
935
Michal Vasko5a721fd2016-02-16 12:16:48 +0100936struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +0100937lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200938{
Michal Vasko5b998712017-01-26 10:34:06 +0100939 char *enlarged_data = NULL;
Michal Vasko5a721fd2016-02-16 12:16:48 +0100940 struct lys_submodule *submod = NULL;
Michal Vasko5b998712017-01-26 10:34:06 +0100941 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200943 assert(module);
944 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200945
Michal Vasko5b998712017-01-26 10:34:06 +0100946 if (format == LYS_IN_YANG) {
947 /* enlarge data by 2 bytes for flex */
948 len = strlen(data);
949 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
950 if (!enlarged_data) {
951 LOGMEM;
952 return NULL;
953 }
954 memcpy(enlarged_data, data, len);
955 enlarged_data[len] = enlarged_data[len + 1] = '\0';
956 data = enlarged_data;
957 }
958
Radek Krejcic071c542016-01-27 14:57:51 +0100959 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +0200960 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200962 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200963 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +0100964 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200965 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200966 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100967 submod = yang_read_submodule(module, data, 0, unres);
968 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200969 default:
Radek Krejci90a550a2016-04-13 16:00:58 +0200970 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200971 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200973
Michal Vasko5b998712017-01-26 10:34:06 +0100974 free(enlarged_data);
Michal Vasko5a721fd2016-02-16 12:16:48 +0100975 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200976}
977
Michal Vasko1e62a092015-12-01 12:27:20 +0100978API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +0100979lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
980{
981 int fd;
982 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +0200983 const char *rev, *dot, *filename;
984 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +0100985
986 if (!ctx || !path) {
987 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
988 return NULL;
989 }
990
991 fd = open(path, O_RDONLY);
992 if (fd == -1) {
993 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
994 return NULL;
995 }
996
997 ret = lys_parse_fd(ctx, fd, format);
998 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +0100999
Radek Krejcid80c8602016-10-25 11:56:03 +02001000 if (!ret) {
1001 /* error */
1002 return NULL;
1003 }
1004
1005 /* check that name and revision match filename */
1006 filename = strrchr(path, '/');
1007 if (!filename) {
1008 filename = path;
1009 } else {
1010 filename++;
1011 }
1012 rev = strchr(filename, '@');
1013 dot = strrchr(filename, '.');
1014
1015 /* name */
1016 len = strlen(ret->name);
1017 if (strncmp(filename, ret->name, len) ||
1018 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Radek Krejcic0c82302016-10-25 14:21:33 +02001019 LOGWRN("File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +02001020 }
1021 if (rev) {
1022 len = dot - ++rev;
1023 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
1024 LOGWRN("File name \"%s\" does not match module revision \"%s\".", filename,
1025 ret->rev_size ? ret->rev[0].date : "none");
1026 }
1027 }
1028
1029 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001030 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001031 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001032 }
1033
Michal Vasko662610a2015-12-07 11:25:45 +01001034 return ret;
1035}
1036
1037API const struct lys_module *
1038lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001039{
Michal Vasko1e62a092015-12-01 12:27:20 +01001040 const struct lys_module *module;
Radek Krejci0fb11502017-01-31 16:45:42 +01001041 size_t length;
Radek Krejci63a91a92015-07-29 13:31:04 +02001042 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001043 char buf[PATH_MAX];
1044 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001045
1046 if (!ctx || fd < 0) {
1047 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1048 return NULL;
1049 }
1050
Radek Krejci0fb11502017-01-31 16:45:42 +01001051 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001052 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001053 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001054 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001055 } else if (!addr) {
1056 LOGERR(LY_EINVAL, "Empty schema file.");
Pavol Vicane36ea262015-11-12 11:57:47 +01001057 return NULL;
1058 }
Radek Krejci0fb11502017-01-31 16:45:42 +01001059
Radek Krejcia1df1682016-04-11 14:56:59 +02001060 module = lys_parse_mem_(ctx, addr, format, 1);
Radek Krejci0fb11502017-01-31 16:45:42 +01001061 lyp_munmap(addr, length);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001062
Radek Krejcia77904e2016-02-25 16:23:45 +01001063 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001064 /* get URI if there is /proc */
1065 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001066 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1067 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1068 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1069 }
1070 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001071 }
Radek Krejcib051f722016-02-25 15:12:21 +01001072 }
1073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001074 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001075}
1076
Michal Vasko5a721fd2016-02-16 12:16:48 +01001077struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001078lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001079{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001080 struct lys_submodule *submodule;
Radek Krejci0fb11502017-01-31 16:45:42 +01001081 size_t length;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001082 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084 assert(module);
1085 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001086
Radek Krejci0fb11502017-01-31 16:45:42 +01001087 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001088 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001089 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001090 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001091 } else if (!addr) {
1092 LOGERR(LY_EINVAL, "Empty submodule schema file.");
Michal Vasko2e7241e2016-02-15 16:06:34 +01001093 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001094 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001095
Michal Vasko5b998712017-01-26 10:34:06 +01001096 /* get the main module */
1097 module = lys_main_module(module);
1098
1099 switch (format) {
1100 case LYS_IN_YIN:
1101 submodule = yin_read_submodule(module, addr, unres);
1102 break;
1103 case LYS_IN_YANG:
1104 submodule = yang_read_submodule(module, addr, 0, unres);
1105 break;
1106 default:
1107 assert(0);
1108 break;
1109 }
1110
Radek Krejcic645a3a2017-01-31 16:59:00 +01001111 lyp_munmap(addr, length);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001112 return submodule;
1113
Radek Krejciefaeba32015-05-27 14:30:57 +02001114}
1115
Radek Krejcibf285832017-01-26 16:05:41 +01001116int
1117lys_ext_iter(struct lys_ext_instance **ext, uint8_t ext_size, uint8_t start, LYEXT_SUBSTMT substmt)
1118{
1119 unsigned int u;
1120
1121 for (u = start; u < ext_size; u++) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001122 if (ext[u]->insubstmt == substmt) {
Radek Krejcibf285832017-01-26 16:05:41 +01001123 return u;
1124 }
1125 }
1126
1127 return -1;
1128}
1129
Radek Krejcifdc0d702017-01-23 15:58:38 +01001130/*
1131 * duplicate extension instance
1132 */
1133int
Radek Krejci8d6b7422017-02-03 14:42:13 +01001134lys_ext_dup(struct lys_module *mod, struct lys_ext_instance **orig, uint8_t size,
Radek Krejcifdc0d702017-01-23 15:58:38 +01001135 void *parent, LYEXT_PAR parent_type, struct lys_ext_instance ***new, struct unres_schema *unres)
1136{
1137 int i;
1138 uint8_t u = 0;
1139 struct lys_ext_instance **result;
1140 struct unres_ext *info, *info_orig;
1141
1142 assert(new);
1143
1144 if (!size) {
1145 if (orig) {
1146 LOGINT;
1147 return EXIT_FAILURE;
1148 }
1149 (*new) = NULL;
1150 return EXIT_SUCCESS;
1151 }
1152
1153 (*new) = result = calloc(size, sizeof *result);
1154 for (u = 0; u < size; u++) {
Radek Krejci9722c6d2017-02-03 15:39:01 +01001155 /* TODO cover complex extension instances */
1156
Radek Krejcifdc0d702017-01-23 15:58:38 +01001157 if (orig[u]) {
1158 /* resolved extension instance, just duplicate it */
1159 switch(lys_ext_instance_type(orig[u])) {
1160 case LYEXT_FLAG:
1161 result[u] = malloc(sizeof(struct lys_ext_instance));
1162 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001163 case LYEXT_COMPLEX:
1164 result[u] = calloc(1, ((struct lyext_plugin_complex*)orig[u]->def->plugin)->instance_size);
Radek Krejcif95b6292017-02-13 15:57:37 +01001165 ((struct lys_ext_instance_complex*)result[u])->nodetype = LYS_EXT;
Radek Krejci9722c6d2017-02-03 15:39:01 +01001166 ((struct lys_ext_instance_complex*)result[u])->module = mod;
Radek Krejcifebdad72017-02-06 11:35:51 +01001167 ((struct lys_ext_instance_complex*)result[u])->substmt = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001168 /* TODO duplicate data in extension instance content */
1169 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001170 case LYEXT_ERR:
1171 LOGINT;
1172 break;
1173 }
1174 /* generic part */
1175 result[u]->def = orig[u]->def;
1176 result[u]->flags = 0;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001177 result[u]->arg_value = lydict_insert(mod->ctx, orig[u]->arg_value, 0);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001178 result[u]->parent = parent;
1179 result[u]->parent_type = parent_type;
Radek Krejcifebdad72017-02-06 11:35:51 +01001180 result[u]->insubstmt = orig[u]->insubstmt;
1181 result[u]->insubstmt_index = orig[u]->insubstmt_index;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001182
1183 /* extensions */
1184 orig[u]->ext = NULL;
1185 result[u]->ext_size = orig[u]->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001186 if (lys_ext_dup(mod, orig[u]->ext, orig[u]->ext_size, result[u],
Radek Krejcif0bb3602017-01-25 17:05:08 +01001187 LYEXT_PAR_EXTINST, &result[u]->ext, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001188 goto error;
1189 }
1190 } else {
1191 /* original extension is not yet resolved, so duplicate it in unres */
1192 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1193 if (i == -1) {
1194 /* extension not found in unres */
1195 LOGINT;
1196 goto error;
1197 }
1198 info_orig = unres->str_snode[i];
1199 info = malloc(sizeof *info);
1200 info->datatype = info_orig->datatype;
1201 if (info->datatype == LYS_IN_YIN) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001202 info->data.yin = lyxml_dup_elem(mod->ctx, info_orig->data.yin, NULL, 1);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001203 } /* else TODO YANG */
1204 info->parent = parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001205 info->mod = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001206 info->parent_type = parent_type;
1207 info->ext_index = u;
1208 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1209 goto error;
1210 }
1211 }
1212 }
1213
1214 return EXIT_SUCCESS;
1215
1216error:
1217 (*new) = NULL;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001218 lys_extension_instances_free(mod->ctx, result, u);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001219 return EXIT_FAILURE;
1220}
1221
Radek Krejci1d82ef62015-08-07 14:44:40 +02001222static struct lys_restr *
Radek Krejci8d6b7422017-02-03 14:42:13 +01001223lys_restr_dup(struct lys_module *mod, struct lys_restr *old, int size, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001224{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001225 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001226 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001227
Radek Krejci3733a802015-06-19 13:43:21 +02001228 if (!size) {
1229 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001230 }
Radek Krejci3733a802015-06-19 13:43:21 +02001231
1232 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001233 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001234 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001235 return NULL;
1236 }
Radek Krejci3733a802015-06-19 13:43:21 +02001237 for (i = 0; i < size; i++) {
Radek Krejci77f22b22017-01-17 15:23:03 +01001238 result[i].ext_size = old[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001239 lys_ext_dup(mod, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_RESTR, &result[i].ext, unres);
1240 result[i].expr = lydict_insert(mod->ctx, old[i].expr, 0);
1241 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1242 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1243 result[i].eapptag = lydict_insert(mod->ctx, old[i].eapptag, 0);
1244 result[i].emsg = lydict_insert(mod->ctx, old[i].emsg, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001245 }
1246
1247 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001248}
1249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001250void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001251lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001252{
1253 assert(ctx);
1254 if (!restr) {
1255 return;
1256 }
1257
Radek Krejcifccd1442017-01-16 10:26:57 +01001258 lys_extension_instances_free(ctx, restr->ext, restr->ext_size);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001259 lydict_remove(ctx, restr->expr);
1260 lydict_remove(ctx, restr->dsc);
1261 lydict_remove(ctx, restr->ref);
1262 lydict_remove(ctx, restr->eapptag);
1263 lydict_remove(ctx, restr->emsg);
1264}
1265
Pavol Vican05810b62016-11-23 14:07:22 +01001266void
Radek Krejci5323b492017-01-16 15:40:11 +01001267lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size)
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001268{
1269 uint8_t i;
1270
1271 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci5323b492017-01-16 15:40:11 +01001272 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001273 free(iffeature[i].expr);
1274 free(iffeature[i].features);
1275 }
1276 free(iffeature);
1277}
1278
Michal Vaskob84f88a2015-09-24 13:16:10 +02001279static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001280type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001281 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001282{
1283 int i;
1284
1285 switch (base) {
1286 case LY_TYPE_BINARY:
1287 if (old->info.binary.length) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001288 new->info.binary.length = lys_restr_dup(mod, old->info.binary.length, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001289 }
1290 break;
1291
1292 case LY_TYPE_BITS:
1293 new->info.bits.count = old->info.bits.count;
1294 if (new->info.bits.count) {
1295 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1296 if (!new->info.bits.bit) {
1297 LOGMEM;
1298 return -1;
1299 }
1300 for (i = 0; i < new->info.bits.count; i++) {
1301 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1302 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1303 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1304 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1305 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001306 new->info.bits.bit[i].ext_size = old->info.bits.bit[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001307 if (lys_ext_dup(mod, old->info.bits.bit[i].ext, old->info.bits.bit[i].ext_size,
Radek Krejcif0bb3602017-01-25 17:05:08 +01001308 &new->info.bits.bit[i], LYEXT_PAR_TYPE_BIT,
1309 &new->info.bits.bit[i].ext, unres)) {
1310 return -1;
1311 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001312 }
1313 }
1314 break;
1315
1316 case LY_TYPE_DEC64:
1317 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001318 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001319 if (old->info.dec64.range) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001320 new->info.dec64.range = lys_restr_dup(mod, old->info.dec64.range, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001321 }
1322 break;
1323
1324 case LY_TYPE_ENUM:
1325 new->info.enums.count = old->info.enums.count;
1326 if (new->info.enums.count) {
1327 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1328 if (!new->info.enums.enm) {
1329 LOGMEM;
1330 return -1;
1331 }
1332 for (i = 0; i < new->info.enums.count; i++) {
1333 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1334 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1335 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1336 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1337 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001338 new->info.enums.enm[i].ext_size = old->info.enums.enm[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001339 if (lys_ext_dup(mod, old->info.enums.enm[i].ext, old->info.enums.enm[i].ext_size,
Radek Krejcif0bb3602017-01-25 17:05:08 +01001340 &new->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM,
1341 &new->info.enums.enm[i].ext, unres)) {
1342 return -1;
1343 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001344 }
1345 }
1346 break;
1347
1348 case LY_TYPE_IDENT:
Michal Vaskoaffc37f2016-10-10 18:05:03 +00001349 new->info.ident.count = old->info.ident.count;
Michal Vasko878e38d2016-09-05 12:17:53 +02001350 if (old->info.ident.count) {
1351 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1352 if (!new->info.ident.ref) {
1353 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001354 return -1;
1355 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001356 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1357 } else {
1358 /* there can be several unresolved base identities, duplicate them all */
1359 i = -1;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001360 do {
1361 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1362 if (i != -1) {
1363 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1364 return -1;
1365 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001366 }
1367 --i;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001368 } while (i > -1);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001369 }
1370 break;
1371
1372 case LY_TYPE_INST:
1373 new->info.inst.req = old->info.inst.req;
1374 break;
1375
1376 case LY_TYPE_INT8:
1377 case LY_TYPE_INT16:
1378 case LY_TYPE_INT32:
1379 case LY_TYPE_INT64:
1380 case LY_TYPE_UINT8:
1381 case LY_TYPE_UINT16:
1382 case LY_TYPE_UINT32:
1383 case LY_TYPE_UINT64:
1384 if (old->info.num.range) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001385 new->info.num.range = lys_restr_dup(mod, old->info.num.range, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001386 }
1387 break;
1388
1389 case LY_TYPE_LEAFREF:
1390 if (old->info.lref.path) {
1391 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001392 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001393 return -1;
1394 }
1395 }
1396 break;
1397
1398 case LY_TYPE_STRING:
1399 if (old->info.str.length) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01001400 new->info.str.length = lys_restr_dup(mod, old->info.str.length, 1, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001401 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01001402 new->info.str.patterns = lys_restr_dup(mod, old->info.str.patterns, old->info.str.pat_count, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001403 new->info.str.pat_count = old->info.str.pat_count;
1404 break;
1405
1406 case LY_TYPE_UNION:
1407 new->info.uni.count = old->info.uni.count;
1408 if (new->info.uni.count) {
1409 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1410 if (!new->info.uni.types) {
1411 LOGMEM;
1412 return -1;
1413 }
1414 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001415 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 +02001416 return -1;
1417 }
1418 }
1419 }
1420 break;
1421
1422 default:
1423 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1424 break;
1425 }
1426 return EXIT_SUCCESS;
1427}
1428
1429struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001430lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1431 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001432{
1433 struct yang_type *new;
1434
1435 new = calloc(1, sizeof *new);
1436 if (!new) {
1437 LOGMEM;
1438 return NULL;
1439 }
1440 new->flags = old->flags;
1441 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001442 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001443 new->type = type;
1444 if (!new->name) {
1445 LOGMEM;
1446 goto error;
1447 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001448 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001449 new->type->base = new->base;
1450 lys_type_free(module->ctx, new->type);
1451 memset(&new->type->info, 0, sizeof new->type->info);
1452 goto error;
1453 }
1454 return new;
1455
1456 error:
1457 free(new);
1458 return NULL;
1459}
1460
Radek Krejci43ce4b72017-01-04 11:02:38 +01001461API const void *
1462lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1463{
1464 if (!ext) {
1465 return NULL;
1466 }
1467
Radek Krejcifebdad72017-02-06 11:35:51 +01001468 switch (ext->insubstmt) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001469 case LYEXT_SUBSTMT_SELF:
1470 case LYEXT_SUBSTMT_MODIFIER:
1471 case LYEXT_SUBSTMT_VERSION:
1472 return NULL;
1473 case LYEXT_SUBSTMT_ARGUMENT:
1474 if (ext->parent_type == LYEXT_PAR_EXT) {
1475 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1476 }
1477 break;
1478 case LYEXT_SUBSTMT_BASE:
1479 if (ext->parent_type == LYEXT_PAR_TYPE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001480 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001481 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001482 return ((struct lys_ident*)ext->parent)->base[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001483 }
1484 break;
1485 case LYEXT_SUBSTMT_BELONGSTO:
1486 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1487 return ((struct lys_submodule*)ext->parent)->belongsto;
1488 }
1489 break;
1490 case LYEXT_SUBSTMT_CONFIG:
1491 case LYEXT_SUBSTMT_MANDATORY:
1492 if (ext->parent_type == LYEXT_PAR_NODE) {
1493 return &((struct lys_node*)ext->parent)->flags;
1494 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1495 return &((struct lys_deviate*)ext->parent)->flags;
1496 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1497 return &((struct lys_refine*)ext->parent)->flags;
1498 }
1499 break;
1500 case LYEXT_SUBSTMT_CONTACT:
1501 if (ext->parent_type == LYEXT_PAR_MODULE) {
1502 return ((struct lys_module*)ext->parent)->contact;
1503 }
1504 break;
1505 case LYEXT_SUBSTMT_DEFAULT:
1506 if (ext->parent_type == LYEXT_PAR_NODE) {
1507 switch (((struct lys_node*)ext->parent)->nodetype) {
1508 case LYS_LEAF:
1509 case LYS_LEAFLIST:
1510 /* in case of leaf, the index is supposed to be 0, so it will return the
1511 * correct pointer despite the leaf structure does not have dflt as array */
Radek Krejcifebdad72017-02-06 11:35:51 +01001512 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001513 case LYS_CHOICE:
1514 return ((struct lys_node_choice*)ext->parent)->dflt;
1515 default:
1516 /* internal error */
1517 break;
1518 }
1519 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1520 return ((struct lys_tpdf*)ext->parent)->dflt;
1521 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001522 return ((struct lys_deviate*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001523 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001524 return &((struct lys_refine*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001525 }
1526 break;
1527 case LYEXT_SUBSTMT_DESCRIPTION:
1528 switch (ext->parent_type) {
1529 case LYEXT_PAR_NODE:
1530 return ((struct lys_node*)ext->parent)->dsc;
1531 case LYEXT_PAR_MODULE:
1532 return ((struct lys_module*)ext->parent)->dsc;
1533 case LYEXT_PAR_IMPORT:
1534 return ((struct lys_import*)ext->parent)->dsc;
1535 case LYEXT_PAR_INCLUDE:
1536 return ((struct lys_include*)ext->parent)->dsc;
1537 case LYEXT_PAR_EXT:
1538 return ((struct lys_ext*)ext->parent)->dsc;
1539 case LYEXT_PAR_FEATURE:
1540 return ((struct lys_feature*)ext->parent)->dsc;
1541 case LYEXT_PAR_TPDF:
1542 return ((struct lys_tpdf*)ext->parent)->dsc;
1543 case LYEXT_PAR_TYPE_BIT:
1544 return ((struct lys_type_bit*)ext->parent)->dsc;
1545 case LYEXT_PAR_TYPE_ENUM:
1546 return ((struct lys_type_enum*)ext->parent)->dsc;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001547 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001548 return ((struct lys_restr*)ext->parent)->dsc;
1549 case LYEXT_PAR_WHEN:
1550 return ((struct lys_when*)ext->parent)->dsc;
1551 case LYEXT_PAR_IDENT:
1552 return ((struct lys_ident*)ext->parent)->dsc;
1553 case LYEXT_PAR_DEVIATION:
1554 return ((struct lys_deviation*)ext->parent)->dsc;
1555 case LYEXT_PAR_REVISION:
1556 return ((struct lys_revision*)ext->parent)->dsc;
1557 case LYEXT_PAR_REFINE:
1558 return ((struct lys_refine*)ext->parent)->dsc;
1559 default:
1560 break;
1561 }
1562 break;
1563 case LYEXT_SUBSTMT_ERRTAG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001564 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001565 return ((struct lys_restr*)ext->parent)->eapptag;
1566 }
1567 break;
1568 case LYEXT_SUBSTMT_ERRMSG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001569 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001570 return ((struct lys_restr*)ext->parent)->emsg;
1571 }
1572 break;
1573 case LYEXT_SUBSTMT_DIGITS:
1574 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
1575 return &((struct lys_type*)ext->parent)->info.dec64.dig;
1576 }
1577 break;
1578 case LYEXT_SUBSTMT_KEY:
1579 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1580 return ((struct lys_node_list*)ext->parent)->keys;
1581 }
1582 break;
1583 case LYEXT_SUBSTMT_MAX:
1584 if (ext->parent_type == LYEXT_PAR_NODE) {
1585 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1586 return &((struct lys_node_list*)ext->parent)->max;
1587 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1588 return &((struct lys_node_leaflist*)ext->parent)->max;
1589 }
1590 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1591 return &((struct lys_refine*)ext->parent)->mod.list.max;
1592 }
1593 break;
1594 case LYEXT_SUBSTMT_MIN:
1595 if (ext->parent_type == LYEXT_PAR_NODE) {
1596 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1597 return &((struct lys_node_list*)ext->parent)->min;
1598 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1599 return &((struct lys_node_leaflist*)ext->parent)->min;
1600 }
1601 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1602 return &((struct lys_refine*)ext->parent)->mod.list.min;
1603 }
1604 break;
1605 case LYEXT_SUBSTMT_NAMESPACE:
1606 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
1607 return ((struct lys_module*)ext->parent)->ns;
1608 }
1609 break;
1610 case LYEXT_SUBSTMT_ORDEREDBY:
1611 if (ext->parent_type == LYEXT_PAR_NODE &&
1612 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
1613 return &((struct lys_node_list*)ext->parent)->flags;
1614 }
1615 break;
1616 case LYEXT_SUBSTMT_ORGANIZATION:
1617 if (ext->parent_type == LYEXT_PAR_MODULE) {
1618 return ((struct lys_module*)ext->parent)->org;
1619 }
1620 break;
1621 case LYEXT_SUBSTMT_PATH:
1622 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1623 return ((struct lys_type*)ext->parent)->info.lref.path;
1624 }
1625 break;
1626 case LYEXT_SUBSTMT_POSITION:
1627 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
1628 return &((struct lys_type_bit*)ext->parent)->pos;
1629 }
1630 break;
1631 case LYEXT_SUBSTMT_PREFIX:
1632 if (ext->parent_type == LYEXT_PAR_MODULE) {
1633 /* covers also lys_submodule */
1634 return ((struct lys_module*)ext->parent)->prefix;
1635 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
1636 return ((struct lys_import*)ext->parent)->prefix;
1637 }
1638 break;
1639 case LYEXT_SUBSTMT_PRESENCE:
1640 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
1641 return ((struct lys_node_container*)ext->parent)->presence;
1642 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1643 return ((struct lys_refine*)ext->parent)->mod.presence;
1644 }
1645 break;
1646 case LYEXT_SUBSTMT_REFERENCE:
1647 switch (ext->parent_type) {
1648 case LYEXT_PAR_NODE:
1649 return ((struct lys_node*)ext->parent)->ref;
1650 case LYEXT_PAR_MODULE:
1651 return ((struct lys_module*)ext->parent)->ref;
1652 case LYEXT_PAR_IMPORT:
1653 return ((struct lys_import*)ext->parent)->ref;
1654 case LYEXT_PAR_INCLUDE:
1655 return ((struct lys_include*)ext->parent)->ref;
1656 case LYEXT_PAR_EXT:
1657 return ((struct lys_ext*)ext->parent)->ref;
1658 case LYEXT_PAR_FEATURE:
1659 return ((struct lys_feature*)ext->parent)->ref;
1660 case LYEXT_PAR_TPDF:
1661 return ((struct lys_tpdf*)ext->parent)->ref;
1662 case LYEXT_PAR_TYPE_BIT:
1663 return ((struct lys_type_bit*)ext->parent)->ref;
1664 case LYEXT_PAR_TYPE_ENUM:
1665 return ((struct lys_type_enum*)ext->parent)->ref;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001666 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001667 return ((struct lys_restr*)ext->parent)->ref;
1668 case LYEXT_PAR_WHEN:
1669 return ((struct lys_when*)ext->parent)->ref;
1670 case LYEXT_PAR_IDENT:
1671 return ((struct lys_ident*)ext->parent)->ref;
1672 case LYEXT_PAR_DEVIATION:
1673 return ((struct lys_deviation*)ext->parent)->ref;
1674 case LYEXT_PAR_REVISION:
1675 return ((struct lys_revision*)ext->parent)->ref;
1676 case LYEXT_PAR_REFINE:
1677 return ((struct lys_refine*)ext->parent)->ref;
1678 default:
1679 break;
1680 }
1681 break;
Radek Krejcibe336392017-02-07 10:54:24 +01001682 case LYEXT_SUBSTMT_REQINSTANCE:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001683 if (ext->parent_type == LYEXT_PAR_TYPE) {
1684 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1685 return &((struct lys_type*)ext->parent)->info.lref.req;
1686 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
1687 return &((struct lys_type*)ext->parent)->info.inst.req;
1688 }
1689 }
1690 break;
1691 case LYEXT_SUBSTMT_REVISIONDATE:
1692 if (ext->parent_type == LYEXT_PAR_IMPORT) {
1693 return ((struct lys_import*)ext->parent)->rev;
1694 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
1695 return ((struct lys_include*)ext->parent)->rev;
1696 }
1697 break;
1698 case LYEXT_SUBSTMT_STATUS:
1699 switch (ext->parent_type) {
1700 case LYEXT_PAR_NODE:
1701 case LYEXT_PAR_IDENT:
1702 case LYEXT_PAR_TPDF:
1703 case LYEXT_PAR_EXT:
1704 case LYEXT_PAR_FEATURE:
1705 case LYEXT_PAR_TYPE_ENUM:
1706 case LYEXT_PAR_TYPE_BIT:
1707 /* in all structures the flags member is at the same offset */
1708 return &((struct lys_node*)ext->parent)->flags;
1709 default:
1710 break;
1711 }
1712 break;
1713 case LYEXT_SUBSTMT_UNIQUE:
1714 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001715 return &((struct lys_deviate*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001716 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001717 return &((struct lys_node_list*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001718 }
1719 break;
1720 case LYEXT_SUBSTMT_UNITS:
1721 if (ext->parent_type == LYEXT_PAR_NODE &&
1722 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1723 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
1724 return ((struct lys_node_leaf*)ext->parent)->units;
1725 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1726 return ((struct lys_tpdf*)ext->parent)->units;
1727 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1728 return ((struct lys_deviate*)ext->parent)->units;
1729 }
1730 break;
1731 case LYEXT_SUBSTMT_VALUE:
1732 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
1733 return &((struct lys_type_enum*)ext->parent)->value;
1734 }
1735 break;
1736 case LYEXT_SUBSTMT_YINELEM:
1737 if (ext->parent_type == LYEXT_PAR_EXT) {
1738 return &((struct lys_ext*)ext->parent)->flags;
1739 }
1740 break;
1741 }
1742 LOGINT;
1743 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01001744}
1745
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001746static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001747lys_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 +02001748 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001749{
1750 int i;
1751
Michal Vasko1dca6882015-10-22 14:29:42 +02001752 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001753 new->base = old->base;
1754 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001755 new->parent = (struct lys_tpdf *)parent;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001756 new->ext_size = old->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001757 if (lys_ext_dup(mod, old->ext, old->ext_size, new, LYEXT_PAR_TYPE, &new->ext, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01001758 return -1;
Radek Krejcie534c132016-11-23 13:32:31 +01001759 }
Radek Krejci3733a802015-06-19 13:43:21 +02001760
Michal Vasko878e38d2016-09-05 12:17:53 +02001761 i = unres_schema_find(unres, -1, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001762 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001763 /* HACK (serious one) for unres */
1764 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001765 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001766 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 +02001767 } else {
1768 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1769 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001770 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001771 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001772 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001773 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001774 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001775 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001776 }
1777
Radek Krejci3a5501d2016-07-18 22:03:34 +02001778 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001779}
1780
1781void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001782lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001783{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001784 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001786 assert(ctx);
1787 if (!type) {
1788 return;
1789 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001790
Michal Vasko1dca6882015-10-22 14:29:42 +02001791 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001792
Radek Krejcie534c132016-11-23 13:32:31 +01001793 lys_extension_instances_free(ctx, type->ext, type->ext_size);
1794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001795 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001796 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001797 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001798 free(type->info.binary.length);
1799 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001800 case LY_TYPE_BITS:
1801 for (i = 0; i < type->info.bits.count; i++) {
1802 lydict_remove(ctx, type->info.bits.bit[i].name);
1803 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1804 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001805 lys_iffeature_free(ctx, type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci9b15fea2017-01-23 11:31:43 +01001806 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 +02001807 }
1808 free(type->info.bits.bit);
1809 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001810
1811 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001812 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001813 free(type->info.dec64.range);
1814 break;
1815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001816 case LY_TYPE_ENUM:
1817 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001818 lydict_remove(ctx, type->info.enums.enm[i].name);
1819 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1820 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001821 lys_iffeature_free(ctx, type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci9b15fea2017-01-23 11:31:43 +01001822 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 +02001823 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001824 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001825 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001826
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001827 case LY_TYPE_INT8:
1828 case LY_TYPE_INT16:
1829 case LY_TYPE_INT32:
1830 case LY_TYPE_INT64:
1831 case LY_TYPE_UINT8:
1832 case LY_TYPE_UINT16:
1833 case LY_TYPE_UINT32:
1834 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001835 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001836 free(type->info.num.range);
1837 break;
1838
Radek Krejcidc4c1412015-06-19 15:39:54 +02001839 case LY_TYPE_LEAFREF:
1840 lydict_remove(ctx, type->info.lref.path);
1841 break;
1842
Radek Krejci3733a802015-06-19 13:43:21 +02001843 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001844 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001845 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001846 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001847 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001848 }
1849 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001850 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001851
Radek Krejcie4c366b2015-07-02 10:11:31 +02001852 case LY_TYPE_UNION:
1853 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001854 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001855 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001856 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001857 break;
1858
Michal Vaskod3282192016-09-05 11:27:57 +02001859 case LY_TYPE_IDENT:
1860 free(type->info.ident.ref);
1861 break;
1862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001863 default:
Michal Vaskod3282192016-09-05 11:27:57 +02001864 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001865 break;
1866 }
Radek Krejci5a065542015-05-22 15:02:07 +02001867}
1868
Radek Krejci1d82ef62015-08-07 14:44:40 +02001869static void
1870lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001871{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001872 assert(ctx);
1873 if (!tpdf) {
1874 return;
1875 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001877 lydict_remove(ctx, tpdf->name);
1878 lydict_remove(ctx, tpdf->dsc);
1879 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001880
Radek Krejci1d82ef62015-08-07 14:44:40 +02001881 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001883 lydict_remove(ctx, tpdf->units);
1884 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01001885
1886 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001887}
1888
Radek Krejci1d82ef62015-08-07 14:44:40 +02001889static struct lys_when *
Radek Krejci8d6b7422017-02-03 14:42:13 +01001890lys_when_dup(struct lys_module *mod, struct lys_when *old, struct unres_schema *unres)
Radek Krejci00768f42015-06-18 17:04:04 +02001891{
Radek Krejci76512572015-08-04 09:47:08 +02001892 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001893
1894 if (!old) {
1895 return NULL;
1896 }
1897
1898 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001899 if (!new) {
1900 LOGMEM;
1901 return NULL;
1902 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01001903 new->cond = lydict_insert(mod->ctx, old->cond, 0);
1904 new->dsc = lydict_insert(mod->ctx, old->dsc, 0);
1905 new->ref = lydict_insert(mod->ctx, old->ref, 0);
Radek Krejcif0bb3602017-01-25 17:05:08 +01001906 new->ext_size = old->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001907 lys_ext_dup(mod, old->ext, old->ext_size, new, LYEXT_PAR_WHEN, &new->ext, unres);
Radek Krejci00768f42015-06-18 17:04:04 +02001908
1909 return new;
1910}
1911
Michal Vasko0308dd62015-10-07 09:14:40 +02001912void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001913lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001914{
1915 if (!w) {
1916 return;
1917 }
1918
Radek Krejci5323b492017-01-16 15:40:11 +01001919 lys_extension_instances_free(ctx, w->ext, w->ext_size);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001920 lydict_remove(ctx, w->cond);
1921 lydict_remove(ctx, w->dsc);
1922 lydict_remove(ctx, w->ref);
1923
1924 free(w);
1925}
1926
Radek Krejcib7f5e412015-08-13 10:15:51 +02001927static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001928lys_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 +02001929{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001930 struct lys_node *next, *sub;
1931
Radek Krejcic071c542016-01-27 14:57:51 +01001932 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01001933 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001934 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001935 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001936 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001937 }
1938
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001939 lydict_remove(ctx, aug->target_name);
1940 lydict_remove(ctx, aug->dsc);
1941 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001942
Radek Krejci5323b492017-01-16 15:40:11 +01001943 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01001944 lys_extension_instances_free(ctx, aug->ext, aug->ext_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001945
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001946 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001947}
1948
Radek Krejci1d82ef62015-08-07 14:44:40 +02001949static void
1950lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001951{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001952 assert(ctx);
1953 if (!ident) {
1954 return;
1955 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001956
Radek Krejci018f1f52016-08-03 16:01:20 +02001957 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02001958 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 lydict_remove(ctx, ident->name);
1960 lydict_remove(ctx, ident->dsc);
1961 lydict_remove(ctx, ident->ref);
Radek Krejci5323b492017-01-16 15:40:11 +01001962 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size);
Radek Krejcie534c132016-11-23 13:32:31 +01001963 lys_extension_instances_free(ctx, ident->ext, ident->ext_size);
Radek Krejci6793db02015-05-22 17:49:54 +02001964
1965}
1966
Radek Krejci1d82ef62015-08-07 14:44:40 +02001967static void
1968lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001969{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001970 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001971
Radek Krejcid12f57b2015-08-06 10:43:39 +02001972 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001973 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001974 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001975 }
1976 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001977}
1978
Radek Krejci1d82ef62015-08-07 14:44:40 +02001979static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001980lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001981{
1982 int i;
1983
1984 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1985 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001986 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001987 }
1988 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02001989
1990 for (i = 0; i < io->must_size; i++) {
1991 lys_restr_free(ctx, &io->must[i]);
1992 }
1993 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001994}
1995
Radek Krejci1d82ef62015-08-07 14:44:40 +02001996static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02001997lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
1998{
1999 int i;
2000
2001 for (i = 0; i < notif->must_size; i++) {
2002 lys_restr_free(ctx, &notif->must[i]);
2003 }
2004 free(notif->must);
2005
2006 for (i = 0; i < notif->tpdf_size; i++) {
2007 lys_tpdf_free(ctx, &notif->tpdf[i]);
2008 }
2009 free(notif->tpdf);
2010}
2011static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02002012lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02002013{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002014 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002016 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002017 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 }
2019 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002020
Radek Krejci1d82ef62015-08-07 14:44:40 +02002021 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002022}
2023
Radek Krejci1d82ef62015-08-07 14:44:40 +02002024static void
2025lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02002026{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002027 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002028
Radek Krejci85a54be2016-10-20 12:39:56 +02002029 /* leafref backlinks */
2030 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002032 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002033 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002034 }
2035 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002036
Radek Krejci1d82ef62015-08-07 14:44:40 +02002037 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002038
Radek Krejci1d82ef62015-08-07 14:44:40 +02002039 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002040 lydict_remove(ctx, leaf->units);
2041 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002042}
2043
Radek Krejci1d82ef62015-08-07 14:44:40 +02002044static void
2045lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02002046{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002048
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002049 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002050 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002051 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002052 }
2053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002054 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002055 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 }
2057 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002058
Pavol Vican38321d02016-08-16 14:56:02 +02002059 for (i = 0; i < llist->dflt_size; i++) {
2060 lydict_remove(ctx, llist->dflt[i]);
2061 }
2062 free(llist->dflt);
2063
Radek Krejci1d82ef62015-08-07 14:44:40 +02002064 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002065
Radek Krejci1d82ef62015-08-07 14:44:40 +02002066 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002068}
2069
Radek Krejci1d82ef62015-08-07 14:44:40 +02002070static void
2071lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002072{
Radek Krejci581ce772015-11-10 17:22:40 +01002073 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 /* handle only specific parts for LY_NODE_LIST */
2076 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002077 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 }
2079 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002081 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002082 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 }
2084 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002085
Radek Krejci1d82ef62015-08-07 14:44:40 +02002086 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002088 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002089 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002090 lydict_remove(ctx, list->unique[i].expr[j]);
2091 }
2092 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 }
2094 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002097}
2098
Radek Krejci1d82ef62015-08-07 14:44:40 +02002099static void
2100lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002101{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 /* handle only specific parts for LY_NODE_CONTAINER */
2105 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002108 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 }
2110 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002111
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002113 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 }
2115 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002116
Radek Krejci1d82ef62015-08-07 14:44:40 +02002117 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002118}
2119
Radek Krejci1d82ef62015-08-07 14:44:40 +02002120static void
2121lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02002122{
2123 lydict_remove(ctx, f->name);
2124 lydict_remove(ctx, f->dsc);
2125 lydict_remove(ctx, f->ref);
Radek Krejci5323b492017-01-16 15:40:11 +01002126 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size);
Radek Krejci9de2c042016-10-19 16:53:06 +02002127 ly_set_free(f->depfeatures);
Radek Krejcie534c132016-11-23 13:32:31 +01002128 lys_extension_instances_free(ctx, f->ext, f->ext_size);
2129}
2130
2131static void
2132lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e)
2133{
2134 lydict_remove(ctx, e->name);
2135 lydict_remove(ctx, e->dsc);
2136 lydict_remove(ctx, e->ref);
2137 lydict_remove(ctx, e->argument);
2138 lys_extension_instances_free(ctx, e->ext, e->ext_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002139}
2140
Radek Krejci1d82ef62015-08-07 14:44:40 +02002141static void
Michal Vaskoff006c12016-02-17 11:15:19 +01002142lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02002143{
Radek Krejci581ce772015-11-10 17:22:40 +01002144 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002145 struct ly_ctx *ctx;
2146 struct lys_node *next, *elem;
2147
2148 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002149
2150 lydict_remove(ctx, dev->target_name);
2151 lydict_remove(ctx, dev->dsc);
2152 lydict_remove(ctx, dev->ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002153 lys_extension_instances_free(ctx, dev->ext, dev->ext_size);
Radek Krejcieb00f512015-07-01 16:44:58 +02002154
Pavol Vican64d0b762016-08-25 10:44:59 +02002155 if (!dev->deviate) {
2156 return ;
2157 }
2158
Michal Vaskoff006c12016-02-17 11:15:19 +01002159 /* the module was freed, but we only need the context from orig_node, use ours */
2160 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2161 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2162 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2163 elem->module = module;
2164
2165 LY_TREE_DFS_END(dev->orig_node, next, elem);
2166 }
2167 lys_node_free(dev->orig_node, NULL, 0);
2168 } else {
2169 /* it's just a shallow copy, freeing one node */
2170 dev->orig_node->module = module;
2171 lys_node_free(dev->orig_node, NULL, 1);
2172 }
2173
Radek Krejcieb00f512015-07-01 16:44:58 +02002174 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002175 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size);
2176
Radek Krejcid5a5c282016-08-15 15:38:08 +02002177 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002178 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002179 }
2180 free(dev->deviate[i].dflt);
2181
Radek Krejcieb00f512015-07-01 16:44:58 +02002182 lydict_remove(ctx, dev->deviate[i].units);
2183
2184 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2185 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002186 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002187 }
2188 free(dev->deviate[i].must);
2189
2190 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002191 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2192 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2193 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002194 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002195 }
2196 free(dev->deviate[i].unique);
2197 }
2198 }
2199 free(dev->deviate);
2200}
2201
Radek Krejci1d82ef62015-08-07 14:44:40 +02002202static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002203lys_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 +02002204{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002205 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002208 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 lydict_remove(ctx, uses->refine[i].dsc);
2210 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002211
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002212 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002213 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 }
2215 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002216
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002217 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002218 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002219 }
2220 free(uses->refine[i].dflt);
2221
Radek Krejcie534c132016-11-23 13:32:31 +01002222 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size);
2223
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002224 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 lydict_remove(ctx, uses->refine[i].mod.presence);
2226 }
2227 }
2228 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002231 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 }
2233 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002234
Radek Krejci1d82ef62015-08-07 14:44:40 +02002235 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002236}
2237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002239lys_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 +02002240{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002242 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 if (!node) {
2245 return;
2246 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 assert(node->module);
2249 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002252
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002253 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002254 if (node->priv && private_destructor) {
2255 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002256 }
2257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002259 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002260 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci5323b492017-01-16 15:40:11 +01002261 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002262 lydict_remove(ctx, node->dsc);
2263 lydict_remove(ctx, node->ref);
2264 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002265
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002266 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002267 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002268 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002269 }
2270 }
2271
Radek Krejcie534c132016-11-23 13:32:31 +01002272 lys_extension_instances_free(ctx, node->ext, node->ext_size);
2273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 /* specific part */
2275 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002276 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002277 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 break;
Radek Krejci76512572015-08-04 09:47:08 +02002279 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002280 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 break;
Radek Krejci76512572015-08-04 09:47:08 +02002282 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002283 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002284 break;
Radek Krejci76512572015-08-04 09:47:08 +02002285 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002286 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002287 break;
Radek Krejci76512572015-08-04 09:47:08 +02002288 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002289 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 break;
Radek Krejci76512572015-08-04 09:47:08 +02002291 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002292 case LYS_ANYDATA:
2293 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 break;
Radek Krejci76512572015-08-04 09:47:08 +02002295 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002296 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 break;
Radek Krejci76512572015-08-04 09:47:08 +02002298 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002299 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002300 break;
Radek Krejci76512572015-08-04 09:47:08 +02002301 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302 /* do nothing */
2303 break;
Radek Krejci76512572015-08-04 09:47:08 +02002304 case LYS_GROUPING:
2305 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002306 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002307 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002309 case LYS_NOTIF:
2310 lys_notif_free(ctx, (struct lys_node_notif *)node);
2311 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002312 case LYS_INPUT:
2313 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02002314 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002315 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01002316 case LYS_EXT:
Michal Vasko591e0b22015-08-13 13:53:43 +02002317 case LYS_UNKNOWN:
2318 LOGINT;
2319 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 }
Radek Krejci5a065542015-05-22 15:02:07 +02002321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002323 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002325}
2326
Radek Krejci2eee5c02016-12-06 19:18:05 +01002327API struct lys_module *
2328lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002329{
2330 struct ly_ctx *ctx;
2331 int i;
2332
2333 if (!mod || mod->implemented) {
2334 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002335 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002336 }
2337
2338 ctx = mod->ctx;
2339 for (i = 0; i < ctx->models.used; i++) {
2340 if (!ctx->models.list[i]->implemented) {
2341 continue;
2342 }
2343
2344 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2345 /* we have some revision of the module implemented */
2346 return ctx->models.list[i];
2347 }
2348 }
2349
2350 /* we have no revision of the module implemented, return the module itself,
2351 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002352 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002353}
2354
2355const struct lys_module *
Radek Krejcie534c132016-11-23 13:32:31 +01002356lys_get_import_module_ns(const struct lys_module *module, const char *ns)
2357{
2358 int i;
2359
2360 assert(module && ns);
2361
Radek Krejcic789d692017-01-11 11:31:14 +01002362 if (module->type) {
2363 /* the module is actually submodule and to get the namespace, we need the main module */
2364 if (ly_strequal(((struct lys_submodule *)module)->belongsto->ns, ns, 0)) {
2365 return ((struct lys_submodule *)module)->belongsto;
2366 }
2367 } else {
2368 /* modul's own namespace */
2369 if (ly_strequal(module->ns, ns, 0)) {
2370 return module;
2371 }
Radek Krejcie534c132016-11-23 13:32:31 +01002372 }
2373
2374 /* imported modules */
2375 for (i = 0; i < module->imp_size; ++i) {
2376 if (ly_strequal(module->imp[i].module->ns, ns, 0)) {
2377 return module->imp[i].module;
2378 }
2379 }
2380
2381 return NULL;
2382}
2383
2384const struct lys_module *
Michal Vasko1e62a092015-12-01 12:27:20 +01002385lys_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 +02002386{
Radek Krejcic071c542016-01-27 14:57:51 +01002387 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02002388 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002389 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002390
Michal Vaskoa7789a82016-02-11 15:42:55 +01002391 assert(!prefix || !name);
2392
Michal Vaskob6729c62015-10-21 12:09:47 +02002393 if (prefix && !pref_len) {
2394 pref_len = strlen(prefix);
2395 }
2396 if (name && !name_len) {
2397 name_len = strlen(name);
2398 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002399
Radek Krejcic4283442016-04-22 09:19:27 +02002400 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002401
2402 /* module own prefix, submodule own prefix, (sub)module own name */
2403 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2404 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002405 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002406 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002407 }
2408
Michal Vasko89563fc2016-07-28 16:19:35 +02002409 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02002410 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002411 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2412 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002413 return module->imp[i].module;
2414 }
2415 }
2416
Michal Vasko89563fc2016-07-28 16:19:35 +02002417 /* module required by a foreign grouping, deviation, or submodule */
2418 if (name) {
2419 str = strndup(name, name_len);
2420 if (!str) {
2421 LOGMEM;
2422 return NULL;
2423 }
2424 main_module = ly_ctx_get_module(module->ctx, str, NULL);
2425 free(str);
2426 return main_module;
2427 }
2428
Michal Vasko8ce24d72015-10-21 11:27:26 +02002429 return NULL;
2430}
2431
Michal Vasko13b15832015-08-19 11:04:48 +02002432/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002434module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002435{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002436 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002437 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002440 assert(module->ctx);
2441 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002442
Michal Vaskob746fff2016-02-11 11:37:50 +01002443 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002444 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002445 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002446 lydict_remove(ctx, module->imp[i].dsc);
2447 lydict_remove(ctx, module->imp[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002448 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size);
Radek Krejci225376f2016-02-16 17:36:22 +01002449 }
Radek Krejcidce51452015-06-16 15:20:08 +02002450 free(module->imp);
2451
Radek Krejcic071c542016-01-27 14:57:51 +01002452 /* submodules don't have data tree, the data nodes
2453 * are placed in the main module altogether */
2454 if (!module->type) {
2455 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002456 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002457 }
Radek Krejci21181962015-06-30 14:11:00 +02002458 }
Radek Krejci5a065542015-05-22 15:02:07 +02002459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002460 lydict_remove(ctx, module->dsc);
2461 lydict_remove(ctx, module->ref);
2462 lydict_remove(ctx, module->org);
2463 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002464 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002465
Radek Krejcieb00f512015-07-01 16:44:58 +02002466 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002467 for (i = 0; i < module->rev_size; i++) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01002468 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002469 lydict_remove(ctx, module->rev[i].dsc);
2470 lydict_remove(ctx, module->rev[i].ref);
2471 }
2472 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002473
Radek Krejcieb00f512015-07-01 16:44:58 +02002474 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002475 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002476 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 }
2478 module->ident_size = 0;
2479 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002480
Radek Krejcieb00f512015-07-01 16:44:58 +02002481 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002482 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002483 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002484 }
2485 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002486
Radek Krejcie534c132016-11-23 13:32:31 +01002487 /* extension instances */
2488 lys_extension_instances_free(ctx, module->ext, module->ext_size);
2489
Radek Krejcieb00f512015-07-01 16:44:58 +02002490 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002492 lydict_remove(ctx, module->inc[i].dsc);
2493 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcie534c132016-11-23 13:32:31 +01002494 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size);
Radek Krejcic071c542016-01-27 14:57:51 +01002495 /* complete submodule free is done only from main module since
2496 * submodules propagate their includes to the main module */
2497 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002498 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002499 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500 }
2501 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002502
Radek Krejcieb00f512015-07-01 16:44:58 +02002503 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002504 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002505 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002506 }
2507 free(module->augment);
2508
Radek Krejcieb00f512015-07-01 16:44:58 +02002509 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002510 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002511 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002512 }
2513 free(module->features);
2514
Radek Krejcieb00f512015-07-01 16:44:58 +02002515 /* deviations */
2516 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002517 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002518 }
2519 free(module->deviation);
2520
Radek Krejcie534c132016-11-23 13:32:31 +01002521 /* extensions */
2522 for (i = 0; i < module->extensions_size; i++) {
2523 lys_extension_free(ctx, &module->extensions[i]);
2524 }
2525 free(module->extensions);
2526
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002528 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002529}
2530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531void
Michal Vaskob746fff2016-02-11 11:37:50 +01002532lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002533{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002534 if (!submodule) {
2535 return;
2536 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002539 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002543 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002544}
2545
Radek Krejci3a5501d2016-07-18 22:03:34 +02002546static int
2547ingrouping(const struct lys_node *node)
2548{
2549 const struct lys_node *iter = node;
2550 assert(node);
2551
2552 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2553 if (!iter) {
2554 return 0;
2555 } else {
2556 return 1;
2557 }
2558}
2559
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002560/*
2561 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2562 */
2563static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002564lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002565 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002566{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002567 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002568 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002569 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002570 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002571 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002572 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002573
Michal Vaskoc07187d2015-08-13 15:20:57 +02002574 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002575 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002576 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002577 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002578 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002579 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002580 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002581 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002582 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002583 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002584 struct lys_node_anydata *any = NULL;
2585 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002586 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002587 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002588 struct lys_node_rpc_action *rpc = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002589 struct lys_node_inout *io = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002590 struct lys_node_rpc_action *ntf = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002591 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002592 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002594 /* we cannot just duplicate memory since the strings are stored in
2595 * dictionary and we need to update dictionary counters.
2596 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002597
Radek Krejci1d82ef62015-08-07 14:44:40 +02002598 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002599 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002601 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002602 break;
2603
Radek Krejci76512572015-08-04 09:47:08 +02002604 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002605 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002606 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607 break;
2608
Radek Krejci76512572015-08-04 09:47:08 +02002609 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002610 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002611 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002612 break;
2613
Radek Krejci76512572015-08-04 09:47:08 +02002614 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002615 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002616 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002617 break;
2618
Radek Krejci76512572015-08-04 09:47:08 +02002619 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002620 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002621 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002622 break;
2623
Radek Krejci76512572015-08-04 09:47:08 +02002624 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002625 case LYS_ANYDATA:
2626 any = calloc(1, sizeof *any);
2627 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002628 break;
2629
Radek Krejci76512572015-08-04 09:47:08 +02002630 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002631 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002632 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002633 break;
2634
Radek Krejci76512572015-08-04 09:47:08 +02002635 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002636 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002637 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 break;
2639
Radek Krejci76512572015-08-04 09:47:08 +02002640 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002641 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002642 rpc = calloc(1, sizeof *rpc);
2643 retval = (struct lys_node *)rpc;
2644 break;
2645
Radek Krejci76512572015-08-04 09:47:08 +02002646 case LYS_INPUT:
2647 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002648 io = calloc(1, sizeof *io);
2649 retval = (struct lys_node *)io;
2650 break;
2651
Radek Krejci76512572015-08-04 09:47:08 +02002652 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002653 ntf = calloc(1, sizeof *ntf);
2654 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002655 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002657 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002658 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002659 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002660 }
Radek Krejcib388c152015-06-04 17:03:03 +02002661
Michal Vasko253035f2015-12-17 16:58:13 +01002662 if (!retval) {
2663 LOGMEM;
2664 return NULL;
2665 }
2666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002667 /*
2668 * duplicate generic part of the structure
2669 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002670 retval->name = lydict_insert(ctx, node->name, 0);
2671 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2672 retval->ref = lydict_insert(ctx, node->ref, 0);
2673 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002674
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002675 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002676 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002677
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002678 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002679
Radek Krejcif0bb3602017-01-25 17:05:08 +01002680 retval->ext_size = node->ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002681 if (lys_ext_dup(module, node->ext, node->ext_size, retval, LYEXT_PAR_NODE, &retval->ext, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002682 goto error;
2683 }
2684
Radek Krejci06214042016-11-04 16:25:58 +01002685 if (node->iffeature_size) {
2686 retval->iffeature_size = node->iffeature_size;
2687 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2688 if (!retval->iffeature) {
2689 LOGMEM;
2690 goto error;
2691 }
Michal Vasko253035f2015-12-17 16:58:13 +01002692 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002693
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002694 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002695 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002696 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2697 if (size1) {
2698 /* there is something to duplicate */
2699
2700 /* duplicate compiled expression */
2701 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2702 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2703 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2704
2705 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002706 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002707 for (j = 0; (unsigned int)j < size2; j++) {
2708 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2709 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002710 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002711 /* feature is resolved in origin, so copy it
2712 * - duplication is used for instantiating groupings
2713 * and if-feature inside grouping is supposed to be
2714 * resolved inside the original grouping, so we want
2715 * to keep pointers to features from the grouping
2716 * context */
2717 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2718 } else if (rc == -1) {
2719 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002720 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002721 }
2722 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01002723
2724 /* duplicate if-feature's extensions */
2725 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002726 if (lys_ext_dup(module, node->iffeature[i].ext, node->iffeature[i].ext_size,
Radek Krejcif0bb3602017-01-25 17:05:08 +01002727 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, unres)) {
2728 goto error;
2729 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002730 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002731
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002732 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01002733 p = parent;
2734 do {
2735 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
2736 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002737 if (iter) {
2738 flags = iter->flags & LYS_CONFIG_MASK;
2739 } else {
2740 /* default */
2741 flags = LYS_CONFIG_W;
2742 }
2743
2744 switch (finalize) {
2745 case 1:
2746 /* inherit config flags */
2747 if (retval->flags & LYS_CONFIG_SET) {
2748 /* skip nodes with an explicit config value */
2749 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
2750 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +01002751 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002752 goto error;
2753 }
2754 break;
2755 }
2756
2757 if (retval->nodetype != LYS_USES) {
2758 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
2759 }
2760 break;
2761 case 2:
2762 /* erase config flags */
2763 retval->flags &= ~LYS_CONFIG_MASK;
2764 retval->flags &= ~LYS_CONFIG_SET;
2765 break;
2766 }
2767
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002768 /* connect it to the parent */
2769 if (lys_node_addchild(parent, retval->module, retval)) {
2770 goto error;
2771 }
Radek Krejcidce51452015-06-16 15:20:08 +02002772
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002773 /* go recursively */
2774 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002775 LY_TREE_FOR(node->child, iter) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002776 if (iter->nodetype & LYS_GROUPING) {
2777 /* do not instantiate groupings */
2778 continue;
2779 }
Radek Krejci6ff885d2017-01-03 14:06:22 +01002780 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002781 goto error;
2782 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783 }
2784 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002785
2786 if (finalize == 1) {
2787 /* check that configuration lists have keys
2788 * - we really want to check keys_size in original node, because the keys are
2789 * not yet resolved here, it is done below in nodetype specific part */
2790 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
2791 && !((struct lys_node_list *)node)->keys_size) {
2792 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
2793 goto error;
2794 }
2795 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002796 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002797 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002798 }
2799
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002800 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 * duplicate specific part of the structure
2802 */
2803 switch (node->nodetype) {
2804 case LYS_CONTAINER:
2805 if (cont_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002806 cont->when = lys_when_dup(module, cont_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002807 }
2808 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002810 cont->must_size = cont_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002811 cont->must = lys_restr_dup(module, cont_orig->must, cont->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812
Radek Krejcif0bb3602017-01-25 17:05:08 +01002813 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
2814
2815 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002816 case LYS_CHOICE:
2817 if (choice_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002818 choice->when = lys_when_dup(module, choice_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002819 }
2820
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002821 if (!shallow) {
2822 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002823 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2824 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2825 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002826 if (rc) {
2827 if (rc == EXIT_FAILURE) {
2828 LOGINT;
2829 }
2830 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002831 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002832 } else {
2833 /* useless to check return value, we don't know whether
2834 * there really wasn't any default defined or it just hasn't
2835 * been resolved, we just hope for the best :)
2836 */
2837 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002838 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002839 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002840 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002841 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002842 break;
2843
2844 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002845 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002846 goto error;
2847 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002848 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2849
2850 if (leaf_orig->dflt) {
2851 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci51673202016-11-01 17:00:32 +01002852 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
2853 (struct lys_node *)(&leaf->dflt)) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002854 goto error;
2855 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002856 }
2857
2858 leaf->must_size = leaf_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002859 leaf->must = lys_restr_dup(module, leaf_orig->must, leaf->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002860
2861 if (leaf_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002862 leaf->when = lys_when_dup(module, leaf_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002863 }
2864 break;
2865
2866 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002867 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002868 goto error;
2869 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002870 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2871
2872 llist->min = llist_orig->min;
2873 llist->max = llist_orig->max;
2874
2875 llist->must_size = llist_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002876 llist->must = lys_restr_dup(module, llist_orig->must, llist->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002877
Radek Krejci51673202016-11-01 17:00:32 +01002878 llist->dflt_size = llist_orig->dflt_size;
2879 llist->dflt = malloc(llist->dflt_size * sizeof *llist->dflt);
2880 for (i = 0; i < llist->dflt_size; i++) {
2881 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
2882 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2883 (struct lys_node *)(&llist->dflt[i])) == -1) {
2884 goto error;
2885 }
2886 }
2887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002888 if (llist_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002889 llist->when = lys_when_dup(module, llist_orig->when, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002890 }
2891 break;
2892
2893 case LYS_LIST:
2894 list->min = list_orig->min;
2895 list->max = list_orig->max;
2896
2897 list->must_size = list_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002898 list->must = lys_restr_dup(module, list_orig->must, list->must_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899
Radek Krejcif0bb3602017-01-25 17:05:08 +01002900 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Michal Vasko38d01f72015-06-15 09:41:06 +02002901
Radek Krejci581ce772015-11-10 17:22:40 +01002902 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002903 if (list->keys_size) {
2904 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejci5c08a992016-11-02 13:30:04 +01002905 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Michal Vasko253035f2015-12-17 16:58:13 +01002906 if (!list->keys) {
2907 LOGMEM;
2908 goto error;
2909 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002910
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002911 if (!shallow) {
Radek Krejci5c08a992016-11-02 13:30:04 +01002912 /* the keys are going to be resolved only if the list is instantiated in data tree, not just
2913 * in another grouping */
2914 for (iter = parent; iter && iter->nodetype != LYS_GROUPING; iter = iter->parent);
2915 if (!iter && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
2916 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02002917 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002918 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002919 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002920 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002921 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002922
Radek Krejci581ce772015-11-10 17:22:40 +01002923 list->unique_size = list_orig->unique_size;
2924 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002925 if (!list->unique) {
2926 LOGMEM;
2927 goto error;
2928 }
Radek Krejci581ce772015-11-10 17:22:40 +01002929 for (i = 0; i < list->unique_size; ++i) {
2930 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2931 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002932 if (!list->unique[i].expr) {
2933 LOGMEM;
2934 goto error;
2935 }
Radek Krejci581ce772015-11-10 17:22:40 +01002936 for (j = 0; j < list->unique[i].expr_size; j++) {
2937 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2938
2939 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02002940 unique_info = malloc(sizeof *unique_info);
2941 unique_info->list = (struct lys_node *)list;
2942 unique_info->expr = list->unique[i].expr[j];
2943 unique_info->trg_type = &list->unique[i].trg_type;
2944 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002945 }
2946 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002948 if (list_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002949 list->when = lys_when_dup(module, list_orig->when, unres);
Radek Krejciefaeba32015-05-27 14:30:57 +02002950 }
Radek Krejcidce51452015-06-16 15:20:08 +02002951 break;
2952
2953 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002954 case LYS_ANYDATA:
2955 any->must_size = any_orig->must_size;
Radek Krejci8d6b7422017-02-03 14:42:13 +01002956 any->must = lys_restr_dup(module, any_orig->must, any->must_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002957
Radek Krejcibf2abff2016-08-23 15:51:52 +02002958 if (any_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002959 any->when = lys_when_dup(module, any_orig->when, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002960 }
2961 break;
2962
2963 case LYS_USES:
2964 uses->grp = uses_orig->grp;
2965
2966 if (uses_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002967 uses->when = lys_when_dup(module, uses_orig->when, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002968 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002969 /* it is not needed to duplicate refine, nor augment. They are already applied to the uses children */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002970 break;
2971
2972 case LYS_CASE:
2973 if (cs_orig->when) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002974 cs->when = lys_when_dup(module, cs_orig->when, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002975 }
2976 break;
2977
Radek Krejci96935402016-11-04 16:27:28 +01002978 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02002979 case LYS_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 case LYS_INPUT:
2981 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002982 case LYS_NOTIF:
Radek Krejcif0bb3602017-01-25 17:05:08 +01002983 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002984 break;
2985
2986 default:
2987 /* LY_NODE_AUGMENT */
2988 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002989 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002990 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002991
2992 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002993
2994error:
2995
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002996 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002997 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002998}
2999
Radek Krejcib3142312016-11-09 11:04:12 +01003000int
3001lys_has_xpath(const struct lys_node *node)
3002{
3003 assert(node);
3004
3005 switch (node->nodetype) {
3006 case LYS_AUGMENT:
3007 if (((struct lys_node_augment *)node)->when) {
3008 return 1;
3009 }
3010 break;
3011 case LYS_CASE:
3012 if (((struct lys_node_case *)node)->when) {
3013 return 1;
3014 }
3015 break;
3016 case LYS_CHOICE:
3017 if (((struct lys_node_choice *)node)->when) {
3018 return 1;
3019 }
3020 break;
3021 case LYS_ANYDATA:
3022 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3023 return 1;
3024 }
3025 break;
3026 case LYS_LEAF:
3027 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3028 return 1;
3029 }
3030 break;
3031 case LYS_LEAFLIST:
3032 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3033 return 1;
3034 }
3035 break;
3036 case LYS_LIST:
3037 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3038 return 1;
3039 }
3040 break;
3041 case LYS_CONTAINER:
3042 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3043 return 1;
3044 }
3045 break;
3046 case LYS_INPUT:
3047 case LYS_OUTPUT:
3048 if (((struct lys_node_inout *)node)->must_size) {
3049 return 1;
3050 }
3051 break;
3052 case LYS_NOTIF:
3053 if (((struct lys_node_notif *)node)->must_size) {
3054 return 1;
3055 }
3056 break;
3057 case LYS_USES:
3058 if (((struct lys_node_uses *)node)->when) {
3059 return 1;
3060 }
3061 break;
3062 default:
3063 /* does not have XPath */
3064 break;
3065 }
3066
3067 return 0;
3068}
3069
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003070struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003071lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003072 struct unres_schema *unres, int shallow)
3073{
3074 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003075 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003076 struct lys_node *result, *iter, *next;
3077
3078 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003079 /* 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 +02003080 for (p = parent;
3081 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3082 p = lys_parent(p));
3083 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3084 }
3085
Radek Krejci6ff885d2017-01-03 14:06:22 +01003086 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003087 if (finalize) {
3088 /* check xpath expressions in the instantiated tree */
3089 for (iter = next = parent->child; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003090 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003091 /* invalid xpath */
3092 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003093 }
3094
3095 /* select next item */
3096 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3097 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3098 next = NULL;
3099 } else {
3100 next = iter->child;
3101 }
3102 if (!next) {
3103 /* no children, try siblings */
3104 next = iter->next;
3105 }
3106 while (!next) {
3107 /* parent is already processed, go to its sibling */
3108 iter = lys_parent(iter);
3109 if (iter == parent) {
3110 /* we are done, no next element to process */
3111 break;
3112 }
3113 next = iter->next;
3114 }
3115 }
3116 }
3117
3118 return result;
3119}
3120
Michal Vasko13b15832015-08-19 11:04:48 +02003121void
Michal Vaskoff006c12016-02-17 11:15:19 +01003122lys_node_switch(struct lys_node *dst, struct lys_node *src)
3123{
3124 struct lys_node *child;
3125
Michal Vaskob42b6972016-06-06 14:21:30 +02003126 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003127
3128 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02003129 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01003130 dst->prev->next = src;
3131 }
3132
3133 /* sibling prev */
3134 if (dst->next) {
3135 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02003136 } else {
3137 for (child = dst->prev; child->prev->next; child = child->prev);
3138 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003139 }
3140
3141 /* next */
3142 src->next = dst->next;
3143 dst->next = NULL;
3144
3145 /* prev */
3146 if (dst->prev != dst) {
3147 src->prev = dst->prev;
3148 }
3149 dst->prev = dst;
3150
3151 /* parent child */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003152 if (dst->parent) {
3153 if (dst->parent->child == dst) {
3154 dst->parent->child = src;
3155 }
3156 } else if (dst->module->data == dst) {
3157 dst->module->data = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003158 }
3159
3160 /* parent */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003161 src->parent = dst->parent; dst->parent = NULL;
3162
Michal Vaskoff006c12016-02-17 11:15:19 +01003163
3164 /* child parent */
3165 LY_TREE_FOR(dst->child, child) {
3166 if (child->parent == dst) {
3167 child->parent = src;
3168 }
3169 }
3170
3171 /* child */
3172 src->child = dst->child;
3173 dst->child = NULL;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003174
3175 /* node-specific data */
3176 switch (dst->nodetype) {
3177 case LYS_CONTAINER:
3178 ((struct lys_node_container *)src)->tpdf_size = ((struct lys_node_container *)dst)->tpdf_size;
3179 ((struct lys_node_container *)src)->tpdf = ((struct lys_node_container *)dst)->tpdf;
3180 ((struct lys_node_container *)dst)->tpdf_size = 0;
3181 ((struct lys_node_container *)dst)->tpdf = NULL;
3182 break;
3183 case LYS_LIST:
3184 ((struct lys_node_list *)src)->tpdf_size = ((struct lys_node_list *)dst)->tpdf_size;
3185 ((struct lys_node_list *)src)->tpdf = ((struct lys_node_list *)dst)->tpdf;
3186 ((struct lys_node_list *)dst)->tpdf_size = 0;
3187 ((struct lys_node_list *)dst)->tpdf = NULL;
3188 break;
3189 case LYS_RPC:
3190 case LYS_ACTION:
3191 ((struct lys_node_rpc_action *)src)->tpdf_size = ((struct lys_node_rpc_action *)dst)->tpdf_size;
3192 ((struct lys_node_rpc_action *)src)->tpdf = ((struct lys_node_rpc_action *)dst)->tpdf;
3193 ((struct lys_node_rpc_action *)dst)->tpdf_size = 0;
3194 ((struct lys_node_rpc_action *)dst)->tpdf = NULL;
3195 break;
3196 case LYS_NOTIF:
3197 ((struct lys_node_notif *)src)->tpdf_size = ((struct lys_node_notif *)dst)->tpdf_size;
3198 ((struct lys_node_notif *)src)->tpdf = ((struct lys_node_notif *)dst)->tpdf;
3199 ((struct lys_node_notif *)dst)->tpdf_size = 0;
3200 ((struct lys_node_notif *)dst)->tpdf = NULL;
3201 break;
3202 case LYS_INPUT:
3203 case LYS_OUTPUT:
3204 ((struct lys_node_inout *)src)->tpdf_size = ((struct lys_node_inout *)dst)->tpdf_size;
3205 ((struct lys_node_inout *)src)->tpdf = ((struct lys_node_inout *)dst)->tpdf;
3206 ((struct lys_node_inout *)dst)->tpdf_size = 0;
3207 ((struct lys_node_inout *)dst)->tpdf = NULL;
3208 break;
3209 default:
3210 /* nothing special */
3211 break;
3212 }
3213
Michal Vaskoff006c12016-02-17 11:15:19 +01003214}
3215
3216void
Michal Vasko627975a2016-02-11 11:39:03 +01003217lys_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 +02003218{
3219 struct ly_ctx *ctx;
3220 int i;
3221
3222 if (!module) {
3223 return;
3224 }
3225
3226 /* remove schema from the context */
3227 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003228 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003229 for (i = 0; i < ctx->models.used; i++) {
3230 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003231 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003232 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003233 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 +02003234 ctx->models.list[ctx->models.used] = NULL;
3235 /* we are done */
3236 break;
3237 }
3238 }
3239 }
3240
3241 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003242 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003243
3244 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003245 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003246
3247 free(module);
3248}
Radek Krejci7e97c352015-06-19 16:26:34 +02003249
Radek Krejci9de2c042016-10-19 16:53:06 +02003250static void
3251lys_features_disable_recursive(struct lys_feature *f)
3252{
3253 unsigned int i;
3254 struct lys_feature *depf;
3255
3256 /* disable the feature */
3257 f->flags &= ~LYS_FENABLED;
3258
3259 /* by disabling feature we have to disable also all features that depends on this feature */
3260 if (f->depfeatures) {
3261 for (i = 0; i < f->depfeatures->number; i++) {
3262 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3263 if (depf->flags & LYS_FENABLED) {
3264 lys_features_disable_recursive(depf);
3265 }
3266 }
3267 }
3268}
3269
3270
Radek Krejci7e97c352015-06-19 16:26:34 +02003271/*
3272 * op: 1 - enable, 0 - disable
3273 */
3274static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003275lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003276{
3277 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003278 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003279 int progress, faili, failj, failk;
3280
3281 uint8_t fsize;
3282 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003283
3284 if (!module || !name || !strlen(name)) {
3285 return EXIT_FAILURE;
3286 }
3287
3288 if (!strcmp(name, "*")) {
3289 /* enable all */
3290 all = 1;
3291 }
3292
Radek Krejcia889c1f2016-10-19 15:50:11 +02003293 progress = failk = 1;
3294 while (progress && failk) {
3295 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3296 if (i == -1) {
3297 fsize = module->features_size;
3298 f = module->features;
3299 } else {
3300 fsize = module->inc[i].submodule->features_size;
3301 f = module->inc[i].submodule->features;
3302 }
3303
3304 for (j = 0; j < fsize; j++) {
3305 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003306 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3307 if (all) {
3308 /* skip already set features */
3309 continue;
3310 } else {
3311 /* feature already set correctly */
3312 return EXIT_SUCCESS;
3313 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003314 }
3315
3316 if (op) {
3317 /* check referenced features if they are enabled */
3318 for (k = 0; k < f[j].iffeature_size; k++) {
3319 if (!resolve_iffeature(&f[j].iffeature[k])) {
3320 if (all) {
3321 faili = i;
3322 failj = j;
3323 failk = k + 1;
3324 break;
3325 } else {
3326 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3327 f[j].name, k + 1);
3328 return EXIT_FAILURE;
3329 }
3330 }
3331 }
3332
3333 if (k == f[j].iffeature_size) {
3334 /* the last check passed, do the change */
3335 f[j].flags |= LYS_FENABLED;
3336 progress++;
3337 }
3338 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003339 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003340 progress++;
3341 }
3342 if (!all) {
3343 /* stop in case changing a single feature */
3344 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003345 }
3346 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003347 }
3348 }
3349 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003350 if (failk) {
3351 /* print info about the last failing feature */
3352 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3353 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3354 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003355 }
3356
3357 if (all) {
3358 return EXIT_SUCCESS;
3359 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003360 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003361 return EXIT_FAILURE;
3362 }
3363}
3364
3365API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003366lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003367{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003368 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003369}
3370
3371API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003372lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003373{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003374 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003375}
3376
3377API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003378lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003379{
3380 int i, j;
3381
3382 if (!module || !feature) {
3383 return -1;
3384 }
3385
3386 /* search for the specified feature */
3387 /* module itself */
3388 for (i = 0; i < module->features_size; i++) {
3389 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003390 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003391 return 1;
3392 } else {
3393 return 0;
3394 }
3395 }
3396 }
3397
3398 /* submodules */
3399 for (j = 0; j < module->inc_size; j++) {
3400 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3401 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003402 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003403 return 1;
3404 } else {
3405 return 0;
3406 }
3407 }
3408 }
3409 }
3410
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003411 /* feature definition not found */
3412 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003413}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003414
Radek Krejci96a10da2015-07-30 11:00:14 +02003415API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003416lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003417{
Radek Krejci96a10da2015-07-30 11:00:14 +02003418 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003419 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003420 unsigned int count;
3421
3422 if (!module) {
3423 return NULL;
3424 }
3425
3426 count = module->features_size;
3427 for (i = 0; i < module->inc_size; i++) {
3428 count += module->inc[i].submodule->features_size;
3429 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003430 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01003431 if (!result) {
3432 LOGMEM;
3433 return NULL;
3434 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003435 if (states) {
3436 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01003437 if (!(*states)) {
3438 LOGMEM;
3439 free(result);
3440 return NULL;
3441 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003442 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003443 count = 0;
3444
3445 /* module itself */
3446 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003447 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003448 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003449 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003450 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003451 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003452 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003453 }
3454 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003455 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003456 }
3457
3458 /* submodules */
3459 for (j = 0; j < module->inc_size; j++) {
3460 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003461 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003462 if (states) {
3463 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3464 (*states)[count] = 1;
3465 } else {
3466 (*states)[count] = 0;
3467 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003468 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003469 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003470 }
3471 }
3472
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003473 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003474 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003475
3476 return result;
3477}
Michal Vaskobaefb032015-09-24 14:52:10 +02003478
Radek Krejci6910a032016-04-13 10:06:21 +02003479API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003480lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003481{
Michal Vaskof53187d2017-01-13 13:23:14 +01003482 if (!node) {
3483 return NULL;
3484 }
3485
Radek Krejcic071c542016-01-27 14:57:51 +01003486 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3487}
3488
Radek Krejci6910a032016-04-13 10:06:21 +02003489API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003490lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003491{
Michal Vaskof53187d2017-01-13 13:23:14 +01003492 if (!module) {
3493 return NULL;
3494 }
3495
Michal Vasko320e8532016-02-15 13:11:57 +01003496 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3497}
3498
Michal Vaskobaefb032015-09-24 14:52:10 +02003499API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003500lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003501{
Radek Krejcif95b6292017-02-13 15:57:37 +01003502 struct lys_node *parent;
3503
3504 if (!node) {
Michal Vaskobaefb032015-09-24 14:52:10 +02003505 return NULL;
3506 }
3507
Radek Krejcif95b6292017-02-13 15:57:37 +01003508 if (node->nodetype == LYS_EXT) {
3509 if (((struct lys_ext_instance_complex*)node)->parent_type != LYEXT_PAR_NODE) {
3510 return NULL;
3511 }
3512 parent = (struct lys_node*)((struct lys_ext_instance_complex*)node)->parent;
3513 } else if (!node->parent) {
3514 return NULL;
3515 } else {
3516 parent = node->parent;
Michal Vaskobaefb032015-09-24 14:52:10 +02003517 }
3518
Radek Krejcif95b6292017-02-13 15:57:37 +01003519 if (parent->nodetype == LYS_AUGMENT) {
3520 return ((struct lys_node_augment *)parent)->target;
3521 } else {
3522 return parent;
3523 }
3524}
3525
3526struct lys_node **
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01003527lys_child(const struct lys_node *node, LYS_NODE nodetype)
Radek Krejcif95b6292017-02-13 15:57:37 +01003528{
3529 void *pp;
3530 assert(node);
3531
3532 if (node->nodetype == LYS_EXT) {
3533 pp = lys_ext_complex_get_substmt(lys_snode2stmt(nodetype), (struct lys_ext_instance_complex*)node, NULL);
3534 if (!pp) {
3535 return NULL;
3536 }
3537 return (struct lys_node **)pp;
3538 } else {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01003539 return (struct lys_node **)&node->child;
Radek Krejcif95b6292017-02-13 15:57:37 +01003540 }
Michal Vaskobaefb032015-09-24 14:52:10 +02003541}
Michal Vasko1b229152016-01-13 11:28:38 +01003542
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003543API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003544lys_set_private(const struct lys_node *node, void *priv)
3545{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003546 void *prev;
3547
Michal Vasko1b229152016-01-13 11:28:38 +01003548 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003549 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
3550 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003551 }
3552
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003553 prev = node->priv;
3554 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003555
3556 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003557}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003558
Michal Vasko01c6fd22016-05-20 11:43:05 +02003559int
3560lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3561{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003562 struct lys_node_leaf *iter = leafref_target;
3563
Michal Vasko48a573d2016-07-01 11:46:02 +02003564 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003565 LOGINT;
3566 return -1;
3567 }
3568
Pavol Vican93175152016-08-30 15:34:44 +02003569 /* check for config flag */
3570 if ((leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
3571 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
3572 "The %s is config but refers to a non-config %s.",
3573 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
3574 return -1;
3575 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003576 /* check for cycles */
3577 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3578 if ((void *)iter == (void *)leafref) {
3579 /* cycle detected */
3580 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3581 return -1;
3582 }
3583 iter = iter->type.info.lref.target;
3584 }
3585
3586 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003587 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02003588 if (!leafref_target->backlinks) {
3589 leafref_target->backlinks = (void*)ly_set_new();
3590 if (!leafref_target->backlinks) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003591 LOGMEM;
3592 return -1;
3593 }
3594 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003595 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003596
3597 return 0;
3598}
3599
Michal Vasko8548e082016-07-22 12:00:18 +02003600/* not needed currently */
3601#if 0
3602
Michal Vasko5b3492c2016-07-20 09:37:40 +02003603static const char *
3604lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3605{
3606 struct lys_module *prev_mod;
3607 uint32_t str_len, mod_len, buf_idx;
3608
Radek Krejcibf2abff2016-08-23 15:51:52 +02003609 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003610 LOGINT;
3611 return NULL;
3612 }
3613
3614 buf_idx = buf_len - 1;
3615 buf[buf_idx] = '\0';
3616
3617 while (node) {
3618 if (lys_parent(node)) {
3619 prev_mod = lys_node_module(lys_parent(node));
3620 } else {
3621 prev_mod = NULL;
3622 }
3623
Radek Krejcibf2abff2016-08-23 15:51:52 +02003624 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003625 str_len = strlen(node->name);
3626
3627 if (prev_mod != node->module) {
3628 mod_len = strlen(node->module->name);
3629 } else {
3630 mod_len = 0;
3631 }
3632
3633 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3634 LOGINT;
3635 return NULL;
3636 }
3637
3638 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3639
3640 buf[buf_idx] = '/';
3641 if (mod_len) {
3642 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3643 buf[buf_idx + 1 + mod_len] = ':';
3644 }
3645 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3646 }
3647
3648 node = lys_parent(node);
3649 }
3650
3651 return buf + buf_idx;
3652}
3653
Michal Vasko8548e082016-07-22 12:00:18 +02003654#endif
3655
3656API struct ly_set *
Michal Vasko2611e192017-01-23 10:33:21 +01003657lys_find_xpath(struct ly_ctx *ctx, const struct lys_node *node, const char *expr, int options)
Michal Vasko46a4bf92016-09-08 08:23:49 +02003658{
3659 struct lyxp_set set;
3660 struct ly_set *ret_set;
3661 uint32_t i;
Michal Vaskodb1da032016-09-08 10:07:38 +02003662 int opts;
Michal Vasko46a4bf92016-09-08 08:23:49 +02003663
Michal Vasko2611e192017-01-23 10:33:21 +01003664 if ((!ctx && !node) || !expr) {
Michal Vasko46a4bf92016-09-08 08:23:49 +02003665 ly_errno = LY_EINVAL;
3666 return NULL;
3667 }
3668
Michal Vasko2611e192017-01-23 10:33:21 +01003669 if (!node) {
3670 node = ly_ctx_get_node(ctx, NULL, "/ietf-yang-library:modules-state");
3671 if (!node) {
3672 ly_errno = LY_EINT;
3673 return NULL;
3674 }
3675 }
3676
Michal Vasko46a4bf92016-09-08 08:23:49 +02003677 memset(&set, 0, sizeof set);
3678
Michal Vaskodb1da032016-09-08 10:07:38 +02003679 opts = LYXP_SNODE;
3680 if (options & LYS_FIND_OUTPUT) {
3681 opts |= LYXP_SNODE_OUTPUT;
3682 }
3683
Michal Vaskodb1da032016-09-08 10:07:38 +02003684 if (lyxp_atomize(expr, node, LYXP_NODE_ELEM, &set, opts)) {
Michal Vaskoc90f3ff2017-01-23 13:51:58 +01003685 /* just find a relevant node to put in path, if it fails, use the original one */
3686 for (i = 0; i < set.used; ++i) {
3687 if (set.val.snodes[i].in_ctx == 1) {
3688 node = set.val.snodes[i].snode;
3689 break;
3690 }
3691 }
Michal Vasko46a4bf92016-09-08 08:23:49 +02003692 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003693 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko46a4bf92016-09-08 08:23:49 +02003694 return NULL;
3695 }
3696
3697 ret_set = ly_set_new();
3698
3699 for (i = 0; i < set.used; ++i) {
3700 if (!set.val.snodes[i].in_ctx) {
3701 continue;
3702 }
3703 assert(set.val.snodes[i].in_ctx == 1);
3704
3705 switch (set.val.snodes[i].type) {
3706 case LYXP_NODE_ELEM:
3707 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
3708 ly_set_free(ret_set);
3709 free(set.val.snodes);
3710 return NULL;
3711 }
3712 break;
3713 default:
3714 /* ignore roots, text and attr should not ever appear */
3715 break;
3716 }
3717 }
3718
3719 free(set.val.snodes);
3720 return ret_set;
3721}
3722
3723API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02003724lys_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 +02003725{
Michal Vasko508a50d2016-09-07 14:50:33 +02003726 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003727 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003728 uint32_t i;
3729
Michal Vaskob94a5e42016-09-08 14:01:56 +02003730 if (!cur_snode || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02003731 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003732 }
3733
Michal Vaskob94a5e42016-09-08 14:01:56 +02003734 /* adjust the root */
3735 if ((cur_snode_type == LYXP_NODE_ROOT) || (cur_snode_type == LYXP_NODE_ROOT_CONFIG)) {
3736 do {
3737 cur_snode = lys_getnext(NULL, NULL, lys_node_module(cur_snode), 0);
3738 } while ((cur_snode_type == LYXP_NODE_ROOT_CONFIG) && (cur_snode->flags & LYS_CONFIG_R));
3739 }
3740
Michal Vasko508a50d2016-09-07 14:50:33 +02003741 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003742
3743 if (options & LYXP_MUST) {
3744 options &= ~LYXP_MUST;
3745 options |= LYXP_SNODE_MUST;
3746 } else if (options & LYXP_WHEN) {
3747 options &= ~LYXP_WHEN;
3748 options |= LYXP_SNODE_WHEN;
3749 } else {
3750 options |= LYXP_SNODE;
3751 }
3752
Michal Vasko508a50d2016-09-07 14:50:33 +02003753 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
3754 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003755 LOGVAL(LYE_SPEC, LY_VLOG_LYS, cur_snode, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02003756 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003757 }
3758
Michal Vasko8548e082016-07-22 12:00:18 +02003759 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003760
Michal Vasko508a50d2016-09-07 14:50:33 +02003761 for (i = 0; i < set.used; ++i) {
3762 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003763 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003764 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003765 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003766 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003767 return NULL;
3768 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003769 break;
3770 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003771 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003772 break;
3773 }
3774 }
3775
Michal Vasko508a50d2016-09-07 14:50:33 +02003776 free(set.val.snodes);
3777 return ret_set;
3778}
3779
3780API struct ly_set *
3781lys_node_xpath_atomize(const struct lys_node *node, int options)
3782{
3783 const struct lys_node *next, *elem, *parent, *tmp;
3784 struct lyxp_set set;
3785 struct ly_set *ret_set;
3786 uint16_t i;
3787
3788 if (!node) {
3789 return NULL;
3790 }
3791
3792 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3793 if (!parent) {
3794 /* not in input, output, or notification */
3795 return NULL;
3796 }
3797
3798 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003799 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003800 return NULL;
3801 }
3802
3803 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003804 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_XPATH_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003805 /* elem has no dependencies from other subtrees and local nodes get discarded */
3806 goto next_iter;
3807 }
3808
Michal Vasko769f8032017-01-24 13:11:55 +01003809 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003810 ly_set_free(ret_set);
3811 free(set.val.snodes);
3812 return NULL;
3813 }
3814
3815 for (i = 0; i < set.used; ++i) {
3816 switch (set.val.snodes[i].type) {
3817 case LYXP_NODE_ELEM:
3818 if (options & LYXP_NO_LOCAL) {
3819 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3820 if (tmp) {
3821 /* in local subtree, discard */
3822 break;
3823 }
3824 }
3825 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3826 ly_set_free(ret_set);
3827 free(set.val.snodes);
3828 return NULL;
3829 }
3830 break;
3831 default:
3832 /* ignore roots, text and attr should not ever appear */
3833 break;
3834 }
3835 }
3836
3837 free(set.val.snodes);
3838 if (!(options & LYXP_RECURSIVE)) {
3839 break;
3840 }
3841next_iter:
3842 LY_TREE_DFS_END(node, next, elem);
3843 }
3844
Michal Vasko8548e082016-07-22 12:00:18 +02003845 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003846}
3847
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003848static void
Radek Krejci0ec51da2016-12-14 16:42:03 +01003849apply_aug(struct lys_node_augment *augment)
3850{
3851 struct lys_node *last;
3852
3853 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
3854
3855 /* reconnect augmenting data into the target - add them to the target child list */
3856 if (augment->target->child) {
3857 last = augment->target->child->prev;
3858 last->next = augment->child;
3859 augment->target->child->prev = augment->child->prev;
3860 augment->child->prev = last;
3861 } else {
3862 augment->target->child = augment->child;
3863 }
3864
3865 /* remove the flag about not applicability */
3866 augment->flags &= ~LYS_NOTAPPLIED;
3867}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003868
Radek Krejcib2541a32016-12-12 16:45:57 +01003869static void
3870remove_aug(struct lys_node_augment *augment)
3871{
3872 struct lys_node *last, *elem;
3873
3874 if (!augment->target) {
3875 /* skip not resolved augments */
3876 return;
3877 }
3878
3879 elem = augment->child;
3880 if (elem) {
3881 LY_TREE_FOR(elem, last) {
3882 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
3883 break;
3884 }
3885 }
3886 /* elem is first augment child, last is the last child */
3887
3888 /* parent child ptr */
3889 if (augment->target->child == elem) {
3890 augment->target->child = last->next;
3891 }
3892
3893 /* parent child next ptr */
3894 if (elem->prev->next) {
3895 elem->prev->next = last->next;
3896 }
3897
3898 /* parent child prev ptr */
3899 if (last->next) {
3900 last->next->prev = elem->prev;
3901 } else if (augment->target->child) {
3902 augment->target->child->prev = elem->prev;
3903 }
3904
3905 /* update augment children themselves */
3906 elem->prev = last;
3907 last->next = NULL;
3908 }
3909
Radek Krejci0ec51da2016-12-14 16:42:03 +01003910 /* augment->target still keeps the resolved target, but for lys_augment_free()
3911 * we have to keep information that this augment is not applied to free its data */
3912 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01003913}
3914
Radek Krejci30bfcd22017-01-27 16:54:48 +01003915/*
3916 * @param[in] module - the module where the deviation is defined
3917 */
3918static void
3919lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module)
3920{
3921 int ret;
3922 char *parent_path;
3923 struct lys_node *target = NULL, *parent;
3924
3925 if (!dev->deviate) {
3926 return ;
3927 }
3928
3929 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3930 if (dev->orig_node) {
3931 /* removing not-supported deviation ... */
3932 if (strrchr(dev->target_name, '/') != dev->target_name) {
3933 /* ... from a parent */
3934
3935 /* reconnect to its previous position */
3936 parent = dev->orig_node->parent;
3937 if (parent) {
3938 /* the original node was actually from augment, we have to get know if the augment is
3939 * applied (its module is enabled and implemented). If yes, the node will be connected
3940 * to the augment and the linkage with the target will be fixed if needed, otherwise
3941 * it will be connected only to the augment */
3942 /* first, connect it into the augment */
3943 lys_node_addchild(parent, NULL, dev->orig_node);
3944 if (!parent->module->disabled && parent->module->implemented) {
3945 /* augment is supposed to be applied, so fix pointers in target and the status of the original node */
3946 if (parent->child == dev->orig_node) {
3947 /* the only node in augment */
3948 dev->orig_node->flags |= LYS_NOTAPPLIED;
3949 apply_aug((struct lys_node_augment *)parent);
3950 } else {
3951 /* other nodes from augment applied, nothing more needed in target, everything was done
3952 * by lys_node_addchild() */
3953 dev->orig_node->flags |= parent->child->flags & LYS_NOTAPPLIED;
3954 }
3955 } else {
3956 /* augment is not supposed to be applied */
3957 dev->orig_node->flags |= LYS_NOTAPPLIED;
3958 }
3959 } else {
3960 /* non-augment, non-toplevel */
3961 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3962 ret = resolve_augment_schema_nodeid(parent_path, NULL, module, 1,
3963 (const struct lys_node **)&target);
3964 free(parent_path);
3965 if (ret || !target) {
3966 LOGINT;
3967 return;
3968 }
3969 lys_node_addchild(target, NULL, dev->orig_node);
3970 }
3971 } else {
3972 /* ... from top-level data */
3973 lys_node_addchild(NULL, (struct lys_module *)dev->orig_node->module, dev->orig_node);
3974 }
3975
3976 dev->orig_node = NULL;
3977 } else {
3978 /* adding not-supported deviation */
3979 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1,
3980 (const struct lys_node **)&target);
3981 if (ret || !target) {
3982 LOGINT;
3983 return;
3984 }
3985
3986 /* unlink and store the original node */
3987 parent = target->parent;
3988 lys_node_unlink(target);
3989 if (parent && parent->nodetype == LYS_AUGMENT) {
3990 /* hack for augment, because when the original will be sometime reconnected back, we actually need
3991 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
3992 * path), so we need to remember the augment as an addition */
3993 target->parent = parent;
3994 }
3995 dev->orig_node = target;
3996 }
3997 } else {
3998 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1,
3999 (const struct lys_node **)&target);
4000 if (ret || !target) {
4001 LOGINT;
4002 return;
4003 }
4004
4005 lys_node_switch(target, dev->orig_node);
4006 dev->orig_node = target;
4007 }
4008}
4009
4010/* temporarily removes or applies deviations, updates module deviation flag accordingly */
4011void
4012lys_switch_deviations(struct lys_module *module)
4013{
4014 uint32_t i = 0, j;
4015 const struct lys_module *mod;
4016 const char *ptr;
4017
4018 if (module->deviated) {
4019 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
4020 if (mod == module) {
4021 continue;
4022 }
4023
4024 for (j = 0; j < mod->deviation_size; ++j) {
4025 ptr = strstr(mod->deviation[j].target_name, module->name);
4026 if (ptr && ptr[strlen(module->name)] == ':') {
4027 lys_switch_deviation(&mod->deviation[j], mod);
4028 }
4029 }
4030 }
4031
4032 if (module->deviated == 2) {
4033 module->deviated = 1;
4034 } else {
4035 module->deviated = 2;
4036 }
4037 }
4038}
4039
4040static void
4041apply_dev(struct lys_deviation *dev, const struct lys_module *module)
4042{
4043 lys_switch_deviation(dev, module);
4044
4045 assert(dev->orig_node);
4046 lys_node_module(dev->orig_node)->deviated = 1;
4047}
4048
4049static void
4050remove_dev(struct lys_deviation *dev, const struct lys_module *module)
4051{
4052 uint32_t idx = 0, j;
4053 const struct lys_module *mod;
4054 struct lys_module *target_mod;
4055 const char *ptr;
4056
4057 if (dev->orig_node) {
4058 target_mod = lys_node_module(dev->orig_node);
4059 } else {
4060 LOGINT;
4061 return;
4062 }
4063 lys_switch_deviation(dev, module);
4064
4065 /* clear the deviation flag if possible */
4066 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4067 if ((mod == module) || (mod == target_mod)) {
4068 continue;
4069 }
4070
4071 for (j = 0; j < mod->deviation_size; ++j) {
4072 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4073 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4074 /* some other module deviation targets the inspected module, flag remains */
4075 break;
4076 }
4077 }
4078
4079 if (j < mod->deviation_size) {
4080 break;
4081 }
4082 }
4083
4084 if (!mod) {
4085 target_mod->deviated = 0;
4086 }
4087}
4088
4089void
4090lys_sub_module_apply_devs_augs(struct lys_module *module)
4091{
4092 uint8_t u, v;
4093
4094 /* remove applied deviations */
4095 for (u = 0; u < module->deviation_size; ++u) {
4096 apply_dev(&module->deviation[u], module);
4097 }
4098 /* remove applied augments */
4099 for (u = 0; u < module->augment_size; ++u) {
4100 apply_aug(&module->augment[u]);
4101 }
4102
4103 /* remove deviation and augments defined in submodules */
4104 for (v = 0; v < module->inc_size; ++v) {
4105 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4106 apply_dev(&module->inc[v].submodule->deviation[u], module);
4107 }
4108
4109 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4110 apply_aug(&module->inc[v].submodule->augment[u]);
4111 }
4112 }
4113}
4114
Radek Krejcib2541a32016-12-12 16:45:57 +01004115void
4116lys_sub_module_remove_devs_augs(struct lys_module *module)
4117{
4118 uint8_t u, v;
4119
4120 /* remove applied deviations */
4121 for (u = 0; u < module->deviation_size; ++u) {
4122 remove_dev(&module->deviation[u], module);
4123 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004124 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004125 for (u = 0; u < module->augment_size; ++u) {
4126 remove_aug(&module->augment[u]);
4127 }
4128
4129 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004130 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01004131 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4132 remove_dev(&module->inc[v].submodule->deviation[u], module);
Radek Krejcidbc15262016-06-16 14:58:29 +02004133 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004134
Radek Krejcib2541a32016-12-12 16:45:57 +01004135 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4136 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004137 }
4138 }
4139}
4140
Radek Krejci27fe55e2016-09-13 17:13:35 +02004141static int
4142lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
4143{
4144 struct lys_node *root, *next, *node;
4145 uint8_t i;
4146
4147 for (i = 0; i < module->augment_size; i++) {
4148 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02004149 if (!module->augment[i].target
4150 && (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004151 return -1;
4152 }
4153 }
4154 LY_TREE_FOR(module->data, root) {
4155 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4156 LY_TREE_DFS_BEGIN(root, next, node) {
4157 if (node->nodetype == LYS_GROUPING) {
4158 goto nextsibling;
4159 }
4160 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4161 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4162 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4163 UNRES_TYPE_LEAFREF, node) == -1) {
4164 return EXIT_FAILURE;
4165 }
4166 }
4167 }
4168
4169 /* modified LY_TREE_DFS_END */
4170 next = node->child;
4171 /* child exception for leafs, leaflists and anyxml without children */
4172 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4173 next = NULL;
4174 }
4175 if (!next) {
4176nextsibling:
4177 /* no children */
4178 if (node == root) {
4179 /* we are done, root has no children */
4180 break;
4181 }
4182 /* try siblings */
4183 next = node->next;
4184 }
4185 while (!next) {
4186 /* parent is already processed, go to its sibling */
4187 node = lys_parent(node);
4188 /* no siblings, go back through parents */
4189 if (lys_parent(node) == lys_parent(root)) {
4190 /* we are done, no next element to process */
4191 break;
4192 }
4193 next = node->next;
4194 }
4195 }
4196 }
4197
4198 return EXIT_SUCCESS;
4199}
4200
4201API int
4202lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004203{
4204 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004205 struct unres_schema *unres;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004206 int i, j, disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004207
Radek Krejci27fe55e2016-09-13 17:13:35 +02004208 if (!module) {
4209 ly_errno = LY_EINVAL;
4210 return EXIT_FAILURE;
4211 }
4212
4213 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004214
4215 if (module->disabled) {
4216 disabled = 1;
4217 lys_set_enabled(module);
4218 }
4219
Michal Vasko26055752016-05-03 11:36:31 +02004220 if (module->implemented) {
4221 return EXIT_SUCCESS;
4222 }
4223
4224 ctx = module->ctx;
4225
4226 for (i = 0; i < ctx->models.used; ++i) {
4227 if (module == ctx->models.list[i]) {
4228 continue;
4229 }
4230
4231 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4232 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004233 if (disabled) {
4234 /* set it back disabled */
4235 lys_set_disabled(module);
4236 }
Michal Vasko26055752016-05-03 11:36:31 +02004237 return EXIT_FAILURE;
4238 }
4239 }
4240
Radek Krejci27fe55e2016-09-13 17:13:35 +02004241 unres = calloc(1, sizeof *unres);
4242 if (!unres) {
4243 LOGMEM;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004244 if (disabled) {
4245 /* set it back disabled */
4246 lys_set_disabled(module);
4247 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004248 return EXIT_FAILURE;
4249 }
4250 /* recursively make the module implemented */
4251 ((struct lys_module *)module)->implemented = 1;
4252 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
4253 goto error;
4254 }
4255 /* process augments in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004256 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004257 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
4258 /* apply augment */
Radek Krejcic8c22532016-11-09 15:11:24 +01004259 if (!module->inc[i].submodule->augment[j].target
4260 && (unres_schema_add_node((struct lys_module *)module->inc[j].submodule, unres,
4261 &module->inc[i].submodule->augment[j], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01004262
Radek Krejci27fe55e2016-09-13 17:13:35 +02004263 goto error;
4264 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004265 }
4266 }
Radek Krejcidf46e222016-11-08 11:57:37 +01004267 /* try again resolve augments in other modules possibly augmenting this one,
4268 * since we have just enabled it
4269 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004270 /* resolve rest of unres items */
4271 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4272 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004273 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004274 unres_schema_free((struct lys_module *)module, &unres);
Michal Vasko26055752016-05-03 11:36:31 +02004275
4276 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004277
4278error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004279
4280 if (disabled) {
4281 /* set it back disabled */
4282 lys_set_disabled(module);
4283 }
4284
Radek Krejci27fe55e2016-09-13 17:13:35 +02004285 ((struct lys_module *)module)->implemented = 0;
4286 unres_schema_free((struct lys_module *)module, &unres);
4287 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004288}
4289
4290void
4291lys_submodule_module_data_free(struct lys_submodule *submodule)
4292{
4293 struct lys_node *next, *elem;
4294
4295 /* remove parsed data */
4296 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4297 if (elem->module == (struct lys_module *)submodule) {
4298 lys_node_free(elem, NULL, 0);
4299 }
4300 }
4301}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004302
4303int
4304lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
4305{
4306 uint8_t i;
4307
4308 for (i = 0; i < list->keys_size; i++) {
4309 if (list->keys[i] == leaf) {
4310 return i + 1;
4311 }
4312 }
4313
4314 return 0;
4315}
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004316
4317API char *
4318lys_path(const struct lys_node *node)
4319{
4320 char *buf_backup = NULL, *buf = ly_buf(), *result = NULL;
4321 uint16_t index = LY_BUF_SIZE - 1;
4322
4323 if (!node) {
4324 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
4325 return NULL;
4326 }
4327
4328 /* backup the shared internal buffer */
4329 if (ly_buf_used && buf[0]) {
4330 buf_backup = strndup(buf, LY_BUF_SIZE - 1);
4331 }
4332 ly_buf_used++;
4333
4334 /* build the path */
4335 buf[index] = '\0';
Michal Vasko5efa25c2017-01-10 11:34:30 +01004336 ly_vlog_build_path_reverse(LY_VLOG_LYS, node, buf, &index, 0);
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004337 result = strdup(&buf[index]);
4338
4339 /* restore the shared internal buffer */
4340 if (buf_backup) {
4341 strcpy(buf, buf_backup);
4342 free(buf_backup);
4343 }
4344 ly_buf_used--;
4345
4346 return result;
4347}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004348
Radek Krejci8d6b7422017-02-03 14:42:13 +01004349static void
4350lys_extcomplex_free_str(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext, LY_STMT stmt)
4351{
4352 struct lyext_substmt *info;
Radek Krejcib71243e2017-02-08 16:20:08 +01004353 const char **str, ***a;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004354 int c;
4355
4356 str = lys_ext_complex_get_substmt(stmt, ext, &info);
4357 if (!str || !(*str)) {
4358 return;
4359 }
4360 if (info->cardinality >= LY_STMT_CARD_SOME) {
4361 /* we have array */
Radek Krejcib71243e2017-02-08 16:20:08 +01004362 a = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01004363 for (str = (*(const char ***)str), c = 0; str[c]; c++) {
4364 lydict_remove(ctx, str[c]);
Radek Krejci8d6b7422017-02-03 14:42:13 +01004365 }
Radek Krejci56c80412017-02-09 10:44:16 +01004366 free(a[0]);
4367 if (stmt == LY_STMT_BELONGSTO) {
4368 for (str = a[1], c = 0; str[c]; c++) {
4369 lydict_remove(ctx, str[c]);
4370 }
4371 free(a[1]);
4372 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004373 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01004374 lydict_remove(ctx, str[0]);
4375 if (stmt == LY_STMT_BELONGSTO) {
4376 lydict_remove(ctx, str[1]);
4377 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004378 }
4379}
4380void
4381lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size)
4382{
Radek Krejcif8d05c22017-02-10 15:33:35 +01004383 unsigned int i, j, k;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004384 struct lyext_substmt *substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004385 void **pp, **start;
Radek Krejcif95b6292017-02-13 15:57:37 +01004386 struct lys_node *siter, *snext;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004387
4388#define EXTCOMPLEX_FREE_STRUCT(STMT, TYPE, FUNC, FREE, ARGS...) \
Radek Krejcib84686f2017-02-09 16:04:55 +01004389 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)e[i], NULL); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004390 if (!pp || !(*pp)) { break; } \
Radek Krejcib84686f2017-02-09 16:04:55 +01004391 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004392 for (start = pp = *pp; *pp; pp++) { \
4393 FUNC(ctx, (TYPE *)(*pp), ##ARGS); \
4394 if (FREE) { free(*pp); } \
4395 } \
4396 free(start); \
4397 } else { /* single item */ \
4398 FUNC(ctx, (TYPE *)(*pp), ##ARGS); \
4399 if (FREE) { free(*pp); } \
4400 }
4401
4402 if (!size || !e || !(*e)) {
4403 return;
4404 }
4405
4406 for (i = 0; i < size; i++) {
4407 if (!e[i]) {
4408 continue;
4409 }
4410
4411 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
4412 /* no free, this is just a shadow copy of the original extension instance */
4413 } else {
4414 if (e[i]->flags & (LYEXT_OPT_YANG)) {
4415 free(e[i]->def); /* remove name of instance extension */
PavolVican19dc6152017-02-06 12:04:15 +01004416 e[i]->def = NULL;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004417 free(e[i]->parent); /* remove backup part of yang file */
4418 }
4419 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size);
4420 lydict_remove(ctx, e[i]->arg_value);
4421 }
4422
4423 if (e[i]->def && e[i]->def->plugin && e[i]->def->plugin->type == LYEXT_COMPLEX) {
Radek Krejcifebdad72017-02-06 11:35:51 +01004424 substmt = ((struct lys_ext_instance_complex *)e[i])->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004425 for (j = 0; substmt[j].stmt; j++) {
4426 switch(substmt[j].stmt) {
4427 case LY_STMT_DESCRIPTION:
4428 case LY_STMT_REFERENCE:
4429 case LY_STMT_UNITS:
Radek Krejcib71243e2017-02-08 16:20:08 +01004430 case LY_STMT_ARGUMENT:
4431 case LY_STMT_DEFAULT:
4432 case LY_STMT_ERRTAG:
4433 case LY_STMT_ERRMSG:
4434 case LY_STMT_PREFIX:
4435 case LY_STMT_NAMESPACE:
4436 case LY_STMT_PRESENCE:
4437 case LY_STMT_REVISIONDATE:
4438 case LY_STMT_KEY:
4439 case LY_STMT_BASE:
4440 case LY_STMT_BELONGSTO:
4441 case LY_STMT_CONTACT:
4442 case LY_STMT_ORGANIZATION:
4443 case LY_STMT_PATH:
Radek Krejcib71243e2017-02-08 16:20:08 +01004444 case LY_STMT_VALUE:
Radek Krejci8d6b7422017-02-03 14:42:13 +01004445 lys_extcomplex_free_str(ctx, (struct lys_ext_instance_complex *)e[i], substmt[j].stmt);
4446 break;
4447 case LY_STMT_TYPE:
4448 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPE, struct lys_type, lys_type_free, 1);
4449 break;
Radek Krejci63fc0962017-02-15 13:20:18 +01004450 case LY_STMT_TYPEDEF:
4451 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPEDEF, struct lys_tpdf, lys_tpdf_free, 1);
4452 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004453 case LY_STMT_IFFEATURE:
4454 EXTCOMPLEX_FREE_STRUCT(LY_STMT_IFFEATURE, struct lys_iffeature, lys_iffeature_free, 0, 1);
4455 break;
Radek Krejci5496fae2017-02-10 13:26:48 +01004456 case LY_STMT_MAX:
4457 case LY_STMT_MIN:
4458 case LY_STMT_POSITION:
Radek Krejcif8d05c22017-02-10 15:33:35 +01004459 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
Radek Krejci716cd7a2017-02-15 12:23:41 +01004460 if (substmt[j].cardinality >= LY_STMT_CARD_SOME && *pp) {
Radek Krejcif8d05c22017-02-10 15:33:35 +01004461 for(k = 0; ((uint32_t**)(*pp))[k]; k++) {
4462 free(((uint32_t**)(*pp))[k]);
4463 }
4464 }
4465 free(*pp);
4466 break;
4467 case LY_STMT_DIGITS:
Radek Krejcib84686f2017-02-09 16:04:55 +01004468 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
4469 /* free the array */
4470 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4471 free(*pp);
4472 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004473 break;
Radek Krejci37f9ba32017-02-10 16:50:35 +01004474 case LY_STMT_MODULE:
4475 /* modules are part of the context, so they will be freed there */
4476 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
4477 /* free the array */
4478 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4479 free(*pp);
4480 }
4481 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01004482 case LY_STMT_ACTION:
Radek Krejcib31762b2017-02-15 10:48:42 +01004483 case LY_STMT_ANYDATA:
4484 case LY_STMT_ANYXML:
4485 case LY_STMT_CASE:
4486 case LY_STMT_CHOICE:
4487 case LY_STMT_CONTAINER:
4488 case LY_STMT_GROUPING:
4489 case LY_STMT_INPUT:
4490 case LY_STMT_LEAF:
4491 case LY_STMT_LEAFLIST:
4492 case LY_STMT_LIST:
4493 case LY_STMT_NOTIFICATION:
4494 case LY_STMT_OUTPUT:
4495 case LY_STMT_RPC:
4496 case LY_STMT_USES:
Radek Krejcif95b6292017-02-13 15:57:37 +01004497 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4498 LY_TREE_FOR_SAFE((struct lys_node *)(*pp), snext, siter) {
4499 lys_node_free(siter, NULL, 0);
4500 }
Radek Krejcib31762b2017-02-15 10:48:42 +01004501 *pp = NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01004502 break;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004503 case LY_STMT_UNIQUE:
4504 pp = lys_ext_complex_get_substmt(LY_STMT_UNIQUE, (struct lys_ext_instance_complex *)e[i], NULL);
4505 if (!pp || !(*pp)) {
4506 break;
4507 }
4508 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
4509 for (start = pp = *pp; *pp; pp++) {
4510 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
4511 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
4512 }
4513 free((*(struct lys_unique**)pp)->expr);
4514 free(*pp);
4515 }
4516 free(start);
4517 } else { /* single item */
4518 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
4519 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
4520 }
4521 free((*(struct lys_unique**)pp)->expr);
4522 free(*pp);
4523 }
4524 break;
Radek Krejciaa9c5202017-02-15 16:10:14 +01004525 case LY_STMT_LENGTH:
4526 case LY_STMT_MUST:
4527 case LY_STMT_PATTERN:
4528 case LY_STMT_RANGE:
4529 EXTCOMPLEX_FREE_STRUCT(substmt[j].stmt, struct lys_restr, lys_restr_free, 1);
4530 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004531 default:
Radek Krejcib84686f2017-02-09 16:04:55 +01004532 /* nothing to free */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004533 break;
4534 }
4535 }
4536 }
4537
4538 free(e[i]);
4539 }
4540 free(e);
4541
4542#undef EXTCOMPLEX_FREE_STRUCT
4543}