blob: babb099b40e393b5bd81194c1926ee81476d9c75 [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 *
Michal Vasko53b7da02018-02-13 15:28:42 +01006 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
Radek Krejcida04f4a2015-05-21 12:54:09 +02007 *
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
Michal Vaskob0bbf5f2018-02-16 09:35:59 +010017#ifdef __APPLE__
18# include <sys/param.h>
19#endif
Radek Krejci812b10a2015-05-28 16:48:25 +020020#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020021#include <ctype.h>
Radek Krejcib051f722016-02-25 15:12:21 +010022#include <limits.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <stdlib.h>
24#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010025#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020026#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010027#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020028#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010029#include <unistd.h>
30#include <errno.h>
Radek Krejci72cdfac2018-08-15 14:47:33 +020031#include <dirent.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020032
33#include "common.h"
34#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020035#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020036#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010037#include "xml.h"
Michal Vasko5b3492c2016-07-20 09:37:40 +020038#include "xpath.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020039#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020040#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020041#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010042#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020043
Radek Krejci8d6b7422017-02-03 14:42:13 +010044static int lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci5138e9f2017-04-12 13:10:46 +020045 int in_grp, int shallow, struct unres_schema *unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020046
Radek Krejci65aca412018-01-24 11:23:06 +010047API const struct lys_node_list *
48lys_is_key(const struct lys_node_leaf *node, uint8_t *index)
49{
50 struct lys_node *parent = (struct lys_node *)node;
51 struct lys_node_list *list;
52 uint8_t i;
53
54 if (!node || node->nodetype != LYS_LEAF) {
55 return NULL;
56 }
57
58 do {
59 parent = lys_parent(parent);
60 } while (parent && parent->nodetype == LYS_USES);
61
62 if (!parent || parent->nodetype != LYS_LIST) {
63 return NULL;
64 }
65
66 list = (struct lys_node_list*)parent;
67 for (i = 0; i < list->keys_size; i++) {
68 if (list->keys[i] == node) {
69 if (index) {
70 (*index) = i;
71 }
72 return list;
73 }
74 }
75 return NULL;
76}
77
Radek Krejci9ff0a922016-07-14 13:08:05 +020078API const struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010079lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020080{
Radek Krejci9ff0a922016-07-14 13:08:05 +020081 int i;
Radek Krejci48061fb2015-08-05 15:41:07 +020082
Radek Krejci27fe55e2016-09-13 17:13:35 +020083 if (!node) {
84 return NULL;
85 }
86
Radek Krejci48061fb2015-08-05 15:41:07 +020087check:
88 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
89 /* input/output does not have if-feature, so skip them */
90
91 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020092 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci69b8d922016-07-27 13:13:41 +020093 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020094 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020095 }
96 }
97 }
98
99 if (!recursive) {
100 return NULL;
101 }
102
103 /* go through parents */
104 if (node->nodetype == LYS_AUGMENT) {
105 /* go to parent actually means go to the target node */
106 node = ((struct lys_node_augment *)node)->target;
Michal Vasko17549192017-03-13 10:19:33 +0100107 if (!node) {
108 /* unresolved augment, let's say it's enabled */
109 return NULL;
110 }
Radek Krejci48061fb2015-08-05 15:41:07 +0200111 } else if (node->parent) {
112 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +0200113 } else {
114 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +0200115 }
116
Radek Krejci074bf852015-08-19 14:22:16 +0200117 if (recursive == 2) {
118 /* continue only if the node cannot have a data instance */
119 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
120 return NULL;
121 }
122 }
123 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +0200124}
125
Michal Vasko1dca6882015-10-22 14:29:42 +0200126int
Michal Vasko36cbaa42015-12-14 13:15:48 +0100127lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
128 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +0200129{
Radek Krejcic071c542016-01-27 14:57:51 +0100130 const struct lys_node *node, *parent = NULL;
131 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +0100132 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +0200133
Michal Vasko36cbaa42015-12-14 13:15:48 +0100134 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +0200135 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +0200136
Michal Vasko36cbaa42015-12-14 13:15:48 +0100137 /* fill the lengths in case the caller is so indifferent */
138 if (!mod_name_len) {
139 mod_name_len = strlen(mod_name);
140 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200141 if (!nam_len) {
142 nam_len = strlen(name);
143 }
144
Michal Vasko9e635ac2016-10-17 11:44:09 +0200145 while (siblings && (siblings->nodetype == LYS_USES)) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200146 siblings = siblings->child;
147 }
Michal Vasko9e635ac2016-10-17 11:44:09 +0200148 if (!siblings) {
149 /* unresolved uses */
150 return EXIT_FAILURE;
151 }
152
Michal Vasko680f8b42016-10-17 10:27:37 +0200153 if (siblings->nodetype == LYS_GROUPING) {
154 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
155 if (node->nodetype == LYS_GROUPING) {
156 /* we went through all the siblings, only groupings there - no valid sibling */
157 return EXIT_FAILURE;
158 }
159 /* update siblings to be valid */
160 siblings = node;
161 }
162
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200163 /* set parent correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100164 parent = lys_parent(siblings);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200165
Michal Vasko680f8b42016-10-17 10:27:37 +0200166 /* go up all uses */
167 while (parent && (parent->nodetype == LYS_USES)) {
168 parent = lys_parent(parent);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200169 }
170
Radek Krejcic071c542016-01-27 14:57:51 +0100171 if (!parent) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200172 /* handle situation when there is a top-level uses referencing a foreign grouping */
173 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
174 mod = lys_node_module(node);
Michal Vasko1dca6882015-10-22 14:29:42 +0200175 }
176
Radek Krejcic071c542016-01-27 14:57:51 +0100177 /* try to find the node */
178 node = NULL;
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100179 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
Radek Krejcic071c542016-01-27 14:57:51 +0100180 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100181 /* module name comparison */
182 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200183 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 +0100184 continue;
185 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200186
Radek Krejcic071c542016-01-27 14:57:51 +0100187 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200188 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100189 if (ret) {
190 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200191 }
Radek Krejcic071c542016-01-27 14:57:51 +0100192 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200193 }
194 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200195 }
196
197 return EXIT_FAILURE;
198}
199
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200200int
Michal Vaskobb520442017-05-23 10:55:18 +0200201lys_getnext_data(const struct lys_module *mod, const struct lys_node *parent, const char *name, int nam_len,
202 LYS_NODE type, const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200203{
Michal Vaskobb520442017-05-23 10:55:18 +0200204 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200205
Michal Vaskobb520442017-05-23 10:55:18 +0200206 assert((mod || parent) && name);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200207 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
208
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200209 if (!mod) {
Michal Vaskobb520442017-05-23 10:55:18 +0200210 mod = lys_node_module(parent);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200211 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200212
Michal Vasko4f0dad02016-02-15 14:08:23 +0100213 /* try to find the node */
214 node = NULL;
Michal Vasko24476fa2017-03-08 12:33:48 +0100215 while ((node = lys_getnext(node, parent, mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100216 if (!type || (node->nodetype & type)) {
217 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200218 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100219 continue;
220 }
221
Michal Vasko4f0dad02016-02-15 14:08:23 +0100222 /* direct name check */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100223 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100224 if (ret) {
225 *ret = node;
226 }
227 return EXIT_SUCCESS;
228 }
Radek Krejcic071c542016-01-27 14:57:51 +0100229 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200230 }
231
232 return EXIT_FAILURE;
233}
234
Michal Vasko1e62a092015-12-01 12:27:20 +0100235API const struct lys_node *
236lys_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 +0200237{
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100238 const struct lys_node *next, *aug_parent;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100239 struct lys_node **snode;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200240
Michal Vasko75702cd2018-02-12 11:27:09 +0100241 if ((!parent && !module) || (module && module->type) || (parent && (parent->nodetype == LYS_USES) && !(options & LYS_GETNEXT_PARENTUSES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100242 LOGARG;
Michal Vasko24476fa2017-03-08 12:33:48 +0100243 return NULL;
244 }
245
Radek Krejci8bc87f62015-09-02 16:19:05 +0200246 if (!last) {
247 /* first call */
248
249 /* get know where to start */
250 if (parent) {
251 /* schema subtree */
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100252 snode = lys_child(parent, LYS_UNKNOWN);
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100253 /* do not return anything if the augment does not have any children */
Radek Krejcibb08db32017-07-03 11:29:17 +0200254 if (!snode || !(*snode) || ((parent->nodetype == LYS_AUGMENT) && ((*snode)->parent != parent))) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100255 return NULL;
256 }
257 next = last = *snode;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200258 } else {
259 /* top level data */
Michal Vaskocb45f472018-02-12 10:47:42 +0100260 if (!(options & LYS_GETNEXT_NOSTATECHECK) && (module->disabled || !module->implemented)) {
261 /* nothing to return from a disabled/imported module */
262 return NULL;
263 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200264 next = last = module->data;
265 }
Radek Krejci972724f2016-08-12 15:24:40 +0200266 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
267 /* continue with uses content */
268 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200269 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200270 /* continue after the last returned value */
271 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200272 }
273
274repeat:
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100275 if (parent && (parent->nodetype == LYS_AUGMENT) && next) {
276 /* do not return anything outside the parent augment */
277 aug_parent = next->parent;
278 do {
279 while (aug_parent && (aug_parent->nodetype != LYS_AUGMENT)) {
280 aug_parent = aug_parent->parent;
281 }
282 if (aug_parent) {
283 if (aug_parent == parent) {
284 break;
285 }
286 aug_parent = ((struct lys_node_augment *)aug_parent)->target;
287 }
288
289 } while (aug_parent);
290 if (!aug_parent) {
291 return NULL;
292 }
293 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200294 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200295 if (options & LYS_GETNEXT_WITHGROUPING) {
296 return next;
297 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200298 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200299 }
300
Radek Krejci972724f2016-08-12 15:24:40 +0200301 if (!next) { /* cover case when parent is augment */
302 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200303 /* no next element */
304 return NULL;
305 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200306 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200307 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200308 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200309 } else {
310 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200311 }
312
Michal Vaskocb45f472018-02-12 10:47:42 +0100313 if (!(options & LYS_GETNEXT_NOSTATECHECK) && lys_is_disabled(next, 0)) {
314 next = next->next;
315 goto repeat;
316 }
317
Radek Krejci7f40ce32015-08-12 20:38:46 +0200318 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200319 case LYS_INPUT:
320 case LYS_OUTPUT:
321 if (options & LYS_GETNEXT_WITHINOUT) {
322 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200323 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200324 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200325 } else {
326 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200327 }
Radek Krejci972724f2016-08-12 15:24:40 +0200328 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200329
Michal Vaskoa5835e92015-10-20 15:07:39 +0200330 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200331 if (options & LYS_GETNEXT_WITHCASE) {
332 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200333 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200334 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200335 } else {
336 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200337 }
Radek Krejci972724f2016-08-12 15:24:40 +0200338 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200339
Michal Vasko1dca6882015-10-22 14:29:42 +0200340 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200341 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200342 if (options & LYS_GETNEXT_WITHUSES) {
343 return next;
344 } else if (next->child) {
345 next = next->child;
346 } else {
347 next = next->next;
348 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200349 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200350
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200351 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200352 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200353 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200354 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200355 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200356 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200357 case LYS_LIST:
358 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200359 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200360
Radek Krejci972724f2016-08-12 15:24:40 +0200361 case LYS_CONTAINER:
362 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
363 if (next->child) {
364 /* go into */
365 next = next->child;
366 } else {
367 next = next->next;
368 }
369 goto repeat;
370 } else {
371 return next;
372 }
373
Radek Krejci8bc87f62015-09-02 16:19:05 +0200374 case LYS_CHOICE:
375 if (options & LYS_GETNEXT_WITHCHOICE) {
376 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200377 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200378 /* go into */
379 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200380 } else {
381 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200382 }
Radek Krejci972724f2016-08-12 15:24:40 +0200383 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200384
Radek Krejci7f40ce32015-08-12 20:38:46 +0200385 default:
386 /* we should not be here */
387 return NULL;
388 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200389}
390
Radek Krejcibf285832017-01-26 16:05:41 +0100391void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200392lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200393{
Michal Vaskof75b2772018-03-14 09:55:33 +0100394 struct lys_node *parent, *first, **pp = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +0100395 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200397 if (!node) {
398 return;
399 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200401 /* unlink from data model if necessary */
402 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100403 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100404 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100405 if (main_module->data == node) {
406 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200407 }
408 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200410 /* store pointers to important nodes */
411 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200412 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200413 /* handle augments - first, unlink it from the augment parent ... */
414 if (parent->child == node) {
Radek Krejcic9d78692017-08-24 17:17:18 +0200415 parent->child = (node->next && node->next->parent == parent) ? node->next : NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200416 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100417
418 if (parent->flags & LYS_NOTAPPLIED) {
419 /* data are not connected in the target, so we cannot continue with the target as a parent */
420 parent = NULL;
421 } else {
422 /* data are connected in target, so we will continue with the target as a parent */
423 parent = ((struct lys_node_augment *)parent)->target;
424 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200425 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200427 /* unlink from parent */
428 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100429 if (parent->nodetype == LYS_EXT) {
430 pp = (struct lys_node **)lys_ext_complex_get_substmt(lys_snode2stmt(node->nodetype),
431 (struct lys_ext_instance_complex*)parent, NULL);
432 if (*pp == node) {
433 *pp = node->next;
434 }
435 } else if (parent->child == node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200436 parent->child = node->next;
437 }
438 node->parent = NULL;
439 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200441 /* unlink from siblings */
442 if (node->prev == node) {
443 /* there are no more siblings */
444 return;
445 }
446 if (node->next) {
447 node->next->prev = node->prev;
448 } else {
449 /* unlinking the last element */
450 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100451 if (parent->nodetype == LYS_EXT) {
452 first = *(struct lys_node **)pp;
453 } else {
454 first = parent->child;
455 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200456 } else {
457 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200458 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200459 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200460 }
461 }
462 first->prev = node->prev;
463 }
464 if (node->prev->next) {
465 node->prev->next = node->next;
466 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200468 /* clean up the unlinked element */
469 node->next = NULL;
470 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200471}
472
Michal Vasko563ef092015-09-04 13:17:23 +0200473struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100474lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200475{
476 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200477
478 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200479 /* top-level augment, look into module (uses augment is handled correctly below) */
480 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
Radek Krejci115fa882017-03-01 16:15:07 +0100481 par_iter = lys_main_module(par_iter->parent->module)->data;
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200482 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200483 break;
484 }
485 }
486
Michal Vasko38a00412018-03-14 10:01:50 +0100487 if (par_iter->nodetype == LYS_EXT) {
488 /* we are in a top-level extension, search grouping in top-level groupings */
489 par_iter = lys_main_module(par_iter->module)->data;
490 if (!par_iter) {
491 /* not connected yet, wait */
492 return NULL;
493 }
494 } else if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200495 continue;
496 }
497
498 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
499 if (!stop) {
500 stop = par_iter;
501 } else if (iter == stop) {
502 break;
503 }
504 if (iter->nodetype != LYS_GROUPING) {
505 continue;
506 }
507
Radek Krejcif8426a72015-10-31 23:14:03 +0100508 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200509 return (struct lys_node_grp *)iter;
510 }
511 }
512 }
513
Michal Vasko563ef092015-09-04 13:17:23 +0200514 return NULL;
515}
516
Radek Krejci10c760e2015-08-14 14:45:43 +0200517/*
518 * get next grouping in the root's subtree, in the
519 * first call, tha last is NULL
520 */
521static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200522lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200523{
Radek Krejci10c760e2015-08-14 14:45:43 +0200524 struct lys_node *last = (struct lys_node *)lastgrp;
525 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200526
Radek Krejci10c760e2015-08-14 14:45:43 +0200527 assert(root);
528
529 if (!last) {
530 last = root;
531 }
532
533 while (1) {
534 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
535 next = last->child;
536 } else {
537 next = NULL;
538 }
539 if (!next) {
540 if (last == root) {
541 /* we are done */
542 return NULL;
543 }
544
545 /* no children, go to siblings */
546 next = last->next;
547 }
548 while (!next) {
549 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100550 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200551 /* we are done */
552 return NULL;
553 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200554 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100555 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200556 }
557
558 if (next->nodetype == LYS_GROUPING) {
559 return (struct lys_node_grp *)next;
560 }
561
562 last = next;
563 }
564}
565
Michal Vasko0d343d12015-08-24 14:57:36 +0200566/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200567int
Radek Krejci07911992015-08-14 15:13:31 +0200568lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
569{
Michal Vasko563ef092015-09-04 13:17:23 +0200570 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200571 struct lys_node_grp *grp;
Radek Krejcif95b6292017-02-13 15:57:37 +0100572 int down, up;
Radek Krejci07911992015-08-14 15:13:31 +0200573
574 assert(node);
575
576 if (!parent) {
577 assert(module);
578 } else {
579 module = parent->module;
580 }
Radek Krejci115fa882017-03-01 16:15:07 +0100581 module = lys_main_module(module);
Radek Krejci07911992015-08-14 15:13:31 +0200582
583 switch (node->nodetype) {
584 case LYS_GROUPING:
585 /* 6.2.1, rule 6 */
586 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100587 start = *lys_child(parent, LYS_GROUPING);
588 if (!start) {
Radek Krejci07911992015-08-14 15:13:31 +0200589 down = 0;
590 start = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100591 } else {
592 down = 1;
593 }
594 if (parent->nodetype == LYS_EXT) {
595 up = 0;
596 } else {
597 up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200598 }
599 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100600 down = up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200601 start = module->data;
602 }
603 /* go up */
Radek Krejcif95b6292017-02-13 15:57:37 +0100604 if (up && lys_find_grouping_up(node->name, start)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100605 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200606 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200607 }
608 /* go down, because grouping can be defined after e.g. container in which is collision */
609 if (down) {
610 for (iter = start, stop = NULL; iter; iter = iter->prev) {
611 if (!stop) {
612 stop = start;
613 } else if (iter == stop) {
614 break;
615 }
616 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
617 continue;
618 }
619
620 grp = NULL;
621 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100622 if (ly_strequal(node->name, grp->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100623 LOGVAL(module->ctx, LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200624 return EXIT_FAILURE;
625 }
626 }
627 }
628 }
629 break;
630 case LYS_LEAF:
631 case LYS_LEAFLIST:
632 case LYS_LIST:
633 case LYS_CONTAINER:
634 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200635 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200636 /* 6.2.1, rule 7 */
637 if (parent) {
638 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200639 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
640 if (iter->nodetype == LYS_AUGMENT) {
641 if (((struct lys_node_augment *)iter)->target) {
642 /* augment is resolved, go up */
643 iter = ((struct lys_node_augment *)iter)->target;
644 continue;
645 }
646 /* augment is not resolved, this is the final parent */
647 break;
648 }
Radek Krejci07911992015-08-14 15:13:31 +0200649 iter = iter->parent;
650 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200651
Radek Krejci07911992015-08-14 15:13:31 +0200652 if (!iter) {
653 stop = NULL;
654 iter = module->data;
Radek Krejcif95b6292017-02-13 15:57:37 +0100655 } else if (iter->nodetype == LYS_EXT) {
656 stop = iter;
PavolVican9d61d402018-02-05 15:52:48 +0100657 iter = (struct lys_node *)lys_child(iter, node->nodetype);
658 if (iter) {
659 iter = *(struct lys_node **)iter;
660 }
Radek Krejci07911992015-08-14 15:13:31 +0200661 } else {
662 stop = iter;
663 iter = iter->child;
664 }
665 } else {
666 stop = NULL;
667 iter = module->data;
668 }
669 while (iter) {
670 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
671 iter = iter->child;
672 continue;
673 }
674
Radek Krejcibf2abff2016-08-23 15:51:52 +0200675 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100676 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100677 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200678 return EXIT_FAILURE;
679 }
680 }
681
682 /* special case for choice - we must check the choice's name as
683 * well as the names of nodes under the choice
684 */
685 if (iter->nodetype == LYS_CHOICE) {
686 iter = iter->child;
687 continue;
688 }
689
690 /* go to siblings */
691 if (!iter->next) {
692 /* no sibling, go to parent's sibling */
693 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200694 /* for parent LYS_AUGMENT */
695 if (iter->parent == stop) {
696 iter = stop;
697 break;
698 }
699 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200700 if (iter && iter->next) {
701 break;
702 }
703 } while (iter != stop);
704
705 if (iter == stop) {
706 break;
707 }
708 }
709 iter = iter->next;
710 }
711 break;
712 case LYS_CASE:
713 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100714 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100715 start = *lys_child(parent, LYS_CASE);
Radek Krejcic071c542016-01-27 14:57:51 +0100716 } else {
717 start = module->data;
718 }
719
720 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200721 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200722 continue;
723 }
724
Radek Krejci749190d2016-02-18 16:26:25 +0100725 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100726 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200727 return EXIT_FAILURE;
728 }
729 }
730 break;
731 default:
732 /* no check needed */
733 break;
734 }
735
736 return EXIT_SUCCESS;
737}
738
Michal Vasko0d343d12015-08-24 14:57:36 +0200739/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200740int
Michal Vasko8d30dd82018-09-10 10:06:12 +0200741lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child, int options)
Radek Krejci10c760e2015-08-14 14:45:43 +0200742{
Michal Vasko53b7da02018-02-13 15:28:42 +0100743 struct ly_ctx *ctx = child->module->ctx;
Radek Krejcic9d78692017-08-24 17:17:18 +0200744 struct lys_node *iter, **pchild;
Michal Vasko56601c92018-08-06 10:03:06 +0200745 struct lys_node_inout *in, *out;
Radek Krejci744c2d42017-03-26 13:30:00 -0500746 struct lys_node_case *c;
747 int type, shortcase = 0;
Radek Krejcif95b6292017-02-13 15:57:37 +0100748 void *p;
749 struct lyext_substmt *info = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200751 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200752
Radek Krejci10c760e2015-08-14 14:45:43 +0200753 if (parent) {
754 type = parent->nodetype;
755 module = parent->module;
756 } else {
757 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100758 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200759 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200760 }
761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200762 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200763 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200764 case LYS_CONTAINER:
765 case LYS_LIST:
766 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100767 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200768 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200769 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200770 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100771 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200772 return EXIT_FAILURE;
773 }
774 break;
Radek Krejci76512572015-08-04 09:47:08 +0200775 case LYS_INPUT:
776 case LYS_OUTPUT:
777 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200778 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200779 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200780 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100781 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200782 return EXIT_FAILURE;
783 }
784 break;
Radek Krejci76512572015-08-04 09:47:08 +0200785 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200786 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200787 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100788 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200789 return EXIT_FAILURE;
790 }
Radek Krejci744c2d42017-03-26 13:30:00 -0500791 if (child->nodetype != LYS_CASE) {
792 shortcase = 1;
793 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200794 break;
Radek Krejci76512572015-08-04 09:47:08 +0200795 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200796 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200797 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100798 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200799 return EXIT_FAILURE;
800 }
801 break;
Radek Krejci76512572015-08-04 09:47:08 +0200802 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200803 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200804 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100805 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200806 return EXIT_FAILURE;
807 }
808 break;
Radek Krejci76512572015-08-04 09:47:08 +0200809 case LYS_LEAF:
810 case LYS_LEAFLIST:
811 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200812 case LYS_ANYDATA:
Michal Vasko53b7da02018-02-13 15:28:42 +0100813 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
814 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100815 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200816 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200817 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200818 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200819 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100820 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100821 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200822 return EXIT_FAILURE;
823 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200824 break;
825 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200826 /* top level */
827 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200828 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200829 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100830 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200831 return EXIT_FAILURE;
832 }
Radek Krejcif95b6292017-02-13 15:57:37 +0100833 break;
834 case LYS_EXT:
835 /* plugin-defined */
836 p = lys_ext_complex_get_substmt(lys_snode2stmt(child->nodetype), (struct lys_ext_instance_complex*)parent, &info);
837 if (!p) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100838 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype),
Radek Krejcif95b6292017-02-13 15:57:37 +0100839 ((struct lys_ext_instance_complex*)parent)->def->name);
840 return EXIT_FAILURE;
841 }
842 /* TODO check cardinality */
Radek Krejcic071c542016-01-27 14:57:51 +0100843 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200844 }
845
846 /* check identifier uniqueness */
Michal Vasko15a43372017-09-25 14:12:42 +0200847 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && lys_check_id(child, parent, module)) {
Radek Krejci07911992015-08-14 15:13:31 +0200848 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200849 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200850
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200851 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200852 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200853 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200854
Radek Krejcif95b6292017-02-13 15:57:37 +0100855 if ((child->nodetype & (LYS_INPUT | LYS_OUTPUT)) && parent->nodetype != LYS_EXT) {
Michal Vasko56601c92018-08-06 10:03:06 +0200856 /* find the implicit input/output node */
857 LY_TREE_FOR(parent->child, iter) {
858 if (iter->nodetype == child->nodetype) {
859 break;
860 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200861 }
Michal Vasko56601c92018-08-06 10:03:06 +0200862 assert(iter);
863
864 /* switch the old implicit node (iter) with the new one (child) */
865 if (parent->child == iter) {
866 /* first child */
867 parent->child = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200868 } else {
Michal Vasko56601c92018-08-06 10:03:06 +0200869 iter->prev->next = child;
870 }
871 child->prev = iter->prev;
872 child->next = iter->next;
873 if (iter->next) {
874 iter->next->prev = child;
875 } else {
876 /* last child */
Radek Krejci41a349b2016-10-24 19:21:59 +0200877 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200878 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200879 child->parent = parent;
Michal Vasko56601c92018-08-06 10:03:06 +0200880
881 /* isolate the node and free it */
882 iter->next = NULL;
883 iter->prev = iter;
884 iter->parent = NULL;
885 lys_node_free(iter, NULL, 0);
Radek Krejci41a349b2016-10-24 19:21:59 +0200886 } else {
Radek Krejci744c2d42017-03-26 13:30:00 -0500887 if (shortcase) {
888 /* create the implicit case to allow it to serve as a target of the augments,
889 * it won't be printed, but it will be present in the tree */
890 c = calloc(1, sizeof *c);
Michal Vasko53b7da02018-02-13 15:28:42 +0100891 LY_CHECK_ERR_RETURN(!c, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejci744c2d42017-03-26 13:30:00 -0500892 c->name = lydict_insert(module->ctx, child->name, 0);
893 c->flags = LYS_IMPLICIT;
Michal Vasko8d30dd82018-09-10 10:06:12 +0200894 if (!(options & (LYS_PARSE_OPT_CFG_IGNORE | LYS_PARSE_OPT_CFG_NOINHERIT))) {
895 /* get config flag from parent */
896 c->flags |= parent->flags & LYS_CONFIG_MASK;
897 }
Radek Krejci744c2d42017-03-26 13:30:00 -0500898 c->module = module;
899 c->nodetype = LYS_CASE;
900 c->prev = (struct lys_node*)c;
Michal Vasko8d30dd82018-09-10 10:06:12 +0200901 lys_node_addchild(parent, module, (struct lys_node*)c, options);
Radek Krejci744c2d42017-03-26 13:30:00 -0500902 parent = (struct lys_node*)c;
903 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200904 /* connect the child correctly */
905 if (!parent) {
906 if (module->data) {
907 module->data->prev->next = child;
908 child->prev = module->data->prev;
909 module->data->prev = child;
910 } else {
911 module->data = child;
912 }
913 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100914 pchild = lys_child(parent, child->nodetype);
915 assert(pchild);
916
Radek Krejcic9d78692017-08-24 17:17:18 +0200917 child->parent = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100918 if (!(*pchild)) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200919 /* the only/first child of the parent */
Radek Krejcif95b6292017-02-13 15:57:37 +0100920 *pchild = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200921 iter = child;
922 } else {
923 /* add a new child at the end of parent's child list */
Radek Krejcif95b6292017-02-13 15:57:37 +0100924 iter = (*pchild)->prev;
Radek Krejci41a349b2016-10-24 19:21:59 +0200925 iter->next = child;
926 child->prev = iter;
927 }
928 while (iter->next) {
929 iter = iter->next;
930 iter->parent = parent;
931 }
Radek Krejcic9d78692017-08-24 17:17:18 +0200932 (*pchild)->prev = iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200933 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200934 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200935
Michal Vaskoe022a562016-09-27 14:24:15 +0200936 /* check config value (but ignore them in groupings and augments) */
Radek Krejcif95b6292017-02-13 15:57:37 +0100937 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); iter = iter->parent);
Michal Vaskoe022a562016-09-27 14:24:15 +0200938 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200939 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
940 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100941 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, child, "true", "config");
942 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200943 return EXIT_FAILURE;
944 }
945 }
946
Radek Krejci41771502016-04-14 17:52:32 +0200947 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200948 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200949 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200950 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200951 /* store it only into container or list - the only data inner nodes */
952 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
953 if (iter->flags & LYS_INCL_STATUS) {
954 /* done, someone else set it already from here */
955 break;
956 }
957 /* set flag about including status data */
958 iter->flags |= LYS_INCL_STATUS;
959 }
960 }
961 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200962
963 /* create implicit input/output nodes to have available them as possible target for augment */
Radek Krejci60251232017-08-24 17:13:08 +0200964 if ((child->nodetype & (LYS_RPC | LYS_ACTION)) && !child->child) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200965 in = calloc(1, sizeof *in);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200966 out = calloc(1, sizeof *out);
967 if (!in || !out) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100968 LOGMEM(ctx);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200969 free(in);
970 free(out);
971 return EXIT_FAILURE;
972 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200973 in->nodetype = LYS_INPUT;
974 in->name = lydict_insert(child->module->ctx, "input", 5);
Radek Krejci41a349b2016-10-24 19:21:59 +0200975 out->nodetype = LYS_OUTPUT;
Radek Krejcia8d111f2017-05-31 13:57:37 +0200976 out->name = lydict_insert(child->module->ctx, "output", 6);
Radek Krejci41a349b2016-10-24 19:21:59 +0200977 in->module = out->module = child->module;
978 in->parent = out->parent = child;
979 in->flags = out->flags = LYS_IMPLICIT;
980 in->next = (struct lys_node *)out;
981 in->prev = (struct lys_node *)out;
982 out->prev = (struct lys_node *)in;
983 child->child = (struct lys_node *)in;
984 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200985 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200986}
987
Michal Vasko29245662017-04-18 15:56:31 +0200988const struct lys_module *
Michal Vaskofb98dc42018-01-11 13:38:28 +0100989lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, const char *revision, int internal, int implement)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200990{
Radek Krejcia1df1682016-04-11 14:56:59 +0200991 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200992 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200993 unsigned int len;
Radek Krejcif347abc2016-06-22 10:18:47 +0200994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200995 if (!ctx || !data) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100996 LOGARG;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 return NULL;
998 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200999
Radek Krejcia1df1682016-04-11 14:56:59 +02001000 if (!internal && format == LYS_IN_YANG) {
1001 /* enlarge data by 2 bytes for flex */
1002 len = strlen(data);
1003 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Michal Vasko53b7da02018-02-13 15:28:42 +01001004 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(ctx), NULL);
Radek Krejcia1df1682016-04-11 14:56:59 +02001005 memcpy(enlarged_data, data, len);
1006 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1007 data = enlarged_data;
1008 }
1009
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001010 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001011 case LYS_IN_YIN:
Michal Vaskofb98dc42018-01-11 13:38:28 +01001012 mod = yin_read_module(ctx, data, revision, implement);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001013 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001014 case LYS_IN_YANG:
Michal Vaskofb98dc42018-01-11 13:38:28 +01001015 mod = yang_read_module(ctx, data, 0, revision, implement);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001016 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001017 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001018 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001019 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001020 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001021
Radek Krejcia1df1682016-04-11 14:56:59 +02001022 free(enlarged_data);
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001023
1024 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
1025 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
1026 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
1027 * the anotation definitions available in the internal schema structure. There is another hack in schema
1028 * printers to do not print this internally added annotation. */
1029 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
Radek Krejci5b190662017-04-13 08:56:14 +02001030 if (lyp_add_ietf_netconf_annotations(mod)) {
Michal Vasko10681e82018-01-16 14:54:16 +01001031 lys_free(mod, NULL, 1, 1);
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001032 return NULL;
1033 }
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001034 }
1035
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001036 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001037}
1038
Radek Krejcia1df1682016-04-11 14:56:59 +02001039API const struct lys_module *
1040lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1041{
Michal Vaskofb98dc42018-01-11 13:38:28 +01001042 return lys_parse_mem_(ctx, data, format, NULL, 0, 1);
Radek Krejcia1df1682016-04-11 14:56:59 +02001043}
1044
Michal Vasko5a721fd2016-02-16 12:16:48 +01001045struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001046lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001047{
Michal Vasko5b998712017-01-26 10:34:06 +01001048 char *enlarged_data = NULL;
Michal Vasko5a721fd2016-02-16 12:16:48 +01001049 struct lys_submodule *submod = NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001050 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001052 assert(module);
1053 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001054
Michal Vasko5b998712017-01-26 10:34:06 +01001055 if (format == LYS_IN_YANG) {
1056 /* enlarge data by 2 bytes for flex */
1057 len = strlen(data);
1058 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Michal Vasko53b7da02018-02-13 15:28:42 +01001059 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(module->ctx), NULL);
Michal Vasko5b998712017-01-26 10:34:06 +01001060 memcpy(enlarged_data, data, len);
1061 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1062 data = enlarged_data;
1063 }
1064
Radek Krejcic071c542016-01-27 14:57:51 +01001065 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001066 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001068 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001069 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001070 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001071 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001072 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001073 submod = yang_read_submodule(module, data, 0, unres);
1074 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001075 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001076 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001077 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001078 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001079
Michal Vasko5b998712017-01-26 10:34:06 +01001080 free(enlarged_data);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001081 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001082}
1083
Michal Vasko1e62a092015-12-01 12:27:20 +01001084API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001085lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1086{
1087 int fd;
1088 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +02001089 const char *rev, *dot, *filename;
1090 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +01001091
1092 if (!ctx || !path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001093 LOGARG;
Michal Vasko662610a2015-12-07 11:25:45 +01001094 return NULL;
1095 }
1096
1097 fd = open(path, O_RDONLY);
1098 if (fd == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001099 LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
Michal Vasko662610a2015-12-07 11:25:45 +01001100 return NULL;
1101 }
1102
1103 ret = lys_parse_fd(ctx, fd, format);
1104 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001105
Radek Krejcid80c8602016-10-25 11:56:03 +02001106 if (!ret) {
1107 /* error */
1108 return NULL;
1109 }
1110
1111 /* check that name and revision match filename */
1112 filename = strrchr(path, '/');
1113 if (!filename) {
1114 filename = path;
1115 } else {
1116 filename++;
1117 }
1118 rev = strchr(filename, '@');
1119 dot = strrchr(filename, '.');
1120
1121 /* name */
1122 len = strlen(ret->name);
1123 if (strncmp(filename, ret->name, len) ||
1124 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001125 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +02001126 }
1127 if (rev) {
1128 len = dot - ++rev;
1129 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001130 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
Radek Krejcid80c8602016-10-25 11:56:03 +02001131 ret->rev_size ? ret->rev[0].date : "none");
1132 }
1133 }
1134
1135 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001136 /* store URI */
Alexandre Snarskii12b22182018-09-04 17:12:28 +03001137 char rpath[PATH_MAX];
1138 if (realpath(path, rpath) != NULL) {
1139 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, rpath, 0);
1140 } else {
1141 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
1142 }
Radek Krejci23f5de52016-02-25 15:53:17 +01001143 }
1144
Michal Vasko662610a2015-12-07 11:25:45 +01001145 return ret;
1146}
1147
1148API const struct lys_module *
1149lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001150{
Michal Vaskofb98dc42018-01-11 13:38:28 +01001151 return lys_parse_fd_(ctx, fd, format, NULL, 1);
1152}
1153
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001154static void
1155lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
1156{
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001157#ifdef __APPLE__
1158 char path[MAXPATHLEN];
1159#else
Michal Vasko25601f32018-02-16 09:41:46 +01001160 int len;
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001161 char path[PATH_MAX], proc_path[32];
1162#endif
1163
1164#ifdef __APPLE__
1165 if (fcntl(fd, F_GETPATH, path) != -1) {
1166 *filename = lydict_insert(ctx, path, 0);
1167 }
1168#else
1169 /* get URI if there is /proc */
1170 sprintf(proc_path, "/proc/self/fd/%d", fd);
1171 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
1172 *filename = lydict_insert(ctx, path, len);
1173 }
1174#endif
1175}
1176
Michal Vaskofb98dc42018-01-11 13:38:28 +01001177const struct lys_module *
1178lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, const char *revision, int implement)
1179{
Michal Vasko1e62a092015-12-01 12:27:20 +01001180 const struct lys_module *module;
Radek Krejci0fb11502017-01-31 16:45:42 +01001181 size_t length;
Radek Krejci63a91a92015-07-29 13:31:04 +02001182 char *addr;
1183
1184 if (!ctx || fd < 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001185 LOGARG;
Radek Krejci63a91a92015-07-29 13:31:04 +02001186 return NULL;
1187 }
1188
Michal Vasko53b7da02018-02-13 15:28:42 +01001189 if (lyp_mmap(ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1190 LOGERR(ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001191 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001192 } else if (!addr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001193 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
Pavol Vicane36ea262015-11-12 11:57:47 +01001194 return NULL;
1195 }
Radek Krejci0fb11502017-01-31 16:45:42 +01001196
Michal Vaskofb98dc42018-01-11 13:38:28 +01001197 module = lys_parse_mem_(ctx, addr, format, revision, 1, implement);
Radek Krejci0fb11502017-01-31 16:45:42 +01001198 lyp_munmap(addr, length);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001199
Radek Krejcia77904e2016-02-25 16:23:45 +01001200 if (module && !module->filepath) {
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001201 lys_parse_set_filename(ctx, (const char **)&module->filepath, fd);
Radek Krejcib051f722016-02-25 15:12:21 +01001202 }
1203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001204 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001205}
1206
Michal Vasko5a721fd2016-02-16 12:16:48 +01001207struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001208lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001209{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001210 struct lys_submodule *submodule;
Radek Krejci0fb11502017-01-31 16:45:42 +01001211 size_t length;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001212 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001214 assert(module);
1215 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001216
Michal Vasko53b7da02018-02-13 15:28:42 +01001217 if (lyp_mmap(module->ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1218 LOGERR(module->ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001219 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001220 } else if (!addr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001221 LOGERR(module->ctx, LY_EINVAL, "Empty submodule schema file.");
Michal Vasko2e7241e2016-02-15 16:06:34 +01001222 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001223 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001224
Michal Vasko5b998712017-01-26 10:34:06 +01001225 /* get the main module */
1226 module = lys_main_module(module);
1227
1228 switch (format) {
1229 case LYS_IN_YIN:
1230 submodule = yin_read_submodule(module, addr, unres);
1231 break;
1232 case LYS_IN_YANG:
1233 submodule = yang_read_submodule(module, addr, 0, unres);
1234 break;
1235 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001236 LOGINT(module->ctx);
Michal Vasko85d41522017-02-24 09:49:16 +01001237 return NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001238 }
1239
Radek Krejcic645a3a2017-01-31 16:59:00 +01001240 lyp_munmap(addr, length);
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001241
1242 if (submodule && !submodule->filepath) {
1243 lys_parse_set_filename(module->ctx, (const char **)&submodule->filepath, fd);
1244 }
1245
Michal Vasko5a721fd2016-02-16 12:16:48 +01001246 return submodule;
1247
Radek Krejciefaeba32015-05-27 14:30:57 +02001248}
1249
Radek Krejci72cdfac2018-08-15 14:47:33 +02001250API int
Radek Krejcicf3b7ca2018-08-17 09:55:06 +02001251lys_search_localfile(const char * const *searchpaths, int cwd, const char *name, const char *revision, char **localfile, LYS_INFORMAT *format)
Radek Krejci72cdfac2018-08-15 14:47:33 +02001252{
1253 size_t len, flen, match_len = 0, dir_len;
1254 int i, implicit_cwd = 0, ret = EXIT_FAILURE;
1255 char *wd, *wn = NULL;
1256 DIR *dir = NULL;
1257 struct dirent *file;
1258 char *match_name = NULL;
1259 LYS_INFORMAT format_aux, match_format = 0;
1260 unsigned int u;
1261 struct ly_set *dirs;
1262 struct stat st;
1263
1264 if (!localfile) {
1265 LOGARG;
1266 return EXIT_FAILURE;
1267 }
1268
1269 /* start to fill the dir fifo with the context's search path (if set)
1270 * and the current working directory */
1271 dirs = ly_set_new();
1272 if (!dirs) {
1273 LOGMEM(NULL);
1274 return EXIT_FAILURE;
1275 }
1276
1277 len = strlen(name);
Radek Krejcicf3b7ca2018-08-17 09:55:06 +02001278 if (cwd) {
1279 wd = get_current_dir_name();
1280 if (!wd) {
1281 LOGMEM(NULL);
Radek Krejci72cdfac2018-08-15 14:47:33 +02001282 goto cleanup;
Radek Krejcicf3b7ca2018-08-17 09:55:06 +02001283 } else {
1284 /* add implicit current working directory (./) to be searched,
1285 * this directory is not searched recursively */
1286 if (ly_set_add(dirs, wd, 0) == -1) {
1287 goto cleanup;
1288 }
1289 implicit_cwd = 1;
Radek Krejci72cdfac2018-08-15 14:47:33 +02001290 }
Radek Krejci72cdfac2018-08-15 14:47:33 +02001291 }
1292 if (searchpaths) {
1293 for (i = 0; searchpaths[i]; i++) {
1294 /* check for duplicities with the implicit current working directory */
1295 if (implicit_cwd && !strcmp(dirs->set.g[0], searchpaths[i])) {
1296 implicit_cwd = 0;
1297 continue;
1298 }
1299 wd = strdup(searchpaths[i]);
1300 if (!wd) {
1301 LOGMEM(NULL);
1302 goto cleanup;
1303 } else if (ly_set_add(dirs, wd, 0) == -1) {
1304 goto cleanup;
1305 }
1306 }
1307 }
1308 wd = NULL;
1309
1310 /* start searching */
1311 while (dirs->number) {
1312 free(wd);
1313 free(wn); wn = NULL;
1314
1315 dirs->number--;
1316 wd = (char *)dirs->set.g[dirs->number];
1317 dirs->set.g[dirs->number] = NULL;
1318 LOGVRB("Searching for \"%s\" in %s.", name, wd);
1319
1320 if (dir) {
1321 closedir(dir);
1322 }
1323 dir = opendir(wd);
1324 dir_len = strlen(wd);
1325 if (!dir) {
1326 LOGWRN(NULL, "Unable to open directory \"%s\" for searching (sub)modules (%s).", wd, strerror(errno));
1327 } else {
1328 while ((file = readdir(dir))) {
1329 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
1330 /* skip . and .. */
1331 continue;
1332 }
1333 free(wn);
1334 if (asprintf(&wn, "%s/%s", wd, file->d_name) == -1) {
1335 LOGMEM(NULL);
1336 goto cleanup;
1337 }
1338 if (stat(wn, &st) == -1) {
1339 LOGWRN(NULL, "Unable to get information about \"%s\" file in \"%s\" when searching for (sub)modules (%s)",
1340 file->d_name, wd, strerror(errno));
1341 continue;
1342 }
1343 if (S_ISDIR(st.st_mode) && (dirs->number || !implicit_cwd)) {
1344 /* we have another subdirectory in searchpath to explore,
1345 * subdirectories are not taken into account in current working dir (dirs->set.g[0]) */
1346 if (ly_set_add(dirs, wn, 0) == -1) {
1347 goto cleanup;
1348 }
1349 /* continue with the next item in current directory */
1350 wn = NULL;
1351 continue;
1352 } else if (!S_ISREG(st.st_mode)) {
1353 /* not a regular file (note that we see the target of symlinks instead of symlinks */
1354 continue;
1355 }
1356
1357 /* here we know that the item is a file which can contain a module */
1358 if (strncmp(name, file->d_name, len) ||
1359 (file->d_name[len] != '.' && file->d_name[len] != '@')) {
1360 /* different filename than the module we search for */
1361 continue;
1362 }
1363
1364 /* get type according to filename suffix */
1365 flen = strlen(file->d_name);
1366 if (!strcmp(&file->d_name[flen - 4], ".yin")) {
1367 format_aux = LYS_IN_YIN;
1368 } else if (!strcmp(&file->d_name[flen - 5], ".yang")) {
1369 format_aux = LYS_IN_YANG;
1370 } else {
1371 /* not supportde suffix/file format */
1372 continue;
1373 }
1374
1375 if (revision) {
1376 /* we look for the specific revision, try to get it from the filename */
1377 if (file->d_name[len] == '@') {
1378 /* check revision from the filename */
1379 if (strncmp(revision, &file->d_name[len + 1], strlen(revision))) {
1380 /* another revision */
1381 continue;
1382 } else {
1383 /* exact revision */
1384 free(match_name);
1385 match_name = wn;
1386 wn = NULL;
1387 match_len = dir_len + 1 + len;
1388 match_format = format_aux;
1389 goto success;
1390 }
1391 } else {
1392 /* continue trying to find exact revision match, use this only if not found */
1393 free(match_name);
1394 match_name = wn;
1395 wn = NULL;
1396 match_len = dir_len + 1 +len;
1397 match_format = format_aux;
1398 continue;
1399 }
1400 } else {
1401 /* remember the revision and try to find the newest one */
1402 if (match_name) {
1403 if (file->d_name[len] != '@' || lyp_check_date(NULL, &file->d_name[len + 1])) {
1404 continue;
1405 } else if (match_name[match_len] == '@' &&
1406 (strncmp(&match_name[match_len + 1], &file->d_name[len + 1], LY_REV_SIZE - 1) >= 0)) {
1407 continue;
1408 }
1409 free(match_name);
1410 }
1411
1412 match_name = wn;
1413 wn = NULL;
1414 match_len = dir_len + 1 + len;
1415 match_format = format_aux;
1416 continue;
1417 }
1418 }
1419 }
1420 }
1421
1422success:
1423 (*localfile) = match_name;
1424 match_name = NULL;
1425 if (format) {
1426 (*format) = match_format;
1427 }
1428 ret = EXIT_SUCCESS;
1429
1430cleanup:
1431 free(wn);
1432 free(wd);
1433 if (dir) {
1434 closedir(dir);
1435 }
1436 free(match_name);
1437 for (u = 0; u < dirs->number; u++) {
1438 free(dirs->set.g[u]);
1439 }
1440 ly_set_free(dirs);
1441
1442 return ret;
1443}
1444
Radek Krejcibf285832017-01-26 16:05:41 +01001445int
1446lys_ext_iter(struct lys_ext_instance **ext, uint8_t ext_size, uint8_t start, LYEXT_SUBSTMT substmt)
1447{
1448 unsigned int u;
1449
1450 for (u = start; u < ext_size; u++) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001451 if (ext[u]->insubstmt == substmt) {
Radek Krejcibf285832017-01-26 16:05:41 +01001452 return u;
1453 }
1454 }
1455
1456 return -1;
1457}
1458
Radek Krejcifdc0d702017-01-23 15:58:38 +01001459/*
1460 * duplicate extension instance
1461 */
1462int
Michal Vasko17e8ba32018-02-15 10:58:56 +01001463lys_ext_dup(struct ly_ctx *ctx, struct lys_module *mod, struct lys_ext_instance **orig, uint8_t size, void *parent,
1464 LYEXT_PAR parent_type, struct lys_ext_instance ***new, int shallow, struct unres_schema *unres)
Radek Krejcifdc0d702017-01-23 15:58:38 +01001465{
1466 int i;
1467 uint8_t u = 0;
1468 struct lys_ext_instance **result;
1469 struct unres_ext *info, *info_orig;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001470 size_t len;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001471
1472 assert(new);
1473
1474 if (!size) {
1475 if (orig) {
Michal Vasko17e8ba32018-02-15 10:58:56 +01001476 LOGINT(ctx);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001477 return EXIT_FAILURE;
1478 }
1479 (*new) = NULL;
1480 return EXIT_SUCCESS;
1481 }
1482
1483 (*new) = result = calloc(size, sizeof *result);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001484 LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001485 for (u = 0; u < size; u++) {
1486 if (orig[u]) {
1487 /* resolved extension instance, just duplicate it */
Radek Krejci8de8f612017-02-16 15:03:32 +01001488 switch(orig[u]->ext_type) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001489 case LYEXT_FLAG:
1490 result[u] = malloc(sizeof(struct lys_ext_instance));
Michal Vasko17e8ba32018-02-15 10:58:56 +01001491 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001492 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001493 case LYEXT_COMPLEX:
fanchanghu8d86f6b2017-06-10 12:49:54 +08001494 len = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->instance_size;
1495 result[u] = calloc(1, len);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001496 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001497
Radek Krejcifebdad72017-02-06 11:35:51 +01001498 ((struct lys_ext_instance_complex*)result[u])->substmt = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001499 /* TODO duplicate data in extension instance content */
fanchanghu8d86f6b2017-06-10 12:49:54 +08001500 memcpy((void*)result[u] + sizeof(**orig), (void*)orig[u] + sizeof(**orig), len - sizeof(**orig));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001501 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001502 }
1503 /* generic part */
1504 result[u]->def = orig[u]->def;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001505 result[u]->flags = LYEXT_OPT_CONTENT;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001506 result[u]->arg_value = lydict_insert(ctx, orig[u]->arg_value, 0);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001507 result[u]->parent = parent;
1508 result[u]->parent_type = parent_type;
Radek Krejcifebdad72017-02-06 11:35:51 +01001509 result[u]->insubstmt = orig[u]->insubstmt;
1510 result[u]->insubstmt_index = orig[u]->insubstmt_index;
Radek Krejci8de8f612017-02-16 15:03:32 +01001511 result[u]->ext_type = orig[u]->ext_type;
Radek Krejci7f1d47e2017-04-12 15:29:02 +02001512 result[u]->priv = NULL;
1513 result[u]->nodetype = LYS_EXT;
1514 result[u]->module = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001515
1516 /* extensions */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001517 result[u]->ext_size = orig[u]->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001518 if (lys_ext_dup(ctx, mod, orig[u]->ext, orig[u]->ext_size, result[u],
Radek Krejci5138e9f2017-04-12 13:10:46 +02001519 LYEXT_PAR_EXTINST, &result[u]->ext, shallow, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001520 goto error;
1521 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001522
1523 /* in case of shallow copy (duplication for deviation), duplicate only the link to private data
1524 * in a new copy, otherwise (grouping instantiation) do not duplicate the private data */
1525 if (shallow) {
1526 result[u]->priv = orig[u]->priv;
1527 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01001528 } else {
1529 /* original extension is not yet resolved, so duplicate it in unres */
1530 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1531 if (i == -1) {
1532 /* extension not found in unres */
Michal Vasko17e8ba32018-02-15 10:58:56 +01001533 LOGINT(ctx);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001534 goto error;
1535 }
1536 info_orig = unres->str_snode[i];
1537 info = malloc(sizeof *info);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001538 LY_CHECK_ERR_GOTO(!info, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001539 info->datatype = info_orig->datatype;
1540 if (info->datatype == LYS_IN_YIN) {
Michal Vasko17e8ba32018-02-15 10:58:56 +01001541 info->data.yin = lyxml_dup_elem(ctx, info_orig->data.yin, NULL, 1);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001542 } /* else TODO YANG */
1543 info->parent = parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001544 info->mod = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001545 info->parent_type = parent_type;
1546 info->ext_index = u;
1547 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1548 goto error;
1549 }
1550 }
1551 }
1552
1553 return EXIT_SUCCESS;
1554
1555error:
1556 (*new) = NULL;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001557 lys_extension_instances_free(ctx, result, u, NULL);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001558 return EXIT_FAILURE;
1559}
1560
Radek Krejci1d82ef62015-08-07 14:44:40 +02001561static struct lys_restr *
Radek Krejci5138e9f2017-04-12 13:10:46 +02001562lys_restr_dup(struct lys_module *mod, struct lys_restr *old, int size, int shallow, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001563{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001564 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001565 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001566
Radek Krejci3733a802015-06-19 13:43:21 +02001567 if (!size) {
1568 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001569 }
Radek Krejci3733a802015-06-19 13:43:21 +02001570
1571 result = calloc(size, sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +01001572 LY_CHECK_ERR_RETURN(!result, LOGMEM(mod->ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001573
Radek Krejci3733a802015-06-19 13:43:21 +02001574 for (i = 0; i < size; i++) {
Radek Krejci77f22b22017-01-17 15:23:03 +01001575 result[i].ext_size = old[i].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001576 lys_ext_dup(mod->ctx, mod, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_RESTR, &result[i].ext, shallow, unres);
Radek Krejci8d6b7422017-02-03 14:42:13 +01001577 result[i].expr = lydict_insert(mod->ctx, old[i].expr, 0);
1578 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1579 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1580 result[i].eapptag = lydict_insert(mod->ctx, old[i].eapptag, 0);
1581 result[i].emsg = lydict_insert(mod->ctx, old[i].emsg, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001582 }
1583
1584 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001585}
1586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001588lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr,
1589 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci0bd5db42015-06-19 13:30:07 +02001590{
1591 assert(ctx);
1592 if (!restr) {
1593 return;
1594 }
1595
Radek Krejci5138e9f2017-04-12 13:10:46 +02001596 lys_extension_instances_free(ctx, restr->ext, restr->ext_size, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001597 lydict_remove(ctx, restr->expr);
1598 lydict_remove(ctx, restr->dsc);
1599 lydict_remove(ctx, restr->ref);
1600 lydict_remove(ctx, restr->eapptag);
1601 lydict_remove(ctx, restr->emsg);
1602}
1603
Pavol Vican05810b62016-11-23 14:07:22 +01001604void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001605lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size,
Frank Rimplerc4db1c72017-09-12 12:56:39 +00001606 int shallow, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001607{
1608 uint8_t i;
1609
1610 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001611 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size, private_destructor);
Michal Vasko15a43372017-09-25 14:12:42 +02001612 if (!shallow) {
Frank Rimpler2a503f52017-09-12 15:21:18 +00001613 free(iffeature[i].expr);
1614 free(iffeature[i].features);
1615 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001616 }
1617 free(iffeature);
1618}
1619
Michal Vaskob84f88a2015-09-24 13:16:10 +02001620static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001621type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001622 LY_DATA_TYPE base, int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001623{
1624 int i;
Radek Krejcidce5f972017-09-12 15:47:49 +02001625 unsigned int u;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001626
1627 switch (base) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001628 case LY_TYPE_BINARY:
1629 if (old->info.binary.length) {
1630 new->info.binary.length = lys_restr_dup(mod, old->info.binary.length, 1, shallow, unres);
1631 }
1632 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001633
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001634 case LY_TYPE_BITS:
1635 new->info.bits.count = old->info.bits.count;
1636 if (new->info.bits.count) {
1637 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko53b7da02018-02-13 15:28:42 +01001638 LY_CHECK_ERR_RETURN(!new->info.bits.bit, LOGMEM(mod->ctx), -1);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001639
Radek Krejcidce5f972017-09-12 15:47:49 +02001640 for (u = 0; u < new->info.bits.count; u++) {
1641 new->info.bits.bit[u].name = lydict_insert(mod->ctx, old->info.bits.bit[u].name, 0);
1642 new->info.bits.bit[u].dsc = lydict_insert(mod->ctx, old->info.bits.bit[u].dsc, 0);
1643 new->info.bits.bit[u].ref = lydict_insert(mod->ctx, old->info.bits.bit[u].ref, 0);
1644 new->info.bits.bit[u].flags = old->info.bits.bit[u].flags;
1645 new->info.bits.bit[u].pos = old->info.bits.bit[u].pos;
1646 new->info.bits.bit[u].ext_size = old->info.bits.bit[u].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001647 if (lys_ext_dup(mod->ctx, mod, old->info.bits.bit[u].ext, old->info.bits.bit[u].ext_size,
Radek Krejcidce5f972017-09-12 15:47:49 +02001648 &new->info.bits.bit[u], LYEXT_PAR_TYPE_BIT,
1649 &new->info.bits.bit[u].ext, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001650 return -1;
1651 }
1652 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001653 }
1654 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001655
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001656 case LY_TYPE_DEC64:
1657 new->info.dec64.dig = old->info.dec64.dig;
1658 new->info.dec64.div = old->info.dec64.div;
1659 if (old->info.dec64.range) {
1660 new->info.dec64.range = lys_restr_dup(mod, old->info.dec64.range, 1, shallow, unres);
1661 }
1662 break;
1663
1664 case LY_TYPE_ENUM:
1665 new->info.enums.count = old->info.enums.count;
1666 if (new->info.enums.count) {
1667 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko53b7da02018-02-13 15:28:42 +01001668 LY_CHECK_ERR_RETURN(!new->info.enums.enm, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001669
Radek Krejcidce5f972017-09-12 15:47:49 +02001670 for (u = 0; u < new->info.enums.count; u++) {
1671 new->info.enums.enm[u].name = lydict_insert(mod->ctx, old->info.enums.enm[u].name, 0);
1672 new->info.enums.enm[u].dsc = lydict_insert(mod->ctx, old->info.enums.enm[u].dsc, 0);
1673 new->info.enums.enm[u].ref = lydict_insert(mod->ctx, old->info.enums.enm[u].ref, 0);
1674 new->info.enums.enm[u].flags = old->info.enums.enm[u].flags;
1675 new->info.enums.enm[u].value = old->info.enums.enm[u].value;
1676 new->info.enums.enm[u].ext_size = old->info.enums.enm[u].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001677 if (lys_ext_dup(mod->ctx, mod, old->info.enums.enm[u].ext, old->info.enums.enm[u].ext_size,
Radek Krejcidce5f972017-09-12 15:47:49 +02001678 &new->info.enums.enm[u], LYEXT_PAR_TYPE_ENUM,
1679 &new->info.enums.enm[u].ext, shallow, unres)) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001680 return -1;
1681 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001682 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001683 }
1684 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001685
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001686 case LY_TYPE_IDENT:
1687 new->info.ident.count = old->info.ident.count;
1688 if (old->info.ident.count) {
1689 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
Michal Vasko53b7da02018-02-13 15:28:42 +01001690 LY_CHECK_ERR_RETURN(!new->info.ident.ref, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001691 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1692 } else {
1693 /* there can be several unresolved base identities, duplicate them all */
1694 i = -1;
1695 do {
1696 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1697 if (i != -1) {
1698 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001699 return -1;
1700 }
1701 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001702 --i;
1703 } while (i > -1);
1704 }
1705 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001706
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001707 case LY_TYPE_INST:
1708 new->info.inst.req = old->info.inst.req;
1709 break;
1710
1711 case LY_TYPE_INT8:
1712 case LY_TYPE_INT16:
1713 case LY_TYPE_INT32:
1714 case LY_TYPE_INT64:
1715 case LY_TYPE_UINT8:
1716 case LY_TYPE_UINT16:
1717 case LY_TYPE_UINT32:
1718 case LY_TYPE_UINT64:
1719 if (old->info.num.range) {
1720 new->info.num.range = lys_restr_dup(mod, old->info.num.range, 1, shallow, unres);
1721 }
1722 break;
1723
1724 case LY_TYPE_LEAFREF:
1725 if (old->info.lref.path) {
1726 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1727 if (!in_grp && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
1728 return -1;
1729 }
1730 }
1731 break;
1732
1733 case LY_TYPE_STRING:
1734 if (old->info.str.length) {
1735 new->info.str.length = lys_restr_dup(mod, old->info.str.length, 1, shallow, unres);
1736 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001737 if (old->info.str.pat_count) {
1738 new->info.str.patterns = lys_restr_dup(mod, old->info.str.patterns, old->info.str.pat_count, shallow, unres);
1739 new->info.str.pat_count = old->info.str.pat_count;
Michal Vaskofcd974b2017-08-22 10:17:49 +02001740#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001741 if (!in_grp) {
1742 new->info.str.patterns_pcre = malloc(new->info.str.pat_count * 2 * sizeof *new->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001743 LY_CHECK_ERR_RETURN(!new->info.str.patterns_pcre, LOGMEM(mod->ctx), -1);
Radek Krejcia4c107d2017-10-27 14:19:26 +02001744 for (u = 0; u < new->info.str.pat_count; u++) {
Michal Vaskoa26db302018-02-14 15:22:10 +01001745 if (lyp_precompile_pattern(mod->ctx, &new->info.str.patterns[u].expr[1],
Radek Krejcia4c107d2017-10-27 14:19:26 +02001746 (pcre**)&new->info.str.patterns_pcre[2 * u],
1747 (pcre_extra**)&new->info.str.patterns_pcre[2 * u + 1])) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001748 free(new->info.str.patterns_pcre);
1749 new->info.str.patterns_pcre = NULL;
1750 return -1;
1751 }
1752 }
1753 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001754#endif
Radek Krejcib53154b2017-07-19 09:14:13 +02001755 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001756 break;
1757
1758 case LY_TYPE_UNION:
1759 new->info.uni.has_ptr_type = old->info.uni.has_ptr_type;
1760 new->info.uni.count = old->info.uni.count;
1761 if (new->info.uni.count) {
1762 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001763 LY_CHECK_ERR_RETURN(!new->info.uni.types, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001764
Radek Krejcidce5f972017-09-12 15:47:49 +02001765 for (u = 0; u < new->info.uni.count; u++) {
1766 if (lys_type_dup(mod, parent, &(new->info.uni.types[u]), &(old->info.uni.types[u]), in_grp,
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001767 shallow, unres)) {
1768 return -1;
1769 }
1770 }
1771 }
1772 break;
1773
1774 default:
1775 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1776 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001777 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001778
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001779 return EXIT_SUCCESS;
1780}
1781
1782struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001783lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
Radek Krejci5138e9f2017-04-12 13:10:46 +02001784 int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001785{
1786 struct yang_type *new;
1787
1788 new = calloc(1, sizeof *new);
Michal Vasko53b7da02018-02-13 15:28:42 +01001789 LY_CHECK_ERR_RETURN(!new, LOGMEM(module->ctx), NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001790 new->flags = old->flags;
1791 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001792 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001793 new->type = type;
1794 if (!new->name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001795 LOGMEM(module->ctx);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001796 goto error;
1797 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001798 if (type_dup(module, parent, type, old->type, new->base, in_grp, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001799 new->type->base = new->base;
Radek Krejci5138e9f2017-04-12 13:10:46 +02001800 lys_type_free(module->ctx, new->type, NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001801 memset(&new->type->info, 0, sizeof new->type->info);
1802 goto error;
1803 }
1804 return new;
1805
Michal Vasko53b7da02018-02-13 15:28:42 +01001806error:
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001807 free(new);
1808 return NULL;
1809}
1810
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001811int
1812lys_copy_union_leafrefs(struct lys_module *mod, struct lys_node *parent, struct lys_type *type, struct lys_type *prev_new,
1813 struct unres_schema *unres)
1814{
1815 struct lys_type new;
Radek Krejcidce5f972017-09-12 15:47:49 +02001816 unsigned int i, top_type;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001817 struct lys_ext_instance **ext;
1818 uint8_t ext_size;
1819 void *reloc;
1820
1821 if (!prev_new) {
1822 /* this is the "top-level" type, meaning it is a real type and no typedef directly above */
1823 top_type = 1;
1824
1825 memset(&new, 0, sizeof new);
1826
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001827 new.base = type->base;
1828 new.parent = (struct lys_tpdf *)parent;
1829
1830 prev_new = &new;
1831 } else {
1832 /* this is not top-level type, just a type of a typedef */
1833 top_type = 0;
1834 }
1835
Radek Krejci9c5cb6d2017-08-09 11:15:23 +02001836 assert(type->der);
1837 if (type->der->module) {
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001838 /* typedef, skip it, but keep the extensions */
1839 ext_size = type->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001840 if (lys_ext_dup(mod->ctx, mod, type->ext, type->ext_size, prev_new, LYEXT_PAR_TYPE, &ext, 0, unres)) {
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001841 return -1;
1842 }
1843 if (prev_new->ext) {
1844 reloc = realloc(prev_new->ext, (prev_new->ext_size + ext_size) * sizeof *prev_new->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001845 LY_CHECK_ERR_RETURN(!reloc, LOGMEM(mod->ctx), -1);
Radek Krejci70379e22017-08-09 11:21:07 +02001846 prev_new->ext = reloc;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001847
1848 memcpy(prev_new->ext + prev_new->ext_size, ext, ext_size * sizeof *ext);
1849 free(ext);
1850
1851 prev_new->ext_size += ext_size;
1852 } else {
1853 prev_new->ext = ext;
1854 prev_new->ext_size = ext_size;
1855 }
1856
1857 if (lys_copy_union_leafrefs(mod, parent, &type->der->type, prev_new, unres)) {
1858 return -1;
1859 }
1860 } else {
1861 /* type, just make a deep copy */
1862 switch (type->base) {
1863 case LY_TYPE_UNION:
1864 prev_new->info.uni.has_ptr_type = type->info.uni.has_ptr_type;
1865 prev_new->info.uni.count = type->info.uni.count;
1866 /* this cannot be a typedef anymore */
1867 assert(prev_new->info.uni.count);
1868
1869 prev_new->info.uni.types = calloc(prev_new->info.uni.count, sizeof *prev_new->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001870 LY_CHECK_ERR_RETURN(!prev_new->info.uni.types, LOGMEM(mod->ctx), -1);
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001871
1872 for (i = 0; i < prev_new->info.uni.count; i++) {
1873 if (lys_copy_union_leafrefs(mod, parent, &(type->info.uni.types[i]), &(prev_new->info.uni.types[i]), unres)) {
1874 return -1;
1875 }
1876 }
1877
1878 prev_new->der = type->der;
1879 break;
1880 default:
1881 if (lys_type_dup(mod, parent, prev_new, type, 0, 0, unres)) {
1882 return -1;
1883 }
1884 break;
1885 }
1886 }
1887
1888 if (top_type) {
1889 memcpy(type, prev_new, sizeof *type);
1890 }
1891 return EXIT_SUCCESS;
1892}
1893
Radek Krejci43ce4b72017-01-04 11:02:38 +01001894API const void *
1895lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1896{
1897 if (!ext) {
1898 return NULL;
1899 }
1900
Radek Krejcifebdad72017-02-06 11:35:51 +01001901 switch (ext->insubstmt) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001902 case LYEXT_SUBSTMT_SELF:
1903 case LYEXT_SUBSTMT_MODIFIER:
1904 case LYEXT_SUBSTMT_VERSION:
1905 return NULL;
1906 case LYEXT_SUBSTMT_ARGUMENT:
1907 if (ext->parent_type == LYEXT_PAR_EXT) {
1908 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1909 }
1910 break;
1911 case LYEXT_SUBSTMT_BASE:
1912 if (ext->parent_type == LYEXT_PAR_TYPE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001913 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001914 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001915 return ((struct lys_ident*)ext->parent)->base[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001916 }
1917 break;
1918 case LYEXT_SUBSTMT_BELONGSTO:
1919 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1920 return ((struct lys_submodule*)ext->parent)->belongsto;
1921 }
1922 break;
1923 case LYEXT_SUBSTMT_CONFIG:
1924 case LYEXT_SUBSTMT_MANDATORY:
1925 if (ext->parent_type == LYEXT_PAR_NODE) {
1926 return &((struct lys_node*)ext->parent)->flags;
1927 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1928 return &((struct lys_deviate*)ext->parent)->flags;
1929 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1930 return &((struct lys_refine*)ext->parent)->flags;
1931 }
1932 break;
1933 case LYEXT_SUBSTMT_CONTACT:
1934 if (ext->parent_type == LYEXT_PAR_MODULE) {
1935 return ((struct lys_module*)ext->parent)->contact;
1936 }
1937 break;
1938 case LYEXT_SUBSTMT_DEFAULT:
1939 if (ext->parent_type == LYEXT_PAR_NODE) {
1940 switch (((struct lys_node*)ext->parent)->nodetype) {
1941 case LYS_LEAF:
1942 case LYS_LEAFLIST:
1943 /* in case of leaf, the index is supposed to be 0, so it will return the
1944 * correct pointer despite the leaf structure does not have dflt as array */
Radek Krejcifebdad72017-02-06 11:35:51 +01001945 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001946 case LYS_CHOICE:
1947 return ((struct lys_node_choice*)ext->parent)->dflt;
1948 default:
1949 /* internal error */
1950 break;
1951 }
1952 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1953 return ((struct lys_tpdf*)ext->parent)->dflt;
1954 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001955 return ((struct lys_deviate*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001956 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001957 return &((struct lys_refine*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001958 }
1959 break;
1960 case LYEXT_SUBSTMT_DESCRIPTION:
1961 switch (ext->parent_type) {
1962 case LYEXT_PAR_NODE:
1963 return ((struct lys_node*)ext->parent)->dsc;
1964 case LYEXT_PAR_MODULE:
1965 return ((struct lys_module*)ext->parent)->dsc;
1966 case LYEXT_PAR_IMPORT:
1967 return ((struct lys_import*)ext->parent)->dsc;
1968 case LYEXT_PAR_INCLUDE:
1969 return ((struct lys_include*)ext->parent)->dsc;
1970 case LYEXT_PAR_EXT:
1971 return ((struct lys_ext*)ext->parent)->dsc;
1972 case LYEXT_PAR_FEATURE:
1973 return ((struct lys_feature*)ext->parent)->dsc;
1974 case LYEXT_PAR_TPDF:
1975 return ((struct lys_tpdf*)ext->parent)->dsc;
1976 case LYEXT_PAR_TYPE_BIT:
1977 return ((struct lys_type_bit*)ext->parent)->dsc;
1978 case LYEXT_PAR_TYPE_ENUM:
1979 return ((struct lys_type_enum*)ext->parent)->dsc;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001980 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001981 return ((struct lys_restr*)ext->parent)->dsc;
1982 case LYEXT_PAR_WHEN:
1983 return ((struct lys_when*)ext->parent)->dsc;
1984 case LYEXT_PAR_IDENT:
1985 return ((struct lys_ident*)ext->parent)->dsc;
1986 case LYEXT_PAR_DEVIATION:
1987 return ((struct lys_deviation*)ext->parent)->dsc;
1988 case LYEXT_PAR_REVISION:
1989 return ((struct lys_revision*)ext->parent)->dsc;
1990 case LYEXT_PAR_REFINE:
1991 return ((struct lys_refine*)ext->parent)->dsc;
1992 default:
1993 break;
1994 }
1995 break;
1996 case LYEXT_SUBSTMT_ERRTAG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001997 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001998 return ((struct lys_restr*)ext->parent)->eapptag;
1999 }
2000 break;
2001 case LYEXT_SUBSTMT_ERRMSG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01002002 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01002003 return ((struct lys_restr*)ext->parent)->emsg;
2004 }
2005 break;
2006 case LYEXT_SUBSTMT_DIGITS:
2007 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
2008 return &((struct lys_type*)ext->parent)->info.dec64.dig;
2009 }
2010 break;
2011 case LYEXT_SUBSTMT_KEY:
2012 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2013 return ((struct lys_node_list*)ext->parent)->keys;
2014 }
2015 break;
2016 case LYEXT_SUBSTMT_MAX:
2017 if (ext->parent_type == LYEXT_PAR_NODE) {
2018 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2019 return &((struct lys_node_list*)ext->parent)->max;
2020 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
2021 return &((struct lys_node_leaflist*)ext->parent)->max;
2022 }
2023 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2024 return &((struct lys_refine*)ext->parent)->mod.list.max;
2025 }
2026 break;
2027 case LYEXT_SUBSTMT_MIN:
2028 if (ext->parent_type == LYEXT_PAR_NODE) {
2029 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2030 return &((struct lys_node_list*)ext->parent)->min;
2031 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
2032 return &((struct lys_node_leaflist*)ext->parent)->min;
2033 }
2034 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2035 return &((struct lys_refine*)ext->parent)->mod.list.min;
2036 }
2037 break;
2038 case LYEXT_SUBSTMT_NAMESPACE:
2039 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
2040 return ((struct lys_module*)ext->parent)->ns;
2041 }
2042 break;
2043 case LYEXT_SUBSTMT_ORDEREDBY:
2044 if (ext->parent_type == LYEXT_PAR_NODE &&
2045 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
2046 return &((struct lys_node_list*)ext->parent)->flags;
2047 }
2048 break;
2049 case LYEXT_SUBSTMT_ORGANIZATION:
2050 if (ext->parent_type == LYEXT_PAR_MODULE) {
2051 return ((struct lys_module*)ext->parent)->org;
2052 }
2053 break;
2054 case LYEXT_SUBSTMT_PATH:
2055 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
2056 return ((struct lys_type*)ext->parent)->info.lref.path;
2057 }
2058 break;
2059 case LYEXT_SUBSTMT_POSITION:
2060 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
2061 return &((struct lys_type_bit*)ext->parent)->pos;
2062 }
2063 break;
2064 case LYEXT_SUBSTMT_PREFIX:
2065 if (ext->parent_type == LYEXT_PAR_MODULE) {
2066 /* covers also lys_submodule */
2067 return ((struct lys_module*)ext->parent)->prefix;
2068 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
2069 return ((struct lys_import*)ext->parent)->prefix;
2070 }
2071 break;
2072 case LYEXT_SUBSTMT_PRESENCE:
2073 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
2074 return ((struct lys_node_container*)ext->parent)->presence;
2075 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2076 return ((struct lys_refine*)ext->parent)->mod.presence;
2077 }
2078 break;
2079 case LYEXT_SUBSTMT_REFERENCE:
2080 switch (ext->parent_type) {
2081 case LYEXT_PAR_NODE:
2082 return ((struct lys_node*)ext->parent)->ref;
2083 case LYEXT_PAR_MODULE:
2084 return ((struct lys_module*)ext->parent)->ref;
2085 case LYEXT_PAR_IMPORT:
2086 return ((struct lys_import*)ext->parent)->ref;
2087 case LYEXT_PAR_INCLUDE:
2088 return ((struct lys_include*)ext->parent)->ref;
2089 case LYEXT_PAR_EXT:
2090 return ((struct lys_ext*)ext->parent)->ref;
2091 case LYEXT_PAR_FEATURE:
2092 return ((struct lys_feature*)ext->parent)->ref;
2093 case LYEXT_PAR_TPDF:
2094 return ((struct lys_tpdf*)ext->parent)->ref;
2095 case LYEXT_PAR_TYPE_BIT:
2096 return ((struct lys_type_bit*)ext->parent)->ref;
2097 case LYEXT_PAR_TYPE_ENUM:
2098 return ((struct lys_type_enum*)ext->parent)->ref;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002099 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01002100 return ((struct lys_restr*)ext->parent)->ref;
2101 case LYEXT_PAR_WHEN:
2102 return ((struct lys_when*)ext->parent)->ref;
2103 case LYEXT_PAR_IDENT:
2104 return ((struct lys_ident*)ext->parent)->ref;
2105 case LYEXT_PAR_DEVIATION:
2106 return ((struct lys_deviation*)ext->parent)->ref;
2107 case LYEXT_PAR_REVISION:
2108 return ((struct lys_revision*)ext->parent)->ref;
2109 case LYEXT_PAR_REFINE:
2110 return ((struct lys_refine*)ext->parent)->ref;
2111 default:
2112 break;
2113 }
2114 break;
Radek Krejcibe336392017-02-07 10:54:24 +01002115 case LYEXT_SUBSTMT_REQINSTANCE:
Radek Krejci43ce4b72017-01-04 11:02:38 +01002116 if (ext->parent_type == LYEXT_PAR_TYPE) {
2117 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
2118 return &((struct lys_type*)ext->parent)->info.lref.req;
2119 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
2120 return &((struct lys_type*)ext->parent)->info.inst.req;
2121 }
2122 }
2123 break;
2124 case LYEXT_SUBSTMT_REVISIONDATE:
2125 if (ext->parent_type == LYEXT_PAR_IMPORT) {
2126 return ((struct lys_import*)ext->parent)->rev;
2127 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
2128 return ((struct lys_include*)ext->parent)->rev;
2129 }
2130 break;
2131 case LYEXT_SUBSTMT_STATUS:
2132 switch (ext->parent_type) {
2133 case LYEXT_PAR_NODE:
2134 case LYEXT_PAR_IDENT:
2135 case LYEXT_PAR_TPDF:
2136 case LYEXT_PAR_EXT:
2137 case LYEXT_PAR_FEATURE:
2138 case LYEXT_PAR_TYPE_ENUM:
2139 case LYEXT_PAR_TYPE_BIT:
2140 /* in all structures the flags member is at the same offset */
2141 return &((struct lys_node*)ext->parent)->flags;
2142 default:
2143 break;
2144 }
2145 break;
2146 case LYEXT_SUBSTMT_UNIQUE:
2147 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01002148 return &((struct lys_deviate*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01002149 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
Radek Krejcifebdad72017-02-06 11:35:51 +01002150 return &((struct lys_node_list*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01002151 }
2152 break;
2153 case LYEXT_SUBSTMT_UNITS:
2154 if (ext->parent_type == LYEXT_PAR_NODE &&
2155 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2156 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
2157 return ((struct lys_node_leaf*)ext->parent)->units;
2158 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
2159 return ((struct lys_tpdf*)ext->parent)->units;
2160 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
2161 return ((struct lys_deviate*)ext->parent)->units;
2162 }
2163 break;
2164 case LYEXT_SUBSTMT_VALUE:
2165 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
2166 return &((struct lys_type_enum*)ext->parent)->value;
2167 }
2168 break;
2169 case LYEXT_SUBSTMT_YINELEM:
2170 if (ext->parent_type == LYEXT_PAR_EXT) {
2171 return &((struct lys_ext*)ext->parent)->flags;
2172 }
2173 break;
2174 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002175 LOGINT(ext->module->ctx);
Radek Krejci43ce4b72017-01-04 11:02:38 +01002176 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01002177}
2178
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02002179static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002180lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002181 int in_grp, int shallow, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02002182{
2183 int i;
2184
Radek Krejci3733a802015-06-19 13:43:21 +02002185 new->base = old->base;
2186 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02002187 new->parent = (struct lys_tpdf *)parent;
Radek Krejcif0bb3602017-01-25 17:05:08 +01002188 new->ext_size = old->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01002189 if (lys_ext_dup(mod->ctx, mod, old->ext, old->ext_size, new, LYEXT_PAR_TYPE, &new->ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002190 return -1;
Radek Krejcie534c132016-11-23 13:32:31 +01002191 }
Radek Krejci3733a802015-06-19 13:43:21 +02002192
Michal Vasko1c007172017-03-10 10:20:44 +01002193 i = unres_schema_find(unres, -1, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002194 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01002195 /* HACK (serious one) for unres */
2196 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02002197 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002198 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, in_grp,
2199 shallow, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02002200 } else {
2201 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
2202 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02002203 /* all these unres additions can fail even though they did not before */
Michal Vasko1c007172017-03-10 10:20:44 +01002204 if (!new->der || (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent) == -1)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002205 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02002206 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02002207 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002208 }
2209
Radek Krejci5138e9f2017-04-12 13:10:46 +02002210 return type_dup(mod, parent, new, old, new->base, in_grp, shallow, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02002211}
2212
2213void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002214lys_type_free(struct ly_ctx *ctx, struct lys_type *type,
2215 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002216{
Radek Krejcidce5f972017-09-12 15:47:49 +02002217 unsigned int i;
Radek Krejci5a065542015-05-22 15:02:07 +02002218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002219 assert(ctx);
2220 if (!type) {
2221 return;
2222 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002223
Radek Krejci5138e9f2017-04-12 13:10:46 +02002224 lys_extension_instances_free(ctx, type->ext, type->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02002227 case LY_TYPE_BINARY:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002228 lys_restr_free(ctx, type->info.binary.length, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02002229 free(type->info.binary.length);
2230 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02002231 case LY_TYPE_BITS:
2232 for (i = 0; i < type->info.bits.count; i++) {
2233 lydict_remove(ctx, type->info.bits.bit[i].name);
2234 lydict_remove(ctx, type->info.bits.bit[i].dsc);
2235 lydict_remove(ctx, type->info.bits.bit[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002236 lys_iffeature_free(ctx, type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size, 0,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002237 private_destructor);
2238 lys_extension_instances_free(ctx, type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size,
2239 private_destructor);
Radek Krejci994b6f62015-06-18 16:47:27 +02002240 }
2241 free(type->info.bits.bit);
2242 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02002243
2244 case LY_TYPE_DEC64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002245 lys_restr_free(ctx, type->info.dec64.range, private_destructor);
Radek Krejcif9401c32015-06-26 16:47:36 +02002246 free(type->info.dec64.range);
2247 break;
2248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 case LY_TYPE_ENUM:
2250 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002251 lydict_remove(ctx, type->info.enums.enm[i].name);
2252 lydict_remove(ctx, type->info.enums.enm[i].dsc);
2253 lydict_remove(ctx, type->info.enums.enm[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002254 lys_iffeature_free(ctx, type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size, 0,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002255 private_destructor);
2256 lys_extension_instances_free(ctx, type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size,
2257 private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02002259 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02002261
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02002262 case LY_TYPE_INT8:
2263 case LY_TYPE_INT16:
2264 case LY_TYPE_INT32:
2265 case LY_TYPE_INT64:
2266 case LY_TYPE_UINT8:
2267 case LY_TYPE_UINT16:
2268 case LY_TYPE_UINT32:
2269 case LY_TYPE_UINT64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002270 lys_restr_free(ctx, type->info.num.range, private_destructor);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02002271 free(type->info.num.range);
2272 break;
2273
Radek Krejcidc4c1412015-06-19 15:39:54 +02002274 case LY_TYPE_LEAFREF:
2275 lydict_remove(ctx, type->info.lref.path);
2276 break;
2277
Radek Krejci3733a802015-06-19 13:43:21 +02002278 case LY_TYPE_STRING:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002279 lys_restr_free(ctx, type->info.str.length, private_destructor);
Radek Krejci3733a802015-06-19 13:43:21 +02002280 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02002281 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002282 lys_restr_free(ctx, &type->info.str.patterns[i], private_destructor);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002283#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002284 if (type->info.str.patterns_pcre) {
2285 pcre_free((pcre*)type->info.str.patterns_pcre[2 * i]);
2286 pcre_free_study((pcre_extra*)type->info.str.patterns_pcre[2 * i + 1]);
2287 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02002288#endif
Radek Krejci5fbc9162015-06-19 14:11:11 +02002289 }
2290 free(type->info.str.patterns);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002291#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002292 free(type->info.str.patterns_pcre);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002293#endif
Radek Krejci3733a802015-06-19 13:43:21 +02002294 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002295
Radek Krejcie4c366b2015-07-02 10:11:31 +02002296 case LY_TYPE_UNION:
2297 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002298 lys_type_free(ctx, &type->info.uni.types[i], private_destructor);
Radek Krejcie4c366b2015-07-02 10:11:31 +02002299 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02002300 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002301 break;
2302
Michal Vaskod3282192016-09-05 11:27:57 +02002303 case LY_TYPE_IDENT:
2304 free(type->info.ident.ref);
2305 break;
2306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 default:
Michal Vaskod3282192016-09-05 11:27:57 +02002308 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002309 break;
2310 }
Radek Krejci5a065542015-05-22 15:02:07 +02002311}
2312
Radek Krejci1d82ef62015-08-07 14:44:40 +02002313static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002314lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf,
2315 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002316{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 assert(ctx);
2318 if (!tpdf) {
2319 return;
2320 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 lydict_remove(ctx, tpdf->name);
2323 lydict_remove(ctx, tpdf->dsc);
2324 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002325
Radek Krejci5138e9f2017-04-12 13:10:46 +02002326 lys_type_free(ctx, &tpdf->type, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002328 lydict_remove(ctx, tpdf->units);
2329 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01002330
Radek Krejci5138e9f2017-04-12 13:10:46 +02002331 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002332}
2333
Radek Krejci1d82ef62015-08-07 14:44:40 +02002334static struct lys_when *
Radek Krejci5138e9f2017-04-12 13:10:46 +02002335lys_when_dup(struct lys_module *mod, struct lys_when *old, int shallow, struct unres_schema *unres)
Radek Krejci00768f42015-06-18 17:04:04 +02002336{
Radek Krejci76512572015-08-04 09:47:08 +02002337 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02002338
2339 if (!old) {
2340 return NULL;
2341 }
2342
2343 new = calloc(1, sizeof *new);
Michal Vasko53b7da02018-02-13 15:28:42 +01002344 LY_CHECK_ERR_RETURN(!new, LOGMEM(mod->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01002345 new->cond = lydict_insert(mod->ctx, old->cond, 0);
2346 new->dsc = lydict_insert(mod->ctx, old->dsc, 0);
2347 new->ref = lydict_insert(mod->ctx, old->ref, 0);
Radek Krejcif0bb3602017-01-25 17:05:08 +01002348 new->ext_size = old->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01002349 lys_ext_dup(mod->ctx, mod, old->ext, old->ext_size, new, LYEXT_PAR_WHEN, &new->ext, shallow, unres);
Radek Krejci00768f42015-06-18 17:04:04 +02002350
2351 return new;
2352}
2353
Michal Vasko0308dd62015-10-07 09:14:40 +02002354void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002355lys_when_free(struct ly_ctx *ctx, struct lys_when *w,
2356 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002357{
2358 if (!w) {
2359 return;
2360 }
2361
Radek Krejci5138e9f2017-04-12 13:10:46 +02002362 lys_extension_instances_free(ctx, w->ext, w->ext_size, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002363 lydict_remove(ctx, w->cond);
2364 lydict_remove(ctx, w->dsc);
2365 lydict_remove(ctx, w->ref);
2366
2367 free(w);
2368}
2369
Radek Krejcib7f5e412015-08-13 10:15:51 +02002370static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002371lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug,
2372 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02002373{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002374 struct lys_node *next, *sub;
2375
Radek Krejcic071c542016-01-27 14:57:51 +01002376 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01002377 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002378 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002379 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002380 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002381 }
2382
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002383 lydict_remove(ctx, aug->target_name);
2384 lydict_remove(ctx, aug->dsc);
2385 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002386
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002387 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002388 lys_extension_instances_free(ctx, aug->ext, aug->ext_size, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002389
Radek Krejci5138e9f2017-04-12 13:10:46 +02002390 lys_when_free(ctx, aug->when, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002391}
2392
Radek Krejci1d82ef62015-08-07 14:44:40 +02002393static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002394lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident,
2395 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci6793db02015-05-22 17:49:54 +02002396{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002397 assert(ctx);
2398 if (!ident) {
2399 return;
2400 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002401
Radek Krejci018f1f52016-08-03 16:01:20 +02002402 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02002403 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002404 lydict_remove(ctx, ident->name);
2405 lydict_remove(ctx, ident->dsc);
2406 lydict_remove(ctx, ident->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002407 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002408 lys_extension_instances_free(ctx, ident->ext, ident->ext_size, private_destructor);
Radek Krejci6793db02015-05-22 17:49:54 +02002409
2410}
2411
Radek Krejci1d82ef62015-08-07 14:44:40 +02002412static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002413lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp,
2414 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002415{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002417
Radek Krejcid12f57b2015-08-06 10:43:39 +02002418 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002419 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002420 lys_tpdf_free(ctx, &grp->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 }
2422 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002423}
2424
Radek Krejci1d82ef62015-08-07 14:44:40 +02002425static void
Michal Vasko1e82a3b2018-07-03 12:16:58 +02002426lys_rpc_action_free(struct ly_ctx *ctx, struct lys_node_rpc_action *rpc_act,
2427 void (*private_destructor)(const struct lys_node *node, void *priv))
2428{
2429 int i;
2430
2431 /* handle only specific parts for LYS_GROUPING */
2432 for (i = 0; i < rpc_act->tpdf_size; i++) {
2433 lys_tpdf_free(ctx, &rpc_act->tpdf[i], private_destructor);
2434 }
2435 free(rpc_act->tpdf);
2436}
2437
2438static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002439lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io,
2440 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcid12f57b2015-08-06 10:43:39 +02002441{
2442 int i;
2443
2444 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
2445 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002446 lys_tpdf_free(ctx, &io->tpdf[i], private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002447 }
2448 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002449
2450 for (i = 0; i < io->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002451 lys_restr_free(ctx, &io->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002452 }
2453 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002454}
2455
Radek Krejci1d82ef62015-08-07 14:44:40 +02002456static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002457lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif,
2458 void (*private_destructor)(const struct lys_node *node, void *priv))
Pavol Vican7cff97e2016-08-09 14:56:08 +02002459{
2460 int i;
2461
2462 for (i = 0; i < notif->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002463 lys_restr_free(ctx, &notif->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002464 }
2465 free(notif->must);
2466
2467 for (i = 0; i < notif->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002468 lys_tpdf_free(ctx, &notif->tpdf[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002469 }
2470 free(notif->tpdf);
2471}
2472static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002473lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml,
2474 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci537cf382015-06-04 11:07:01 +02002475{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002476 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002478 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002479 lys_restr_free(ctx, &anyxml->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002480 }
2481 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002482
Radek Krejci5138e9f2017-04-12 13:10:46 +02002483 lys_when_free(ctx, anyxml->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002484}
2485
Radek Krejci1d82ef62015-08-07 14:44:40 +02002486static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002487lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf,
2488 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002489{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002490 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002491
Radek Krejci85a54be2016-10-20 12:39:56 +02002492 /* leafref backlinks */
2493 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002496 lys_restr_free(ctx, &leaf->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002497 }
2498 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002499
Radek Krejci5138e9f2017-04-12 13:10:46 +02002500 lys_when_free(ctx, leaf->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002501
Radek Krejci5138e9f2017-04-12 13:10:46 +02002502 lys_type_free(ctx, &leaf->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 lydict_remove(ctx, leaf->units);
2504 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002505}
2506
Radek Krejci1d82ef62015-08-07 14:44:40 +02002507static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002508lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist,
2509 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002510{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002511 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002512
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002513 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002514 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002515 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002516 }
2517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002518 for (i = 0; i < llist->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002519 lys_restr_free(ctx, &llist->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002520 }
2521 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002522
Pavol Vican38321d02016-08-16 14:56:02 +02002523 for (i = 0; i < llist->dflt_size; i++) {
2524 lydict_remove(ctx, llist->dflt[i]);
2525 }
2526 free(llist->dflt);
2527
Radek Krejci5138e9f2017-04-12 13:10:46 +02002528 lys_when_free(ctx, llist->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002529
Radek Krejci5138e9f2017-04-12 13:10:46 +02002530 lys_type_free(ctx, &llist->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002532}
2533
Radek Krejci1d82ef62015-08-07 14:44:40 +02002534static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002535lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list,
2536 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002537{
Radek Krejci581ce772015-11-10 17:22:40 +01002538 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002540 /* handle only specific parts for LY_NODE_LIST */
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002541 lys_when_free(ctx, list->when, private_destructor);
Radek Krejci537cf382015-06-04 11:07:01 +02002542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002543 for (i = 0; i < list->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002544 lys_restr_free(ctx, &list->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002545 }
2546 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002547
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002548 for (i = 0; i < list->tpdf_size; i++) {
2549 lys_tpdf_free(ctx, &list->tpdf[i], private_destructor);
2550 }
2551 free(list->tpdf);
2552
2553 free(list->keys);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002556 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002557 lydict_remove(ctx, list->unique[i].expr[j]);
2558 }
2559 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002560 }
2561 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002562
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002563 lydict_remove(ctx, list->keys_str);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002564}
2565
Radek Krejci1d82ef62015-08-07 14:44:40 +02002566static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002567lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont,
2568 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002569{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002570 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002572 /* handle only specific parts for LY_NODE_CONTAINER */
2573 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002575 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002576 lys_tpdf_free(ctx, &cont->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002577 }
2578 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002580 for (i = 0; i < cont->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002581 lys_restr_free(ctx, &cont->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002582 }
2583 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002584
Radek Krejci5138e9f2017-04-12 13:10:46 +02002585 lys_when_free(ctx, cont->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002586}
2587
Radek Krejci1d82ef62015-08-07 14:44:40 +02002588static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002589lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f,
2590 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci3cf9e222015-06-18 11:37:50 +02002591{
2592 lydict_remove(ctx, f->name);
2593 lydict_remove(ctx, f->dsc);
2594 lydict_remove(ctx, f->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002595 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size, 0, private_destructor);
Radek Krejci9de2c042016-10-19 16:53:06 +02002596 ly_set_free(f->depfeatures);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002597 lys_extension_instances_free(ctx, f->ext, f->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002598}
2599
2600static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002601lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e,
2602 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie534c132016-11-23 13:32:31 +01002603{
2604 lydict_remove(ctx, e->name);
2605 lydict_remove(ctx, e->dsc);
2606 lydict_remove(ctx, e->ref);
2607 lydict_remove(ctx, e->argument);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002608 lys_extension_instances_free(ctx, e->ext, e->ext_size, private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002609}
2610
Radek Krejci1d82ef62015-08-07 14:44:40 +02002611static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002612lys_deviation_free(struct lys_module *module, struct lys_deviation *dev,
2613 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcieb00f512015-07-01 16:44:58 +02002614{
Radek Krejci581ce772015-11-10 17:22:40 +01002615 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002616 struct ly_ctx *ctx;
2617 struct lys_node *next, *elem;
2618
2619 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002620
2621 lydict_remove(ctx, dev->target_name);
2622 lydict_remove(ctx, dev->dsc);
2623 lydict_remove(ctx, dev->ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002624 lys_extension_instances_free(ctx, dev->ext, dev->ext_size, private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002625
Pavol Vican64d0b762016-08-25 10:44:59 +02002626 if (!dev->deviate) {
Michal Vasko7427b262018-05-14 15:23:55 +02002627 return;
Pavol Vican64d0b762016-08-25 10:44:59 +02002628 }
2629
Michal Vasko7427b262018-05-14 15:23:55 +02002630 /* it could not be applied because it failed to be applied */
2631 if (dev->orig_node) {
2632 /* the module was freed, but we only need the context from orig_node, use ours */
2633 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2634 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2635 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2636 elem->module = module;
Michal Vaskoff006c12016-02-17 11:15:19 +01002637
Michal Vasko7427b262018-05-14 15:23:55 +02002638 LY_TREE_DFS_END(dev->orig_node, next, elem);
2639 }
2640 lys_node_free(dev->orig_node, NULL, 0);
2641 } else {
2642 /* it's just a shallow copy, freeing one node */
2643 dev->orig_node->module = module;
2644 lys_node_free(dev->orig_node, NULL, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002645 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002646 }
2647
Radek Krejcieb00f512015-07-01 16:44:58 +02002648 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002649 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size, private_destructor);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002650
Radek Krejcid5a5c282016-08-15 15:38:08 +02002651 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002652 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002653 }
2654 free(dev->deviate[i].dflt);
2655
Radek Krejcieb00f512015-07-01 16:44:58 +02002656 lydict_remove(ctx, dev->deviate[i].units);
2657
2658 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2659 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002660 lys_restr_free(ctx, &dev->deviate[i].must[j], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002661 }
2662 free(dev->deviate[i].must);
2663
2664 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002665 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2666 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2667 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002668 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002669 }
2670 free(dev->deviate[i].unique);
2671 }
2672 }
2673 free(dev->deviate);
2674}
2675
Radek Krejci1d82ef62015-08-07 14:44:40 +02002676static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002677lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses,
2678 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02002679{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002680 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002682 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002683 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002684 lydict_remove(ctx, uses->refine[i].dsc);
2685 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002686
Radek Krejcifde04bd2017-09-13 16:38:38 +02002687 lys_iffeature_free(ctx, uses->refine[i].iffeature, uses->refine[i].iffeature_size, 0, private_destructor);
2688
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002689 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002690 lys_restr_free(ctx, &uses->refine[i].must[j], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002691 }
2692 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002693
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002694 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002695 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002696 }
2697 free(uses->refine[i].dflt);
2698
Radek Krejci5138e9f2017-04-12 13:10:46 +02002699 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002700
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002701 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002702 lydict_remove(ctx, uses->refine[i].mod.presence);
2703 }
2704 }
2705 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002706
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002707 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002708 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002709 }
2710 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002711
Radek Krejci5138e9f2017-04-12 13:10:46 +02002712 lys_when_free(ctx, uses->when, private_destructor);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002713}
2714
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002715void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002716lys_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 +02002717{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002718 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002719 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002721 if (!node) {
2722 return;
2723 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002725 assert(node->module);
2726 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002728 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002729
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002730 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002731 if (node->priv && private_destructor) {
2732 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002733 }
2734
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002735 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002736 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002737 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002738 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size, shallow, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002739 lydict_remove(ctx, node->dsc);
2740 lydict_remove(ctx, node->ref);
2741 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002742
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002743 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002744 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002745 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002746 }
2747 }
2748
Radek Krejci5138e9f2017-04-12 13:10:46 +02002749 lys_extension_instances_free(ctx, node->ext, node->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002751 /* specific part */
2752 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002753 case LYS_CONTAINER:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002754 lys_container_free(ctx, (struct lys_node_container *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002755 break;
Radek Krejci76512572015-08-04 09:47:08 +02002756 case LYS_CHOICE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002757 lys_when_free(ctx, ((struct lys_node_choice *)node)->when, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002758 break;
Radek Krejci76512572015-08-04 09:47:08 +02002759 case LYS_LEAF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002760 lys_leaf_free(ctx, (struct lys_node_leaf *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 break;
Radek Krejci76512572015-08-04 09:47:08 +02002762 case LYS_LEAFLIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002763 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 break;
Radek Krejci76512572015-08-04 09:47:08 +02002765 case LYS_LIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002766 lys_list_free(ctx, (struct lys_node_list *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002767 break;
Radek Krejci76512572015-08-04 09:47:08 +02002768 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002769 case LYS_ANYDATA:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002770 lys_anydata_free(ctx, (struct lys_node_anydata *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002771 break;
Radek Krejci76512572015-08-04 09:47:08 +02002772 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002773 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774 break;
Radek Krejci76512572015-08-04 09:47:08 +02002775 case LYS_CASE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002776 lys_when_free(ctx, ((struct lys_node_case *)node)->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002777 break;
Radek Krejci76512572015-08-04 09:47:08 +02002778 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 /* do nothing */
2780 break;
Radek Krejci76512572015-08-04 09:47:08 +02002781 case LYS_GROUPING:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02002782 lys_grp_free(ctx, (struct lys_node_grp *)node, private_destructor);
2783 break;
Radek Krejci76512572015-08-04 09:47:08 +02002784 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002785 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02002786 lys_rpc_action_free(ctx, (struct lys_node_rpc_action *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002787 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002788 case LYS_NOTIF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002789 lys_notif_free(ctx, (struct lys_node_notif *)node, private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002790 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002791 case LYS_INPUT:
2792 case LYS_OUTPUT:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002793 lys_inout_free(ctx, (struct lys_node_inout *)node, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002794 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01002795 case LYS_EXT:
Michal Vasko591e0b22015-08-13 13:53:43 +02002796 case LYS_UNKNOWN:
Michal Vasko53b7da02018-02-13 15:28:42 +01002797 LOGINT(ctx);
Michal Vasko591e0b22015-08-13 13:53:43 +02002798 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 }
Radek Krejci5a065542015-05-22 15:02:07 +02002800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002802 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002803 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002804}
2805
Radek Krejci2eee5c02016-12-06 19:18:05 +01002806API struct lys_module *
2807lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002808{
2809 struct ly_ctx *ctx;
2810 int i;
2811
2812 if (!mod || mod->implemented) {
2813 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002814 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002815 }
2816
2817 ctx = mod->ctx;
2818 for (i = 0; i < ctx->models.used; i++) {
2819 if (!ctx->models.list[i]->implemented) {
2820 continue;
2821 }
2822
2823 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2824 /* we have some revision of the module implemented */
2825 return ctx->models.list[i];
2826 }
2827 }
2828
2829 /* we have no revision of the module implemented, return the module itself,
2830 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002831 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002832}
2833
Michal Vasko13b15832015-08-19 11:04:48 +02002834/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002835static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002836module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002837{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002838 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002839 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002840 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002841
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002842 assert(module->ctx);
2843 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002844
Michal Vaskob746fff2016-02-11 11:37:50 +01002845 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002846 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002847 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002848 lydict_remove(ctx, module->imp[i].dsc);
2849 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002850 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size, private_destructor);
Radek Krejci225376f2016-02-16 17:36:22 +01002851 }
Radek Krejcidce51452015-06-16 15:20:08 +02002852 free(module->imp);
2853
Radek Krejcic071c542016-01-27 14:57:51 +01002854 /* submodules don't have data tree, the data nodes
2855 * are placed in the main module altogether */
2856 if (!module->type) {
2857 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002858 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002859 }
Radek Krejci21181962015-06-30 14:11:00 +02002860 }
Radek Krejci5a065542015-05-22 15:02:07 +02002861
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002862 lydict_remove(ctx, module->dsc);
2863 lydict_remove(ctx, module->ref);
2864 lydict_remove(ctx, module->org);
2865 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002866 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002867
Radek Krejcieb00f512015-07-01 16:44:58 +02002868 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002869 for (i = 0; i < module->rev_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002870 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002871 lydict_remove(ctx, module->rev[i].dsc);
2872 lydict_remove(ctx, module->rev[i].ref);
2873 }
2874 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002875
Radek Krejcieb00f512015-07-01 16:44:58 +02002876 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002877 for (i = 0; i < module->ident_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002878 lys_ident_free(ctx, &module->ident[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002879 }
2880 module->ident_size = 0;
2881 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002882
Radek Krejcieb00f512015-07-01 16:44:58 +02002883 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002885 lys_tpdf_free(ctx, &module->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002886 }
2887 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002888
Radek Krejcie534c132016-11-23 13:32:31 +01002889 /* extension instances */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002890 lys_extension_instances_free(ctx, module->ext, module->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002891
Radek Krejcieb00f512015-07-01 16:44:58 +02002892 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002893 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002894 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002895 }
2896 free(module->augment);
2897
Radek Krejcieb00f512015-07-01 16:44:58 +02002898 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002899 for (i = 0; i < module->features_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002900 lys_feature_free(ctx, &module->features[i], private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002901 }
2902 free(module->features);
2903
Radek Krejcieb00f512015-07-01 16:44:58 +02002904 /* deviations */
2905 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002906 lys_deviation_free(module, &module->deviation[i], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002907 }
2908 free(module->deviation);
2909
Radek Krejcie534c132016-11-23 13:32:31 +01002910 /* extensions */
2911 for (i = 0; i < module->extensions_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002912 lys_extension_free(ctx, &module->extensions[i], private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002913 }
2914 free(module->extensions);
2915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002916 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002917 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002918}
2919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920void
Michal Vaskob746fff2016-02-11 11:37:50 +01002921lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002922{
Michal Vasko10681e82018-01-16 14:54:16 +01002923 int i;
2924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002925 if (!submodule) {
2926 return;
2927 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002930 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002931
Michal Vasko10681e82018-01-16 14:54:16 +01002932 /* include */
2933 for (i = 0; i < submodule->inc_size; i++) {
2934 lydict_remove(submodule->ctx, submodule->inc[i].dsc);
2935 lydict_remove(submodule->ctx, submodule->inc[i].ref);
2936 lys_extension_instances_free(submodule->ctx, submodule->inc[i].ext, submodule->inc[i].ext_size, private_destructor);
2937 /* complete submodule free is done only from main module since
2938 * submodules propagate their includes to the main module */
2939 }
2940 free(submodule->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002942 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002943}
2944
Radek Krejcib53154b2017-07-19 09:14:13 +02002945int
2946lys_ingrouping(const struct lys_node *node)
Radek Krejci3a5501d2016-07-18 22:03:34 +02002947{
2948 const struct lys_node *iter = node;
2949 assert(node);
2950
2951 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2952 if (!iter) {
2953 return 0;
2954 } else {
2955 return 1;
2956 }
2957}
2958
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002959/*
2960 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2961 */
2962static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002963lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002964 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002965{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002966 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002967 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002968 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002969 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002970 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002971 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002972
Michal Vaskoc07187d2015-08-13 15:20:57 +02002973 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002974 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002975 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002976 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002977 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002978 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002979 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002980 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002981 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002982 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002983 struct lys_node_anydata *any = NULL;
2984 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002985 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002986 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002987 struct lys_node_rpc_action *rpc = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002988 struct lys_node_inout *io = NULL;
Radek Krejcic43151c2017-03-12 07:10:52 +01002989 struct lys_node_notif *ntf = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002990 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002991 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002992
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002993 /* we cannot just duplicate memory since the strings are stored in
2994 * dictionary and we need to update dictionary counters.
2995 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002996
Radek Krejci1d82ef62015-08-07 14:44:40 +02002997 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002998 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003000 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003001 break;
3002
Radek Krejci76512572015-08-04 09:47:08 +02003003 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003004 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02003005 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 break;
3007
Radek Krejci76512572015-08-04 09:47:08 +02003008 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003009 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02003010 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011 break;
3012
Radek Krejci76512572015-08-04 09:47:08 +02003013 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003014 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003015 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 break;
3017
Radek Krejci76512572015-08-04 09:47:08 +02003018 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003020 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 break;
3022
Radek Krejci76512572015-08-04 09:47:08 +02003023 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003024 case LYS_ANYDATA:
3025 any = calloc(1, sizeof *any);
3026 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 break;
3028
Radek Krejci76512572015-08-04 09:47:08 +02003029 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003030 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02003031 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 break;
3033
Radek Krejci76512572015-08-04 09:47:08 +02003034 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02003036 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003037 break;
3038
Radek Krejci76512572015-08-04 09:47:08 +02003039 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02003040 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02003041 rpc = calloc(1, sizeof *rpc);
3042 retval = (struct lys_node *)rpc;
3043 break;
3044
Radek Krejci76512572015-08-04 09:47:08 +02003045 case LYS_INPUT:
3046 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02003047 io = calloc(1, sizeof *io);
3048 retval = (struct lys_node *)io;
3049 break;
3050
Radek Krejci76512572015-08-04 09:47:08 +02003051 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02003052 ntf = calloc(1, sizeof *ntf);
3053 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02003054 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003056 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01003057 LOGINT(ctx);
Michal Vasko49168a22015-08-17 16:35:41 +02003058 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003060 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Michal Vasko253035f2015-12-17 16:58:13 +01003061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003062 /*
3063 * duplicate generic part of the structure
3064 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003065 retval->name = lydict_insert(ctx, node->name, 0);
3066 retval->dsc = lydict_insert(ctx, node->dsc, 0);
3067 retval->ref = lydict_insert(ctx, node->ref, 0);
3068 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003071 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003074
Radek Krejcif0bb3602017-01-25 17:05:08 +01003075 retval->ext_size = node->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01003076 if (lys_ext_dup(ctx, module, node->ext, node->ext_size, retval, LYEXT_PAR_NODE, &retval->ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003077 goto error;
3078 }
3079
Radek Krejci06214042016-11-04 16:25:58 +01003080 if (node->iffeature_size) {
3081 retval->iffeature_size = node->iffeature_size;
3082 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003083 LY_CHECK_ERR_GOTO(!retval->iffeature, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01003084 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003085
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003086 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003087 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02003088 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
3089 if (size1) {
3090 /* there is something to duplicate */
3091
3092 /* duplicate compiled expression */
3093 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
3094 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01003095 LY_CHECK_ERR_GOTO(!retval->iffeature[i].expr, LOGMEM(ctx), error);
Radek Krejci9ff0a922016-07-14 13:08:05 +02003096 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
3097
3098 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02003099 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Michal Vasko53b7da02018-02-13 15:28:42 +01003100 LY_CHECK_ERR_GOTO(!retval->iffeature[i].features, LOGMEM(ctx); free(retval->iffeature[i].expr), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003101
Radek Krejci9ff0a922016-07-14 13:08:05 +02003102 for (j = 0; (unsigned int)j < size2; j++) {
3103 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
3104 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02003105 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02003106 /* feature is resolved in origin, so copy it
3107 * - duplication is used for instantiating groupings
3108 * and if-feature inside grouping is supposed to be
3109 * resolved inside the original grouping, so we want
3110 * to keep pointers to features from the grouping
3111 * context */
3112 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
3113 } else if (rc == -1) {
3114 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003115 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02003116 }
3117 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01003118
3119 /* duplicate if-feature's extensions */
3120 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01003121 if (lys_ext_dup(ctx, module, node->iffeature[i].ext, node->iffeature[i].ext_size,
Radek Krejci5138e9f2017-04-12 13:10:46 +02003122 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003123 goto error;
3124 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 }
Michal Vaskoff006c12016-02-17 11:15:19 +01003126
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003127 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01003128 p = parent;
3129 do {
3130 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
3131 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003132 if (iter) {
3133 flags = iter->flags & LYS_CONFIG_MASK;
3134 } else {
3135 /* default */
3136 flags = LYS_CONFIG_W;
3137 }
3138
3139 switch (finalize) {
3140 case 1:
3141 /* inherit config flags */
3142 if (retval->flags & LYS_CONFIG_SET) {
3143 /* skip nodes with an explicit config value */
3144 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003145 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
3146 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003147 goto error;
3148 }
3149 break;
3150 }
3151
3152 if (retval->nodetype != LYS_USES) {
3153 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
3154 }
Radek Krejci2cc25322017-09-06 16:32:02 +02003155
3156 /* inherit status */
Radek Krejcie2807ea2017-09-07 10:52:21 +02003157 if ((parent->flags & LYS_STATUS_MASK) > (retval->flags & LYS_STATUS_MASK)) {
3158 /* but do it only in case the parent has a stonger status */
3159 retval->flags &= ~LYS_STATUS_MASK;
3160 retval->flags |= (parent->flags & LYS_STATUS_MASK);
3161 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003162 break;
3163 case 2:
3164 /* erase config flags */
3165 retval->flags &= ~LYS_CONFIG_MASK;
3166 retval->flags &= ~LYS_CONFIG_SET;
3167 break;
3168 }
3169
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003170 /* connect it to the parent */
Michal Vasko8d30dd82018-09-10 10:06:12 +02003171 if (lys_node_addchild(parent, retval->module, retval, 0)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003172 goto error;
3173 }
Radek Krejcidce51452015-06-16 15:20:08 +02003174
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003175 /* go recursively */
3176 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003177 LY_TREE_FOR(node->child, iter) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003178 if (iter->nodetype & LYS_GROUPING) {
3179 /* do not instantiate groupings */
3180 continue;
3181 }
Radek Krejci6ff885d2017-01-03 14:06:22 +01003182 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003183 goto error;
3184 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 }
3186 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003187
3188 if (finalize == 1) {
3189 /* check that configuration lists have keys
3190 * - we really want to check keys_size in original node, because the keys are
3191 * not yet resolved here, it is done below in nodetype specific part */
3192 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
3193 && !((struct lys_node_list *)node)->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003194 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003195 goto error;
3196 }
3197 }
Michal Vaskoff006c12016-02-17 11:15:19 +01003198 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003199 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 }
3201
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003202 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003203 * duplicate specific part of the structure
3204 */
3205 switch (node->nodetype) {
3206 case LYS_CONTAINER:
3207 if (cont_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003208 cont->when = lys_when_dup(module, cont_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003209 LY_CHECK_GOTO(!cont->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 }
3211 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003212
Radek Krejcia8d111f2017-05-31 13:57:37 +02003213 if (cont_orig->must) {
3214 cont->must = lys_restr_dup(module, cont_orig->must, cont_orig->must_size, shallow, unres);
3215 LY_CHECK_GOTO(!cont->must, error);
3216 cont->must_size = cont_orig->must_size;
3217 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218
Radek Krejcif0bb3602017-01-25 17:05:08 +01003219 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
3220
3221 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 case LYS_CHOICE:
3223 if (choice_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003224 choice->when = lys_when_dup(module, choice_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003225 LY_CHECK_GOTO(!choice->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003226 }
3227
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003228 if (!shallow) {
3229 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003230 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
3231 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
3232 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003233 if (rc) {
3234 if (rc == EXIT_FAILURE) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003235 LOGINT(ctx);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003236 }
3237 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02003238 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003239 } else {
3240 /* useless to check return value, we don't know whether
3241 * there really wasn't any default defined or it just hasn't
3242 * been resolved, we just hope for the best :)
3243 */
3244 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02003245 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003246 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003247 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003248 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003249 break;
3250
3251 case LYS_LEAF:
Radek Krejcib53154b2017-07-19 09:14:13 +02003252 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02003253 goto error;
3254 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003255 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
3256
3257 if (leaf_orig->dflt) {
3258 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003259 }
3260
Radek Krejcia8d111f2017-05-31 13:57:37 +02003261 if (leaf_orig->must) {
3262 leaf->must = lys_restr_dup(module, leaf_orig->must, leaf_orig->must_size, shallow, unres);
3263 LY_CHECK_GOTO(!leaf->must, error);
3264 leaf->must_size = leaf_orig->must_size;
3265 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003266
3267 if (leaf_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003268 leaf->when = lys_when_dup(module, leaf_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003269 LY_CHECK_GOTO(!leaf->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 }
3271 break;
3272
3273 case LYS_LEAFLIST:
Radek Krejcib53154b2017-07-19 09:14:13 +02003274 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02003275 goto error;
3276 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003277 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
3278
3279 llist->min = llist_orig->min;
3280 llist->max = llist_orig->max;
3281
Radek Krejcia8d111f2017-05-31 13:57:37 +02003282 if (llist_orig->must) {
3283 llist->must = lys_restr_dup(module, llist_orig->must, llist_orig->must_size, shallow, unres);
3284 LY_CHECK_GOTO(!llist->must, error);
3285 llist->must_size = llist_orig->must_size;
3286 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003287
Radek Krejcia8d111f2017-05-31 13:57:37 +02003288 if (llist_orig->dflt) {
3289 llist->dflt = malloc(llist_orig->dflt_size * sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003290 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003291 llist->dflt_size = llist_orig->dflt_size;
Radek Krejcia8d111f2017-05-31 13:57:37 +02003292
Radek Krejcic699e422017-06-02 15:18:58 +02003293 for (i = 0; i < llist->dflt_size; i++) {
3294 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
Radek Krejci51673202016-11-01 17:00:32 +01003295 }
3296 }
3297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003298 if (llist_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003299 llist->when = lys_when_dup(module, llist_orig->when, shallow, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300 }
3301 break;
3302
3303 case LYS_LIST:
3304 list->min = list_orig->min;
3305 list->max = list_orig->max;
3306
Radek Krejcia8d111f2017-05-31 13:57:37 +02003307 if (list_orig->must) {
3308 list->must = lys_restr_dup(module, list_orig->must, list_orig->must_size, shallow, unres);
3309 LY_CHECK_GOTO(!list->must, error);
3310 list->must_size = list_orig->must_size;
3311 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312
Radek Krejcif0bb3602017-01-25 17:05:08 +01003313 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Michal Vasko38d01f72015-06-15 09:41:06 +02003314
Radek Krejcia8d111f2017-05-31 13:57:37 +02003315 if (list_orig->keys_size) {
3316 list->keys = calloc(list_orig->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01003317 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejci5c08a992016-11-02 13:30:04 +01003318 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003319 list->keys_size = list_orig->keys_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02003320
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003321 if (!shallow) {
Radek Krejci7a1e6072018-08-13 14:59:16 +02003322 if (unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci5c08a992016-11-02 13:30:04 +01003323 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003324 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003325 } else {
Radek Krejcia8d111f2017-05-31 13:57:37 +02003326 memcpy(list->keys, list_orig->keys, list_orig->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02003327 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003328 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329
Radek Krejcia8d111f2017-05-31 13:57:37 +02003330 if (list_orig->unique) {
3331 list->unique = malloc(list_orig->unique_size * sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01003332 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003333 list->unique_size = list_orig->unique_size;
Radek Krejci581ce772015-11-10 17:22:40 +01003334
Radek Krejcic699e422017-06-02 15:18:58 +02003335 for (i = 0; i < list->unique_size; ++i) {
3336 list->unique[i].expr = malloc(list_orig->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01003337 LY_CHECK_ERR_GOTO(!list->unique[i].expr, LOGMEM(ctx), error);
Radek Krejcic699e422017-06-02 15:18:58 +02003338 list->unique[i].expr_size = list_orig->unique[i].expr_size;
3339 for (j = 0; j < list->unique[i].expr_size; j++) {
3340 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
3341
3342 /* if it stays in unres list, duplicate it also there */
3343 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01003344 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcic699e422017-06-02 15:18:58 +02003345 unique_info->list = (struct lys_node *)list;
3346 unique_info->expr = list->unique[i].expr[j];
3347 unique_info->trg_type = &list->unique[i].trg_type;
3348 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
3349 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 }
3351 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003353 if (list_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003354 list->when = lys_when_dup(module, list_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003355 LY_CHECK_GOTO(!list->when, error);
Radek Krejciefaeba32015-05-27 14:30:57 +02003356 }
Radek Krejcidce51452015-06-16 15:20:08 +02003357 break;
3358
3359 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003360 case LYS_ANYDATA:
Radek Krejcia8d111f2017-05-31 13:57:37 +02003361 if (any_orig->must) {
3362 any->must = lys_restr_dup(module, any_orig->must, any_orig->must_size, shallow, unres);
3363 LY_CHECK_GOTO(!any->must, error);
3364 any->must_size = any_orig->must_size;
3365 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003366
Radek Krejcibf2abff2016-08-23 15:51:52 +02003367 if (any_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003368 any->when = lys_when_dup(module, any_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003369 LY_CHECK_GOTO(!any->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003370 }
3371 break;
3372
3373 case LYS_USES:
3374 uses->grp = uses_orig->grp;
3375
3376 if (uses_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003377 uses->when = lys_when_dup(module, uses_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003378 LY_CHECK_GOTO(!uses->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003379 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003380 /* it is not needed to duplicate refine, nor augment. They are already applied to the uses children */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003381 break;
3382
3383 case LYS_CASE:
3384 if (cs_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003385 cs->when = lys_when_dup(module, cs_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003386 LY_CHECK_GOTO(!cs->when, error);
Radek Krejcidce51452015-06-16 15:20:08 +02003387 }
3388 break;
3389
Radek Krejci96935402016-11-04 16:27:28 +01003390 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02003391 case LYS_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003392 case LYS_INPUT:
3393 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02003394 case LYS_NOTIF:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003395 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003396 break;
3397
3398 default:
3399 /* LY_NODE_AUGMENT */
Michal Vasko53b7da02018-02-13 15:28:42 +01003400 LOGINT(ctx);
Michal Vasko49168a22015-08-17 16:35:41 +02003401 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003402 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003403
3404 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02003405
3406error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003407 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02003408 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003409}
3410
Radek Krejcib3142312016-11-09 11:04:12 +01003411int
3412lys_has_xpath(const struct lys_node *node)
3413{
3414 assert(node);
3415
3416 switch (node->nodetype) {
3417 case LYS_AUGMENT:
3418 if (((struct lys_node_augment *)node)->when) {
3419 return 1;
3420 }
3421 break;
3422 case LYS_CASE:
3423 if (((struct lys_node_case *)node)->when) {
3424 return 1;
3425 }
3426 break;
3427 case LYS_CHOICE:
3428 if (((struct lys_node_choice *)node)->when) {
3429 return 1;
3430 }
3431 break;
3432 case LYS_ANYDATA:
3433 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3434 return 1;
3435 }
3436 break;
3437 case LYS_LEAF:
3438 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3439 return 1;
3440 }
3441 break;
3442 case LYS_LEAFLIST:
3443 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3444 return 1;
3445 }
3446 break;
3447 case LYS_LIST:
3448 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3449 return 1;
3450 }
3451 break;
3452 case LYS_CONTAINER:
3453 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3454 return 1;
3455 }
3456 break;
3457 case LYS_INPUT:
3458 case LYS_OUTPUT:
3459 if (((struct lys_node_inout *)node)->must_size) {
3460 return 1;
3461 }
3462 break;
3463 case LYS_NOTIF:
3464 if (((struct lys_node_notif *)node)->must_size) {
3465 return 1;
3466 }
3467 break;
3468 case LYS_USES:
3469 if (((struct lys_node_uses *)node)->when) {
3470 return 1;
3471 }
3472 break;
3473 default:
3474 /* does not have XPath */
3475 break;
3476 }
3477
3478 return 0;
3479}
3480
Michal Vasko568b1952018-01-30 15:53:30 +01003481int
3482lys_type_is_local(const struct lys_type *type)
3483{
3484 if (!type->der->module) {
3485 /* build-in type */
3486 return 1;
3487 }
3488 /* type->parent can be either a typedef or leaf/leaf-list, but module pointers are compatible */
3489 return (lys_main_module(type->der->module) == lys_main_module(((struct lys_tpdf *)type->parent)->module));
3490}
3491
Radek Krejci2cc25322017-09-06 16:32:02 +02003492/*
3493 * shallow -
3494 * - do not inherit status from the parent
3495 */
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003496struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003497lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003498 struct unres_schema *unres, int shallow)
3499{
3500 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003501 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003502 struct lys_node *result, *iter, *next;
3503
3504 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003505 /* 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 +02003506 for (p = parent;
3507 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3508 p = lys_parent(p));
3509 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3510 }
3511
Radek Krejci6ff885d2017-01-03 14:06:22 +01003512 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003513 if (finalize) {
3514 /* check xpath expressions in the instantiated tree */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003515 for (iter = next = result; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003516 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003517 /* invalid xpath */
3518 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003519 }
3520
3521 /* select next item */
3522 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3523 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3524 next = NULL;
3525 } else {
3526 next = iter->child;
3527 }
3528 if (!next) {
3529 /* no children, try siblings */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003530 if (iter == result) {
3531 /* we are done, no next element to process */
3532 break;
3533 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003534 next = iter->next;
3535 }
3536 while (!next) {
3537 /* parent is already processed, go to its sibling */
3538 iter = lys_parent(iter);
Radek Krejci7212e0a2017-03-08 15:58:22 +01003539 if (lys_parent(iter) == lys_parent(result)) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003540 /* we are done, no next element to process */
3541 break;
3542 }
3543 next = iter->next;
3544 }
3545 }
3546 }
3547
3548 return result;
3549}
3550
Michal Vasko81c71442018-08-03 12:56:53 +02003551/**
3552 * @brief Switch contents of two same schema nodes. One of the nodes
3553 * is expected to be ashallow copy of the other.
3554 *
3555 * @param[in] node1 Node whose contents will be switched with \p node2.
3556 * @param[in] node2 Node whose contents will be switched with \p node1.
3557 */
3558static void
3559lys_node_switch(struct lys_node *node1, struct lys_node *node2)
Michal Vaskoff006c12016-02-17 11:15:19 +01003560{
Michal Vasko81c71442018-08-03 12:56:53 +02003561 const size_t mem_size = 104;
3562 uint8_t mem[mem_size];
3563 size_t offset, size;
Michal Vaskoff006c12016-02-17 11:15:19 +01003564
Michal Vasko81c71442018-08-03 12:56:53 +02003565 assert((node1->module == node2->module) && ly_strequal(node1->name, node2->name, 1) && (node1->nodetype == node2->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003566
Michal Vasko81c71442018-08-03 12:56:53 +02003567 /*
3568 * Initially, the nodes were really switched in the tree which
3569 * caused problems for some other nodes with pointers (augments, leafrefs, ...)
3570 * because their pointers were not being updated. Code kept in case there is
3571 * a use of it in future (it took some debugging to cover all the cases).
3572
3573 * sibling next *
3574 if (node1->prev->next) {
3575 node1->prev->next = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003576 }
3577
Michal Vasko81c71442018-08-03 12:56:53 +02003578 * sibling prev *
3579 if (node1->next) {
3580 node1->next->prev = node2;
Michal Vasko8328da82016-08-25 09:27:22 +02003581 } else {
Michal Vasko81c71442018-08-03 12:56:53 +02003582 for (child = node1->prev; child->prev->next; child = child->prev);
3583 child->prev = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003584 }
3585
Michal Vasko81c71442018-08-03 12:56:53 +02003586 * next *
3587 node2->next = node1->next;
3588 node1->next = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01003589
Michal Vasko81c71442018-08-03 12:56:53 +02003590 * prev *
3591 if (node1->prev != node1) {
3592 node2->prev = node1->prev;
Michal Vaskoff006c12016-02-17 11:15:19 +01003593 }
Michal Vasko81c71442018-08-03 12:56:53 +02003594 node1->prev = node1;
Michal Vaskoff006c12016-02-17 11:15:19 +01003595
Michal Vasko81c71442018-08-03 12:56:53 +02003596 * parent child *
3597 if (node1->parent) {
3598 if (node1->parent->child == node1) {
3599 node1->parent->child = node2;
Radek Krejci30bfcd22017-01-27 16:54:48 +01003600 }
Michal Vasko81c71442018-08-03 12:56:53 +02003601 } else if (lys_main_module(node1->module)->data == node1) {
3602 lys_main_module(node1->module)->data = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003603 }
3604
Michal Vasko81c71442018-08-03 12:56:53 +02003605 * parent *
3606 node2->parent = node1->parent;
3607 node1->parent = NULL;
Radek Krejci30bfcd22017-01-27 16:54:48 +01003608
Michal Vasko81c71442018-08-03 12:56:53 +02003609 * child parent *
3610 LY_TREE_FOR(node1->child, child) {
3611 if (child->parent == node1) {
3612 child->parent = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003613 }
3614 }
3615
Michal Vasko81c71442018-08-03 12:56:53 +02003616 * child *
3617 node2->child = node1->child;
3618 node1->child = NULL;
3619 */
Radek Krejcif0bb3602017-01-25 17:05:08 +01003620
Michal Vasko81c71442018-08-03 12:56:53 +02003621 /* switch common node part */
3622 offset = 3 * sizeof(char *);
3623 size = sizeof(uint16_t) + 6 * sizeof(uint8_t) + sizeof(struct lys_ext_instance **) + sizeof(struct lys_iffeature *);
3624 memcpy(mem, ((uint8_t *)node1) + offset, size);
3625 memcpy(((uint8_t *)node1) + offset, ((uint8_t *)node2) + offset, size);
3626 memcpy(((uint8_t *)node2) + offset, mem, size);
3627
3628 /* switch node-specific data */
3629 offset = sizeof(struct lys_node);
3630 switch (node1->nodetype) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003631 case LYS_CONTAINER:
Michal Vasko81c71442018-08-03 12:56:53 +02003632 size = sizeof(struct lys_node_container) - offset;
3633 break;
3634 case LYS_CHOICE:
3635 size = sizeof(struct lys_node_choice) - offset;
3636 break;
3637 case LYS_LEAF:
3638 size = sizeof(struct lys_node_leaf) - offset;
3639 break;
3640 case LYS_LEAFLIST:
3641 size = sizeof(struct lys_node_leaflist) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003642 break;
3643 case LYS_LIST:
Michal Vasko81c71442018-08-03 12:56:53 +02003644 size = sizeof(struct lys_node_list) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003645 break;
Michal Vasko81c71442018-08-03 12:56:53 +02003646 case LYS_ANYDATA:
3647 case LYS_ANYXML:
3648 size = sizeof(struct lys_node_anydata) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003649 break;
Michal Vasko81c71442018-08-03 12:56:53 +02003650 case LYS_CASE:
3651 size = sizeof(struct lys_node_case) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003652 break;
3653 case LYS_INPUT:
3654 case LYS_OUTPUT:
Michal Vasko81c71442018-08-03 12:56:53 +02003655 size = sizeof(struct lys_node_inout) - offset;
3656 break;
3657 case LYS_NOTIF:
3658 size = sizeof(struct lys_node_notif) - offset;
3659 break;
3660 case LYS_RPC:
3661 case LYS_ACTION:
3662 size = sizeof(struct lys_node_rpc_action) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003663 break;
3664 default:
Michal Vasko81c71442018-08-03 12:56:53 +02003665 assert(0);
3666 LOGINT(node1->module->ctx);
3667 return;
3668 }
3669 assert(size <= mem_size);
3670 memcpy(mem, ((uint8_t *)node1) + offset, size);
3671 memcpy(((uint8_t *)node1) + offset, ((uint8_t *)node2) + offset, size);
3672 memcpy(((uint8_t *)node2) + offset, mem, size);
3673
Michal Vasko114ffd42018-08-03 14:30:36 +02003674 /* typedefs were not copied to the backup node, so always reuse them,
3675 * in leaves/leaf-lists we must correct the type parent pointer */
Michal Vasko81c71442018-08-03 12:56:53 +02003676 switch (node1->nodetype) {
3677 case LYS_CONTAINER:
3678 ((struct lys_node_container *)node1)->tpdf_size = ((struct lys_node_container *)node2)->tpdf_size;
3679 ((struct lys_node_container *)node1)->tpdf = ((struct lys_node_container *)node2)->tpdf;
3680 ((struct lys_node_container *)node2)->tpdf_size = 0;
3681 ((struct lys_node_container *)node2)->tpdf = NULL;
3682 break;
3683 case LYS_LIST:
3684 ((struct lys_node_list *)node1)->tpdf_size = ((struct lys_node_list *)node2)->tpdf_size;
3685 ((struct lys_node_list *)node1)->tpdf = ((struct lys_node_list *)node2)->tpdf;
3686 ((struct lys_node_list *)node2)->tpdf_size = 0;
3687 ((struct lys_node_list *)node2)->tpdf = NULL;
3688 break;
3689 case LYS_RPC:
3690 case LYS_ACTION:
3691 ((struct lys_node_rpc_action *)node1)->tpdf_size = ((struct lys_node_rpc_action *)node2)->tpdf_size;
3692 ((struct lys_node_rpc_action *)node1)->tpdf = ((struct lys_node_rpc_action *)node2)->tpdf;
3693 ((struct lys_node_rpc_action *)node2)->tpdf_size = 0;
3694 ((struct lys_node_rpc_action *)node2)->tpdf = NULL;
3695 break;
3696 case LYS_NOTIF:
3697 ((struct lys_node_notif *)node1)->tpdf_size = ((struct lys_node_notif *)node2)->tpdf_size;
3698 ((struct lys_node_notif *)node1)->tpdf = ((struct lys_node_notif *)node2)->tpdf;
3699 ((struct lys_node_notif *)node2)->tpdf_size = 0;
3700 ((struct lys_node_notif *)node2)->tpdf = NULL;
3701 break;
3702 case LYS_INPUT:
3703 case LYS_OUTPUT:
3704 ((struct lys_node_inout *)node1)->tpdf_size = ((struct lys_node_inout *)node2)->tpdf_size;
3705 ((struct lys_node_inout *)node1)->tpdf = ((struct lys_node_inout *)node2)->tpdf;
3706 ((struct lys_node_inout *)node2)->tpdf_size = 0;
3707 ((struct lys_node_inout *)node2)->tpdf = NULL;
3708 break;
Michal Vasko114ffd42018-08-03 14:30:36 +02003709 case LYS_LEAF:
3710 case LYS_LEAFLIST:
3711 ((struct lys_node_leaf *)node1)->type.parent = (struct lys_tpdf *)node1;
3712 ((struct lys_node_leaf *)node2)->type.parent = (struct lys_tpdf *)node2;
Michal Vasko81c71442018-08-03 12:56:53 +02003713 default:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003714 break;
3715 }
Michal Vaskoff006c12016-02-17 11:15:19 +01003716}
3717
3718void
Michal Vasko10681e82018-01-16 14:54:16 +01003719lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int free_subs, int remove_from_ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003720{
3721 struct ly_ctx *ctx;
3722 int i;
3723
3724 if (!module) {
3725 return;
3726 }
3727
3728 /* remove schema from the context */
3729 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003730 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003731 for (i = 0; i < ctx->models.used; i++) {
3732 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003733 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003734 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003735 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 +02003736 ctx->models.list[ctx->models.used] = NULL;
3737 /* we are done */
3738 break;
3739 }
3740 }
3741 }
3742
3743 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003744 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003745
Michal Vasko10681e82018-01-16 14:54:16 +01003746 /* include */
3747 for (i = 0; i < module->inc_size; i++) {
3748 lydict_remove(ctx, module->inc[i].dsc);
3749 lydict_remove(ctx, module->inc[i].ref);
3750 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size, private_destructor);
3751 /* complete submodule free is done only from main module since
3752 * submodules propagate their includes to the main module */
3753 if (free_subs) {
3754 lys_submodule_free(module->inc[i].submodule, private_destructor);
3755 }
3756 }
3757 free(module->inc);
3758
Radek Krejcida04f4a2015-05-21 12:54:09 +02003759 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003760 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003761
3762 free(module);
3763}
Radek Krejci7e97c352015-06-19 16:26:34 +02003764
Radek Krejci9de2c042016-10-19 16:53:06 +02003765static void
3766lys_features_disable_recursive(struct lys_feature *f)
3767{
3768 unsigned int i;
3769 struct lys_feature *depf;
3770
3771 /* disable the feature */
3772 f->flags &= ~LYS_FENABLED;
3773
3774 /* by disabling feature we have to disable also all features that depends on this feature */
3775 if (f->depfeatures) {
3776 for (i = 0; i < f->depfeatures->number; i++) {
3777 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3778 if (depf->flags & LYS_FENABLED) {
3779 lys_features_disable_recursive(depf);
3780 }
3781 }
3782 }
3783}
3784
Radek Krejci7e97c352015-06-19 16:26:34 +02003785/*
3786 * op: 1 - enable, 0 - disable
3787 */
3788static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003789lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003790{
3791 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003792 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003793 int progress, faili, failj, failk;
3794
3795 uint8_t fsize;
3796 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003797
3798 if (!module || !name || !strlen(name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003799 LOGARG;
Radek Krejci7e97c352015-06-19 16:26:34 +02003800 return EXIT_FAILURE;
3801 }
3802
3803 if (!strcmp(name, "*")) {
3804 /* enable all */
3805 all = 1;
3806 }
3807
Radek Krejcia889c1f2016-10-19 15:50:11 +02003808 progress = failk = 1;
3809 while (progress && failk) {
3810 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3811 if (i == -1) {
3812 fsize = module->features_size;
3813 f = module->features;
3814 } else {
3815 fsize = module->inc[i].submodule->features_size;
3816 f = module->inc[i].submodule->features;
3817 }
3818
3819 for (j = 0; j < fsize; j++) {
3820 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003821 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3822 if (all) {
3823 /* skip already set features */
3824 continue;
3825 } else {
3826 /* feature already set correctly */
3827 return EXIT_SUCCESS;
3828 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003829 }
3830
3831 if (op) {
3832 /* check referenced features if they are enabled */
3833 for (k = 0; k < f[j].iffeature_size; k++) {
3834 if (!resolve_iffeature(&f[j].iffeature[k])) {
3835 if (all) {
3836 faili = i;
3837 failj = j;
3838 failk = k + 1;
3839 break;
3840 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003841 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
Radek Krejcia889c1f2016-10-19 15:50:11 +02003842 f[j].name, k + 1);
3843 return EXIT_FAILURE;
3844 }
3845 }
3846 }
3847
3848 if (k == f[j].iffeature_size) {
3849 /* the last check passed, do the change */
3850 f[j].flags |= LYS_FENABLED;
3851 progress++;
3852 }
3853 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003854 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003855 progress++;
3856 }
3857 if (!all) {
3858 /* stop in case changing a single feature */
3859 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003860 }
3861 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003862 }
3863 }
3864 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003865 if (failk) {
3866 /* print info about the last failing feature */
Michal Vasko53b7da02018-02-13 15:28:42 +01003867 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
Radek Krejcia889c1f2016-10-19 15:50:11 +02003868 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3869 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003870 }
3871
3872 if (all) {
3873 return EXIT_SUCCESS;
3874 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003875 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003876 return EXIT_FAILURE;
3877 }
3878}
3879
3880API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003881lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003882{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003883 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003884}
3885
3886API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003887lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003888{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003889 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003890}
3891
3892API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003893lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003894{
3895 int i, j;
3896
3897 if (!module || !feature) {
3898 return -1;
3899 }
3900
3901 /* search for the specified feature */
3902 /* module itself */
3903 for (i = 0; i < module->features_size; i++) {
3904 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003905 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003906 return 1;
3907 } else {
3908 return 0;
3909 }
3910 }
3911 }
3912
3913 /* submodules */
3914 for (j = 0; j < module->inc_size; j++) {
3915 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3916 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003917 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003918 return 1;
3919 } else {
3920 return 0;
3921 }
3922 }
3923 }
3924 }
3925
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003926 /* feature definition not found */
3927 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003928}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003929
Radek Krejci96a10da2015-07-30 11:00:14 +02003930API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003931lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003932{
Radek Krejci96a10da2015-07-30 11:00:14 +02003933 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003934 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003935 unsigned int count;
3936
3937 if (!module) {
3938 return NULL;
3939 }
3940
3941 count = module->features_size;
3942 for (i = 0; i < module->inc_size; i++) {
3943 count += module->inc[i].submodule->features_size;
3944 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003945 result = malloc((count + 1) * sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +01003946 LY_CHECK_ERR_RETURN(!result, LOGMEM(module->ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003947
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003948 if (states) {
3949 *states = malloc((count + 1) * sizeof **states);
Michal Vasko53b7da02018-02-13 15:28:42 +01003950 LY_CHECK_ERR_RETURN(!(*states), LOGMEM(module->ctx); free(result), NULL);
Michal Vasko2367e7c2015-07-07 11:33:44 +02003951 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003952 count = 0;
3953
3954 /* module itself */
3955 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003956 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003957 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003958 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003959 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003960 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003961 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003962 }
3963 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003964 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003965 }
3966
3967 /* submodules */
3968 for (j = 0; j < module->inc_size; j++) {
3969 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003970 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003971 if (states) {
3972 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3973 (*states)[count] = 1;
3974 } else {
3975 (*states)[count] = 0;
3976 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003977 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003978 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003979 }
3980 }
3981
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003982 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003983 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003984
3985 return result;
3986}
Michal Vaskobaefb032015-09-24 14:52:10 +02003987
Radek Krejci6910a032016-04-13 10:06:21 +02003988API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003989lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003990{
Michal Vaskof53187d2017-01-13 13:23:14 +01003991 if (!node) {
3992 return NULL;
3993 }
3994
Radek Krejcic071c542016-01-27 14:57:51 +01003995 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3996}
3997
Radek Krejci6910a032016-04-13 10:06:21 +02003998API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003999lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01004000{
Michal Vaskof53187d2017-01-13 13:23:14 +01004001 if (!module) {
4002 return NULL;
4003 }
4004
Michal Vasko320e8532016-02-15 13:11:57 +01004005 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
4006}
4007
Michal Vaskobaefb032015-09-24 14:52:10 +02004008API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01004009lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02004010{
Radek Krejcif95b6292017-02-13 15:57:37 +01004011 struct lys_node *parent;
4012
4013 if (!node) {
Michal Vaskobaefb032015-09-24 14:52:10 +02004014 return NULL;
4015 }
4016
Radek Krejcif95b6292017-02-13 15:57:37 +01004017 if (node->nodetype == LYS_EXT) {
4018 if (((struct lys_ext_instance_complex*)node)->parent_type != LYEXT_PAR_NODE) {
4019 return NULL;
4020 }
4021 parent = (struct lys_node*)((struct lys_ext_instance_complex*)node)->parent;
4022 } else if (!node->parent) {
4023 return NULL;
4024 } else {
4025 parent = node->parent;
Michal Vaskobaefb032015-09-24 14:52:10 +02004026 }
4027
Radek Krejcif95b6292017-02-13 15:57:37 +01004028 if (parent->nodetype == LYS_AUGMENT) {
4029 return ((struct lys_node_augment *)parent)->target;
4030 } else {
4031 return parent;
4032 }
4033}
4034
4035struct lys_node **
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004036lys_child(const struct lys_node *node, LYS_NODE nodetype)
Radek Krejcif95b6292017-02-13 15:57:37 +01004037{
4038 void *pp;
4039 assert(node);
4040
4041 if (node->nodetype == LYS_EXT) {
4042 pp = lys_ext_complex_get_substmt(lys_snode2stmt(nodetype), (struct lys_ext_instance_complex*)node, NULL);
4043 if (!pp) {
4044 return NULL;
4045 }
4046 return (struct lys_node **)pp;
Michal Vasko54d4c202017-08-09 14:09:18 +02004047 } else if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Radek Krejcif7fe2cb2017-08-09 10:27:12 +02004048 return NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01004049 } else {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004050 return (struct lys_node **)&node->child;
Radek Krejcif95b6292017-02-13 15:57:37 +01004051 }
Michal Vaskobaefb032015-09-24 14:52:10 +02004052}
Michal Vasko1b229152016-01-13 11:28:38 +01004053
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004054API void *
Michal Vasko1b229152016-01-13 11:28:38 +01004055lys_set_private(const struct lys_node *node, void *priv)
4056{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004057 void *prev;
4058
Michal Vasko1b229152016-01-13 11:28:38 +01004059 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004060 LOGARG;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004061 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01004062 }
4063
Mislav Novakovicb5529e52016-02-29 11:42:43 +01004064 prev = node->priv;
4065 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004066
4067 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01004068}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004069
Michal Vasko01c6fd22016-05-20 11:43:05 +02004070int
4071lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
4072{
Michal Vasko53b7da02018-02-13 15:28:42 +01004073 struct lys_node_leaf *iter;
4074 struct ly_ctx *ctx = leafref_target->module->ctx;
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004075
Michal Vasko48a573d2016-07-01 11:46:02 +02004076 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004077 LOGINT(ctx);
Michal Vasko01c6fd22016-05-20 11:43:05 +02004078 return -1;
4079 }
4080
Pavol Vican93175152016-08-30 15:34:44 +02004081 /* check for config flag */
Radek Krejcic688ca02017-03-20 12:54:39 +01004082 if (((struct lys_node_leaf*)leafref)->type.info.lref.req != -1 &&
4083 (leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004084 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, leafref,
Radek Krejcid831dd42017-03-16 12:59:30 +01004085 "The leafref %s is config but refers to a non-config %s.",
Pavol Vican93175152016-08-30 15:34:44 +02004086 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
4087 return -1;
4088 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004089 /* check for cycles */
Michal Vasko53b7da02018-02-13 15:28:42 +01004090 for (iter = leafref_target; iter && iter->type.base == LY_TYPE_LEAFREF; iter = iter->type.info.lref.target) {
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004091 if ((void *)iter == (void *)leafref) {
4092 /* cycle detected */
Michal Vasko53b7da02018-02-13 15:28:42 +01004093 LOGVAL(ctx, LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004094 return -1;
4095 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004096 }
4097
4098 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02004099 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02004100 if (!leafref_target->backlinks) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004101 leafref_target->backlinks = (void *)ly_set_new();
Radek Krejci85a54be2016-10-20 12:39:56 +02004102 if (!leafref_target->backlinks) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004103 LOGMEM(ctx);
Michal Vasko01c6fd22016-05-20 11:43:05 +02004104 return -1;
4105 }
4106 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01004107 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02004108
4109 return 0;
4110}
4111
Michal Vasko8548e082016-07-22 12:00:18 +02004112/* not needed currently */
4113#if 0
4114
Michal Vasko5b3492c2016-07-20 09:37:40 +02004115static const char *
4116lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
4117{
4118 struct lys_module *prev_mod;
4119 uint32_t str_len, mod_len, buf_idx;
4120
Radek Krejcibf2abff2016-08-23 15:51:52 +02004121 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02004122 LOGINT;
4123 return NULL;
4124 }
4125
4126 buf_idx = buf_len - 1;
4127 buf[buf_idx] = '\0';
4128
4129 while (node) {
4130 if (lys_parent(node)) {
4131 prev_mod = lys_node_module(lys_parent(node));
4132 } else {
4133 prev_mod = NULL;
4134 }
4135
Radek Krejcibf2abff2016-08-23 15:51:52 +02004136 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02004137 str_len = strlen(node->name);
4138
4139 if (prev_mod != node->module) {
4140 mod_len = strlen(node->module->name);
4141 } else {
4142 mod_len = 0;
4143 }
4144
4145 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
4146 LOGINT;
4147 return NULL;
4148 }
4149
4150 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
4151
4152 buf[buf_idx] = '/';
4153 if (mod_len) {
4154 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
4155 buf[buf_idx + 1 + mod_len] = ':';
4156 }
4157 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
4158 }
4159
4160 node = lys_parent(node);
4161 }
4162
4163 return buf + buf_idx;
4164}
4165
Michal Vasko8548e082016-07-22 12:00:18 +02004166#endif
4167
4168API struct ly_set *
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004169lys_xpath_atomize(const struct lys_node *ctx_node, enum lyxp_node_type ctx_node_type, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02004170{
Michal Vasko508a50d2016-09-07 14:50:33 +02004171 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02004172 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004173 uint32_t i;
4174
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004175 if (!ctx_node || !expr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004176 LOGARG;
Michal Vasko8548e082016-07-22 12:00:18 +02004177 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004178 }
4179
Michal Vaskob94a5e42016-09-08 14:01:56 +02004180 /* adjust the root */
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004181 if ((ctx_node_type == LYXP_NODE_ROOT) || (ctx_node_type == LYXP_NODE_ROOT_CONFIG)) {
Michal Vaskob94a5e42016-09-08 14:01:56 +02004182 do {
Michal Vaskocb45f472018-02-12 10:47:42 +01004183 ctx_node = lys_getnext(NULL, NULL, lys_node_module(ctx_node), LYS_GETNEXT_NOSTATECHECK);
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004184 } while ((ctx_node_type == LYXP_NODE_ROOT_CONFIG) && (ctx_node->flags & LYS_CONFIG_R));
Michal Vaskob94a5e42016-09-08 14:01:56 +02004185 }
4186
Michal Vasko508a50d2016-09-07 14:50:33 +02004187 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02004188
4189 if (options & LYXP_MUST) {
4190 options &= ~LYXP_MUST;
4191 options |= LYXP_SNODE_MUST;
4192 } else if (options & LYXP_WHEN) {
4193 options &= ~LYXP_WHEN;
4194 options |= LYXP_SNODE_WHEN;
4195 } else {
4196 options |= LYXP_SNODE;
4197 }
4198
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004199 if (lyxp_atomize(expr, ctx_node, ctx_node_type, &set, options, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004200 free(set.val.snodes);
Michal Vasko53b7da02018-02-13 15:28:42 +01004201 LOGVAL(ctx_node->module->ctx, LYE_SPEC, LY_VLOG_LYS, ctx_node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02004202 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004203 }
4204
Michal Vasko8548e082016-07-22 12:00:18 +02004205 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02004206
Michal Vasko508a50d2016-09-07 14:50:33 +02004207 for (i = 0; i < set.used; ++i) {
4208 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02004209 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02004210 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02004211 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02004212 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02004213 return NULL;
4214 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02004215 break;
4216 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02004217 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02004218 break;
4219 }
4220 }
4221
Michal Vasko508a50d2016-09-07 14:50:33 +02004222 free(set.val.snodes);
4223 return ret_set;
4224}
4225
4226API struct ly_set *
4227lys_node_xpath_atomize(const struct lys_node *node, int options)
4228{
4229 const struct lys_node *next, *elem, *parent, *tmp;
4230 struct lyxp_set set;
4231 struct ly_set *ret_set;
4232 uint16_t i;
4233
4234 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004235 LOGARG;
Michal Vasko508a50d2016-09-07 14:50:33 +02004236 return NULL;
4237 }
4238
4239 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
4240 if (!parent) {
4241 /* not in input, output, or notification */
4242 return NULL;
4243 }
4244
4245 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02004246 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004247 return NULL;
4248 }
4249
4250 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoc04173b2018-03-09 10:43:22 +01004251 if ((options & LYXP_NO_LOCAL) && !(elem->flags & (LYS_XPCONF_DEP | LYS_XPSTATE_DEP))) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004252 /* elem has no dependencies from other subtrees and local nodes get discarded */
4253 goto next_iter;
4254 }
4255
Michal Vaskof96dfb62017-08-17 12:23:49 +02004256 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004257 ly_set_free(ret_set);
4258 free(set.val.snodes);
4259 return NULL;
4260 }
4261
4262 for (i = 0; i < set.used; ++i) {
4263 switch (set.val.snodes[i].type) {
4264 case LYXP_NODE_ELEM:
4265 if (options & LYXP_NO_LOCAL) {
4266 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
4267 if (tmp) {
4268 /* in local subtree, discard */
4269 break;
4270 }
4271 }
4272 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
4273 ly_set_free(ret_set);
4274 free(set.val.snodes);
4275 return NULL;
4276 }
4277 break;
4278 default:
4279 /* ignore roots, text and attr should not ever appear */
4280 break;
4281 }
4282 }
4283
4284 free(set.val.snodes);
4285 if (!(options & LYXP_RECURSIVE)) {
4286 break;
4287 }
4288next_iter:
4289 LY_TREE_DFS_END(node, next, elem);
4290 }
4291
Michal Vasko8548e082016-07-22 12:00:18 +02004292 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004293}
4294
Michal Vasko44ab1462017-05-18 13:18:36 +02004295/* logs */
4296int
4297apply_aug(struct lys_node_augment *augment, struct unres_schema *unres)
Radek Krejci0ec51da2016-12-14 16:42:03 +01004298{
Michal Vasko44ab1462017-05-18 13:18:36 +02004299 struct lys_node *child, *parent;
4300 int clear_config;
4301 unsigned int u;
Michal Vaskod02e30e2018-01-22 13:35:48 +01004302 uint8_t *v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004303 struct lys_ext_instance *ext;
Adam Weast4ca7edd2018-06-14 08:59:22 -05004304
Radek Krejci0ec51da2016-12-14 16:42:03 +01004305 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
4306
Radek Krejcic9d78692017-08-24 17:17:18 +02004307 if (!augment->child) {
4308 /* nothing to apply */
4309 goto success;
4310 }
4311
Radek Krejci0ec51da2016-12-14 16:42:03 +01004312 /* reconnect augmenting data into the target - add them to the target child list */
4313 if (augment->target->child) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004314 child = augment->target->child->prev;
4315 child->next = augment->child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004316 augment->target->child->prev = augment->child->prev;
Michal Vasko44ab1462017-05-18 13:18:36 +02004317 augment->child->prev = child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004318 } else {
4319 augment->target->child = augment->child;
4320 }
4321
Michal Vasko44ab1462017-05-18 13:18:36 +02004322 /* inherit config information from actual parent */
4323 for (parent = augment->target; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); parent = lys_parent(parent));
4324 clear_config = (parent) ? 1 : 0;
4325 LY_TREE_FOR(augment->child, child) {
4326 if (inherit_config_flag(child, augment->target->flags & LYS_CONFIG_MASK, clear_config)) {
4327 return -1;
4328 }
4329 }
4330
4331 /* inherit extensions if any */
4332 for (u = 0; u < augment->target->ext_size; u++) {
4333 ext = augment->target->ext[u]; /* shortcut */
4334 if (ext && ext->def->plugin && (ext->def->plugin->flags & LYEXT_OPT_INHERIT)) {
Michal Vaskod02e30e2018-01-22 13:35:48 +01004335 v = malloc(sizeof *v);
Michal Vasko53b7da02018-02-13 15:28:42 +01004336 LY_CHECK_ERR_RETURN(!v, LOGMEM(augment->module->ctx), -1);
Michal Vaskod02e30e2018-01-22 13:35:48 +01004337 *v = u;
4338 if (unres_schema_add_node(lys_main_module(augment->module), unres, &augment->target->ext,
4339 UNRES_EXT_FINALIZE, (struct lys_node *)v) == -1) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004340 /* something really bad happend since the extension finalization is not actually
4341 * being resolved while adding into unres, so something more serious with the unres
4342 * list itself must happened */
4343 return -1;
4344 }
4345 }
4346 }
4347
Radek Krejcic9d78692017-08-24 17:17:18 +02004348success:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004349 /* remove the flag about not applicability */
4350 augment->flags &= ~LYS_NOTAPPLIED;
Michal Vasko44ab1462017-05-18 13:18:36 +02004351 return EXIT_SUCCESS;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004352}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004353
Radek Krejcib2541a32016-12-12 16:45:57 +01004354static void
4355remove_aug(struct lys_node_augment *augment)
4356{
4357 struct lys_node *last, *elem;
4358
Michal Vaskof1aa47d2017-09-21 12:09:29 +02004359 if ((augment->flags & LYS_NOTAPPLIED) || !augment->target) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004360 /* skip already not applied augment */
Radek Krejcib2541a32016-12-12 16:45:57 +01004361 return;
4362 }
4363
4364 elem = augment->child;
4365 if (elem) {
4366 LY_TREE_FOR(elem, last) {
4367 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
4368 break;
4369 }
4370 }
4371 /* elem is first augment child, last is the last child */
4372
4373 /* parent child ptr */
4374 if (augment->target->child == elem) {
4375 augment->target->child = last->next;
4376 }
4377
4378 /* parent child next ptr */
4379 if (elem->prev->next) {
4380 elem->prev->next = last->next;
4381 }
4382
4383 /* parent child prev ptr */
4384 if (last->next) {
4385 last->next->prev = elem->prev;
4386 } else if (augment->target->child) {
4387 augment->target->child->prev = elem->prev;
4388 }
4389
4390 /* update augment children themselves */
4391 elem->prev = last;
4392 last->next = NULL;
4393 }
4394
Radek Krejci0ec51da2016-12-14 16:42:03 +01004395 /* augment->target still keeps the resolved target, but for lys_augment_free()
4396 * we have to keep information that this augment is not applied to free its data */
4397 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01004398}
4399
Radek Krejci30bfcd22017-01-27 16:54:48 +01004400/*
4401 * @param[in] module - the module where the deviation is defined
4402 */
4403static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004404lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004405{
Radek Krejcic9d78692017-08-24 17:17:18 +02004406 int ret, reapply = 0;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004407 char *parent_path;
4408 struct lys_node *target = NULL, *parent;
Michal Vasko5df038e2018-08-02 09:41:26 +02004409 struct lys_node_inout *inout;
Michal Vasko50576712017-07-28 12:28:33 +02004410 struct ly_set *set;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004411
4412 if (!dev->deviate) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004413 return;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004414 }
4415
4416 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
4417 if (dev->orig_node) {
4418 /* removing not-supported deviation ... */
4419 if (strrchr(dev->target_name, '/') != dev->target_name) {
4420 /* ... from a parent */
4421
4422 /* reconnect to its previous position */
4423 parent = dev->orig_node->parent;
Michal Vaskoa1074a52018-01-03 12:18:53 +01004424 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejcic9d78692017-08-24 17:17:18 +02004425 dev->orig_node->parent = NULL;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004426 /* the original node was actually from augment, we have to get know if the augment is
4427 * applied (its module is enabled and implemented). If yes, the node will be connected
4428 * to the augment and the linkage with the target will be fixed if needed, otherwise
4429 * it will be connected only to the augment */
Radek Krejcic9d78692017-08-24 17:17:18 +02004430 if (!(parent->flags & LYS_NOTAPPLIED)) {
4431 /* start with removing augment if applied before adding nodes, we have to make sure
4432 * that everything will be connect correctly */
4433 remove_aug((struct lys_node_augment *)parent);
4434 reapply = 1;
4435 }
4436 /* connect the deviated node back into the augment */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004437 lys_node_addchild(parent, NULL, dev->orig_node, 0);
Radek Krejcic9d78692017-08-24 17:17:18 +02004438 if (reapply) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004439 /* augment is supposed to be applied, so fix pointers in target and the status of the original node */
Michal Vasko74083ec2018-06-15 10:00:12 +02004440 assert(lys_node_module(parent)->implemented);
Michal Vasko823fbe02017-12-14 11:01:40 +01004441 parent->flags |= LYS_NOTAPPLIED; /* allow apply_aug() */
4442 apply_aug((struct lys_node_augment *)parent, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004443 }
Michal Vaskoa1074a52018-01-03 12:18:53 +01004444 } else if (parent && (parent->nodetype == LYS_USES)) {
4445 /* uses child */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004446 lys_node_addchild(parent, NULL, dev->orig_node, 0);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004447 } else {
4448 /* non-augment, non-toplevel */
4449 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
Michal Vasko50576712017-07-28 12:28:33 +02004450 ret = resolve_schema_nodeid(parent_path, NULL, module, &set, 0, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004451 free(parent_path);
Michal Vasko50576712017-07-28 12:28:33 +02004452 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004453 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004454 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004455 return;
4456 }
Michal Vasko50576712017-07-28 12:28:33 +02004457 target = set->set.s[0];
4458 ly_set_free(set);
4459
Michal Vasko8d30dd82018-09-10 10:06:12 +02004460 lys_node_addchild(target, NULL, dev->orig_node, 0);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004461 }
4462 } else {
4463 /* ... from top-level data */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004464 lys_node_addchild(NULL, (struct lys_module *)dev->orig_node->module, dev->orig_node, 0);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004465 }
4466
4467 dev->orig_node = NULL;
4468 } else {
4469 /* adding not-supported deviation */
Michal Vasko50576712017-07-28 12:28:33 +02004470 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4471 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004472 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004473 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004474 return;
4475 }
Michal Vasko50576712017-07-28 12:28:33 +02004476 target = set->set.s[0];
4477 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004478
4479 /* unlink and store the original node */
4480 parent = target->parent;
4481 lys_node_unlink(target);
Michal Vasko5df038e2018-08-02 09:41:26 +02004482 if (parent) {
4483 if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
4484 /* hack for augment, because when the original will be sometime reconnected back, we actually need
4485 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
4486 * path), so we need to remember the augment as an addition */
4487 /* we also need to remember the parent uses so that we connect it back to it when switching deviation state */
4488 target->parent = parent;
4489 } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
4490 /* re-create implicit node */
4491 inout = calloc(1, sizeof *inout);
4492 LY_CHECK_ERR_RETURN(!inout, LOGMEM(module->ctx), );
4493
4494 inout->nodetype = target->nodetype;
4495 inout->name = lydict_insert(module->ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
4496 inout->module = target->module;
4497 inout->flags = LYS_IMPLICIT;
4498
4499 /* insert it manually */
4500 assert(parent->child && !parent->child->next
4501 && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
4502 parent->child->next = (struct lys_node *)inout;
4503 inout->prev = parent->child;
4504 parent->child->prev = (struct lys_node *)inout;
4505 inout->parent = parent;
4506 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01004507 }
4508 dev->orig_node = target;
4509 }
4510 } else {
Michal Vasko50576712017-07-28 12:28:33 +02004511 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4512 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004513 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004514 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004515 return;
4516 }
Michal Vasko50576712017-07-28 12:28:33 +02004517 target = set->set.s[0];
4518 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004519
Michal Vasko81c71442018-08-03 12:56:53 +02004520 /* contents are switched */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004521 lys_node_switch(target, dev->orig_node);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004522 }
4523}
4524
4525/* temporarily removes or applies deviations, updates module deviation flag accordingly */
4526void
Michal Vasko5a65f212018-03-19 15:08:08 +01004527lys_enable_deviations(struct lys_module *module)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004528{
4529 uint32_t i = 0, j;
4530 const struct lys_module *mod;
4531 const char *ptr;
Michal Vasko44ab1462017-05-18 13:18:36 +02004532 struct unres_schema *unres;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004533
4534 if (module->deviated) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004535 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004536 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Michal Vasko44ab1462017-05-18 13:18:36 +02004537
Radek Krejci30bfcd22017-01-27 16:54:48 +01004538 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
4539 if (mod == module) {
4540 continue;
4541 }
4542
4543 for (j = 0; j < mod->deviation_size; ++j) {
4544 ptr = strstr(mod->deviation[j].target_name, module->name);
4545 if (ptr && ptr[strlen(module->name)] == ':') {
Michal Vasko44ab1462017-05-18 13:18:36 +02004546 lys_switch_deviation(&mod->deviation[j], mod, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004547 }
4548 }
4549 }
4550
Michal Vasko5a65f212018-03-19 15:08:08 +01004551 assert(module->deviated == 2);
4552 module->deviated = 1;
4553
4554 for (j = 0; j < module->inc_size; j++) {
4555 if (module->inc[j].submodule->deviated) {
4556 module->inc[j].submodule->deviated = module->deviated;
4557 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01004558 }
Michal Vasko5a65f212018-03-19 15:08:08 +01004559
4560 if (unres->count) {
4561 resolve_unres_schema(module, unres);
4562 }
4563 unres_schema_free(module, &unres, 1);
4564 }
4565}
4566
4567void
4568lys_disable_deviations(struct lys_module *module)
4569{
4570 uint32_t i, j;
4571 const struct lys_module *mod;
4572 const char *ptr;
4573 struct unres_schema *unres;
4574
4575 if (module->deviated) {
4576 unres = calloc(1, sizeof *unres);
4577 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
4578
4579 i = module->ctx->models.used;
4580 while (i--) {
4581 mod = module->ctx->models.list[i];
4582
4583 if (mod == module) {
4584 continue;
4585 }
4586
4587 j = mod->deviation_size;
4588 while (j--) {
4589 ptr = strstr(mod->deviation[j].target_name, module->name);
4590 if (ptr && ptr[strlen(module->name)] == ':') {
4591 lys_switch_deviation(&mod->deviation[j], mod, unres);
4592 }
4593 }
4594 }
4595
4596 assert(module->deviated == 1);
4597 module->deviated = 2;
4598
Radek Krejci29eac3d2017-06-01 16:50:02 +02004599 for (j = 0; j < module->inc_size; j++) {
4600 if (module->inc[j].submodule->deviated) {
4601 module->inc[j].submodule->deviated = module->deviated;
4602 }
4603 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004604
4605 if (unres->count) {
4606 resolve_unres_schema(module, unres);
4607 }
4608 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004609 }
4610}
4611
4612static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004613apply_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004614{
Michal Vasko44ab1462017-05-18 13:18:36 +02004615 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004616
4617 assert(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004618 lys_node_module(dev->orig_node)->deviated = 1; /* main module */
4619 dev->orig_node->module->deviated = 1; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004620}
4621
4622static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004623remove_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004624{
4625 uint32_t idx = 0, j;
4626 const struct lys_module *mod;
Radek Krejci29eac3d2017-06-01 16:50:02 +02004627 struct lys_module *target_mod, *target_submod;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004628 const char *ptr;
4629
4630 if (dev->orig_node) {
4631 target_mod = lys_node_module(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004632 target_submod = dev->orig_node->module;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004633 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004634 LOGINT(module->ctx);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004635 return;
4636 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004637 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004638
4639 /* clear the deviation flag if possible */
4640 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4641 if ((mod == module) || (mod == target_mod)) {
4642 continue;
4643 }
4644
4645 for (j = 0; j < mod->deviation_size; ++j) {
4646 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4647 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4648 /* some other module deviation targets the inspected module, flag remains */
4649 break;
4650 }
4651 }
4652
4653 if (j < mod->deviation_size) {
4654 break;
4655 }
4656 }
4657
4658 if (!mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02004659 target_mod->deviated = 0; /* main module */
4660 target_submod->deviated = 0; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004661 }
4662}
4663
4664void
4665lys_sub_module_apply_devs_augs(struct lys_module *module)
4666{
4667 uint8_t u, v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004668 struct unres_schema *unres;
4669
Michal Vasko74083ec2018-06-15 10:00:12 +02004670 assert(module->implemented);
4671
Michal Vasko44ab1462017-05-18 13:18:36 +02004672 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004673 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Radek Krejci30bfcd22017-01-27 16:54:48 +01004674
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004675 /* apply deviations */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004676 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004677 apply_dev(&module->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004678 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004679 /* apply augments */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004680 for (u = 0; u < module->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004681 apply_aug(&module->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004682 }
4683
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004684 /* apply deviations and augments defined in submodules */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004685 for (v = 0; v < module->inc_size; ++v) {
4686 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004687 apply_dev(&module->inc[v].submodule->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004688 }
4689
4690 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004691 apply_aug(&module->inc[v].submodule->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004692 }
4693 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004694
4695 if (unres->count) {
4696 resolve_unres_schema(module, unres);
4697 }
4698 /* nothing else left to do even if something is not resolved */
4699 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004700}
4701
Radek Krejcib2541a32016-12-12 16:45:57 +01004702void
4703lys_sub_module_remove_devs_augs(struct lys_module *module)
4704{
4705 uint8_t u, v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004706 struct unres_schema *unres;
4707
4708 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004709 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Radek Krejcib2541a32016-12-12 16:45:57 +01004710
4711 /* remove applied deviations */
4712 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004713 /* the deviation could not be applied because it failed to be applied in the first place*/
Michal Vasko7427b262018-05-14 15:23:55 +02004714 if (module->deviation[u].orig_node) {
4715 remove_dev(&module->deviation[u], module, unres);
4716 }
Radek Krejcib2541a32016-12-12 16:45:57 +01004717 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004718 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004719 for (u = 0; u < module->augment_size; ++u) {
4720 remove_aug(&module->augment[u]);
4721 }
4722
4723 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004724 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01004725 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko7427b262018-05-14 15:23:55 +02004726 if (module->inc[v].submodule->deviation[u].orig_node) {
4727 remove_dev(&module->inc[v].submodule->deviation[u], module, unres);
4728 }
Radek Krejcidbc15262016-06-16 14:58:29 +02004729 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004730
Radek Krejcib2541a32016-12-12 16:45:57 +01004731 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4732 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004733 }
4734 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004735
4736 if (unres->count) {
4737 resolve_unres_schema(module, unres);
4738 }
4739 /* nothing else left to do even if something is not resolved */
4740 unres_schema_free(module, &unres, 1);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004741}
4742
Michal Vasko0f437062018-06-08 15:52:39 +02004743int
4744lys_make_implemented_r(struct lys_module *module, struct unres_schema *unres)
Radek Krejci27fe55e2016-09-13 17:13:35 +02004745{
Michal Vasko0f437062018-06-08 15:52:39 +02004746 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004747 struct lys_node *root, *next, *node;
Michal Vasko74083ec2018-06-15 10:00:12 +02004748 struct lys_module *target_module;
Michal Vasko0f437062018-06-08 15:52:39 +02004749 uint16_t i, j, k;
4750
4751 assert(module->implemented);
4752 ctx = module->ctx;
4753
4754 for (i = 0; i < ctx->models.used; ++i) {
4755 if (module == ctx->models.list[i]) {
4756 continue;
4757 }
4758
4759 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4760 LOGERR(ctx, LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
4761 return EXIT_FAILURE;
4762 }
4763 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004764
4765 for (i = 0; i < module->augment_size; i++) {
Michal Vasko74083ec2018-06-15 10:00:12 +02004766
4767 /* make target module implemented if was not */
4768 assert(module->augment[i].target);
4769 target_module = lys_node_module(module->augment[i].target);
4770 if (!target_module->implemented) {
4771 target_module->implemented = 1;
4772 if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
4773 return -1;
4774 }
4775 }
4776
Radek Krejci27fe55e2016-09-13 17:13:35 +02004777 /* apply augment */
Adam Weast368fd582018-06-14 13:32:35 -05004778 if ((module->augment[i].flags & LYS_NOTAPPLIED) && apply_aug(&module->augment[i], unres)) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004779 return EXIT_FAILURE;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004780 }
4781 }
Adam Weast4ca7edd2018-06-14 08:59:22 -05004782
Radek Krejci9e6af732017-04-27 14:40:25 +02004783 /* identities */
4784 for (i = 0; i < module->ident_size; i++) {
4785 for (j = 0; j < module->ident[i].base_size; j++) {
4786 resolve_identity_backlink_update(&module->ident[i], module->ident[i].base[j]);
4787 }
4788 }
4789
Michal Vasko0f437062018-06-08 15:52:39 +02004790 /* process augments in submodules */
4791 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
4792 module->inc[i].submodule->implemented = 1;
4793
4794 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
Michal Vasko74083ec2018-06-15 10:00:12 +02004795
4796 /* make target module implemented if it was not */
Michal Vaskoda267cb2018-06-15 11:18:00 +02004797 assert(module->inc[i].submodule->augment[j].target);
Michal Vasko74083ec2018-06-15 10:00:12 +02004798 target_module = lys_node_module(module->inc[i].submodule->augment[j].target);
4799 if (!target_module->implemented) {
4800 target_module->implemented = 1;
4801 if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
4802 return -1;
4803 }
4804 }
4805
Michal Vasko0f437062018-06-08 15:52:39 +02004806 /* apply augment */
Adam Weast368fd582018-06-14 13:32:35 -05004807 if ((module->inc[i].submodule->augment[j].flags & LYS_NOTAPPLIED) && apply_aug(&module->inc[i].submodule->augment[j], unres)) {
Michal Vasko0f437062018-06-08 15:52:39 +02004808 return EXIT_FAILURE;
4809 }
4810 }
4811
4812 /* identities */
4813 for (j = 0; j < module->inc[i].submodule->ident_size; j++) {
4814 for (k = 0; k < module->inc[i].submodule->ident[j].base_size; k++) {
4815 resolve_identity_backlink_update(&module->inc[i].submodule->ident[j],
4816 module->inc[i].submodule->ident[j].base[k]);
4817 }
4818 }
4819 }
4820
Radek Krejci27fe55e2016-09-13 17:13:35 +02004821 LY_TREE_FOR(module->data, root) {
4822 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4823 LY_TREE_DFS_BEGIN(root, next, node) {
4824 if (node->nodetype == LYS_GROUPING) {
4825 goto nextsibling;
4826 }
4827 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4828 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4829 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4830 UNRES_TYPE_LEAFREF, node) == -1) {
4831 return EXIT_FAILURE;
4832 }
4833 }
4834 }
4835
4836 /* modified LY_TREE_DFS_END */
4837 next = node->child;
4838 /* child exception for leafs, leaflists and anyxml without children */
4839 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4840 next = NULL;
4841 }
4842 if (!next) {
4843nextsibling:
4844 /* no children */
4845 if (node == root) {
4846 /* we are done, root has no children */
4847 break;
4848 }
4849 /* try siblings */
4850 next = node->next;
4851 }
4852 while (!next) {
4853 /* parent is already processed, go to its sibling */
4854 node = lys_parent(node);
4855 /* no siblings, go back through parents */
4856 if (lys_parent(node) == lys_parent(root)) {
4857 /* we are done, no next element to process */
4858 break;
4859 }
4860 next = node->next;
4861 }
4862 }
4863 }
4864
4865 return EXIT_SUCCESS;
4866}
4867
4868API int
4869lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004870{
Radek Krejci27fe55e2016-09-13 17:13:35 +02004871 struct unres_schema *unres;
Michal Vasko0f437062018-06-08 15:52:39 +02004872 int disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004873
Radek Krejci27fe55e2016-09-13 17:13:35 +02004874 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004875 LOGARG;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004876 return EXIT_FAILURE;
4877 }
4878
4879 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004880
4881 if (module->disabled) {
4882 disabled = 1;
4883 lys_set_enabled(module);
4884 }
4885
Michal Vasko26055752016-05-03 11:36:31 +02004886 if (module->implemented) {
4887 return EXIT_SUCCESS;
4888 }
4889
Radek Krejci27fe55e2016-09-13 17:13:35 +02004890 unres = calloc(1, sizeof *unres);
4891 if (!unres) {
Michal Vasko0f437062018-06-08 15:52:39 +02004892 LOGMEM(module->ctx);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004893 if (disabled) {
4894 /* set it back disabled */
4895 lys_set_disabled(module);
4896 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004897 return EXIT_FAILURE;
4898 }
4899 /* recursively make the module implemented */
4900 ((struct lys_module *)module)->implemented = 1;
Michal Vasko0f437062018-06-08 15:52:39 +02004901 if (lys_make_implemented_r((struct lys_module *)module, unres)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004902 goto error;
4903 }
Radek Krejci9e6af732017-04-27 14:40:25 +02004904
Radek Krejcidf46e222016-11-08 11:57:37 +01004905 /* try again resolve augments in other modules possibly augmenting this one,
4906 * since we have just enabled it
4907 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004908 /* resolve rest of unres items */
4909 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4910 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004911 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004912 unres_schema_free(NULL, &unres, 0);
Michal Vasko26055752016-05-03 11:36:31 +02004913
Michal Vaskobe136f62017-09-21 12:08:39 +02004914 LOGVRB("Module \"%s%s%s\" now implemented.", module->name, (module->rev_size ? "@" : ""),
4915 (module->rev_size ? module->rev[0].date : ""));
Michal Vasko26055752016-05-03 11:36:31 +02004916 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004917
4918error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004919 if (disabled) {
4920 /* set it back disabled */
4921 lys_set_disabled(module);
4922 }
4923
Radek Krejci27fe55e2016-09-13 17:13:35 +02004924 ((struct lys_module *)module)->implemented = 0;
Michal Vasko44ab1462017-05-18 13:18:36 +02004925 unres_schema_free((struct lys_module *)module, &unres, 1);
Radek Krejci27fe55e2016-09-13 17:13:35 +02004926 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004927}
4928
4929void
4930lys_submodule_module_data_free(struct lys_submodule *submodule)
4931{
4932 struct lys_node *next, *elem;
4933
4934 /* remove parsed data */
4935 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4936 if (elem->module == (struct lys_module *)submodule) {
4937 lys_node_free(elem, NULL, 0);
4938 }
4939 }
4940}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004941
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004942API char *
Michal Vasko395b0a02018-01-22 09:36:20 +01004943lys_path(const struct lys_node *node, int options)
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004944{
Michal Vasko53b7da02018-02-13 15:28:42 +01004945 char *buf = NULL;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004946
4947 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004948 LOGARG;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004949 return NULL;
4950 }
4951
Michal Vasko185b5272018-09-13 14:26:12 +02004952 if (ly_vlog_build_path(LY_VLOG_LYS, node, &buf, !options, 0)) {
Michal Vasko59631dd2017-10-02 11:56:11 +02004953 return NULL;
4954 }
4955
Michal Vasko53b7da02018-02-13 15:28:42 +01004956 return buf;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004957}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004958
Michal Vasko50576712017-07-28 12:28:33 +02004959API char *
4960lys_data_path(const struct lys_node *node)
4961{
Michal Vasko53b7da02018-02-13 15:28:42 +01004962 char *result = NULL, buf[1024];
PavolVicanb28bbff2018-02-21 00:44:02 +01004963 const char *separator, *name;
Michal Vasko50576712017-07-28 12:28:33 +02004964 int i, used;
4965 struct ly_set *set;
4966 const struct lys_module *prev_mod;
4967
4968 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004969 LOGARG;
Michal Vasko50576712017-07-28 12:28:33 +02004970 return NULL;
4971 }
4972
Michal Vaskod60a1a32018-05-23 16:31:22 +02004973 buf[0] = '\0';
Michal Vasko50576712017-07-28 12:28:33 +02004974 set = ly_set_new();
Michal Vasko53b7da02018-02-13 15:28:42 +01004975 LY_CHECK_ERR_GOTO(!set, LOGMEM(node->module->ctx), cleanup);
Michal Vasko50576712017-07-28 12:28:33 +02004976
4977 while (node) {
4978 ly_set_add(set, (void *)node, 0);
4979 do {
4980 node = lys_parent(node);
4981 } while (node && (node->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
4982 }
4983
4984 prev_mod = NULL;
4985 used = 0;
4986 for (i = set->number - 1; i > -1; --i) {
4987 node = set->set.s[i];
PavolVicanb28bbff2018-02-21 00:44:02 +01004988 if (node->nodetype == LYS_EXT) {
4989 if (strcmp(((struct lys_ext_instance *)node)->def->name, "yang-data")) {
4990 continue;
4991 }
4992 name = ((struct lys_ext_instance *)node)->arg_value;
4993 separator = ":#";
4994 } else {
4995 name = node->name;
4996 separator = ":";
4997 }
Michal Vasko50576712017-07-28 12:28:33 +02004998 used += sprintf(buf + used, "/%s%s%s", (lys_node_module(node) == prev_mod ? "" : lys_node_module(node)->name),
PavolVicanb28bbff2018-02-21 00:44:02 +01004999 (lys_node_module(node) == prev_mod ? "" : separator), name);
Michal Vasko50576712017-07-28 12:28:33 +02005000 prev_mod = lys_node_module(node);
5001 }
5002
5003 result = strdup(buf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005004 LY_CHECK_ERR_GOTO(!result, LOGMEM(node->module->ctx), cleanup);
Michal Vasko50576712017-07-28 12:28:33 +02005005
Michal Vasko53b7da02018-02-13 15:28:42 +01005006cleanup:
Michal Vasko50576712017-07-28 12:28:33 +02005007 ly_set_free(set);
Michal Vasko50576712017-07-28 12:28:33 +02005008 return result;
5009}
5010
Michal Vaskobb520442017-05-23 10:55:18 +02005011struct lys_node_augment *
5012lys_getnext_target_aug(struct lys_node_augment *last, const struct lys_module *mod, const struct lys_node *aug_target)
5013{
5014 int i, j, last_found;
5015
Michal Vaskob6906872018-03-12 11:35:09 +01005016 assert(mod && aug_target);
5017
Michal Vaskobb520442017-05-23 10:55:18 +02005018 if (!last) {
5019 last_found = 1;
5020 } else {
5021 last_found = 0;
5022 }
5023
5024 /* search module augments */
5025 for (i = 0; i < mod->augment_size; ++i) {
5026 if (!mod->augment[i].target) {
5027 /* still unresolved, skip */
5028 continue;
5029 }
5030
5031 if (mod->augment[i].target == aug_target) {
5032 if (last_found) {
5033 /* next match after last */
5034 return &mod->augment[i];
5035 }
5036
5037 if (&mod->augment[i] == last) {
5038 last_found = 1;
5039 }
5040 }
5041 }
5042
5043 /* search submodule augments */
5044 for (i = 0; i < mod->inc_size; ++i) {
5045 for (j = 0; j < mod->inc[i].submodule->augment_size; ++j) {
5046 if (!mod->inc[i].submodule->augment[j].target) {
5047 continue;
5048 }
5049
5050 if (mod->inc[i].submodule->augment[j].target == aug_target) {
5051 if (last_found) {
5052 /* next match after last */
5053 return &mod->inc[i].submodule->augment[j];
5054 }
5055
5056 if (&mod->inc[i].submodule->augment[j] == last) {
5057 last_found = 1;
5058 }
5059 }
5060 }
5061 }
5062
5063 return NULL;
5064}
5065
Michal Vasko50576712017-07-28 12:28:33 +02005066API struct ly_set *
5067lys_find_path(const struct lys_module *cur_module, const struct lys_node *cur_node, const char *path)
5068{
5069 struct ly_set *ret;
5070 int rc;
5071
5072 if ((!cur_module && !cur_node) || !path) {
5073 return NULL;
5074 }
5075
5076 rc = resolve_schema_nodeid(path, cur_node, cur_module, &ret, 1, 1);
5077 if (rc == -1) {
5078 return NULL;
5079 }
5080
5081 return ret;
5082}
5083
Radek Krejci8d6b7422017-02-03 14:42:13 +01005084static void
5085lys_extcomplex_free_str(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext, LY_STMT stmt)
5086{
5087 struct lyext_substmt *info;
Radek Krejcib71243e2017-02-08 16:20:08 +01005088 const char **str, ***a;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005089 int c;
5090
5091 str = lys_ext_complex_get_substmt(stmt, ext, &info);
5092 if (!str || !(*str)) {
5093 return;
5094 }
5095 if (info->cardinality >= LY_STMT_CARD_SOME) {
5096 /* we have array */
Radek Krejcib71243e2017-02-08 16:20:08 +01005097 a = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01005098 for (str = (*(const char ***)str), c = 0; str[c]; c++) {
5099 lydict_remove(ctx, str[c]);
Radek Krejci8d6b7422017-02-03 14:42:13 +01005100 }
Radek Krejci56c80412017-02-09 10:44:16 +01005101 free(a[0]);
5102 if (stmt == LY_STMT_BELONGSTO) {
5103 for (str = a[1], c = 0; str[c]; c++) {
5104 lydict_remove(ctx, str[c]);
5105 }
5106 free(a[1]);
PavolVican99c70722017-02-18 17:25:52 +01005107 } else if (stmt == LY_STMT_ARGUMENT) {
5108 free(a[1]);
Radek Krejci56c80412017-02-09 10:44:16 +01005109 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005110 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01005111 lydict_remove(ctx, str[0]);
5112 if (stmt == LY_STMT_BELONGSTO) {
5113 lydict_remove(ctx, str[1]);
5114 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005115 }
5116}
Michal Vasko1e82a3b2018-07-03 12:16:58 +02005117
Radek Krejci8d6b7422017-02-03 14:42:13 +01005118void
Radek Krejci5138e9f2017-04-12 13:10:46 +02005119lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size,
5120 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci8d6b7422017-02-03 14:42:13 +01005121{
Radek Krejcif8d05c22017-02-10 15:33:35 +01005122 unsigned int i, j, k;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005123 struct lyext_substmt *substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005124 void **pp, **start;
Radek Krejcif95b6292017-02-13 15:57:37 +01005125 struct lys_node *siter, *snext;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005126
5127#define EXTCOMPLEX_FREE_STRUCT(STMT, TYPE, FUNC, FREE, ARGS...) \
Radek Krejcib84686f2017-02-09 16:04:55 +01005128 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)e[i], NULL); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005129 if (!pp || !(*pp)) { break; } \
Radek Krejcib84686f2017-02-09 16:04:55 +01005130 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005131 for (start = pp = *pp; *pp; pp++) { \
Radek Krejci5138e9f2017-04-12 13:10:46 +02005132 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005133 if (FREE) { free(*pp); } \
5134 } \
5135 free(start); \
5136 } else { /* single item */ \
Radek Krejci5138e9f2017-04-12 13:10:46 +02005137 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005138 if (FREE) { free(*pp); } \
5139 }
5140
PavolVican9d61d402018-02-05 15:52:48 +01005141 if (!size || !e) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01005142 return;
5143 }
5144
5145 for (i = 0; i < size; i++) {
5146 if (!e[i]) {
5147 continue;
5148 }
5149
5150 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
5151 /* no free, this is just a shadow copy of the original extension instance */
5152 } else {
5153 if (e[i]->flags & (LYEXT_OPT_YANG)) {
5154 free(e[i]->def); /* remove name of instance extension */
PavolVican19dc6152017-02-06 12:04:15 +01005155 e[i]->def = NULL;
PavolVicandb0e8172017-02-20 00:46:09 +01005156 yang_free_ext_data((struct yang_ext_substmt *)e[i]->parent); /* remove backup part of yang file */
Radek Krejci8d6b7422017-02-03 14:42:13 +01005157 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02005158 /* remove private object */
5159 if (e[i]->priv && private_destructor) {
5160 private_destructor((struct lys_node*)e[i], e[i]->priv);
5161 }
5162 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size, private_destructor);
Radek Krejci8d6b7422017-02-03 14:42:13 +01005163 lydict_remove(ctx, e[i]->arg_value);
5164 }
5165
fanchanghu8d86f6b2017-06-10 12:49:54 +08005166 if (e[i]->def && e[i]->def->plugin && e[i]->def->plugin->type == LYEXT_COMPLEX
5167 && ((e[i]->flags & LYEXT_OPT_CONTENT) == 0)) {
Radek Krejcifebdad72017-02-06 11:35:51 +01005168 substmt = ((struct lys_ext_instance_complex *)e[i])->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005169 for (j = 0; substmt[j].stmt; j++) {
5170 switch(substmt[j].stmt) {
5171 case LY_STMT_DESCRIPTION:
5172 case LY_STMT_REFERENCE:
5173 case LY_STMT_UNITS:
Radek Krejcib71243e2017-02-08 16:20:08 +01005174 case LY_STMT_ARGUMENT:
5175 case LY_STMT_DEFAULT:
5176 case LY_STMT_ERRTAG:
5177 case LY_STMT_ERRMSG:
5178 case LY_STMT_PREFIX:
5179 case LY_STMT_NAMESPACE:
5180 case LY_STMT_PRESENCE:
5181 case LY_STMT_REVISIONDATE:
5182 case LY_STMT_KEY:
5183 case LY_STMT_BASE:
5184 case LY_STMT_BELONGSTO:
5185 case LY_STMT_CONTACT:
5186 case LY_STMT_ORGANIZATION:
5187 case LY_STMT_PATH:
Radek Krejci8d6b7422017-02-03 14:42:13 +01005188 lys_extcomplex_free_str(ctx, (struct lys_ext_instance_complex *)e[i], substmt[j].stmt);
5189 break;
5190 case LY_STMT_TYPE:
5191 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPE, struct lys_type, lys_type_free, 1);
5192 break;
Radek Krejci63fc0962017-02-15 13:20:18 +01005193 case LY_STMT_TYPEDEF:
5194 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPEDEF, struct lys_tpdf, lys_tpdf_free, 1);
5195 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005196 case LY_STMT_IFFEATURE:
Frank Rimplerc4db1c72017-09-12 12:56:39 +00005197 EXTCOMPLEX_FREE_STRUCT(LY_STMT_IFFEATURE, struct lys_iffeature, lys_iffeature_free, 0, 1, 0);
Radek Krejci8d6b7422017-02-03 14:42:13 +01005198 break;
Radek Krejci5496fae2017-02-10 13:26:48 +01005199 case LY_STMT_MAX:
5200 case LY_STMT_MIN:
5201 case LY_STMT_POSITION:
PavolVican2ed9f4e2017-02-16 00:08:45 +01005202 case LY_STMT_VALUE:
Radek Krejcif8d05c22017-02-10 15:33:35 +01005203 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
Radek Krejci716cd7a2017-02-15 12:23:41 +01005204 if (substmt[j].cardinality >= LY_STMT_CARD_SOME && *pp) {
Radek Krejcif8d05c22017-02-10 15:33:35 +01005205 for(k = 0; ((uint32_t**)(*pp))[k]; k++) {
5206 free(((uint32_t**)(*pp))[k]);
5207 }
5208 }
5209 free(*pp);
5210 break;
5211 case LY_STMT_DIGITS:
Radek Krejcib84686f2017-02-09 16:04:55 +01005212 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
5213 /* free the array */
5214 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5215 free(*pp);
5216 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005217 break;
Radek Krejci37f9ba32017-02-10 16:50:35 +01005218 case LY_STMT_MODULE:
5219 /* modules are part of the context, so they will be freed there */
5220 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
5221 /* free the array */
5222 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5223 free(*pp);
5224 }
5225 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01005226 case LY_STMT_ACTION:
Radek Krejcib31762b2017-02-15 10:48:42 +01005227 case LY_STMT_ANYDATA:
5228 case LY_STMT_ANYXML:
5229 case LY_STMT_CASE:
5230 case LY_STMT_CHOICE:
5231 case LY_STMT_CONTAINER:
5232 case LY_STMT_GROUPING:
5233 case LY_STMT_INPUT:
5234 case LY_STMT_LEAF:
5235 case LY_STMT_LEAFLIST:
5236 case LY_STMT_LIST:
5237 case LY_STMT_NOTIFICATION:
5238 case LY_STMT_OUTPUT:
5239 case LY_STMT_RPC:
5240 case LY_STMT_USES:
Radek Krejcif95b6292017-02-13 15:57:37 +01005241 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5242 LY_TREE_FOR_SAFE((struct lys_node *)(*pp), snext, siter) {
5243 lys_node_free(siter, NULL, 0);
5244 }
Radek Krejcib31762b2017-02-15 10:48:42 +01005245 *pp = NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01005246 break;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01005247 case LY_STMT_UNIQUE:
5248 pp = lys_ext_complex_get_substmt(LY_STMT_UNIQUE, (struct lys_ext_instance_complex *)e[i], NULL);
5249 if (!pp || !(*pp)) {
5250 break;
5251 }
5252 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
5253 for (start = pp = *pp; *pp; pp++) {
5254 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
5255 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
5256 }
5257 free((*(struct lys_unique**)pp)->expr);
5258 free(*pp);
5259 }
5260 free(start);
5261 } else { /* single item */
5262 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
5263 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
5264 }
5265 free((*(struct lys_unique**)pp)->expr);
5266 free(*pp);
5267 }
5268 break;
Radek Krejciaa9c5202017-02-15 16:10:14 +01005269 case LY_STMT_LENGTH:
5270 case LY_STMT_MUST:
5271 case LY_STMT_PATTERN:
5272 case LY_STMT_RANGE:
5273 EXTCOMPLEX_FREE_STRUCT(substmt[j].stmt, struct lys_restr, lys_restr_free, 1);
5274 break;
Radek Krejcic5cc5302017-02-16 10:07:46 +01005275 case LY_STMT_WHEN:
5276 EXTCOMPLEX_FREE_STRUCT(LY_STMT_WHEN, struct lys_when, lys_when_free, 0);
5277 break;
Radek Krejci7417a082017-02-16 11:07:59 +01005278 case LY_STMT_REVISION:
5279 pp = lys_ext_complex_get_substmt(LY_STMT_REVISION, (struct lys_ext_instance_complex *)e[i], NULL);
5280 if (!pp || !(*pp)) {
5281 break;
5282 }
5283 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
5284 for (start = pp = *pp; *pp; pp++) {
5285 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
5286 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
5287 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02005288 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01005289 free(*pp);
5290 }
5291 free(start);
5292 } else { /* single item */
5293 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
5294 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
5295 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02005296 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01005297 free(*pp);
5298 }
5299 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005300 default:
Radek Krejcib84686f2017-02-09 16:04:55 +01005301 /* nothing to free */
Radek Krejci8d6b7422017-02-03 14:42:13 +01005302 break;
5303 }
5304 }
5305 }
5306
5307 free(e[i]);
5308 }
5309 free(e);
5310
5311#undef EXTCOMPLEX_FREE_STRUCT
5312}