blob: cb37fbdfbcff8310905862ae0975615b29754084 [file] [log] [blame]
Michal Vasko1a7a7bd2020-10-16 14:39:15 +02001/**
2 * @file schema_compile_amend.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema compilation of augments, deviations, and refines.
5 *
6 * Copyright (c) 2015 - 2020 CESNET, z.s.p.o.
7 *
8 * 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
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#define _GNU_SOURCE
16
17#include "schema_compile_amend.h"
18
19#include <assert.h>
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020020#include <stddef.h>
21#include <stdint.h>
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020022#include <stdlib.h>
23#include <string.h>
24
25#include "common.h"
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020026#include "log.h"
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020027#include "plugins_exts.h"
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020028#include "schema_compile.h"
29#include "schema_compile_node.h"
30#include "set.h"
31#include "tree.h"
32#include "tree_data.h"
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020033#include "tree_schema.h"
34#include "tree_schema_internal.h"
35#include "xpath.h"
36
37static const struct lys_module *lys_schema_node_get_module(const struct ly_ctx *ctx, const char *nametest,
38 size_t nametest_len, const struct lysp_module *mod, const char **name, size_t *name_len);
39
40static LY_ERR
41lys_nodeid_check(struct lysc_ctx *ctx, const char *nodeid, ly_bool abs, struct lys_module **target_mod,
42 struct lyxp_expr **expr)
43{
44 LY_ERR ret = LY_SUCCESS;
45 struct lyxp_expr *e = NULL;
46 struct lys_module *tmod = NULL, *mod;
47 const char *nodeid_type = abs ? "absolute-schema-nodeid" : "descendant-schema-nodeid";
48 uint32_t i;
49
50 /* parse */
51 ret = lyxp_expr_parse(ctx->ctx, nodeid, strlen(nodeid), 0, &e);
52 if (ret) {
53 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s value \"%s\" - invalid syntax.",
54 nodeid_type, nodeid);
55 ret = LY_EVALID;
56 goto cleanup;
57 }
58
59 if (abs) {
60 /* absolute schema nodeid */
61 i = 0;
62 } else {
63 /* descendant schema nodeid */
64 if (e->tokens[0] != LYXP_TOKEN_NAMETEST) {
65 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid %s value \"%s\" - name test expected instead of \"%.*s\".",
66 nodeid_type, nodeid, e->tok_len[0], e->expr + e->tok_pos[0]);
67 ret = LY_EVALID;
68 goto cleanup;
69 }
70 i = 1;
71 }
72
73 /* check all the tokens */
74 for ( ; i < e->used; i += 2) {
75 if (e->tokens[i] != LYXP_TOKEN_OPER_PATH) {
76 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid %s value \"%s\" - \"/\" expected instead of \"%.*s\".",
77 nodeid_type, nodeid, e->tok_len[i], e->expr + e->tok_pos[i]);
78 ret = LY_EVALID;
79 goto cleanup;
80 } else if (e->used == i + 1) {
81 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
82 "Invalid %s value \"%s\" - unexpected end of expression.", nodeid_type, e->expr);
83 ret = LY_EVALID;
84 goto cleanup;
85 } else if (e->tokens[i + 1] != LYXP_TOKEN_NAMETEST) {
86 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid %s value \"%s\" - name test expected instead of \"%.*s\".",
87 nodeid_type, nodeid, e->tok_len[i + 1], e->expr + e->tok_pos[i + 1]);
88 ret = LY_EVALID;
89 goto cleanup;
90 } else if (abs) {
91 mod = (struct lys_module *)lys_schema_node_get_module(ctx->ctx, e->expr + e->tok_pos[i + 1],
92 e->tok_len[i + 1], ctx->pmod, NULL, NULL);
93 LY_CHECK_ERR_GOTO(!mod, ret = LY_EVALID, cleanup);
94
95 /* only keep the first module */
96 if (!tmod) {
97 tmod = mod;
98 }
99
100 /* all the modules must be implemented */
101 if (!mod->implemented) {
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100102 ret = lys_set_implemented(mod, NULL);
Michal Vasko1a7a7bd2020-10-16 14:39:15 +0200103 LY_CHECK_GOTO(ret, cleanup);
104 }
105 }
106 }
107
108cleanup:
109 if (ret || !expr) {
110 lyxp_expr_free(ctx->ctx, e);
111 e = NULL;
112 }
113 if (expr) {
114 *expr = ret ? NULL : e;
115 }
116 if (target_mod) {
117 *target_mod = ret ? NULL : tmod;
118 }
119 return ret;
120}
121
122/**
123 * @brief Check whether 2 schema nodeids match.
124 *
125 * @param[in] ctx libyang context.
126 * @param[in] exp1 First schema nodeid.
127 * @param[in] exp1p_mod Module of @p exp1 nodes without any prefix.
128 * @param[in] exp2 Second schema nodeid.
129 * @param[in] exp2_pmod Module of @p exp2 nodes without any prefix.
130 * @return Whether the schema nodeids match or not.
131 */
132static ly_bool
133lys_abs_schema_nodeid_match(const struct ly_ctx *ctx, const struct lyxp_expr *exp1, const struct lysp_module *exp1_pmod,
134 const struct lyxp_expr *exp2, const struct lysp_module *exp2_pmod)
135{
136 uint32_t i;
137 const struct lys_module *mod1, *mod2;
Radek Krejci2b18bf12020-11-06 11:20:20 +0100138 const char *name1 = NULL, *name2 = NULL;
139 size_t name1_len = 0, name2_len = 0;
Michal Vasko1a7a7bd2020-10-16 14:39:15 +0200140
141 if (exp1->used != exp2->used) {
142 return 0;
143 }
144
145 for (i = 0; i < exp1->used; ++i) {
146 assert(exp1->tokens[i] == exp2->tokens[i]);
147
148 if (exp1->tokens[i] == LYXP_TOKEN_NAMETEST) {
149 /* check modules of all the nodes in the node ID */
150 mod1 = lys_schema_node_get_module(ctx, exp1->expr + exp1->tok_pos[i], exp1->tok_len[i], exp1_pmod,
151 &name1, &name1_len);
152 assert(mod1);
153 mod2 = lys_schema_node_get_module(ctx, exp2->expr + exp2->tok_pos[i], exp2->tok_len[i], exp2_pmod,
154 &name2, &name2_len);
155 assert(mod2);
156
157 /* compare modules */
158 if (mod1 != mod2) {
159 return 0;
160 }
161
162 /* compare names */
163 if ((name1_len != name2_len) || strncmp(name1, name2, name1_len)) {
164 return 0;
165 }
166 }
167 }
168
169 return 1;
170}
171
172LY_ERR
173lys_precompile_uses_augments_refines(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, const struct lysc_node *ctx_node)
174{
175 LY_ERR ret = LY_SUCCESS;
176 LY_ARRAY_COUNT_TYPE u;
177 struct lyxp_expr *exp = NULL;
178 struct lysc_augment *aug;
179 struct lysc_refine *rfn;
180 struct lysp_refine **new_rfn;
181 uint32_t i;
182
183 LY_ARRAY_FOR(uses_p->augments, u) {
184 lysc_update_path(ctx, NULL, "{augment}");
185 lysc_update_path(ctx, NULL, uses_p->augments[u].nodeid);
186
187 /* parse the nodeid */
188 LY_CHECK_GOTO(ret = lys_nodeid_check(ctx, uses_p->augments[u].nodeid, 0, NULL, &exp), cleanup);
189
190 /* allocate new compiled augment and store it in the set */
191 aug = calloc(1, sizeof *aug);
192 LY_CHECK_ERR_GOTO(!aug, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
193 LY_CHECK_GOTO(ret = ly_set_add(&ctx->uses_augs, aug, 1, NULL), cleanup);
194
195 aug->nodeid = exp;
196 exp = NULL;
197 aug->nodeid_pmod = ctx->pmod;
198 aug->nodeid_ctx_node = ctx_node;
199 aug->aug_p = &uses_p->augments[u];
200
201 lysc_update_path(ctx, NULL, NULL);
202 lysc_update_path(ctx, NULL, NULL);
203 }
204
205 LY_ARRAY_FOR(uses_p->refines, u) {
206 lysc_update_path(ctx, NULL, "{refine}");
207 lysc_update_path(ctx, NULL, uses_p->refines[u].nodeid);
208
209 /* parse the nodeid */
210 LY_CHECK_GOTO(ret = lys_nodeid_check(ctx, uses_p->refines[u].nodeid, 0, NULL, &exp), cleanup);
211
212 /* try to find the node in already compiled refines */
213 rfn = NULL;
214 for (i = 0; i < ctx->uses_rfns.count; ++i) {
215 if (lys_abs_schema_nodeid_match(ctx->ctx, exp, ctx->pmod, ((struct lysc_refine *)ctx->uses_rfns.objs[i])->nodeid,
216 ctx->pmod)) {
217 rfn = ctx->uses_rfns.objs[i];
218 break;
219 }
220 }
221
222 if (!rfn) {
223 /* allocate new compiled refine */
224 rfn = calloc(1, sizeof *rfn);
225 LY_CHECK_ERR_GOTO(!rfn, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
226 LY_CHECK_GOTO(ret = ly_set_add(&ctx->uses_rfns, rfn, 1, NULL), cleanup);
227
228 rfn->nodeid = exp;
229 exp = NULL;
230 rfn->nodeid_pmod = ctx->pmod;
231 rfn->nodeid_ctx_node = ctx_node;
232 } else {
233 /* just free exp */
234 lyxp_expr_free(ctx->ctx, exp);
235 exp = NULL;
236 }
237
238 /* add new parsed refine structure */
239 LY_ARRAY_NEW_GOTO(ctx->ctx, rfn->rfns, new_rfn, ret, cleanup);
240 *new_rfn = &uses_p->refines[u];
241
242 lysc_update_path(ctx, NULL, NULL);
243 lysc_update_path(ctx, NULL, NULL);
244 }
245
246cleanup:
247 lyxp_expr_free(ctx->ctx, exp);
248 return ret;
249}
250
251static LY_ERR
252lysp_ext_dup(const struct ly_ctx *ctx, struct lysp_ext_instance *ext, const struct lysp_ext_instance *orig_ext)
253{
254 LY_ERR ret = LY_SUCCESS;
255
256 *ext = *orig_ext;
257 DUP_STRING(ctx, orig_ext->name, ext->name, ret);
258 DUP_STRING(ctx, orig_ext->argument, ext->argument, ret);
259
260 return ret;
261}
262
263static LY_ERR
264lysp_restr_dup(const struct ly_ctx *ctx, struct lysp_restr *restr, const struct lysp_restr *orig_restr)
265{
266 LY_ERR ret = LY_SUCCESS;
267
268 if (orig_restr) {
269 DUP_STRING(ctx, orig_restr->arg.str, restr->arg.str, ret);
270 restr->arg.mod = orig_restr->arg.mod;
271 DUP_STRING(ctx, orig_restr->emsg, restr->emsg, ret);
272 DUP_STRING(ctx, orig_restr->eapptag, restr->eapptag, ret);
273 DUP_STRING(ctx, orig_restr->dsc, restr->dsc, ret);
274 DUP_STRING(ctx, orig_restr->ref, restr->ref, ret);
275 DUP_ARRAY(ctx, orig_restr->exts, restr->exts, lysp_ext_dup);
276 }
277
278 return ret;
279}
280
281static LY_ERR
282lysp_string_dup(const struct ly_ctx *ctx, const char **str, const char **orig_str)
283{
284 LY_ERR ret = LY_SUCCESS;
285
286 DUP_STRING(ctx, *orig_str, *str, ret);
287
288 return ret;
289}
290
291LY_ERR
292lysp_qname_dup(const struct ly_ctx *ctx, struct lysp_qname *qname, const struct lysp_qname *orig_qname)
293{
294 LY_ERR ret = LY_SUCCESS;
295
296 if (!orig_qname->str) {
297 return LY_SUCCESS;
298 }
299
300 DUP_STRING(ctx, orig_qname->str, qname->str, ret);
301 assert(orig_qname->mod);
302 qname->mod = orig_qname->mod;
303
304 return ret;
305}
306
307static LY_ERR
308lysp_type_enum_dup(const struct ly_ctx *ctx, struct lysp_type_enum *enm, const struct lysp_type_enum *orig_enm)
309{
310 LY_ERR ret = LY_SUCCESS;
311
312 DUP_STRING(ctx, orig_enm->name, enm->name, ret);
313 DUP_STRING(ctx, orig_enm->dsc, enm->dsc, ret);
314 DUP_STRING(ctx, orig_enm->ref, enm->ref, ret);
315 enm->value = orig_enm->value;
316 DUP_ARRAY(ctx, orig_enm->iffeatures, enm->iffeatures, lysp_qname_dup);
317 DUP_ARRAY(ctx, orig_enm->exts, enm->exts, lysp_ext_dup);
318 enm->flags = orig_enm->flags;
319
320 return ret;
321}
322
323static LY_ERR
324lysp_type_dup(const struct ly_ctx *ctx, struct lysp_type *type, const struct lysp_type *orig_type)
325{
326 LY_ERR ret = LY_SUCCESS;
327
328 DUP_STRING_GOTO(ctx, orig_type->name, type->name, ret, done);
329
330 if (orig_type->range) {
331 type->range = calloc(1, sizeof *type->range);
332 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx), LY_EMEM);
333 LY_CHECK_RET(lysp_restr_dup(ctx, type->range, orig_type->range));
334 }
335
336 if (orig_type->length) {
337 type->length = calloc(1, sizeof *type->length);
338 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx), LY_EMEM);
339 LY_CHECK_RET(lysp_restr_dup(ctx, type->length, orig_type->length));
340 }
341
342 DUP_ARRAY(ctx, orig_type->patterns, type->patterns, lysp_restr_dup);
343 DUP_ARRAY(ctx, orig_type->enums, type->enums, lysp_type_enum_dup);
344 DUP_ARRAY(ctx, orig_type->bits, type->bits, lysp_type_enum_dup);
345 LY_CHECK_GOTO(ret = lyxp_expr_dup(ctx, orig_type->path, &type->path), done);
346 DUP_ARRAY(ctx, orig_type->bases, type->bases, lysp_string_dup);
347 DUP_ARRAY(ctx, orig_type->types, type->types, lysp_type_dup);
348 DUP_ARRAY(ctx, orig_type->exts, type->exts, lysp_ext_dup);
349
350 type->pmod = orig_type->pmod;
351 type->compiled = orig_type->compiled;
352
353 type->fraction_digits = orig_type->fraction_digits;
354 type->require_instance = orig_type->require_instance;
355 type->flags = orig_type->flags;
356
357done:
358 return ret;
359}
360
361static LY_ERR
362lysp_when_dup(const struct ly_ctx *ctx, struct lysp_when *when, const struct lysp_when *orig_when)
363{
364 LY_ERR ret = LY_SUCCESS;
365
366 DUP_STRING(ctx, orig_when->cond, when->cond, ret);
367 DUP_STRING(ctx, orig_when->dsc, when->dsc, ret);
368 DUP_STRING(ctx, orig_when->ref, when->ref, ret);
369 DUP_ARRAY(ctx, orig_when->exts, when->exts, lysp_ext_dup);
370
371 return ret;
372}
373
374static LY_ERR
375lysp_node_common_dup(const struct ly_ctx *ctx, struct lysp_node *node, const struct lysp_node *orig)
376{
377 LY_ERR ret = LY_SUCCESS;
378
379 node->parent = NULL;
380 node->nodetype = orig->nodetype;
381 node->flags = orig->flags;
382 node->next = NULL;
383 DUP_STRING(ctx, orig->name, node->name, ret);
384 DUP_STRING(ctx, orig->dsc, node->dsc, ret);
385 DUP_STRING(ctx, orig->ref, node->ref, ret);
386
387 if (orig->when) {
388 node->when = calloc(1, sizeof *node->when);
389 LY_CHECK_ERR_RET(!node->when, LOGMEM(ctx), LY_EMEM);
390 LY_CHECK_RET(lysp_when_dup(ctx, node->when, orig->when));
391 }
392
393 DUP_ARRAY(ctx, orig->iffeatures, node->iffeatures, lysp_qname_dup);
394 DUP_ARRAY(ctx, orig->exts, node->exts, lysp_ext_dup);
395
396 return ret;
397}
398
399static LY_ERR
400lysp_node_dup(const struct ly_ctx *ctx, struct lysp_node *node, const struct lysp_node *orig)
401{
402 LY_ERR ret = LY_SUCCESS;
403 struct lysp_node_container *cont;
404 const struct lysp_node_container *orig_cont;
405 struct lysp_node_leaf *leaf;
406 const struct lysp_node_leaf *orig_leaf;
407 struct lysp_node_leaflist *llist;
408 const struct lysp_node_leaflist *orig_llist;
409 struct lysp_node_list *list;
410 const struct lysp_node_list *orig_list;
411 struct lysp_node_choice *choice;
412 const struct lysp_node_choice *orig_choice;
413 struct lysp_node_case *cas;
414 const struct lysp_node_case *orig_cas;
415 struct lysp_node_anydata *any;
416 const struct lysp_node_anydata *orig_any;
417
418 assert(orig->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE | LYS_CASE | LYS_ANYDATA));
419
420 /* common part */
421 LY_CHECK_RET(lysp_node_common_dup(ctx, node, orig));
422
423 /* specific part */
424 switch (node->nodetype) {
425 case LYS_CONTAINER:
426 cont = (struct lysp_node_container *)node;
427 orig_cont = (const struct lysp_node_container *)orig;
428
429 DUP_ARRAY(ctx, orig_cont->musts, cont->musts, lysp_restr_dup);
430 DUP_STRING(ctx, orig_cont->presence, cont->presence, ret);
431 /* we do not need the rest */
432 break;
433 case LYS_LEAF:
434 leaf = (struct lysp_node_leaf *)node;
435 orig_leaf = (const struct lysp_node_leaf *)orig;
436
437 DUP_ARRAY(ctx, orig_leaf->musts, leaf->musts, lysp_restr_dup);
438 LY_CHECK_RET(lysp_type_dup(ctx, &leaf->type, &orig_leaf->type));
439 DUP_STRING(ctx, orig_leaf->units, leaf->units, ret);
440 LY_CHECK_RET(lysp_qname_dup(ctx, &leaf->dflt, &orig_leaf->dflt));
441 break;
442 case LYS_LEAFLIST:
443 llist = (struct lysp_node_leaflist *)node;
444 orig_llist = (const struct lysp_node_leaflist *)orig;
445
446 DUP_ARRAY(ctx, orig_llist->musts, llist->musts, lysp_restr_dup);
447 LY_CHECK_RET(lysp_type_dup(ctx, &llist->type, &orig_llist->type));
448 DUP_STRING(ctx, orig_llist->units, llist->units, ret);
449 DUP_ARRAY(ctx, orig_llist->dflts, llist->dflts, lysp_qname_dup);
450 llist->min = orig_llist->min;
451 llist->max = orig_llist->max;
452 break;
453 case LYS_LIST:
454 list = (struct lysp_node_list *)node;
455 orig_list = (const struct lysp_node_list *)orig;
456
457 DUP_ARRAY(ctx, orig_list->musts, list->musts, lysp_restr_dup);
458 DUP_STRING(ctx, orig_list->key, list->key, ret);
459 /* we do not need these arrays */
460 DUP_ARRAY(ctx, orig_list->uniques, list->uniques, lysp_qname_dup);
461 list->min = orig_list->min;
462 list->max = orig_list->max;
463 break;
464 case LYS_CHOICE:
465 choice = (struct lysp_node_choice *)node;
466 orig_choice = (const struct lysp_node_choice *)orig;
467
468 /* we do not need children */
469 LY_CHECK_RET(lysp_qname_dup(ctx, &choice->dflt, &orig_choice->dflt));
470 break;
471 case LYS_CASE:
472 cas = (struct lysp_node_case *)node;
473 orig_cas = (const struct lysp_node_case *)orig;
474
475 /* we do not need children */
476 (void)cas;
477 (void)orig_cas;
478 break;
479 case LYS_ANYDATA:
480 case LYS_ANYXML:
481 any = (struct lysp_node_anydata *)node;
482 orig_any = (const struct lysp_node_anydata *)orig;
483
484 DUP_ARRAY(ctx, orig_any->musts, any->musts, lysp_restr_dup);
485 break;
486 default:
487 LOGINT_RET(ctx);
488 }
489
490 return ret;
491}
492
493static LY_ERR
494lysp_action_inout_dup(const struct ly_ctx *ctx, struct lysp_action_inout *inout, const struct lysp_action_inout *orig)
495{
496 inout->parent = NULL;
497 inout->nodetype = orig->nodetype;
498 DUP_ARRAY(ctx, orig->musts, inout->musts, lysp_restr_dup);
499 /* we dot need these arrays */
500 DUP_ARRAY(ctx, orig->exts, inout->exts, lysp_ext_dup);
501
502 return LY_SUCCESS;
503}
504
505static LY_ERR
506lysp_action_dup(const struct ly_ctx *ctx, struct lysp_action *act, const struct lysp_action *orig)
507{
508 LY_ERR ret = LY_SUCCESS;
509
510 act->parent = NULL;
511 act->nodetype = orig->nodetype;
512 act->flags = orig->flags;
513 DUP_STRING(ctx, orig->name, act->name, ret);
514 DUP_STRING(ctx, orig->dsc, act->dsc, ret);
515 DUP_STRING(ctx, orig->ref, act->ref, ret);
516 DUP_ARRAY(ctx, orig->iffeatures, act->iffeatures, lysp_qname_dup);
517
518 act->input.nodetype = orig->input.nodetype;
519 act->output.nodetype = orig->output.nodetype;
520 /* we do not need choldren of in/out */
521 DUP_ARRAY(ctx, orig->exts, act->exts, lysp_ext_dup);
522
523 return ret;
524}
525
526static LY_ERR
527lysp_notif_dup(const struct ly_ctx *ctx, struct lysp_notif *notif, const struct lysp_notif *orig)
528{
529 LY_ERR ret = LY_SUCCESS;
530
531 notif->parent = NULL;
532 notif->nodetype = orig->nodetype;
533 notif->flags = orig->flags;
534 DUP_STRING(ctx, orig->name, notif->name, ret);
535 DUP_STRING(ctx, orig->dsc, notif->dsc, ret);
536 DUP_STRING(ctx, orig->ref, notif->ref, ret);
537 DUP_ARRAY(ctx, orig->iffeatures, notif->iffeatures, lysp_qname_dup);
538 DUP_ARRAY(ctx, orig->musts, notif->musts, lysp_restr_dup);
539 /* we do not need these arrays */
540 DUP_ARRAY(ctx, orig->exts, notif->exts, lysp_ext_dup);
541
542 return ret;
543}
544
545/**
546 * @brief Duplicate a single parsed node. Only attributes that are used in compilation are copied.
547 *
548 * @param[in] ctx libyang context.
549 * @param[in] pnode Node to duplicate.
550 * @param[in] with_links Whether to also copy any links (child, parent pointers).
551 * @param[out] dup_p Duplicated parsed node.
552 * @return LY_ERR value.
553 */
554static LY_ERR
555lysp_dup_single(const struct ly_ctx *ctx, const struct lysp_node *pnode, ly_bool with_links, struct lysp_node **dup_p)
556{
557 LY_ERR ret = LY_SUCCESS;
558 void *mem = NULL;
559
560 if (!pnode) {
561 *dup_p = NULL;
562 return LY_SUCCESS;
563 }
564
565 switch (pnode->nodetype) {
566 case LYS_CONTAINER:
567 mem = calloc(1, sizeof(struct lysp_node_container));
568 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
569 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
570 break;
571 case LYS_LEAF:
572 mem = calloc(1, sizeof(struct lysp_node_leaf));
573 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
574 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
575 break;
576 case LYS_LEAFLIST:
577 mem = calloc(1, sizeof(struct lysp_node_leaflist));
578 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
579 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
580 break;
581 case LYS_LIST:
582 mem = calloc(1, sizeof(struct lysp_node_list));
583 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
584 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
585 break;
586 case LYS_CHOICE:
587 mem = calloc(1, sizeof(struct lysp_node_choice));
588 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
589 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
590 break;
591 case LYS_CASE:
592 mem = calloc(1, sizeof(struct lysp_node_case));
593 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
594 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
595 break;
596 case LYS_ANYDATA:
597 case LYS_ANYXML:
598 mem = calloc(1, sizeof(struct lysp_node_anydata));
599 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
600 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
601 break;
602 case LYS_INPUT:
603 case LYS_OUTPUT:
604 mem = calloc(1, sizeof(struct lysp_action_inout));
605 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
606 LY_CHECK_GOTO(ret = lysp_action_inout_dup(ctx, mem, (struct lysp_action_inout *)pnode), cleanup);
607 break;
608 case LYS_ACTION:
609 case LYS_RPC:
610 mem = calloc(1, sizeof(struct lysp_action));
611 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
612 LY_CHECK_GOTO(ret = lysp_action_dup(ctx, mem, (struct lysp_action *)pnode), cleanup);
613 break;
614 case LYS_NOTIF:
615 mem = calloc(1, sizeof(struct lysp_notif));
616 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
617 LY_CHECK_GOTO(ret = lysp_notif_dup(ctx, mem, (struct lysp_notif *)pnode), cleanup);
618 break;
619 default:
620 LOGINT_RET(ctx);
621 }
622
623 if (with_links) {
624 /* copy also parent and child pointers */
625 ((struct lysp_node *)mem)->parent = pnode->parent;
626 switch (pnode->nodetype) {
627 case LYS_CONTAINER:
628 ((struct lysp_node_container *)mem)->child = ((struct lysp_node_container *)pnode)->child;
629 break;
630 case LYS_LIST:
631 ((struct lysp_node_list *)mem)->child = ((struct lysp_node_list *)pnode)->child;
632 break;
633 case LYS_CHOICE:
634 ((struct lysp_node_choice *)mem)->child = ((struct lysp_node_choice *)pnode)->child;
635 break;
636 case LYS_CASE:
637 ((struct lysp_node_case *)mem)->child = ((struct lysp_node_case *)pnode)->child;
638 break;
639 default:
640 break;
641 }
642 }
643
644cleanup:
645 if (ret) {
646 free(mem);
647 } else {
648 *dup_p = mem;
649 }
650 return ret;
651}
652
653#define AMEND_WRONG_NODETYPE(AMEND_STR, OP_STR, PROPERTY) \
654 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid %s of %s node - it is not possible to %s \"%s\" property.", \
655 AMEND_STR, lys_nodetype2str(target->nodetype), OP_STR, PROPERTY);\
656 ret = LY_EVALID; \
657 goto cleanup;
658
659#define AMEND_CHECK_CARDINALITY(ARRAY, MAX, AMEND_STR, PROPERTY) \
660 if (LY_ARRAY_COUNT(ARRAY) > MAX) { \
661 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Invalid %s of %s with too many (%"LY_PRI_ARRAY_COUNT_TYPE") %s properties.", \
662 AMEND_STR, lys_nodetype2str(target->nodetype), LY_ARRAY_COUNT(ARRAY), PROPERTY); \
663 ret = LY_EVALID; \
664 goto cleanup; \
665 }
666
667/**
668 * @brief Apply refine.
669 *
670 * @param[in] ctx Compile context.
671 * @param[in] rfn Refine to apply.
672 * @param[in,out] target Refine target.
673 * @return LY_ERR value.
674 */
675static LY_ERR
676lys_apply_refine(struct lysc_ctx *ctx, struct lysp_refine *rfn, struct lysp_node *target)
677{
678 LY_ERR ret = LY_SUCCESS;
679 LY_ARRAY_COUNT_TYPE u;
680 struct lysp_qname *qname;
681 struct lysp_restr **musts, *must;
682 uint32_t *num;
683
684 /* default value */
685 if (rfn->dflts) {
686 switch (target->nodetype) {
687 case LYS_LEAF:
688 AMEND_CHECK_CARDINALITY(rfn->dflts, 1, "refine", "default");
689
690 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str);
691 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &((struct lysp_node_leaf *)target)->dflt, &rfn->dflts[0]), cleanup);
692 break;
693 case LYS_LEAFLIST:
694 if (rfn->dflts[0].mod->version < LYS_VERSION_1_1) {
695 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
696 "Invalid refine of default in leaf-list - the default statement is allowed only in YANG 1.1 modules.");
697 ret = LY_EVALID;
698 goto cleanup;
699 }
700
701 FREE_ARRAY(ctx->ctx, ((struct lysp_node_leaflist *)target)->dflts, lysp_qname_free);
702 ((struct lysp_node_leaflist *)target)->dflts = NULL;
703 LY_ARRAY_FOR(rfn->dflts, u) {
704 LY_ARRAY_NEW_GOTO(ctx->ctx, ((struct lysp_node_leaflist *)target)->dflts, qname, ret, cleanup);
705 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, qname, &rfn->dflts[u]), cleanup);
706 }
707 break;
708 case LYS_CHOICE:
709 AMEND_CHECK_CARDINALITY(rfn->dflts, 1, "refine", "default");
710
711 FREE_STRING(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str);
712 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &((struct lysp_node_choice *)target)->dflt, &rfn->dflts[0]), cleanup);
713 break;
714 default:
715 AMEND_WRONG_NODETYPE("refine", "replace", "default");
716 }
717 }
718
719 /* description */
720 if (rfn->dsc) {
721 FREE_STRING(ctx->ctx, target->dsc);
722 DUP_STRING_GOTO(ctx->ctx, rfn->dsc, target->dsc, ret, cleanup);
723 }
724
725 /* reference */
726 if (rfn->ref) {
727 FREE_STRING(ctx->ctx, target->ref);
728 DUP_STRING_GOTO(ctx->ctx, rfn->ref, target->ref, ret, cleanup);
729 }
730
731 /* config */
732 if (rfn->flags & LYS_CONFIG_MASK) {
733 if (ctx->options & (LYS_COMPILE_NOTIFICATION | LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT)) {
734 LOGWRN(ctx->ctx, "Refining config inside %s has no effect (%s).",
735 ctx->options & LYS_COMPILE_NOTIFICATION ? "notification" : "RPC/action", ctx->path);
736 } else {
737 target->flags &= ~LYS_CONFIG_MASK;
738 target->flags |= rfn->flags & LYS_CONFIG_MASK;
739 }
740 }
741
742 /* mandatory */
743 if (rfn->flags & LYS_MAND_MASK) {
744 switch (target->nodetype) {
745 case LYS_LEAF:
746 case LYS_CHOICE:
747 case LYS_ANYDATA:
748 case LYS_ANYXML:
749 break;
750 default:
751 AMEND_WRONG_NODETYPE("refine", "replace", "mandatory");
752 }
753
754 target->flags &= ~LYS_MAND_MASK;
755 target->flags |= rfn->flags & LYS_MAND_MASK;
756 }
757
758 /* presence */
759 if (rfn->presence) {
760 switch (target->nodetype) {
761 case LYS_CONTAINER:
762 break;
763 default:
764 AMEND_WRONG_NODETYPE("refine", "replace", "presence");
765 }
766
767 FREE_STRING(ctx->ctx, ((struct lysp_node_container *)target)->presence);
768 DUP_STRING_GOTO(ctx->ctx, rfn->presence, ((struct lysp_node_container *)target)->presence, ret, cleanup);
769 }
770
771 /* must */
772 if (rfn->musts) {
773 switch (target->nodetype) {
774 case LYS_CONTAINER:
775 case LYS_LIST:
776 case LYS_LEAF:
777 case LYS_LEAFLIST:
778 case LYS_ANYDATA:
779 case LYS_ANYXML:
780 musts = &((struct lysp_node_container *)target)->musts;
781 break;
782 default:
783 AMEND_WRONG_NODETYPE("refine", "add", "must");
784 }
785
786 LY_ARRAY_FOR(rfn->musts, u) {
787 LY_ARRAY_NEW_GOTO(ctx->ctx, *musts, must, ret, cleanup);
788 LY_CHECK_GOTO(ret = lysp_restr_dup(ctx->ctx, must, &rfn->musts[u]), cleanup);
789 }
790 }
791
792 /* min-elements */
793 if (rfn->flags & LYS_SET_MIN) {
794 switch (target->nodetype) {
795 case LYS_LEAFLIST:
796 num = &((struct lysp_node_leaflist *)target)->min;
797 break;
798 case LYS_LIST:
799 num = &((struct lysp_node_list *)target)->min;
800 break;
801 default:
802 AMEND_WRONG_NODETYPE("refine", "replace", "min-elements");
803 }
804
805 *num = rfn->min;
806 }
807
808 /* max-elements */
809 if (rfn->flags & LYS_SET_MAX) {
810 switch (target->nodetype) {
811 case LYS_LEAFLIST:
812 num = &((struct lysp_node_leaflist *)target)->max;
813 break;
814 case LYS_LIST:
815 num = &((struct lysp_node_list *)target)->max;
816 break;
817 default:
818 AMEND_WRONG_NODETYPE("refine", "replace", "max-elements");
819 }
820
821 *num = rfn->max;
822 }
823
824 /* if-feature */
825 if (rfn->iffeatures) {
826 switch (target->nodetype) {
827 case LYS_LEAF:
828 case LYS_LEAFLIST:
829 case LYS_LIST:
830 case LYS_CONTAINER:
831 case LYS_CHOICE:
832 case LYS_CASE:
833 case LYS_ANYDATA:
834 case LYS_ANYXML:
835 break;
836 default:
837 AMEND_WRONG_NODETYPE("refine", "add", "if-feature");
838 }
839
840 LY_ARRAY_FOR(rfn->iffeatures, u) {
841 LY_ARRAY_NEW_GOTO(ctx->ctx, target->iffeatures, qname, ret, cleanup);
842 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, qname, &rfn->iffeatures[u]), cleanup);
843 }
844 }
845
846 /* extension */
847 /* TODO refine extensions */
848
849cleanup:
850 return ret;
851}
852
853/**
854 * @brief Apply deviate add.
855 *
856 * @param[in] ctx Compile context.
857 * @param[in] d Deviate add to apply.
858 * @param[in,out] target Deviation target.
859 * @return LY_ERR value.
860 */
861static LY_ERR
862lys_apply_deviate_add(struct lysc_ctx *ctx, struct lysp_deviate_add *d, struct lysp_node *target)
863{
864 LY_ERR ret = LY_SUCCESS;
865 LY_ARRAY_COUNT_TYPE u;
866 struct lysp_qname *qname;
867 uint32_t *num;
868 struct lysp_restr **musts, *must;
869
870#define DEV_CHECK_NONPRESENCE(TYPE, MEMBER, PROPERTY, VALUEMEMBER) \
871 if (((TYPE)target)->MEMBER) { \
872 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
873 "Invalid deviation adding \"%s\" property which already exists (with value \"%s\").", \
874 PROPERTY, ((TYPE)target)->VALUEMEMBER); \
875 ret = LY_EVALID; \
876 goto cleanup; \
877 }
878
879 /* [units-stmt] */
880 if (d->units) {
881 switch (target->nodetype) {
882 case LYS_LEAF:
883 case LYS_LEAFLIST:
884 break;
885 default:
886 AMEND_WRONG_NODETYPE("deviation", "add", "units");
887 }
888
889 DEV_CHECK_NONPRESENCE(struct lysp_node_leaf *, units, "units", units);
890 DUP_STRING_GOTO(ctx->ctx, d->units, ((struct lysp_node_leaf *)target)->units, ret, cleanup);
891 }
892
893 /* *must-stmt */
894 if (d->musts) {
895 switch (target->nodetype) {
896 case LYS_CONTAINER:
897 case LYS_LIST:
898 case LYS_LEAF:
899 case LYS_LEAFLIST:
900 case LYS_ANYDATA:
901 case LYS_ANYXML:
902 musts = &((struct lysp_node_container *)target)->musts;
903 break;
904 case LYS_NOTIF:
905 musts = &((struct lysp_notif *)target)->musts;
906 break;
907 case LYS_INPUT:
908 case LYS_OUTPUT:
909 musts = &((struct lysp_action_inout *)target)->musts;
910 break;
911 default:
912 AMEND_WRONG_NODETYPE("deviation", "add", "must");
913 }
914
915 LY_ARRAY_FOR(d->musts, u) {
916 LY_ARRAY_NEW_GOTO(ctx->ctx, *musts, must, ret, cleanup);
917 LY_CHECK_GOTO(ret = lysp_restr_dup(ctx->ctx, must, &d->musts[u]), cleanup);
918 }
919 }
920
921 /* *unique-stmt */
922 if (d->uniques) {
923 switch (target->nodetype) {
924 case LYS_LIST:
925 break;
926 default:
927 AMEND_WRONG_NODETYPE("deviation", "add", "unique");
928 }
929
930 LY_ARRAY_FOR(d->uniques, u) {
931 LY_ARRAY_NEW_GOTO(ctx->ctx, ((struct lysp_node_list *)target)->uniques, qname, ret, cleanup);
932 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, qname, &d->uniques[u]), cleanup);
933 }
934 }
935
936 /* *default-stmt */
937 if (d->dflts) {
938 switch (target->nodetype) {
939 case LYS_LEAF:
940 AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default");
941 DEV_CHECK_NONPRESENCE(struct lysp_node_leaf *, dflt.str, "default", dflt.str);
942
943 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &((struct lysp_node_leaf *)target)->dflt, &d->dflts[0]), cleanup);
944 break;
945 case LYS_LEAFLIST:
946 LY_ARRAY_FOR(d->dflts, u) {
947 LY_ARRAY_NEW_GOTO(ctx->ctx, ((struct lysp_node_leaflist *)target)->dflts, qname, ret, cleanup);
948 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, qname, &d->dflts[u]), cleanup);
949 }
950 break;
951 case LYS_CHOICE:
952 AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default");
953 DEV_CHECK_NONPRESENCE(struct lysp_node_choice *, dflt.str, "default", dflt.str);
954
955 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &((struct lysp_node_choice *)target)->dflt, &d->dflts[0]), cleanup);
956 break;
957 default:
958 AMEND_WRONG_NODETYPE("deviation", "add", "default");
959 }
960 }
961
962 /* [config-stmt] */
963 if (d->flags & LYS_CONFIG_MASK) {
964 switch (target->nodetype) {
965 case LYS_CONTAINER:
966 case LYS_LEAF:
967 case LYS_LEAFLIST:
968 case LYS_LIST:
969 case LYS_CHOICE:
970 case LYS_ANYDATA:
971 case LYS_ANYXML:
972 break;
973 default:
974 AMEND_WRONG_NODETYPE("deviation", "add", "config");
975 }
976
977 if (target->flags & LYS_CONFIG_MASK) {
978 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
979 "Invalid deviation adding \"config\" property which already exists (with value \"config %s\").",
980 target->flags & LYS_CONFIG_W ? "true" : "false");
981 ret = LY_EVALID;
982 goto cleanup;
983 }
984
985 target->flags |= d->flags & LYS_CONFIG_MASK;
986 }
987
988 /* [mandatory-stmt] */
989 if (d->flags & LYS_MAND_MASK) {
990 switch (target->nodetype) {
991 case LYS_LEAF:
992 case LYS_CHOICE:
993 case LYS_ANYDATA:
994 case LYS_ANYXML:
995 break;
996 default:
997 AMEND_WRONG_NODETYPE("deviation", "add", "mandatory");
998 }
999
1000 if (target->flags & LYS_MAND_MASK) {
1001 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1002 "Invalid deviation adding \"mandatory\" property which already exists (with value \"mandatory %s\").",
1003 target->flags & LYS_MAND_TRUE ? "true" : "false");
1004 ret = LY_EVALID;
1005 goto cleanup;
1006 }
1007
1008 target->flags |= d->flags & LYS_MAND_MASK;
1009 }
1010
1011 /* [min-elements-stmt] */
1012 if (d->flags & LYS_SET_MIN) {
1013 switch (target->nodetype) {
1014 case LYS_LEAFLIST:
1015 num = &((struct lysp_node_leaflist *)target)->min;
1016 break;
1017 case LYS_LIST:
1018 num = &((struct lysp_node_list *)target)->min;
1019 break;
1020 default:
1021 AMEND_WRONG_NODETYPE("deviation", "add", "min-elements");
1022 }
1023
1024 if (target->flags & LYS_SET_MIN) {
1025 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1026 "Invalid deviation adding \"min-elements\" property which already exists (with value \"%u\").", *num);
1027 ret = LY_EVALID;
1028 goto cleanup;
1029 }
1030
1031 *num = d->min;
1032 }
1033
1034 /* [max-elements-stmt] */
1035 if (d->flags & LYS_SET_MAX) {
1036 switch (target->nodetype) {
1037 case LYS_LEAFLIST:
1038 num = &((struct lysp_node_leaflist *)target)->max;
1039 break;
1040 case LYS_LIST:
1041 num = &((struct lysp_node_list *)target)->max;
1042 break;
1043 default:
1044 AMEND_WRONG_NODETYPE("deviation", "add", "max-elements");
1045 }
1046
1047 if (target->flags & LYS_SET_MAX) {
1048 if (*num) {
1049 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1050 "Invalid deviation adding \"max-elements\" property which already exists (with value \"%u\").",
1051 *num);
1052 } else {
1053 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1054 "Invalid deviation adding \"max-elements\" property which already exists (with value \"unbounded\").");
1055 }
1056 ret = LY_EVALID;
1057 goto cleanup;
1058 }
1059
1060 *num = d->max;
1061 }
1062
1063cleanup:
1064 return ret;
1065}
1066
1067/**
1068 * @brief Apply deviate delete.
1069 *
1070 * @param[in] ctx Compile context.
1071 * @param[in] d Deviate delete to apply.
1072 * @param[in,out] target Deviation target.
1073 * @return LY_ERR value.
1074 */
1075static LY_ERR
1076lys_apply_deviate_delete(struct lysc_ctx *ctx, struct lysp_deviate_del *d, struct lysp_node *target)
1077{
1078 LY_ERR ret = LY_SUCCESS;
1079 struct lysp_restr **musts;
1080 LY_ARRAY_COUNT_TYPE u, v;
1081 struct lysp_qname **uniques, **dflts;
1082
1083#define DEV_DEL_ARRAY(DEV_ARRAY, ORIG_ARRAY, DEV_MEMBER, ORIG_MEMBER, FREE_FUNC, PROPERTY) \
1084 LY_ARRAY_FOR(d->DEV_ARRAY, u) { \
1085 int found = 0; \
1086 LY_ARRAY_FOR(ORIG_ARRAY, v) { \
1087 if (!strcmp(d->DEV_ARRAY[u]DEV_MEMBER, (ORIG_ARRAY)[v]ORIG_MEMBER)) { \
1088 found = 1; \
1089 break; \
1090 } \
1091 } \
1092 if (!found) { \
1093 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
1094 "Invalid deviation deleting \"%s\" property \"%s\" which does not match any of the target's property values.", \
1095 PROPERTY, d->DEV_ARRAY[u]DEV_MEMBER); \
1096 ret = LY_EVALID; \
1097 goto cleanup; \
1098 } \
1099 LY_ARRAY_DECREMENT(ORIG_ARRAY); \
1100 FREE_FUNC(ctx->ctx, &(ORIG_ARRAY)[v]); \
1101 memmove(&(ORIG_ARRAY)[v], &(ORIG_ARRAY)[v + 1], (LY_ARRAY_COUNT(ORIG_ARRAY) - v) * sizeof *(ORIG_ARRAY)); \
1102 } \
1103 if (!LY_ARRAY_COUNT(ORIG_ARRAY)) { \
1104 LY_ARRAY_FREE(ORIG_ARRAY); \
1105 ORIG_ARRAY = NULL; \
1106 }
1107
1108#define DEV_CHECK_PRESENCE_VALUE(TYPE, MEMBER, DEVTYPE, PROPERTY, VALUE) \
1109 if (!((TYPE)target)->MEMBER) { \
1110 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DEV_NOT_PRESENT, DEVTYPE, PROPERTY, VALUE); \
1111 ret = LY_EVALID; \
1112 goto cleanup; \
1113 } else if (strcmp(((TYPE)target)->MEMBER, VALUE)) { \
1114 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
1115 "Invalid deviation deleting \"%s\" property \"%s\" which does not match the target's property value \"%s\".", \
1116 PROPERTY, VALUE, ((TYPE)target)->MEMBER); \
1117 ret = LY_EVALID; \
1118 goto cleanup; \
1119 }
1120
1121 /* [units-stmt] */
1122 if (d->units) {
1123 switch (target->nodetype) {
1124 case LYS_LEAF:
1125 case LYS_LEAFLIST:
1126 break;
1127 default:
1128 AMEND_WRONG_NODETYPE("deviation", "delete", "units");
1129 }
1130
1131 DEV_CHECK_PRESENCE_VALUE(struct lysp_node_leaf *, units, "deleting", "units", d->units);
1132 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->units);
1133 ((struct lysp_node_leaf *)target)->units = NULL;
1134 }
1135
1136 /* *must-stmt */
1137 if (d->musts) {
1138 switch (target->nodetype) {
1139 case LYS_CONTAINER:
1140 case LYS_LIST:
1141 case LYS_LEAF:
1142 case LYS_LEAFLIST:
1143 case LYS_ANYDATA:
1144 case LYS_ANYXML:
1145 musts = &((struct lysp_node_container *)target)->musts;
1146 break;
1147 case LYS_NOTIF:
1148 musts = &((struct lysp_notif *)target)->musts;
1149 break;
1150 case LYS_INPUT:
1151 case LYS_OUTPUT:
1152 musts = &((struct lysp_action_inout *)target)->musts;
1153 break;
1154 default:
1155 AMEND_WRONG_NODETYPE("deviation", "delete", "must");
1156 }
1157
1158 DEV_DEL_ARRAY(musts, *musts, .arg.str, .arg.str, lysp_restr_free, "must");
1159 }
1160
1161 /* *unique-stmt */
1162 if (d->uniques) {
1163 switch (target->nodetype) {
1164 case LYS_LIST:
1165 break;
1166 default:
1167 AMEND_WRONG_NODETYPE("deviation", "delete", "unique");
1168 }
1169
1170 uniques = &((struct lysp_node_list *)target)->uniques;
1171 DEV_DEL_ARRAY(uniques, *uniques, .str, .str, lysp_qname_free, "unique");
1172 }
1173
1174 /* *default-stmt */
1175 if (d->dflts) {
1176 switch (target->nodetype) {
1177 case LYS_LEAF:
1178 AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default");
1179 DEV_CHECK_PRESENCE_VALUE(struct lysp_node_leaf *, dflt.str, "deleting", "default", d->dflts[0].str);
1180
1181 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str);
1182 ((struct lysp_node_leaf *)target)->dflt.str = NULL;
1183 break;
1184 case LYS_LEAFLIST:
1185 dflts = &((struct lysp_node_leaflist *)target)->dflts;
1186 DEV_DEL_ARRAY(dflts, *dflts, .str, .str, lysp_qname_free, "default");
1187 break;
1188 case LYS_CHOICE:
1189 AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default");
1190 DEV_CHECK_PRESENCE_VALUE(struct lysp_node_choice *, dflt.str, "deleting", "default", d->dflts[0].str);
1191
1192 FREE_STRING(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str);
1193 ((struct lysp_node_choice *)target)->dflt.str = NULL;
1194 break;
1195 default:
1196 AMEND_WRONG_NODETYPE("deviation", "delete", "default");
1197 }
1198 }
1199
1200cleanup:
1201 return ret;
1202}
1203
1204/**
1205 * @brief Apply deviate replace.
1206 *
1207 * @param[in] ctx Compile context.
1208 * @param[in] d Deviate replace to apply.
1209 * @param[in,out] target Deviation target.
1210 * @return LY_ERR value.
1211 */
1212static LY_ERR
1213lys_apply_deviate_replace(struct lysc_ctx *ctx, struct lysp_deviate_rpl *d, struct lysp_node *target)
1214{
1215 LY_ERR ret = LY_SUCCESS;
1216 uint32_t *num;
1217
1218#define DEV_CHECK_PRESENCE(TYPE, MEMBER, DEVTYPE, PROPERTY, VALUE) \
1219 if (!((TYPE)target)->MEMBER) { \
1220 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DEV_NOT_PRESENT, DEVTYPE, PROPERTY, VALUE); \
1221 ret = LY_EVALID; \
1222 goto cleanup; \
1223 }
1224
1225 /* [type-stmt] */
1226 if (d->type) {
1227 switch (target->nodetype) {
1228 case LYS_LEAF:
1229 case LYS_LEAFLIST:
1230 break;
1231 default:
1232 AMEND_WRONG_NODETYPE("deviation", "replace", "type");
1233 }
1234
1235 lysp_type_free(ctx->ctx, &((struct lysp_node_leaf *)target)->type);
1236 lysp_type_dup(ctx->ctx, &((struct lysp_node_leaf *)target)->type, d->type);
1237 }
1238
1239 /* [units-stmt] */
1240 if (d->units) {
1241 switch (target->nodetype) {
1242 case LYS_LEAF:
1243 case LYS_LEAFLIST:
1244 break;
1245 default:
1246 AMEND_WRONG_NODETYPE("deviation", "replace", "units");
1247 }
1248
1249 DEV_CHECK_PRESENCE(struct lysp_node_leaf *, units, "replacing", "units", d->units);
1250 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->units);
1251 DUP_STRING_GOTO(ctx->ctx, d->units, ((struct lysp_node_leaf *)target)->units, ret, cleanup);
1252 }
1253
1254 /* [default-stmt] */
1255 if (d->dflt.str) {
1256 switch (target->nodetype) {
1257 case LYS_LEAF:
1258 DEV_CHECK_PRESENCE(struct lysp_node_leaf *, dflt.str, "replacing", "default", d->dflt.str);
1259
1260 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str);
1261 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &((struct lysp_node_leaf *)target)->dflt, &d->dflt), cleanup);
1262 break;
1263 case LYS_CHOICE:
1264 DEV_CHECK_PRESENCE(struct lysp_node_choice *, dflt.str, "replacing", "default", d->dflt);
1265
1266 FREE_STRING(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str);
1267 LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &((struct lysp_node_choice *)target)->dflt, &d->dflt), cleanup);
1268 break;
1269 default:
1270 AMEND_WRONG_NODETYPE("deviation", "replace", "default");
1271 }
1272 }
1273
1274 /* [config-stmt] */
1275 if (d->flags & LYS_CONFIG_MASK) {
1276 switch (target->nodetype) {
1277 case LYS_CONTAINER:
1278 case LYS_LEAF:
1279 case LYS_LEAFLIST:
1280 case LYS_LIST:
1281 case LYS_CHOICE:
1282 case LYS_ANYDATA:
1283 case LYS_ANYXML:
1284 break;
1285 default:
1286 AMEND_WRONG_NODETYPE("deviation", "replace", "config");
1287 }
1288
1289 if (!(target->flags & LYS_CONFIG_MASK)) {
1290 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DEV_NOT_PRESENT,
1291 "replacing", "config", d->flags & LYS_CONFIG_W ? "config true" : "config false");
1292 ret = LY_EVALID;
1293 goto cleanup;
1294 }
1295
1296 target->flags &= ~LYS_CONFIG_MASK;
1297 target->flags |= d->flags & LYS_CONFIG_MASK;
1298 }
1299
1300 /* [mandatory-stmt] */
1301 if (d->flags & LYS_MAND_MASK) {
1302 switch (target->nodetype) {
1303 case LYS_LEAF:
1304 case LYS_CHOICE:
1305 case LYS_ANYDATA:
1306 case LYS_ANYXML:
1307 break;
1308 default:
1309 AMEND_WRONG_NODETYPE("deviation", "replace", "mandatory");
1310 }
1311
1312 if (!(target->flags & LYS_MAND_MASK)) {
1313 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DEV_NOT_PRESENT,
1314 "replacing", "mandatory", d->flags & LYS_MAND_TRUE ? "mandatory true" : "mandatory false");
1315 ret = LY_EVALID;
1316 goto cleanup;
1317 }
1318
1319 target->flags &= ~LYS_MAND_MASK;
1320 target->flags |= d->flags & LYS_MAND_MASK;
1321 }
1322
1323 /* [min-elements-stmt] */
1324 if (d->flags & LYS_SET_MIN) {
1325 switch (target->nodetype) {
1326 case LYS_LEAFLIST:
1327 num = &((struct lysp_node_leaflist *)target)->min;
1328 break;
1329 case LYS_LIST:
1330 num = &((struct lysp_node_list *)target)->min;
1331 break;
1332 default:
1333 AMEND_WRONG_NODETYPE("deviation", "replace", "min-elements");
1334 }
1335
1336 if (!(target->flags & LYS_SET_MIN)) {
1337 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1338 "Invalid deviation replacing \"min-elements\" property which is not present.");
1339 ret = LY_EVALID;
1340 goto cleanup;
1341 }
1342
1343 *num = d->min;
1344 }
1345
1346 /* [max-elements-stmt] */
1347 if (d->flags & LYS_SET_MAX) {
1348 switch (target->nodetype) {
1349 case LYS_LEAFLIST:
1350 num = &((struct lysp_node_leaflist *)target)->max;
1351 break;
1352 case LYS_LIST:
1353 num = &((struct lysp_node_list *)target)->max;
1354 break;
1355 default:
1356 AMEND_WRONG_NODETYPE("deviation", "replace", "max-elements");
1357 }
1358
1359 if (!(target->flags & LYS_SET_MAX)) {
1360 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1361 "Invalid deviation replacing \"max-elements\" property which is not present.");
1362 ret = LY_EVALID;
1363 goto cleanup;
1364 }
1365
1366 *num = d->max;
1367 }
1368
1369cleanup:
1370 return ret;
1371}
1372
1373/**
1374 * @brief Get module of a single nodeid node name test.
1375 *
1376 * @param[in] ctx libyang context.
1377 * @param[in] nametest Nametest with an optional prefix.
1378 * @param[in] nametest_len Length of @p nametest.
1379 * @param[in] mod Both current and prefix module for resolving prefixes and to return in case of no prefix.
1380 * @param[out] name Optional pointer to the name test without the prefix.
1381 * @param[out] name_len Length of @p name.
1382 * @return Resolved module.
1383 */
1384static const struct lys_module *
1385lys_schema_node_get_module(const struct ly_ctx *ctx, const char *nametest, size_t nametest_len,
1386 const struct lysp_module *mod, const char **name, size_t *name_len)
1387{
1388 const struct lys_module *target_mod;
1389 const char *ptr;
1390
1391 ptr = ly_strnchr(nametest, ':', nametest_len);
1392 if (ptr) {
1393 target_mod = ly_resolve_prefix(ctx, nametest, ptr - nametest, LY_PREF_SCHEMA, (void *)mod);
1394 if (!target_mod) {
1395 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE,
1396 "Invalid absolute-schema-nodeid nametest \"%.*s\" - prefix \"%.*s\" not defined in module \"%s\".",
1397 nametest_len, nametest, ptr - nametest, nametest, LYSP_MODULE_NAME(mod));
1398 return NULL;
1399 }
1400
1401 if (name) {
1402 *name = ptr + 1;
1403 *name_len = nametest_len - ((ptr - nametest) + 1);
1404 }
1405 } else {
1406 target_mod = mod->mod;
1407 if (name) {
1408 *name = nametest;
1409 *name_len = nametest_len;
1410 }
1411 }
1412
1413 return target_mod;
1414}
1415
1416/**
1417 * @brief Check whether a parsed node matches a single schema nodeid name test.
1418 *
1419 * @param[in] pnode Parsed node to consider.
1420 * @param[in] pnode_mod Compiled @p pnode to-be module.
1421 * @param[in] mod Expected module.
1422 * @param[in] name Expected name.
1423 * @param[in] name_len Length of @p name.
1424 * @return Whether it is a match or not.
1425 */
1426static ly_bool
1427lysp_schema_nodeid_match_pnode(const struct lysp_node *pnode, const struct lys_module *pnode_mod,
1428 const struct lys_module *mod, const char *name, size_t name_len)
1429{
1430 const char *pname;
1431
1432 /* compare with the module of the node */
1433 if (pnode_mod != mod) {
1434 return 0;
1435 }
1436
1437 /* compare names */
1438 if (pnode->nodetype & (LYS_ACTION | LYS_RPC)) {
1439 pname = ((struct lysp_action *)pnode)->name;
1440 } else if (pnode->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
1441 pname = (pnode->nodetype & LYS_INPUT) ? "input" : "output";
1442 } else {
1443 pname = pnode->name;
1444 }
1445 if (ly_strncmp(pname, name, name_len)) {
1446 return 0;
1447 }
1448
1449 return 1;
1450}
1451
1452/**
1453 * @brief Check whether a compiled node matches a single schema nodeid name test.
1454 *
1455 * @param[in,out] node Compiled node to consider. On a match it is moved to its parent.
1456 * @param[in] mod Expected module.
1457 * @param[in] name Expected name.
1458 * @param[in] name_len Length of @p name.
1459 * @return Whether it is a match or not.
1460 */
1461static ly_bool
1462lysp_schema_nodeid_match_node(const struct lysc_node **node, const struct lys_module *mod, const char *name,
1463 size_t name_len)
1464{
1465 const struct lys_module *node_mod;
1466 const char *node_name;
1467
1468 /* compare with the module of the node */
Michal Vasko2a668712020-10-21 11:48:09 +02001469 if ((*node)->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
Michal Vasko208a04a2020-10-21 15:17:12 +02001470 node_mod = lysc_node_parent_full(*node)->module;
Michal Vasko1a7a7bd2020-10-16 14:39:15 +02001471 } else {
1472 node_mod = (*node)->module;
1473 }
1474 if (node_mod != mod) {
1475 return 0;
1476 }
1477
1478 /* compare names */
1479 if ((*node)->nodetype == LYS_INPUT) {
1480 node_name = "input";
1481 } else if ((*node)->nodetype == LYS_OUTPUT) {
1482 node_name = "output";
1483 } else {
1484 node_name = (*node)->name;
1485 }
1486 if (ly_strncmp(node_name, name, name_len)) {
1487 return 0;
1488 }
1489
Michal Vasko2a668712020-10-21 11:48:09 +02001490 /* move to next parent */
Michal Vasko208a04a2020-10-21 15:17:12 +02001491 *node = lysc_node_parent_full(*node);
Michal Vasko1a7a7bd2020-10-16 14:39:15 +02001492
1493 return 1;
1494}
1495
1496/**
1497 * @brief Check whether a node matches specific schema nodeid.
1498 *
1499 * @param[in] exp Parsed nodeid to match.
1500 * @param[in] exp_pmod Module to use for nodes in @p exp without a prefix.
1501 * @param[in] ctx_node Initial context node that should match, only for descendant paths.
1502 * @param[in] parent First compiled parent to consider. If @p pnode is NULL, it is condered the node to be matched.
1503 * @param[in] pnode Parsed node to be matched. May be NULL if the target node was already compiled.
1504 * @param[in] pnode_mod Compiled @p pnode to-be module.
1505 * @return Whether it is a match or not.
1506 */
1507static ly_bool
1508lysp_schema_nodeid_match(const struct lyxp_expr *exp, const struct lysp_module *exp_pmod, const struct lysc_node *ctx_node,
1509 const struct lysc_node *parent, const struct lysp_node *pnode, const struct lys_module *pnode_mod)
1510{
1511 uint32_t i;
1512 const struct lys_module *mod;
Radek Krejci2b18bf12020-11-06 11:20:20 +01001513 const char *name = NULL;
1514 size_t name_len = 0;
Michal Vasko1a7a7bd2020-10-16 14:39:15 +02001515
1516 /* compare last node in the node ID */
1517 i = exp->used - 1;
1518
1519 /* get exp node ID module */
1520 mod = lys_schema_node_get_module(exp_pmod->mod->ctx, exp->expr + exp->tok_pos[i], exp->tok_len[i], exp_pmod, &name, &name_len);
1521 assert(mod);
1522
1523 if (pnode) {
1524 /* compare on the last parsed-only node */
1525 if (!lysp_schema_nodeid_match_pnode(pnode, pnode_mod, mod, name, name_len)) {
1526 return 0;
1527 }
1528 } else {
1529 /* using parent directly */
1530 if (!lysp_schema_nodeid_match_node(&parent, mod, name, name_len)) {
1531 return 0;
1532 }
1533 }
1534
1535 /* now compare all the compiled parents */
1536 while (i > 1) {
1537 i -= 2;
1538 assert(exp->tokens[i] == LYXP_TOKEN_NAMETEST);
1539
1540 if (!parent) {
1541 /* no more parents but path continues */
1542 return 0;
1543 }
1544
1545 /* get exp node ID module */
1546 mod = lys_schema_node_get_module(exp_pmod->mod->ctx, exp->expr + exp->tok_pos[i], exp->tok_len[i], exp_pmod, &name,
1547 &name_len);
1548 assert(mod);
1549
1550 /* compare with the parent */
1551 if (!lysp_schema_nodeid_match_node(&parent, mod, name, name_len)) {
1552 return 0;
1553 }
1554 }
1555
1556 if (ctx_node && (ctx_node != parent)) {
1557 /* descendant path has not finished in the context node */
1558 return 0;
1559 } else if (!ctx_node && parent) {
1560 /* some parent was not matched */
1561 return 0;
1562 }
1563
1564 return 1;
1565}
1566
1567void
1568lysc_augment_free(const struct ly_ctx *ctx, struct lysc_augment *aug)
1569{
1570 if (aug) {
1571 lyxp_expr_free(ctx, aug->nodeid);
1572
1573 free(aug);
1574 }
1575}
1576
1577void
1578lysc_deviation_free(const struct ly_ctx *ctx, struct lysc_deviation *dev)
1579{
1580 if (dev) {
1581 lyxp_expr_free(ctx, dev->nodeid);
1582 LY_ARRAY_FREE(dev->devs);
1583 LY_ARRAY_FREE(dev->dev_pmods);
1584
1585 free(dev);
1586 }
1587}
1588
1589void
1590lysc_refine_free(const struct ly_ctx *ctx, struct lysc_refine *rfn)
1591{
1592 if (rfn) {
1593 lyxp_expr_free(ctx, rfn->nodeid);
1594 LY_ARRAY_FREE(rfn->rfns);
1595
1596 free(rfn);
1597 }
1598}
1599
1600void
1601lysp_dev_node_free(const struct ly_ctx *ctx, struct lysp_node *dev_pnode)
1602{
1603 if (!dev_pnode) {
1604 return;
1605 }
1606
1607 switch (dev_pnode->nodetype) {
1608 case LYS_CONTAINER:
1609 ((struct lysp_node_container *)dev_pnode)->child = NULL;
1610 break;
1611 case LYS_LIST:
1612 ((struct lysp_node_list *)dev_pnode)->child = NULL;
1613 break;
1614 case LYS_CHOICE:
1615 ((struct lysp_node_choice *)dev_pnode)->child = NULL;
1616 break;
1617 case LYS_CASE:
1618 ((struct lysp_node_case *)dev_pnode)->child = NULL;
1619 break;
1620 case LYS_LEAF:
1621 case LYS_LEAFLIST:
1622 case LYS_ANYXML:
1623 case LYS_ANYDATA:
1624 /* no children */
1625 break;
1626 case LYS_NOTIF:
1627 ((struct lysp_notif *)dev_pnode)->data = NULL;
1628 lysp_notif_free((struct ly_ctx *)ctx, (struct lysp_notif *)dev_pnode);
1629 free(dev_pnode);
1630 return;
1631 case LYS_RPC:
1632 case LYS_ACTION:
1633 ((struct lysp_action *)dev_pnode)->input.data = NULL;
1634 ((struct lysp_action *)dev_pnode)->output.data = NULL;
1635 lysp_action_free((struct ly_ctx *)ctx, (struct lysp_action *)dev_pnode);
1636 free(dev_pnode);
1637 return;
1638 case LYS_INPUT:
1639 case LYS_OUTPUT:
1640 ((struct lysp_action_inout *)dev_pnode)->data = NULL;
1641 lysp_action_inout_free((struct ly_ctx *)ctx, (struct lysp_action_inout *)dev_pnode);
1642 free(dev_pnode);
1643 return;
1644 default:
1645 LOGINT(ctx);
1646 return;
1647 }
1648
1649 lysp_node_free((struct ly_ctx *)ctx, dev_pnode);
1650}
1651
1652LY_ERR
1653lys_compile_node_deviations_refines(struct lysc_ctx *ctx, const struct lysp_node *pnode, const struct lysc_node *parent,
1654 struct lysp_node **dev_pnode, ly_bool *not_supported)
1655{
1656 LY_ERR ret = LY_SUCCESS;
1657 uint32_t i;
1658 LY_ARRAY_COUNT_TYPE u;
1659 struct lys_module *orig_mod = ctx->cur_mod;
1660 struct lysp_module *orig_pmod = ctx->pmod;
1661 char orig_path[LYSC_CTX_BUFSIZE];
1662 struct lysc_refine *rfn;
1663 struct lysc_deviation *dev;
1664 struct lysp_deviation *dev_p;
1665 struct lysp_deviate *d;
1666
1667 *dev_pnode = NULL;
1668 *not_supported = 0;
1669
1670 for (i = 0; i < ctx->uses_rfns.count; ++i) {
1671 rfn = ctx->uses_rfns.objs[i];
1672
1673 if (!lysp_schema_nodeid_match(rfn->nodeid, rfn->nodeid_pmod, rfn->nodeid_ctx_node, parent, pnode, ctx->cur_mod)) {
1674 /* not our target node */
1675 continue;
1676 }
1677
1678 if (!*dev_pnode) {
1679 /* first refine on this node, create a copy first */
1680 LY_CHECK_GOTO(ret = lysp_dup_single(ctx->ctx, pnode, 1, dev_pnode), cleanup);
1681 }
1682
1683 /* apply all the refines by changing (the copy of) the parsed node */
1684 LY_ARRAY_FOR(rfn->rfns, u) {
1685 /* apply refine, keep the current path and add to it */
1686 lysc_update_path(ctx, NULL, "{refine}");
1687 lysc_update_path(ctx, NULL, rfn->rfns[u]->nodeid);
1688 ret = lys_apply_refine(ctx, rfn->rfns[u], *dev_pnode);
1689 lysc_update_path(ctx, NULL, NULL);
1690 lysc_update_path(ctx, NULL, NULL);
1691 LY_CHECK_GOTO(ret, cleanup);
1692 }
1693
1694 /* refine was applied, remove it */
1695 lysc_refine_free(ctx->ctx, rfn);
1696 ly_set_rm_index(&ctx->uses_rfns, i, NULL);
1697
1698 /* all the refines for one target node are in one structure, we are done */
1699 break;
1700 }
1701
1702 for (i = 0; i < ctx->devs.count; ++i) {
1703 dev = ctx->devs.objs[i];
1704
1705 if (!lysp_schema_nodeid_match(dev->nodeid, dev->dev_pmods[0], NULL, parent, pnode, ctx->cur_mod)) {
1706 /* not our target node */
1707 continue;
1708 }
1709
1710 if (dev->not_supported) {
1711 /* it is not supported, no more deviations */
1712 *not_supported = 1;
1713 goto dev_applied;
1714 }
1715
1716 if (!*dev_pnode) {
1717 /* first deviation on this node, create a copy first */
1718 LY_CHECK_GOTO(ret = lysp_dup_single(ctx->ctx, pnode, 1, dev_pnode), cleanup);
1719 }
1720
1721 /* apply all the deviates by changing (the copy of) the parsed node */
1722 LY_ARRAY_FOR(dev->devs, u) {
1723 dev_p = dev->devs[u];
1724 LY_LIST_FOR(dev_p->deviates, d) {
1725 /* generate correct path */
1726 strcpy(orig_path, ctx->path);
1727 ctx->path_len = 1;
1728 ctx->cur_mod = dev->dev_pmods[u]->mod;
1729 ctx->pmod = (struct lysp_module *)dev->dev_pmods[u];
1730 lysc_update_path(ctx, NULL, "{deviation}");
1731 lysc_update_path(ctx, NULL, dev_p->nodeid);
1732
1733 switch (d->mod) {
1734 case LYS_DEV_ADD:
1735 ret = lys_apply_deviate_add(ctx, (struct lysp_deviate_add *)d, *dev_pnode);
1736 break;
1737 case LYS_DEV_DELETE:
1738 ret = lys_apply_deviate_delete(ctx, (struct lysp_deviate_del *)d, *dev_pnode);
1739 break;
1740 case LYS_DEV_REPLACE:
1741 ret = lys_apply_deviate_replace(ctx, (struct lysp_deviate_rpl *)d, *dev_pnode);
1742 break;
1743 default:
1744 LOGINT(ctx->ctx);
1745 ret = LY_EINT;
1746 }
1747
1748 /* restore previous path */
1749 strcpy(ctx->path, orig_path);
1750 ctx->path_len = strlen(ctx->path);
1751 ctx->cur_mod = orig_mod;
1752 ctx->pmod = orig_pmod;
1753
1754 LY_CHECK_GOTO(ret, cleanup);
1755 }
1756 }
1757
1758dev_applied:
1759 /* deviation was applied, remove it */
1760 lysc_deviation_free(ctx->ctx, dev);
1761 ly_set_rm_index(&ctx->devs, i, NULL);
1762
1763 /* all the deviations for one target node are in one structure, we are done */
1764 break;
1765 }
1766
1767cleanup:
1768 if (ret) {
1769 lysp_dev_node_free(ctx->ctx, *dev_pnode);
1770 *dev_pnode = NULL;
1771 *not_supported = 0;
1772 }
1773 return ret;
1774}
1775
1776/**
1777 * @brief Compile the parsed augment connecting it into its target.
1778 *
1779 * It is expected that all the data referenced in path are present - augments are ordered so that augment B
1780 * targeting data from augment A is being compiled after augment A. Also the modules referenced in the path
1781 * are already implemented and compiled.
1782 *
1783 * @param[in] ctx Compile context.
1784 * @param[in] aug_p Parsed augment to compile.
1785 * @param[in] target Target node of the augment.
1786 * @return LY_SUCCESS on success.
1787 * @return LY_EVALID on failure.
1788 */
1789static LY_ERR
1790lys_compile_augment(struct lysc_ctx *ctx, struct lysp_augment *aug_p, struct lysc_node *target)
1791{
1792 LY_ERR ret = LY_SUCCESS;
1793 struct lysp_node *pnode;
1794 struct lysc_node *node;
1795 struct lysc_when *when_shared = NULL;
1796 struct lysc_action **actions;
1797 struct lysc_notif **notifs;
1798 ly_bool allow_mandatory = 0;
1799 LY_ARRAY_COUNT_TYPE u;
1800 struct ly_set child_set = {0};
1801 uint32_t i;
1802
1803 if (!(target->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
1804 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1805 "Augment's %s-schema-nodeid \"%s\" refers to a %s node which is not an allowed augment's target.",
1806 aug_p->nodeid[0] == '/' ? "absolute" : "descendant", aug_p->nodeid, lys_nodetype2str(target->nodetype));
1807 ret = LY_EVALID;
1808 goto cleanup;
1809 }
1810
1811 /* check for mandatory nodes
1812 * - new cases augmenting some choice can have mandatory nodes
1813 * - mandatory nodes are allowed only in case the augmentation is made conditional with a when statement
1814 */
1815 if (aug_p->when || (target->nodetype == LYS_CHOICE) || (ctx->cur_mod == target->module)) {
1816 allow_mandatory = 1;
1817 }
1818
1819 LY_LIST_FOR(aug_p->child, pnode) {
1820 /* check if the subnode can be connected to the found target (e.g. case cannot be inserted into container) */
1821 if (((pnode->nodetype == LYS_CASE) && (target->nodetype != LYS_CHOICE)) ||
1822 ((pnode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && !(target->nodetype & (LYS_CONTAINER | LYS_LIST))) ||
1823 ((pnode->nodetype == LYS_USES) && (target->nodetype == LYS_CHOICE))) {
1824 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1825 "Invalid augment of %s node which is not allowed to contain %s node \"%s\".",
1826 lys_nodetype2str(target->nodetype), lys_nodetype2str(pnode->nodetype), pnode->name);
1827 ret = LY_EVALID;
1828 goto cleanup;
1829 }
1830
1831 /* compile the children */
1832 if (target->nodetype == LYS_CHOICE) {
1833 LY_CHECK_GOTO(ret = lys_compile_node_choice_child(ctx, pnode, target, &child_set), cleanup);
1834 } else {
1835 LY_CHECK_GOTO(ret = lys_compile_node(ctx, pnode, target, 0, &child_set), cleanup);
1836 }
1837
1838 /* since the augment node is not present in the compiled tree, we need to pass some of its
1839 * statements to all its children */
1840 for (i = 0; i < child_set.count; ++i) {
1841 node = child_set.snodes[i];
1842 if (!allow_mandatory && (node->flags & LYS_CONFIG_W) && (node->flags & LYS_MAND_TRUE)) {
1843 node->flags &= ~LYS_MAND_TRUE;
1844 lys_compile_mandatory_parents(target, 0);
1845 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
1846 "Invalid augment adding mandatory node \"%s\" without making it conditional via when statement.", node->name);
1847 ret = LY_EVALID;
1848 goto cleanup;
1849 }
1850
1851 if (aug_p->when) {
1852 /* pass augment's when to all the children */
1853 ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_xpath_context(target), node, &when_shared);
1854 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskod9062b02020-11-04 17:15:50 +01001855
1856 if ((node->nodetype == LYS_CONTAINER) && !(node->flags & LYS_PRESENCE)) {
1857 /* container with a when condition */
1858 LOGWRN(ctx->ctx, "Container \"%s\" changed to presence because it has a meaning from its "
1859 "inherited \"when\" condition.", node->name);
1860 node->flags |= LYS_PRESENCE;
1861 }
Michal Vasko1a7a7bd2020-10-16 14:39:15 +02001862 }
1863 }
1864 ly_set_erase(&child_set, NULL);
1865 }
1866
1867 switch (target->nodetype) {
1868 case LYS_CONTAINER:
1869 actions = &((struct lysc_node_container *)target)->actions;
1870 notifs = &((struct lysc_node_container *)target)->notifs;
1871 break;
1872 case LYS_LIST:
1873 actions = &((struct lysc_node_list *)target)->actions;
1874 notifs = &((struct lysc_node_list *)target)->notifs;
1875 break;
1876 default:
1877 actions = NULL;
1878 notifs = NULL;
1879 break;
1880 }
1881
1882 if (aug_p->actions) {
1883 if (!actions) {
1884 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1885 "Invalid augment of %s node which is not allowed to contain RPC/action node \"%s\".",
1886 lys_nodetype2str(target->nodetype), aug_p->actions[0].name);
1887 ret = LY_EVALID;
1888 goto cleanup;
1889 }
1890
1891 /* compile actions into the target */
Michal Vasko5347e3a2020-11-03 17:14:57 +01001892 COMPILE_OP_ARRAY_GOTO(ctx, aug_p->actions, *actions, target, lys_compile_action, 0, ret, cleanup);
Michal Vasko1a7a7bd2020-10-16 14:39:15 +02001893
1894 if (aug_p->when) {
1895 /* inherit when */
1896 LY_ARRAY_FOR(*actions, u) {
1897 ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_xpath_context(target),
1898 (struct lysc_node *)&(*actions)[u], &when_shared);
1899 LY_CHECK_GOTO(ret, cleanup);
1900 }
1901 }
1902 }
1903 if (aug_p->notifs) {
1904 if (!notifs) {
1905 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1906 "Invalid augment of %s node which is not allowed to contain notification node \"%s\".",
1907 lys_nodetype2str(target->nodetype), aug_p->notifs[0].name);
1908 ret = LY_EVALID;
1909 goto cleanup;
1910 }
1911
1912 /* compile notifications into the target */
Michal Vasko5347e3a2020-11-03 17:14:57 +01001913 COMPILE_OP_ARRAY_GOTO(ctx, aug_p->notifs, *notifs, target, lys_compile_notif, 0, ret, cleanup);
Michal Vasko1a7a7bd2020-10-16 14:39:15 +02001914
1915 if (aug_p->when) {
1916 /* inherit when */
1917 LY_ARRAY_FOR(*notifs, u) {
1918 ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_xpath_context(target),
1919 (struct lysc_node *)&(*notifs)[u], &when_shared);
1920 LY_CHECK_GOTO(ret, cleanup);
1921 }
1922 }
1923 }
1924
1925cleanup:
1926 ly_set_erase(&child_set, NULL);
1927 return ret;
1928}
1929
1930LY_ERR
1931lys_compile_node_augments(struct lysc_ctx *ctx, struct lysc_node *node)
1932{
1933 LY_ERR ret = LY_SUCCESS;
1934 struct lys_module *orig_mod = ctx->cur_mod;
1935 struct lysp_module *orig_pmod = ctx->pmod;
1936 uint32_t i;
1937 char orig_path[LYSC_CTX_BUFSIZE];
1938 struct lysc_augment *aug;
1939
1940 /* uses augments */
1941 for (i = 0; i < ctx->uses_augs.count; ) {
1942 aug = ctx->uses_augs.objs[i];
1943
1944 if (!lysp_schema_nodeid_match(aug->nodeid, aug->nodeid_pmod, aug->nodeid_ctx_node, node, NULL, NULL)) {
1945 /* not our target node */
1946 ++i;
1947 continue;
1948 }
1949
1950 /* apply augment, keep the current path and add to it */
1951 lysc_update_path(ctx, NULL, "{augment}");
1952 lysc_update_path(ctx, NULL, aug->aug_p->nodeid);
1953 ret = lys_compile_augment(ctx, aug->aug_p, node);
1954 lysc_update_path(ctx, NULL, NULL);
1955 lysc_update_path(ctx, NULL, NULL);
1956 LY_CHECK_GOTO(ret, cleanup);
1957
1958 /* augment was applied, remove it (index may have changed because other augments could have been applied) */
1959 ly_set_rm(&ctx->uses_augs, aug, NULL);
1960 lysc_augment_free(ctx->ctx, aug);
1961 }
1962
1963 /* top-level augments */
1964 for (i = 0; i < ctx->augs.count; ) {
1965 aug = ctx->augs.objs[i];
1966
1967 if (!lysp_schema_nodeid_match(aug->nodeid, aug->nodeid_pmod, NULL, node, NULL, NULL)) {
1968 /* not our target node */
1969 ++i;
1970 continue;
1971 }
1972
1973 /* apply augment, use the path and modules from the augment */
1974 strcpy(orig_path, ctx->path);
1975 ctx->path_len = 1;
1976 lysc_update_path(ctx, NULL, "{augment}");
1977 lysc_update_path(ctx, NULL, aug->aug_p->nodeid);
1978 ctx->cur_mod = aug->nodeid_pmod->mod;
1979 ctx->pmod = (struct lysp_module *)aug->nodeid_pmod;
1980 ret = lys_compile_augment(ctx, aug->aug_p, node);
1981 strcpy(ctx->path, orig_path);
1982 ctx->path_len = strlen(ctx->path);
1983 LY_CHECK_GOTO(ret, cleanup);
1984
1985 /* augment was applied, remove it */
1986 ly_set_rm(&ctx->augs, aug, NULL);
1987 lysc_augment_free(ctx->ctx, aug);
1988 }
1989
1990cleanup:
1991 ctx->cur_mod = orig_mod;
1992 ctx->pmod = orig_pmod;
1993 return ret;
1994}
1995
1996/**
1997 * @brief Prepare a top-level augment to be applied during data nodes compilation.
1998 *
1999 * @param[in] ctx Compile context.
2000 * @param[in] aug_p Parsed augment to be applied.
2001 * @param[in] pmod Both current and prefix module for @p aug_p.
2002 * @return LY_ERR value.
2003 */
2004static LY_ERR
2005lys_precompile_own_augment(struct lysc_ctx *ctx, struct lysp_augment *aug_p, const struct lysp_module *pmod)
2006{
2007 LY_ERR ret = LY_SUCCESS;
2008 struct lyxp_expr *exp = NULL;
2009 struct lysc_augment *aug;
2010 const struct lys_module *mod;
2011
2012 /* parse its target, it was already parsed and fully checked (except for the existence of the nodes) */
2013 ret = lyxp_expr_parse(ctx->ctx, aug_p->nodeid, strlen(aug_p->nodeid), 0, &exp);
2014 LY_CHECK_GOTO(ret, cleanup);
2015
2016 mod = lys_schema_node_get_module(ctx->ctx, exp->expr + exp->tok_pos[1], exp->tok_len[1], pmod, NULL, NULL);
2017 LY_CHECK_ERR_GOTO(!mod, LOGINT(ctx->ctx); ret = LY_EINT, cleanup);
2018 if (mod != ctx->cur_mod) {
2019 /* augment for another module, ignore */
2020 goto cleanup;
2021 }
2022
2023 /* allocate new compiled augment and store it in the set */
2024 aug = calloc(1, sizeof *aug);
2025 LY_CHECK_ERR_GOTO(!aug, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
2026 LY_CHECK_GOTO(ret = ly_set_add(&ctx->augs, aug, 1, NULL), cleanup);
2027
2028 aug->nodeid = exp;
2029 exp = NULL;
2030 aug->nodeid_pmod = pmod;
2031 aug->aug_p = aug_p;
2032
2033cleanup:
2034 lyxp_expr_free(ctx->ctx, exp);
2035 return ret;
2036}
2037
2038LY_ERR
2039lys_precompile_own_augments(struct lysc_ctx *ctx)
2040{
2041 LY_ARRAY_COUNT_TYPE u, v, w;
2042 const struct lys_module *aug_mod;
2043
2044 LY_ARRAY_FOR(ctx->cur_mod->augmented_by, u) {
2045 aug_mod = ctx->cur_mod->augmented_by[u];
2046
2047 /* collect all module augments */
2048 LY_ARRAY_FOR(aug_mod->parsed->augments, v) {
2049 LY_CHECK_RET(lys_precompile_own_augment(ctx, &aug_mod->parsed->augments[v], aug_mod->parsed));
2050 }
2051
2052 /* collect all submodules augments */
2053 LY_ARRAY_FOR(aug_mod->parsed->includes, v) {
2054 LY_ARRAY_FOR(aug_mod->parsed->includes[v].submodule->augments, w) {
2055 LY_CHECK_RET(lys_precompile_own_augment(ctx, &aug_mod->parsed->includes[v].submodule->augments[w],
2056 (struct lysp_module *)aug_mod->parsed->includes[v].submodule));
2057 }
2058 }
2059 }
2060
2061 return LY_SUCCESS;
2062}
2063
2064/**
2065 * @brief Prepare a deviation to be applied during data nodes compilation.
2066 *
2067 * @param[in] ctx Compile context.
2068 * @param[in] dev_p Parsed deviation to be applied.
2069 * @param[in] pmod Both current and prefix module for @p dev_p.
2070 * @return LY_ERR value.
2071 */
2072static LY_ERR
2073lys_precompile_own_deviation(struct lysc_ctx *ctx, struct lysp_deviation *dev_p, const struct lysp_module *pmod)
2074{
2075 LY_ERR ret = LY_SUCCESS;
2076 struct lysc_deviation *dev = NULL;
2077 struct lyxp_expr *exp = NULL;
2078 struct lysp_deviation **new_dev;
2079 const struct lys_module *mod;
2080 const struct lysp_module **new_dev_pmod;
2081 uint32_t i;
2082
2083 /* parse its target, it was already parsed and fully checked (except for the existence of the nodes) */
2084 ret = lyxp_expr_parse(ctx->ctx, dev_p->nodeid, strlen(dev_p->nodeid), 0, &exp);
2085 LY_CHECK_GOTO(ret, cleanup);
2086
2087 mod = lys_schema_node_get_module(ctx->ctx, exp->expr + exp->tok_pos[1], exp->tok_len[1], pmod, NULL, NULL);
2088 LY_CHECK_ERR_GOTO(!mod, LOGINT(ctx->ctx); ret = LY_EINT, cleanup);
2089 if (mod != ctx->cur_mod) {
2090 /* deviation for another module, ignore */
2091 goto cleanup;
2092 }
2093
2094 /* try to find the node in already compiled deviations */
2095 for (i = 0; i < ctx->devs.count; ++i) {
2096 if (lys_abs_schema_nodeid_match(ctx->ctx, exp, pmod, ((struct lysc_deviation *)ctx->devs.objs[i])->nodeid,
2097 ((struct lysc_deviation *)ctx->devs.objs[i])->dev_pmods[0])) {
2098 dev = ctx->devs.objs[i];
2099 break;
2100 }
2101 }
2102
2103 if (!dev) {
2104 /* allocate new compiled deviation */
2105 dev = calloc(1, sizeof *dev);
2106 LY_CHECK_ERR_GOTO(!dev, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
2107 LY_CHECK_GOTO(ret = ly_set_add(&ctx->devs, dev, 1, NULL), cleanup);
2108
2109 dev->nodeid = exp;
2110 exp = NULL;
2111 }
2112
2113 /* add new parsed deviation structure */
2114 LY_ARRAY_NEW_GOTO(ctx->ctx, dev->devs, new_dev, ret, cleanup);
2115 *new_dev = dev_p;
2116 LY_ARRAY_NEW_GOTO(ctx->ctx, dev->dev_pmods, new_dev_pmod, ret, cleanup);
2117 *new_dev_pmod = pmod;
2118
2119cleanup:
2120 lyxp_expr_free(ctx->ctx, exp);
2121 return ret;
2122}
2123
2124LY_ERR
2125lys_precompile_own_deviations(struct lysc_ctx *ctx)
2126{
2127 LY_ARRAY_COUNT_TYPE u, v, w;
2128 const struct lys_module *dev_mod;
2129 struct lysc_deviation *dev;
2130 struct lysp_deviate *d;
2131 int not_supported;
2132 uint32_t i;
2133
2134 LY_ARRAY_FOR(ctx->cur_mod->deviated_by, u) {
2135 dev_mod = ctx->cur_mod->deviated_by[u];
2136
2137 /* compile all module deviations */
2138 LY_ARRAY_FOR(dev_mod->parsed->deviations, v) {
2139 LY_CHECK_RET(lys_precompile_own_deviation(ctx, &dev_mod->parsed->deviations[v], dev_mod->parsed));
2140 }
2141
2142 /* compile all submodules deviations */
2143 LY_ARRAY_FOR(dev_mod->parsed->includes, v) {
2144 LY_ARRAY_FOR(dev_mod->parsed->includes[v].submodule->deviations, w) {
2145 LY_CHECK_RET(lys_precompile_own_deviation(ctx, &dev_mod->parsed->includes[v].submodule->deviations[w],
2146 (struct lysp_module *)dev_mod->parsed->includes[v].submodule));
2147 }
2148 }
2149 }
2150
2151 /* set not-supported flags for all the deviations */
2152 for (i = 0; i < ctx->devs.count; ++i) {
2153 dev = ctx->devs.objs[i];
2154 not_supported = 0;
2155
2156 LY_ARRAY_FOR(dev->devs, u) {
2157 LY_LIST_FOR(dev->devs[u]->deviates, d) {
2158 if (d->mod == LYS_DEV_NOT_SUPPORTED) {
2159 not_supported = 1;
2160 break;
2161 }
2162 }
2163 if (not_supported) {
2164 break;
2165 }
2166 }
2167 if (not_supported && (LY_ARRAY_COUNT(dev->devs) > 1)) {
2168 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
2169 "Multiple deviations of \"%s\" with one of them being \"not-supported\".", dev->nodeid->expr);
2170 return LY_EVALID;
2171 }
2172
2173 dev->not_supported = not_supported;
2174 }
2175
2176 return LY_SUCCESS;
2177}
2178
2179/**
2180 * @brief Add a module reference into an array, checks for duplicities.
2181 *
2182 * @param[in] ctx Compile context.
2183 * @param[in] mod Module reference to add.
2184 * @param[in,out] mod_array Module sized array to add to.
2185 * @return LY_ERR value.
2186 */
2187static LY_ERR
2188lys_array_add_mod_ref(struct lysc_ctx *ctx, struct lys_module *mod, struct lys_module ***mod_array)
2189{
2190 LY_ARRAY_COUNT_TYPE u;
2191 struct lys_module **new_mod;
2192
2193 LY_ARRAY_FOR(*mod_array, u) {
2194 if ((*mod_array)[u] == mod) {
2195 /* already there */
2196 return LY_EEXIST;
2197 }
2198 }
2199
2200 /* add the new module ref */
2201 LY_ARRAY_NEW_RET(ctx->ctx, *mod_array, new_mod, LY_EMEM);
2202 *new_mod = mod;
2203
2204 return LY_SUCCESS;
2205}
2206
2207LY_ERR
2208lys_precompile_augments_deviations(struct lysc_ctx *ctx)
2209{
2210 LY_ERR ret = LY_SUCCESS;
2211 LY_ARRAY_COUNT_TYPE u, v;
2212 const struct lysp_module *mod_p;
2213 const struct lysc_node *target;
2214 struct lys_module *mod;
2215 struct lysp_submodule *submod;
2216 ly_bool has_dev = 0;
2217 uint16_t flags;
2218 uint32_t idx, opt_prev = ctx->options;
2219
2220 for (idx = 0; idx < ctx->ctx->implementing.count; ++idx) {
2221 if (ctx->cur_mod == ctx->ctx->implementing.objs[idx]) {
2222 break;
2223 }
2224 }
2225 if (idx == ctx->ctx->implementing.count) {
2226 /* it was already implemented and all the augments and deviations fully applied */
2227 return LY_SUCCESS;
2228 }
2229
2230 mod_p = ctx->cur_mod->parsed;
2231
2232 LY_ARRAY_FOR(mod_p->augments, u) {
2233 lysc_update_path(ctx, NULL, "{augment}");
2234 lysc_update_path(ctx, NULL, mod_p->augments[u].nodeid);
2235
2236 /* get target module */
2237 ret = lys_nodeid_check(ctx, mod_p->augments[u].nodeid, 1, &mod, NULL);
2238 LY_CHECK_RET(ret);
2239
2240 /* add this module into the target module augmented_by, if not there already from previous augments */
2241 lys_array_add_mod_ref(ctx, ctx->cur_mod, &mod->augmented_by);
2242
2243 /* if we are compiling this module, we cannot add augments to it yet */
2244 if (mod != ctx->cur_mod) {
2245 /* apply the augment, find the target node first */
2246 flags = 0;
2247 ret = lysc_resolve_schema_nodeid(ctx, mod_p->augments[u].nodeid, 0, NULL, ctx->cur_mod, LY_PREF_SCHEMA,
2248 (void *)mod_p, 0, &target, &flags);
2249 LY_CHECK_RET(ret);
2250
2251 /* apply the augment */
2252 ctx->options |= flags;
2253 ret = lys_compile_augment(ctx, &mod_p->augments[u], (struct lysc_node *)target);
2254 ctx->options = opt_prev;
2255 LY_CHECK_RET(ret);
2256 }
2257
2258 lysc_update_path(ctx, NULL, NULL);
2259 lysc_update_path(ctx, NULL, NULL);
2260 }
2261
2262 LY_ARRAY_FOR(mod_p->deviations, u) {
2263 /* get target module */
2264 lysc_update_path(ctx, NULL, "{deviation}");
2265 lysc_update_path(ctx, NULL, mod_p->deviations[u].nodeid);
2266 ret = lys_nodeid_check(ctx, mod_p->deviations[u].nodeid, 1, &mod, NULL);
2267 lysc_update_path(ctx, NULL, NULL);
2268 lysc_update_path(ctx, NULL, NULL);
2269 LY_CHECK_RET(ret);
2270
2271 /* add this module into the target module deviated_by, if not there already from previous deviations */
2272 lys_array_add_mod_ref(ctx, ctx->cur_mod, &mod->deviated_by);
2273
2274 /* new deviation added to the target module */
2275 has_dev = 1;
2276 }
2277
2278 /* the same for augments and deviations in submodules */
2279 LY_ARRAY_FOR(mod_p->includes, v) {
2280 submod = mod_p->includes[v].submodule;
2281 LY_ARRAY_FOR(submod->augments, u) {
2282 lysc_update_path(ctx, NULL, "{augment}");
2283 lysc_update_path(ctx, NULL, submod->augments[u].nodeid);
2284
2285 ret = lys_nodeid_check(ctx, submod->augments[u].nodeid, 1, &mod, NULL);
2286 LY_CHECK_RET(ret);
2287
2288 lys_array_add_mod_ref(ctx, ctx->cur_mod, &mod->augmented_by);
2289 if (mod != ctx->cur_mod) {
2290 flags = 0;
2291 ret = lysc_resolve_schema_nodeid(ctx, mod_p->augments[u].nodeid, 0, NULL, ctx->cur_mod, LY_PREF_SCHEMA,
2292 submod, 0, &target, &flags);
2293 LY_CHECK_RET(ret);
2294
2295 ctx->options |= flags;
2296 ret = lys_compile_augment(ctx, &submod->augments[u], (struct lysc_node *)target);
2297 ctx->options = opt_prev;
2298 LY_CHECK_RET(ret);
2299 }
2300
2301 lysc_update_path(ctx, NULL, NULL);
2302 lysc_update_path(ctx, NULL, NULL);
2303 }
2304
2305 LY_ARRAY_FOR(submod->deviations, u) {
2306 lysc_update_path(ctx, NULL, "{deviation}");
2307 lysc_update_path(ctx, NULL, submod->deviations[u].nodeid);
2308 ret = lys_nodeid_check(ctx, submod->deviations[u].nodeid, 1, &mod, NULL);
2309 lysc_update_path(ctx, NULL, NULL);
2310 lysc_update_path(ctx, NULL, NULL);
2311 LY_CHECK_RET(ret);
2312
2313 lys_array_add_mod_ref(ctx, ctx->cur_mod, &mod->deviated_by);
2314 has_dev = 1;
2315 }
2316 }
2317
2318 if (!has_dev) {
2319 /* no need to recompile any modules */
2320 return LY_SUCCESS;
2321 }
2322
Michal Vasko916aefb2020-11-02 15:43:16 +01002323 /* recompile all modules except this one */
2324 LY_CHECK_GOTO(ret = lys_recompile(ctx->ctx, mod_p->mod), cleanup);
Michal Vasko1a7a7bd2020-10-16 14:39:15 +02002325
2326cleanup:
2327 return ret;
2328}
2329
2330void
2331lys_precompile_augments_deviations_revert(struct ly_ctx *ctx, const struct lys_module *mod)
2332{
2333 uint32_t i;
2334 LY_ARRAY_COUNT_TYPE u, count;
2335 struct lys_module *m;
2336
2337 for (i = 0; i < ctx->list.count; ++i) {
2338 m = ctx->list.objs[i];
2339
2340 if (m->augmented_by) {
2341 count = LY_ARRAY_COUNT(m->augmented_by);
2342 for (u = 0; u < count; ++u) {
2343 if (m->augmented_by[u] == mod) {
2344 /* keep the order */
2345 if (u < count - 1) {
2346 memmove(m->augmented_by + u, m->augmented_by + u + 1, (count - u) * sizeof *m->augmented_by);
2347 }
2348 LY_ARRAY_DECREMENT(m->augmented_by);
2349 break;
2350 }
2351 }
2352 if (!LY_ARRAY_COUNT(m->augmented_by)) {
2353 LY_ARRAY_FREE(m->augmented_by);
2354 m->augmented_by = NULL;
2355 }
2356 }
2357
2358 if (m->deviated_by) {
2359 count = LY_ARRAY_COUNT(m->deviated_by);
2360 for (u = 0; u < count; ++u) {
2361 if (m->deviated_by[u] == mod) {
2362 /* keep the order */
2363 if (u < count - 1) {
2364 memmove(m->deviated_by + u, m->deviated_by + u + 1, (count - u) * sizeof *m->deviated_by);
2365 }
2366 LY_ARRAY_DECREMENT(m->deviated_by);
2367 break;
2368 }
2369 }
2370 if (!LY_ARRAY_COUNT(m->deviated_by)) {
2371 LY_ARRAY_FREE(m->deviated_by);
2372 m->deviated_by = NULL;
2373 }
2374 }
2375 }
2376}