blob: ad50db6f3ee974df5966710d15e08eccf31118b1 [file] [log] [blame]
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001#define _GNU_SOURCE
2
3#include <stdlib.h>
4#include <assert.h>
5#include <string.h>
6#include <ctype.h>
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02007#include <limits.h>
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02008
9#include "libyang.h"
10#include "resolve.h"
11#include "common.h"
12#include "parse.h"
13#include "dict.h"
14#include "tree_internal.h"
15
Michal Vaskob2daf5b2015-08-05 16:15:37 +020016/* does not log
17 * syntax is assumed to be correct, *local_intv MUST be NULL */
18int
19resolve_len_ran_interval(const char *str_restr, struct lys_type *type, int superior_restr, struct len_ran_intv** local_intv)
20{
21 /* 0 - unsigned, 1 - signed, 2 - floating point */
22 int kind, ret = 0;
23 int64_t local_smin, local_smax;
24 uint64_t local_umin, local_umax;
25 long double local_fmin, local_fmax;
26 const char *seg_ptr, *ptr;
27 struct len_ran_intv *tmp_local_intv, *tmp_intv, *intv = NULL;
28
29 switch (type->base) {
30 case LY_TYPE_BINARY:
31 kind = 0;
32 local_umin = 0;
33 local_umax = 18446744073709551615UL;
34
35 if (!str_restr && type->info.binary.length) {
36 str_restr = type->info.binary.length->expr;
37 }
38 break;
39 case LY_TYPE_DEC64:
40 kind = 2;
41 local_fmin = -9223372036854775808.0;
42 local_fmin /= 1 << type->info.dec64.dig;
43 local_fmax = 9223372036854775807.0;
44 local_fmax /= 1 << type->info.dec64.dig;
45
46 if (!str_restr && type->info.dec64.range) {
47 str_restr = type->info.dec64.range->expr;
48 }
49 break;
50 case LY_TYPE_INT8:
51 kind = 1;
52 local_smin = -128;
53 local_smax = 127;
54
55 if (!str_restr && type->info.num.range) {
56 str_restr = type->info.num.range->expr;
57 }
58 break;
59 case LY_TYPE_INT16:
60 kind = 1;
61 local_smin = -32768;
62 local_smax = 32767;
63
64 if (!str_restr && type->info.num.range) {
65 str_restr = type->info.num.range->expr;
66 }
67 break;
68 case LY_TYPE_INT32:
69 kind = 1;
70 local_smin = -2147483648;
71 local_smax = 2147483647;
72
73 if (!str_restr && type->info.num.range) {
74 str_restr = type->info.num.range->expr;
75 }
76 break;
77 case LY_TYPE_INT64:
78 kind = 1;
79 local_smin = -9223372036854775807L - 1L;
80 local_smax = 9223372036854775807L;
81
82 if (!str_restr && type->info.num.range) {
83 str_restr = type->info.num.range->expr;
84 }
85 break;
86 case LY_TYPE_UINT8:
87 kind = 0;
88 local_umin = 0;
89 local_umax = 255;
90
91 if (!str_restr && type->info.num.range) {
92 str_restr = type->info.num.range->expr;
93 }
94 break;
95 case LY_TYPE_UINT16:
96 kind = 0;
97 local_umin = 0;
98 local_umax = 65535;
99
100 if (!str_restr && type->info.num.range) {
101 str_restr = type->info.num.range->expr;
102 }
103 break;
104 case LY_TYPE_UINT32:
105 kind = 0;
106 local_umin = 0;
107 local_umax = 4294967295;
108
109 if (!str_restr && type->info.num.range) {
110 str_restr = type->info.num.range->expr;
111 }
112 break;
113 case LY_TYPE_UINT64:
114 kind = 0;
115 local_umin = 0;
116 local_umax = 18446744073709551615UL;
117
118 if (!str_restr && type->info.num.range) {
119 str_restr = type->info.num.range->expr;
120 }
121 break;
122 case LY_TYPE_STRING:
123 kind = 0;
124 local_umin = 0;
125 local_umax = 18446744073709551615UL;
126
127 if (!str_restr && type->info.str.length) {
128 str_restr = type->info.str.length->expr;
129 }
130 break;
131 default:
132 LOGINT;
133 return EXIT_FAILURE;
134 }
135
136 /* process superior types */
137 if (type->der && superior_restr) {
138 assert(!resolve_len_ran_interval(NULL, &type->der->type, superior_restr, &intv));
139 assert(!intv || (intv->kind == kind));
140 }
141
142 if (!str_restr) {
143 /* we are validating data and not have any restriction, but a superior type might have */
144 if (type->der && !superior_restr && !intv) {
145 assert(!resolve_len_ran_interval(NULL, &type->der->type, superior_restr, &intv));
146 assert(!intv || (intv->kind == kind));
147 }
148 *local_intv = intv;
149 return EXIT_SUCCESS;
150 }
151
152 /* adjust local min and max */
153 if (intv) {
154 tmp_intv = intv;
155
156 if (kind == 0) {
157 local_umin = tmp_intv->value.uval.min;
158 } else if (kind == 1) {
159 local_smin = tmp_intv->value.sval.min;
160 } else if (kind == 2) {
161 local_fmin = tmp_intv->value.fval.min;
162 }
163
164 while (tmp_intv->next) {
165 tmp_intv = tmp_intv->next;
166 }
167
168 if (kind == 0) {
169 local_umax = tmp_intv->value.uval.max;
170 } else if (kind == 1) {
171 local_smax = tmp_intv->value.sval.max;
172 } else if (kind == 2) {
173 local_fmax = tmp_intv->value.fval.max;
174 }
175 }
176
177 /* finally parse our restriction */
178 seg_ptr = str_restr;
179 while (1) {
180 if (!*local_intv) {
181 *local_intv = malloc(sizeof **local_intv);
182 tmp_local_intv = *local_intv;
183 } else {
184 tmp_local_intv->next = malloc(sizeof **local_intv);
185 tmp_local_intv = tmp_local_intv->next;
186 }
187
188 tmp_local_intv->kind = kind;
189 tmp_local_intv->next = NULL;
190
191 /* min */
192 ptr = seg_ptr;
193 while (isspace(ptr[0])) {
194 ++ptr;
195 }
196 if (isdigit(ptr[0]) || (ptr[0] == '+') || (ptr[0] == '-')) {
197 if (kind == 0) {
198 tmp_local_intv->value.uval.min = atoll(ptr);
199 } else if (kind == 1) {
200 tmp_local_intv->value.sval.min = atoll(ptr);
201 } else if (kind == 2) {
202 tmp_local_intv->value.fval.min = atoll(ptr);
203 }
204
205 if ((ptr[0] == '+') || (ptr[0] == '-')) {
206 ++ptr;
207 }
208 while (isdigit(ptr[0])) {
209 ++ptr;
210 }
211 } else if (!strncmp(ptr, "min", 3)) {
212 if (kind == 0) {
213 tmp_local_intv->value.uval.min = local_umin;
214 } else if (kind == 1) {
215 tmp_local_intv->value.sval.min = local_smin;
216 } else if (kind == 2) {
217 tmp_local_intv->value.fval.min = local_fmin;
218 }
219
220 ptr += 3;
221 } else if (!strncmp(ptr, "max", 3)) {
222 if (kind == 0) {
223 tmp_local_intv->value.uval.min = local_umax;
224 } else if (kind == 1) {
225 tmp_local_intv->value.sval.min = local_smax;
226 } else if (kind == 2) {
227 tmp_local_intv->value.fval.min = local_fmax;
228 }
229
230 ptr += 3;
231 } else {
232 assert(0);
233 }
234
235 while (isspace(ptr[0])) {
236 ptr++;
237 }
238
239 /* no interval or interval */
240 if ((ptr[0] == '|') || !ptr[0]) {
241 if (kind == 0) {
242 tmp_local_intv->value.uval.max = tmp_local_intv->value.uval.min;
243 } else if (kind == 1) {
244 tmp_local_intv->value.sval.max = tmp_local_intv->value.sval.min;
245 } else if (kind == 2) {
246 tmp_local_intv->value.fval.max = tmp_local_intv->value.fval.min;
247 }
248 } else if (!strncmp(ptr, "..", 2)) {
249 /* skip ".." */
250 ptr += 2;
251 while (isspace(ptr[0])) {
252 ++ptr;
253 }
254
255 /* max */
256 if (isdigit(ptr[0]) || (ptr[0] == '+') || (ptr[0] == '-')) {
257 if (kind == 0) {
258 tmp_local_intv->value.uval.max = atoll(ptr);
259 } else if (kind == 1) {
260 tmp_local_intv->value.sval.max = atoll(ptr);
261 } else if (kind == 2) {
262 tmp_local_intv->value.fval.max = atoll(ptr);
263 }
264 } else if (!strncmp(ptr, "max", 3)) {
265 if (kind == 0) {
266 tmp_local_intv->value.uval.max = local_umax;
267 } else if (kind == 1) {
268 tmp_local_intv->value.sval.max = local_smax;
269 } else if (kind == 2) {
270 tmp_local_intv->value.fval.max = local_fmax;
271 }
272 } else {
273 assert(0);
274 }
275 } else {
276 assert(0);
277 }
278
279 /* next segment (next OR) */
280 seg_ptr = strchr(seg_ptr, '|');
281 if (!seg_ptr) {
282 break;
283 }
284 seg_ptr++;
285 }
286
287 /* check local restrictions against superior ones */
288 if (intv) {
289 tmp_intv = intv;
290 tmp_local_intv = *local_intv;
291
292 while (tmp_local_intv && tmp_intv) {
293 /* reuse local variables */
294 if (kind == 0) {
295 local_umin = tmp_local_intv->value.uval.min;
296 local_umax = tmp_local_intv->value.uval.max;
297
298 /* it must be in this interval */
299 if ((local_umin >= tmp_intv->value.uval.min) && (local_umin <= tmp_intv->value.uval.max)) {
300 /* this interval is covered, next one */
301 if (local_umax <= tmp_intv->value.uval.max) {
302 tmp_local_intv = tmp_local_intv->next;
303 continue;
304 /* ascending order of restrictions -> fail */
305 } else {
306 ret = EXIT_FAILURE;
307 goto cleanup;
308 }
309 }
310 } else if (kind == 1) {
311 local_smin = tmp_local_intv->value.sval.min;
312 local_smax = tmp_local_intv->value.sval.max;
313
314 if ((local_smin >= tmp_intv->value.sval.min) && (local_smin <= tmp_intv->value.sval.max)) {
315 if (local_smax <= tmp_intv->value.sval.max) {
316 tmp_local_intv = tmp_local_intv->next;
317 continue;
318 } else {
319 ret = EXIT_FAILURE;
320 goto cleanup;
321 }
322 }
323 } else if (kind == 2) {
324 local_fmin = tmp_local_intv->value.fval.min;
325 local_fmax = tmp_local_intv->value.fval.max;
326
327 if ((local_fmin >= tmp_intv->value.fval.min) && (local_fmin <= tmp_intv->value.fval.max)) {
328 if (local_fmax <= tmp_intv->value.fval.max) {
329 tmp_local_intv = tmp_local_intv->next;
330 continue;
331 } else {
332 ret = EXIT_FAILURE;
333 goto cleanup;
334 }
335 }
336 }
337
338 tmp_intv = tmp_intv->next;
339 }
340
341 /* some interval left uncovered -> fail */
342 if (tmp_local_intv) {
343 ret = EXIT_FAILURE;
344 }
345
346 }
347
348cleanup:
349 while (intv) {
350 tmp_intv = intv->next;
351 free(intv);
352 intv = tmp_intv;
353 }
354
355 /* fail */
356 if (ret) {
357 while (*local_intv) {
358 tmp_local_intv = (*local_intv)->next;
359 free(*local_intv);
360 *local_intv = tmp_local_intv;
361 }
362 }
363
364 return ret;
365}
366
367/* does not log */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200368struct lys_tpdf *
Radek Krejcib8048692015-08-05 13:36:34 +0200369resolve_superior_type(const char *name, const char *prefix, struct lys_module *module, struct lys_node *parent)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200370{
371 int i, j, found = 0;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200372 struct lys_tpdf *tpdf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200373 int tpdf_size;
374
375 if (!prefix) {
376 /* no prefix, try built-in types */
377 for (i = 1; i < LY_DATA_TYPE_COUNT; i++) {
378 if (!strcmp(ly_types[i].def->name, name)) {
379 return ly_types[i].def;
380 }
381 }
382 } else {
383 if (!strcmp(prefix, module->prefix)) {
384 /* prefix refers to the current module, ignore it */
385 prefix = NULL;
386 }
387 }
388
389 if (!prefix && parent) {
390 /* search in local typedefs */
391 while (parent) {
392 switch (parent->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200393 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +0200394 tpdf_size = ((struct lys_node_container *)parent)->tpdf_size;
395 tpdf = ((struct lys_node_container *)parent)->tpdf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200396 break;
397
Radek Krejci76512572015-08-04 09:47:08 +0200398 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +0200399 tpdf_size = ((struct lys_node_list *)parent)->tpdf_size;
400 tpdf = ((struct lys_node_list *)parent)->tpdf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200401 break;
402
Radek Krejci76512572015-08-04 09:47:08 +0200403 case LYS_GROUPING:
Radek Krejcib8048692015-08-05 13:36:34 +0200404 tpdf_size = ((struct lys_node_grp *)parent)->tpdf_size;
405 tpdf = ((struct lys_node_grp *)parent)->tpdf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200406 break;
407
Radek Krejci76512572015-08-04 09:47:08 +0200408 case LYS_RPC:
Radek Krejcib8048692015-08-05 13:36:34 +0200409 tpdf_size = ((struct lys_node_rpc *)parent)->tpdf_size;
410 tpdf = ((struct lys_node_rpc *)parent)->tpdf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200411 break;
412
Radek Krejci76512572015-08-04 09:47:08 +0200413 case LYS_NOTIF:
Radek Krejcib8048692015-08-05 13:36:34 +0200414 tpdf_size = ((struct lys_node_notif *)parent)->tpdf_size;
415 tpdf = ((struct lys_node_notif *)parent)->tpdf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200416 break;
417
Radek Krejci76512572015-08-04 09:47:08 +0200418 case LYS_INPUT:
419 case LYS_OUTPUT:
Radek Krejci4608ada2015-08-05 16:04:37 +0200420 tpdf_size = ((struct lys_node_rpc_inout *)parent)->tpdf_size;
421 tpdf = ((struct lys_node_rpc_inout *)parent)->tpdf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200422 break;
423
424 default:
425 parent = parent->parent;
426 continue;
427 }
428
429 for (i = 0; i < tpdf_size; i++) {
430 if (!strcmp(tpdf[i].name, name)) {
431 return &tpdf[i];
432 }
433 }
434
435 parent = parent->parent;
436 }
437 } else if (prefix) {
438 /* get module where to search */
439 for (i = 0; i < module->imp_size; i++) {
440 if (!strcmp(module->imp[i].prefix, prefix)) {
441 module = module->imp[i].module;
442 found = 1;
443 break;
444 }
445 }
446 if (!found) {
447 return NULL;
448 }
449 }
450
451 /* search in top level typedefs */
452 for (i = 0; i < module->tpdf_size; i++) {
453 if (!strcmp(module->tpdf[i].name, name)) {
454 return &module->tpdf[i];
455 }
456 }
457
458 /* search in submodules */
459 for (i = 0; i < module->inc_size; i++) {
460 for (j = 0; j < module->inc[i].submodule->tpdf_size; j++) {
461 if (!strcmp(module->inc[i].submodule->tpdf[j].name, name)) {
462 return &module->inc[i].submodule->tpdf[j];
463 }
464 }
465 }
466
467 return NULL;
468}
469
470static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200471check_default(struct lys_type *type, const char *value)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200472{
473 /* TODO - RFC 6020, sec. 7.3.4 */
474 (void)type;
475 (void)value;
476 return EXIT_SUCCESS;
477}
478
Michal Vaskof02e3742015-08-05 16:27:02 +0200479/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200480static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200481check_key(struct lys_node_leaf *key, uint8_t flags, struct lys_node_leaf **list, int index, const char *name, int len,
482 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200483{
484 char *dup = NULL;
485 int j;
486
487 /* existence */
488 if (!key) {
Michal Vaskof02e3742015-08-05 16:27:02 +0200489 if (name[len] != '\0') {
490 dup = strdup(name);
491 dup[len] = '\0';
492 name = dup;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200493 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200494 LOGVAL(LYE_KEY_MISS, line, name);
495 free(dup);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200496 return EXIT_FAILURE;
497 }
498
499 /* uniqueness */
500 for (j = index - 1; j >= 0; j--) {
501 if (list[index] == list[j]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200502 LOGVAL(LYE_KEY_DUP, line, key->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200503 return EXIT_FAILURE;
504 }
505 }
506
507 /* key is a leaf */
Radek Krejci76512572015-08-04 09:47:08 +0200508 if (key->nodetype != LYS_LEAF) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200509 LOGVAL(LYE_KEY_NLEAF, line, key->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200510 return EXIT_FAILURE;
511 }
512
513 /* type of the leaf is not built-in empty */
514 if (key->type.base == LY_TYPE_EMPTY) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200515 LOGVAL(LYE_KEY_TYPE, line, key->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200516 return EXIT_FAILURE;
517 }
518
519 /* config attribute is the same as of the list */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200520 if ((flags & LYS_CONFIG_MASK) != (key->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200521 LOGVAL(LYE_KEY_CONFIG, line, key->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200522 return EXIT_FAILURE;
523 }
524
525 return EXIT_SUCCESS;
526}
527
Michal Vaskof02e3742015-08-05 16:27:02 +0200528/* does not log */
529static struct lys_module *
530resolve_import_in_includes_recursive(struct lys_module *mod, const char *prefix, uint32_t pref_len)
531{
532 int i, j;
533 struct lys_submodule *sub_mod;
534 struct lys_module *ret;
535
536 for (i = 0; i < mod->inc_size; i++) {
537 sub_mod = mod->inc[i].submodule;
538 for (j = 0; j < sub_mod->imp_size; j++) {
539 if ((pref_len == strlen(sub_mod->imp[j].prefix))
540 && !strncmp(sub_mod->imp[j].prefix, prefix, pref_len)) {
541 return sub_mod->imp[j].module;
542 }
543 }
544 }
545
546 for (i = 0; i < mod->inc_size; i++) {
547 ret = resolve_import_in_includes_recursive((struct lys_module *)mod->inc[i].submodule, prefix, pref_len);
548 if (ret) {
549 return ret;
550 }
551 }
552
553 return NULL;
554}
555
556/* does not log */
557static struct lys_module *
558resolve_prefixed_module(struct lys_module *mod, const char *prefix, uint32_t pref_len)
559{
560 int i;
561
562 /* module itself */
563 if (!strncmp(mod->prefix, prefix, pref_len) && mod->prefix[pref_len] == '\0') {
564 return mod;
565 }
566
567 /* imported modules */
568 for (i = 0; i < mod->imp_size; i++) {
569 if (!strncmp(mod->imp[i].prefix, prefix, pref_len) && mod->imp[i].prefix[pref_len] == '\0') {
570 return mod->imp[i].module;
571 }
572 }
573
574 /* imports in includes */
575 return resolve_import_in_includes_recursive(mod, prefix, pref_len);
576}
577
578/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200579int
Michal Vaskof02e3742015-08-05 16:27:02 +0200580resolve_unique(struct lys_node *parent, const char *uniq_str, struct lys_unique *uniq_s, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200581{
582 char *uniq_val, *uniq_begin, *start;
583 int i, j;
584
585 /* count the number of unique values */
586 uniq_val = uniq_begin = strdup(uniq_str);
587 uniq_s->leafs_size = 0;
588 while ((uniq_val = strpbrk(uniq_val, " \t\n"))) {
589 uniq_s->leafs_size++;
590 while (isspace(*uniq_val)) {
591 uniq_val++;
592 }
593 }
594 uniq_s->leafs_size++;
595 uniq_s->leafs = calloc(uniq_s->leafs_size, sizeof *uniq_s->leafs);
596
597 /* interconnect unique values with the leafs */
598 uniq_val = uniq_begin;
599 for (i = 0; uniq_val && i < uniq_s->leafs_size; i++) {
600 start = uniq_val;
601 if ((uniq_val = strpbrk(start, " \t\n"))) {
602 *uniq_val = '\0'; /* add terminating NULL byte */
603 uniq_val++;
604 while (isspace(*uniq_val)) {
605 uniq_val++;
606 }
607 } /* else only one nodeid present/left already NULL byte terminated */
608
Michal Vasko2e1a7e42015-08-06 15:08:32 +0200609 uniq_s->leafs[i] = (struct lys_node_leaf *)resolve_schema_nodeid(start, parent->child, parent->module, LYS_LEAF);
610 if (!uniq_s->leafs[i] || (uniq_s->leafs[i]->nodetype != LYS_LEAF)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200611 LOGVAL(LYE_INARG, line, start, "unique");
612 if (!uniq_s->leafs[i]) {
613 LOGVAL(LYE_SPEC, 0, "Target leaf not found.");
614 } else {
615 LOGVAL(LYE_SPEC, 0, "Target is not a leaf.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200616 }
617 goto error;
618 }
619
620 for (j = 0; j < i; j++) {
621 if (uniq_s->leafs[j] == uniq_s->leafs[i]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200622 LOGVAL(LYE_INARG, line, start, "unique");
623 LOGVAL(LYE_SPEC, 0, "The identifier is not unique");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200624 goto error;
625 }
626 }
627 }
628
629 free(uniq_begin);
630 return EXIT_SUCCESS;
631
632error:
633
634 free(uniq_s->leafs);
635 free(uniq_begin);
636
637 return EXIT_FAILURE;
638}
639
Michal Vaskof02e3742015-08-05 16:27:02 +0200640/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200641static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200642resolve_grouping(struct lys_node *parent, struct lys_node_uses *uses, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200643{
Radek Krejcib8048692015-08-05 13:36:34 +0200644 struct lys_module *searchmod = NULL, *module = uses->module;
Radek Krejci1d82ef62015-08-07 14:44:40 +0200645 struct lys_node *node, *node_aux;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200646 const char *name;
647 int prefix_len = 0;
648 int i;
649
650 /* get referenced grouping */
651 name = strchr(uses->name, ':');
652 if (!name) {
653 /* no prefix, search in local tree */
654 name = uses->name;
655 } else {
656 /* there is some prefix, check if it refer the same data model */
657
658 /* set name to correct position after colon */
659 prefix_len = name - uses->name;
660 name++;
661
662 if (!strncmp(uses->name, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
663 /* prefix refers to the current module, ignore it */
664 prefix_len = 0;
665 }
666 }
667
668 /* search */
669 if (prefix_len) {
670 /* in top-level groupings of some other module */
671 for (i = 0; i < module->imp_size; i++) {
672 if (!strncmp(module->imp[i].prefix, uses->name, prefix_len)
673 && !module->imp[i].prefix[prefix_len]) {
674 searchmod = module->imp[i].module;
675 break;
676 }
677 }
678 if (!searchmod) {
679 /* uses refers unknown data model */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200680 LOGVAL(LYE_INPREF, line, name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200681 return EXIT_FAILURE;
682 }
683
Radek Krejci1d82ef62015-08-07 14:44:40 +0200684 LY_TREE_FOR(searchmod->data, node) {
685 if (node->nodetype == LYS_GROUPING && !strcmp(node->name, name)) {
686 uses->grp = (struct lys_node_grp *)node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200687 return EXIT_SUCCESS;
688 }
689 }
690 } else {
691 /* in local tree hierarchy */
Radek Krejci1d82ef62015-08-07 14:44:40 +0200692 for (node_aux = parent; node_aux; node_aux = node_aux->parent) {
693 LY_TREE_FOR(node_aux->child, node) {
694 if (node->nodetype == LYS_GROUPING && !strcmp(node->name, name)) {
695 uses->grp = (struct lys_node_grp *)node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200696 return EXIT_SUCCESS;
697 }
698 }
699 }
700
701 /* search in top level of the current module */
Radek Krejci1d82ef62015-08-07 14:44:40 +0200702 LY_TREE_FOR(module->data, node) {
703 if (node->nodetype == LYS_GROUPING && !strcmp(node->name, name)) {
704 uses->grp = (struct lys_node_grp *)node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200705 return EXIT_SUCCESS;
706 }
707 }
708
709 /* search in top-level of included modules */
710 for (i = 0; i < module->inc_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200711 LY_TREE_FOR(module->inc[i].submodule->data, node) {
712 if (node->nodetype == LYS_GROUPING && !strcmp(node->name, name)) {
713 uses->grp = (struct lys_node_grp *)node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200714 return EXIT_SUCCESS;
715 }
716 }
717 }
718 }
719
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200720 LOGVAL(LYE_INRESOLV, line, "grouping", uses->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200721 return EXIT_FAILURE;
722}
723
Michal Vaskof02e3742015-08-05 16:27:02 +0200724/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +0200725static struct lys_feature *
Michal Vaskof02e3742015-08-05 16:27:02 +0200726resolve_feature(const char *name, struct lys_module *module, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200727{
728 const char *prefix;
Michal Vaskof02e3742015-08-05 16:27:02 +0200729 uint32_t prefix_len = 0;
730 int i, j;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200731
732 assert(name);
733 assert(module);
734
735 /* check prefix */
736 prefix = name;
737 name = strchr(prefix, ':');
738 if (name) {
739 /* there is prefix */
740 prefix_len = name - prefix;
741 name++;
742
743 /* check whether the prefix points to the current module */
744 if (!strncmp(prefix, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
745 /* then ignore prefix and works as there is no prefix */
746 prefix_len = 0;
747 }
748 } else {
749 /* no prefix, set pointers correctly */
750 name = prefix;
751 }
752
753 if (prefix_len) {
754 /* search in imported modules */
Michal Vaskof02e3742015-08-05 16:27:02 +0200755 module = resolve_prefixed_module(module, prefix, prefix_len);
756 if (!module) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200757 /* identity refers unknown data model */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200758 LOGVAL(LYE_INPREF, line, prefix);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200759 return NULL;
760 }
761 } else {
762 /* search in submodules */
763 for (i = 0; i < module->inc_size; i++) {
764 for (j = 0; j < module->inc[i].submodule->features_size; j++) {
765 if (!strcmp(name, module->inc[i].submodule->features[j].name)) {
766 return &(module->inc[i].submodule->features[j]);
767 }
768 }
769 }
770 }
771
772 /* search in the identified module */
773 for (j = 0; j < module->features_size; j++) {
774 if (!strcmp(name, module->features[j].name)) {
775 return &module->features[j];
776 }
777 }
778
779 /* not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200780 LOGVAL(LYE_INRESOLV, line, "feature", prefix);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200781 return NULL;
782}
783
Michal Vaskof02e3742015-08-05 16:27:02 +0200784/* does not log */
Radek Krejci76512572015-08-04 09:47:08 +0200785struct lys_node *
786resolve_child(struct lys_node *parent, const char *name, int len, LYS_NODE type)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200787{
Radek Krejci76512572015-08-04 09:47:08 +0200788 struct lys_node *child, *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200789
790 if (!len) {
791 len = strlen(name);
792 }
793
794 LY_TREE_FOR(parent->child, child) {
Radek Krejci76512572015-08-04 09:47:08 +0200795 if (child->nodetype == LYS_USES) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200796 /* search recursively */
797 result = resolve_child(child, name, len, type);
798 if (result) {
799 return result;
800 }
801 }
802
803 if (child->nodetype & type) {
804 /* direct check */
805 if (child->name == name || (!strncmp(child->name, name, len) && !child->name[len])) {
806 return child;
807 }
808 }
809 }
810
811 return NULL;
812}
813
Michal Vaskof02e3742015-08-05 16:27:02 +0200814/* does not log
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200815 *
Michal Vaskocc9e12e2015-08-04 16:14:37 +0200816 * node_type - LYS_AUGMENT (searches also RPCs and notifications)
Michal Vasko2e1a7e42015-08-06 15:08:32 +0200817 * - LYS_USES (only descendant-schema-nodeid allowed, ".." not allowed, always return a grouping)
Michal Vaskocc9e12e2015-08-04 16:14:37 +0200818 * - LYS_CHOICE (search only start->child, only descendant-schema-nodeid allowed)
Michal Vasko2e1a7e42015-08-06 15:08:32 +0200819 * - LYS_LEAF (like LYS_USES, but always returns a data node)
820 *
821 * If id is absolute, start is ignored. If id is relative, start must be the first child to be searched
822 * continuing with its siblings.
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200823 */
Radek Krejci76512572015-08-04 09:47:08 +0200824struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +0200825resolve_schema_nodeid(const char *id, struct lys_node *start, struct lys_module *mod, LYS_NODE node_type)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200826{
Michal Vaskocc9e12e2015-08-04 16:14:37 +0200827 const char *name, *prefix;
Radek Krejci76512572015-08-04 09:47:08 +0200828 struct lys_node *sibling;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200829 int ret, nam_len, pref_len, is_relative = -1;
Radek Krejcib8048692015-08-05 13:36:34 +0200830 struct lys_module *prefix_mod, *start_mod;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200831 /* 0 - in module, 1 - in 1st submodule, 2 - in 2nd submodule, ... */
832 uint8_t in_submod = 0;
Michal Vaskocc9e12e2015-08-04 16:14:37 +0200833 /* 0 - in data, 1 - in RPCs, 2 - in notifications (relevant only with LYS_AUGMENT) */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200834 uint8_t in_mod_part = 0;
835
836 assert(mod);
837 assert(id);
838
839 if ((ret = parse_schema_nodeid(id, &prefix, &pref_len, &name, &nam_len, &is_relative)) < 1) {
840 return NULL;
841 }
842 id += ret;
843
Michal Vasko2e1a7e42015-08-06 15:08:32 +0200844 if (!is_relative && (node_type & (LYS_USES | LYS_CHOICE | LYS_LEAF))) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200845 return NULL;
846 }
847
848 /* absolute-schema-nodeid */
849 if (!is_relative) {
850 if (prefix) {
851 start_mod = resolve_prefixed_module(mod, prefix, pref_len);
852 if (!start_mod) {
853 return NULL;
854 }
855 start = start_mod->data;
856 } else {
857 start = mod->data;
858 start_mod = mod;
859 }
860 /* descendant-schema-nodeid */
861 } else {
Michal Vasko2e1a7e42015-08-06 15:08:32 +0200862 if (start) {
863 start_mod = start->module;
864 } else {
865 start_mod = mod;
866 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200867 }
868
869 while (1) {
Michal Vasko1e989c02015-08-04 12:33:00 +0200870 sibling = NULL;
871 LY_TREE_FOR(start, sibling) {
872 /* name match */
Michal Vasko2e1a7e42015-08-06 15:08:32 +0200873 if (((sibling->nodetype != LYS_GROUPING) || (node_type == LYS_USES))
874 && ((sibling->name && !strncmp(name, sibling->name, nam_len) && !sibling->name[nam_len])
Michal Vasko1e989c02015-08-04 12:33:00 +0200875 || (!strncmp(name, "input", 5) && (nam_len == 5) && (sibling->nodetype == LYS_INPUT))
Michal Vaskodcc7a802015-08-06 11:59:47 +0200876 || (!strncmp(name, "output", 6) && (nam_len == 6) && (sibling->nodetype == LYS_OUTPUT)))) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200877
Michal Vasko1e989c02015-08-04 12:33:00 +0200878 /* prefix match check */
879 if (prefix) {
Michal Vasko1e989c02015-08-04 12:33:00 +0200880 prefix_mod = resolve_prefixed_module(mod, prefix, pref_len);
881 if (!prefix_mod) {
882 return NULL;
883 }
Michal Vasko2e1a7e42015-08-06 15:08:32 +0200884 } else {
885 prefix_mod = mod;
886 if (prefix_mod->type) {
887 prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
888 }
889 }
Michal Vasko1e989c02015-08-04 12:33:00 +0200890
Michal Vasko2e1a7e42015-08-06 15:08:32 +0200891 /* modules need to always be checked, we want to skip augments */
892 if (!sibling->module->type) {
893 if (prefix_mod != sibling->module) {
894 continue;
895 }
896 } else {
897 if (prefix_mod != ((struct lys_submodule *)sibling->module)->belongsto) {
898 continue;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200899 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200900 }
Michal Vasko1e989c02015-08-04 12:33:00 +0200901
Michal Vasko1e989c02015-08-04 12:33:00 +0200902 /* the result node? */
903 if (!id[0]) {
Michal Vasko2e1a7e42015-08-06 15:08:32 +0200904 /* we're looking only for groupings, this is a data node */
905 if ((node_type == LYS_USES) && (sibling->nodetype != LYS_GROUPING)) {
906 continue;
907 }
Michal Vasko1e989c02015-08-04 12:33:00 +0200908 return sibling;
909 }
910
Michal Vaskodcc7a802015-08-06 11:59:47 +0200911 /* we're looking for a grouping (node_type == LYS_USES),
912 * but this isn't it, we cannot search inside
913 */
914 if (sibling->nodetype == LYS_GROUPING) {
915 continue;
916 }
917
Michal Vasko1e989c02015-08-04 12:33:00 +0200918 /* check for shorthand cases - then 'start' does not change */
919 if (!sibling->parent || (sibling->parent->nodetype != LYS_CHOICE)
920 || (sibling->nodetype == LYS_CASE)) {
921 start = sibling->child;
922 }
923 break;
924 }
925 }
926
927 /* we did not find the case in direct siblings */
928 if (node_type == LYS_CHOICE) {
929 return NULL;
930 }
931
932 /* no match */
933 if (!sibling) {
934 /* on augment search also RPCs and notifications, if we are in top-level */
935 if ((node_type == LYS_AUGMENT) && (!start || !start->parent)) {
936 /* we have searched all the data nodes */
937 if (in_mod_part == 0) {
938 if (!in_submod) {
939 start = start_mod->rpc;
940 } else {
941 start = start_mod->inc[in_submod-1].submodule->rpc;
942 }
943 in_mod_part = 1;
944 continue;
945 }
946 /* we have searched all the RPCs */
947 if (in_mod_part == 1) {
948 if (!in_submod) {
949 start = start_mod->notif;
950 } else {
951 start = start_mod->inc[in_submod-1].submodule->notif;
952 }
953 in_mod_part = 2;
954 continue;
955 }
956 /* we have searched all the notifications, nothing else to search in this module */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200957 }
958
Michal Vasko1e989c02015-08-04 12:33:00 +0200959 /* are we done with the included submodules as well? */
960 if (in_submod == start_mod->inc_size) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200961 return NULL;
962 }
963
Michal Vasko1e989c02015-08-04 12:33:00 +0200964 /* we aren't, check the next one */
965 ++in_submod;
966 in_mod_part = 0;
967 start = start_mod->inc[in_submod-1].submodule->data;
968 continue;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200969 }
970
971 /* we found our submodule */
972 if (in_submod) {
Radek Krejcib8048692015-08-05 13:36:34 +0200973 start_mod = (struct lys_module *)start_mod->inc[in_submod-1].submodule;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200974 in_submod = 0;
975 }
976
977 if ((ret = parse_schema_nodeid(id, &prefix, &pref_len, &name, &nam_len, &is_relative)) < 1) {
978 return NULL;
979 }
980 id += ret;
981 }
982
983 /* cannot get here */
984 return NULL;
985}
986
Michal Vaskof02e3742015-08-05 16:27:02 +0200987/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200988static int
989resolve_data_nodeid(const char *prefix, int pref_len, const char *name, int nam_len, struct lyd_node *data_source,
Michal Vaskof02e3742015-08-05 16:27:02 +0200990 struct unres_data **parents)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200991{
992 int flag;
Radek Krejcib8048692015-08-05 13:36:34 +0200993 struct lys_module *mod;
Michal Vaskof02e3742015-08-05 16:27:02 +0200994 struct unres_data *item, *par_iter;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200995 struct lyd_node *node;
996
997 if (prefix) {
998 /* we have prefix, find appropriate module */
999 mod = resolve_prefixed_module(data_source->schema->module, prefix, pref_len);
1000 if (!mod) {
1001 /* invalid prefix */
Michal Vaskof02e3742015-08-05 16:27:02 +02001002 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001003 }
1004 } else {
1005 /* no prefix, module is the same as of current node */
1006 mod = data_source->schema->module;
1007 }
1008
1009 if (!*parents) {
1010 *parents = malloc(sizeof **parents);
1011 (*parents)->dnode = NULL;
1012 (*parents)->next = NULL;
1013 }
1014 for (par_iter = *parents; par_iter; par_iter = par_iter->next) {
Radek Krejci76512572015-08-04 09:47:08 +02001015 if (par_iter->dnode && (par_iter->dnode->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001016 /* skip */
1017 continue;
1018 }
1019 flag = 0;
1020 LY_TREE_FOR(par_iter->dnode ? par_iter->dnode->child : data_source, node) {
1021 if (node->schema->module == mod && !strncmp(node->schema->name, name, nam_len)
1022 && node->schema->name[nam_len] == '\0') {
1023 /* matching target */
1024 if (!flag) {
1025 /* replace leafref instead of the current parent */
1026 par_iter->dnode = node;
1027 flag = 1;
1028 } else {
1029 /* multiple matching, so create new leafref structure */
1030 item = malloc(sizeof *item);
1031 item->dnode = node;
1032 item->next = par_iter->next;
1033 par_iter->next = item;
1034 par_iter = par_iter->next;
1035 }
1036 }
1037 }
1038 }
1039
1040 return !flag;
1041}
1042
Michal Vaskof02e3742015-08-05 16:27:02 +02001043/* logs directly
1044 * ... /node[source = destination] ... */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001045static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001046resolve_path_predicate_data(const char *pred, struct unres_data **node_match, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001047{
Michal Vaskof02e3742015-08-05 16:27:02 +02001048 struct unres_data *source_match, *dest_match, *node, *node_prev = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001049 const char *path_key_expr, *source, *sour_pref, *dest, *dest_pref;
1050 int pke_len, sour_len, sour_pref_len, dest_len, dest_pref_len, parsed = 0, pke_parsed = 0;
1051 int has_predicate, dest_parent_times, i;
1052
1053 do {
1054 if ((i = parse_path_predicate(pred, &sour_pref, &sour_pref_len, &source, &sour_len, &path_key_expr,
1055 &pke_len, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001056 LOGVAL(LYE_INCHAR, line, pred[-i], pred-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001057 return -parsed+i;
1058 }
1059 parsed += i;
1060 pred += i;
1061
1062 for (node = *node_match; node;) {
1063 /* source */
1064 source_match = NULL;
1065 /* must be leaf (key of a list) */
1066 if (resolve_data_nodeid(sour_pref, sour_pref_len, source, sour_len, node->dnode, &source_match)
1067 || !source_match || source_match->next
Radek Krejci76512572015-08-04 09:47:08 +02001068 || (source_match->dnode->schema->nodetype != LYS_LEAF)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001069 LOGVAL(LYE_LINE, line);
1070 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001071 return -parsed;
1072 }
1073
1074 /* destination */
1075 dest_match = calloc(1, sizeof *dest_match);
1076 dest_match->dnode = node->dnode;
1077 if ((i = parse_path_key_expr(path_key_expr, &dest_pref, &dest_pref_len, &dest, &dest_len,
1078 &dest_parent_times)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001079 LOGVAL(LYE_INCHAR, line, path_key_expr[-i], path_key_expr-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001080 return -parsed+i;
1081 }
1082 pke_parsed += i;
1083 for (i = 0; i < dest_parent_times; ++i) {
1084 dest_match->dnode = dest_match->dnode->parent;
1085 if (!dest_match->dnode) {
1086 free(dest_match);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001087 LOGVAL(LYE_LINE, line);
1088 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001089 return -parsed;
1090 }
1091 }
1092 while (1) {
1093 if (resolve_data_nodeid(dest_pref, dest_pref_len, dest, dest_len, dest_match->dnode, &dest_match)
Michal Vasko1f76a282015-08-04 16:16:53 +02001094 || !dest_match->dnode || dest_match->next) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001095 free(dest_match);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001096 LOGVAL(LYE_LINE, line);
1097 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001098 return -parsed;
1099 }
1100
1101 if (pke_len == pke_parsed) {
1102 break;
1103 }
Michal Vasko1f76a282015-08-04 16:16:53 +02001104 if ((i = parse_path_key_expr(path_key_expr+pke_parsed, &dest_pref, &dest_pref_len, &dest, &dest_len,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001105 &dest_parent_times)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001106 LOGVAL(LYE_INCHAR, line, path_key_expr[-i], path_key_expr-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001107 return -parsed+i;
1108 }
1109 pke_parsed += i;
1110 }
1111
1112 /* check match between source and destination nodes */
Radek Krejcib8048692015-08-05 13:36:34 +02001113 if (((struct lys_node_leaf *)source_match->dnode->schema)->type.base
1114 != ((struct lys_node_leaf *)dest_match->dnode->schema)->type.base) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001115 goto remove_leafref;
1116 }
1117
1118 if (((struct lyd_node_leaf *)source_match->dnode)->value_str
1119 != ((struct lyd_node_leaf *)dest_match->dnode)->value_str) {
1120 goto remove_leafref;
1121 }
1122
1123 /* leafref is ok, continue check with next leafref */
1124 node_prev = node;
1125 node = node->next;
1126 continue;
1127
1128remove_leafref:
1129 /* does not fulfill conditions, remove leafref record */
1130 if (node_prev) {
1131 node_prev->next = node->next;
1132 free(node);
1133 node = node_prev->next;
1134 } else {
1135 node = (*node_match)->next;
1136 free(*node_match);
1137 *node_match = node;
1138 }
1139 }
1140 } while (has_predicate);
1141
1142 return parsed;
1143}
1144
Michal Vaskof02e3742015-08-05 16:27:02 +02001145/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001146int
Michal Vaskof02e3742015-08-05 16:27:02 +02001147resolve_path_arg_data(struct unres_data *unres, const char *path, struct unres_data **ret)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001148{
Radek Krejci71b795b2015-08-10 16:20:39 +02001149 struct lyd_node *data = NULL;
Michal Vaskof02e3742015-08-05 16:27:02 +02001150 struct unres_data *riter = NULL, *raux;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001151 const char *prefix, *name;
Michal Vasko1f76a282015-08-04 16:16:53 +02001152 int pref_len, nam_len, has_predicate, parent_times, i;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001153
1154 *ret = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001155 parent_times = 0;
1156
1157 /* searching for nodeset */
1158 do {
1159 if ((i = parse_path_arg(path, &prefix, &pref_len, &name, &nam_len, &parent_times, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001160 LOGVAL(LYE_INCHAR, unres->line, path[-i], path-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001161 goto error;
1162 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001163 path += i;
1164
1165 if (!*ret) {
1166 *ret = calloc(1, sizeof **ret);
1167 for (i = 0; i < parent_times; ++i) {
1168 /* relative path */
1169 if (!*ret) {
1170 /* error, too many .. */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001171 LOGVAL(LYE_INVAL, unres->line, path, unres->dnode->schema->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001172 goto error;
1173 } else if (!(*ret)->dnode) {
1174 /* first .. */
Radek Krejci71b795b2015-08-10 16:20:39 +02001175 data = (*ret)->dnode = unres->dnode->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001176 } else if (!(*ret)->dnode->parent) {
1177 /* we are in root */
1178 free(*ret);
1179 *ret = NULL;
1180 } else {
1181 /* multiple .. */
Radek Krejci71b795b2015-08-10 16:20:39 +02001182 data = (*ret)->dnode = (*ret)->dnode->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001183 }
1184 }
1185
1186 /* absolute path */
1187 if (parent_times == -1) {
1188 for (data = unres->dnode; data->parent; data = data->parent);
1189 for (; data->prev->next; data = data->prev);
1190 }
1191 }
1192
1193 /* node identifier */
1194 if (resolve_data_nodeid(prefix, pref_len, name, nam_len, data, ret)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001195 LOGVAL(LYE_INELEM_LEN, unres->line, nam_len, name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001196 goto error;
1197 }
1198
1199 if (has_predicate) {
1200 /* we have predicate, so the current results must be lists */
1201 for (raux = NULL, riter = *ret; riter; ) {
Radek Krejci76512572015-08-04 09:47:08 +02001202 if (riter->dnode->schema->nodetype == LYS_LIST &&
Radek Krejcib8048692015-08-05 13:36:34 +02001203 ((struct lys_node_list *)riter->dnode->schema)->keys) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001204 /* leafref is ok, continue check with next leafref */
1205 raux = riter;
1206 riter = riter->next;
1207 continue;
1208 }
1209
1210 /* does not fulfill conditions, remove leafref record */
1211 if (raux) {
1212 raux->next = riter->next;
1213 free(riter);
1214 riter = raux->next;
1215 } else {
1216 *ret = riter->next;
1217 free(riter);
1218 riter = *ret;
1219 }
1220 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001221 if ((i = resolve_path_predicate_data(path, ret, unres->line)) < 1) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001222 goto error;
1223 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001224 path += i;
1225
1226 if (!*ret) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001227 LOGVAL(LYE_LINE, unres->line);
1228 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001229 goto error;
1230 }
1231 }
1232 } while (path[0] != '\0');
1233
Michal Vaskof02e3742015-08-05 16:27:02 +02001234 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001235
1236error:
1237
1238 while (*ret) {
1239 raux = (*ret)->next;
1240 free(*ret);
1241 *ret = raux;
1242 }
1243
Michal Vaskof02e3742015-08-05 16:27:02 +02001244 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001245}
1246
Michal Vaskof02e3742015-08-05 16:27:02 +02001247/* logs directly */
Michal Vasko1f76a282015-08-04 16:16:53 +02001248static int
Radek Krejcib8048692015-08-05 13:36:34 +02001249resolve_path_predicate_schema(const char *pred, struct lys_module *mod, struct lys_node *source_node,
Michal Vaskof02e3742015-08-05 16:27:02 +02001250 struct lys_node *dest_node, uint32_t line)
Michal Vasko1f76a282015-08-04 16:16:53 +02001251{
1252 struct lys_node *src_node, *dst_node;
1253 const char *path_key_expr, *source, *sour_pref, *dest, *dest_pref;
1254 int pke_len, sour_len, sour_pref_len, dest_len, dest_pref_len, parsed = 0, pke_parsed = 0;
1255 int has_predicate, dest_parent_times = 0, i;
1256
1257 do {
1258 if ((i = parse_path_predicate(pred, &sour_pref, &sour_pref_len, &source, &sour_len, &path_key_expr,
1259 &pke_len, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001260 LOGVAL(LYE_INCHAR, line, pred[-i], pred-i);
Michal Vasko1f76a282015-08-04 16:16:53 +02001261 return -parsed+i;
1262 }
1263 parsed += i;
1264 pred += i;
1265
1266 /* source (must be leaf, from the same module) */
1267 if (sour_pref && (resolve_prefixed_module(mod, sour_pref, sour_pref_len) != mod)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001268 LOGVAL(LYE_INPREF_LEN, line, sour_pref_len, sour_pref);
Michal Vasko1f76a282015-08-04 16:16:53 +02001269 return -parsed;
1270 }
1271
1272 src_node = resolve_child(source_node, source, sour_len, LYS_LEAF);
1273 if (!src_node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001274 LOGVAL(LYE_LINE, line);
1275 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001276 return -parsed;
1277 }
1278
1279 /* destination */
1280 if ((i = parse_path_key_expr(path_key_expr, &dest_pref, &dest_pref_len, &dest, &dest_len,
1281 &dest_parent_times)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001282 LOGVAL(LYE_INCHAR, line, path_key_expr[-i], path_key_expr-i);
Michal Vasko1f76a282015-08-04 16:16:53 +02001283 return -parsed;
1284 }
1285 pke_parsed += i;
1286
1287 /* dest_node is actually the parent of this leaf, so skip the first ".." */
1288 dst_node = dest_node;
1289 for (i = 1; i < dest_parent_times; ++i) {
1290 dst_node = dst_node->parent;
1291 if (!dst_node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001292 LOGVAL(LYE_LINE, line);
1293 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001294 return -parsed;
1295 }
1296 }
1297 while (1) {
1298 if (dest_pref && (resolve_prefixed_module(mod, dest_pref, dest_pref_len) != mod)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001299 LOGVAL(LYE_INPREF_LEN, line, dest_pref_len, dest_pref);
Michal Vasko1f76a282015-08-04 16:16:53 +02001300 return -parsed;
1301 }
1302 dst_node = resolve_child(dst_node, dest, dest_len, LYS_CONTAINER | LYS_LIST | LYS_LEAF);
1303 if (!dst_node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001304 LOGVAL(LYE_LINE, line);
1305 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001306 return -parsed;
1307 }
1308
1309 if (pke_len == pke_parsed) {
1310 break;
1311 }
1312
1313 if ((i = parse_path_key_expr(path_key_expr+pke_parsed, &dest_pref, &dest_pref_len, &dest, &dest_len,
1314 &dest_parent_times)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001315 LOGVAL(LYE_INCHAR, line, (path_key_expr+pke_parsed)[-i], (path_key_expr+pke_parsed)-i);
Michal Vasko1f76a282015-08-04 16:16:53 +02001316 return -parsed;
1317 }
1318 pke_parsed += i;
1319 }
1320
1321 /* check source - dest match */
Radek Krejcib8048692015-08-05 13:36:34 +02001322 if ((dst_node->nodetype != LYS_LEAF) || ((struct lys_node_leaf *)dst_node)->type.base
1323 != ((struct lys_node_leaf *)src_node)->type.base) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001324 LOGVAL(LYE_LINE, line);
1325 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001326 return -parsed;
1327 }
1328 } while (has_predicate);
1329
1330 return parsed;
1331}
1332
Michal Vaskof02e3742015-08-05 16:27:02 +02001333/* logs indirectly */
Radek Krejcib1c12512015-08-11 11:22:04 +02001334static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02001335resolve_path_arg_schema(struct lys_module *mod, const char *path, struct lys_node *parent_node, uint32_t line)
Michal Vasko1f76a282015-08-04 16:16:53 +02001336{
1337 struct lys_node *child, *node;
1338 const char *id, *prefix, *name;
1339 int pref_len, nam_len, parent_times, has_predicate;
1340 int i, first;
1341
1342 first = 1;
1343 parent_times = 0;
1344 id = path;
1345
1346 do {
1347 if ((i = parse_path_arg(id, &prefix, &pref_len, &name, &nam_len, &parent_times, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001348 LOGVAL(LYE_INCHAR, line, id[-i], id-i);
Radek Krejcib1c12512015-08-11 11:22:04 +02001349 return NULL;
Michal Vasko1f76a282015-08-04 16:16:53 +02001350 }
1351 id += i;
1352
1353 if (first) {
1354 if (parent_times == -1) {
1355 node = mod->data;
1356 } else if (parent_times > 0) {
1357 node = parent_node;
Michal Vasko73ae2562015-08-06 11:58:13 +02001358 /* node is the parent already, skip one ".." */
1359 for (i = 1; i < parent_times; ++i) {
Michal Vasko1f76a282015-08-04 16:16:53 +02001360 node = node->parent;
1361 if (!node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001362 LOGVAL(LYE_LINE, line);
1363 /* general error, the one written later will suffice */
Radek Krejcib1c12512015-08-11 11:22:04 +02001364 return NULL;
Michal Vasko1f76a282015-08-04 16:16:53 +02001365 }
1366 }
1367 node = node->child;
1368 }
1369 first = 0;
1370 } else {
1371 node = node->child;
1372 }
1373
1374 /* node identifier */
1375 LY_TREE_FOR(node, child) {
1376 if (child->nodetype == LYS_GROUPING) {
1377 continue;
1378 }
1379
1380 if (!strncmp(child->name, name, nam_len) && !child->name[nam_len]) {
1381 break;
1382 }
1383 }
1384 if (!child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001385 LOGVAL(LYE_LINE, line);
1386 /* general error, the one written later will suffice */
Radek Krejcib1c12512015-08-11 11:22:04 +02001387 return NULL;
Michal Vasko1f76a282015-08-04 16:16:53 +02001388 }
1389 node = child;
1390
1391 if (has_predicate) {
1392 /* we have predicate, so the current result must be list */
1393 if (node->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001394 LOGVAL(LYE_LINE, line);
1395 /* general error, the one written later will suffice */
Radek Krejcib1c12512015-08-11 11:22:04 +02001396 return NULL;
Michal Vasko1f76a282015-08-04 16:16:53 +02001397 }
1398
1399 if ((i = resolve_path_predicate_schema(id, mod, node, parent_node, line)) < 1) {
Radek Krejcib1c12512015-08-11 11:22:04 +02001400 return NULL;
Michal Vasko1f76a282015-08-04 16:16:53 +02001401 }
1402 id += i;
1403 }
1404 } while (id[0]);
1405
Radek Krejcib1c12512015-08-11 11:22:04 +02001406 /* the target must be leaf or leaf-list */
1407 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1408 LOGVAL(LYE_LINE, line);
1409 /* general error, the one written later will suffice */
1410 return NULL;
1411 }
1412
1413 return node;
Michal Vasko1f76a282015-08-04 16:16:53 +02001414}
1415
Michal Vaskof02e3742015-08-05 16:27:02 +02001416/* does not log
1417 * ... /node[target = value] ... */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001418static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001419resolve_predicate(const char *pred, struct unres_data **node_match)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001420{
Michal Vaskof02e3742015-08-05 16:27:02 +02001421 struct unres_data *target_match, *node, *node_prev = NULL, *tmp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001422 const char *prefix, *name, *value;
1423 int pref_len, nam_len, val_len, i, has_predicate, cur_idx, idx, parsed;
1424
1425 idx = -1;
1426 parsed = 0;
1427
1428 do {
1429 if ((i = parse_predicate(pred, &prefix, &pref_len, &name, &nam_len, &value, &val_len, &has_predicate)) < 1) {
1430 return -parsed+i;
1431 }
1432 parsed += i;
1433 pred += i;
1434
1435 if (isdigit(name[0])) {
1436 idx = atoi(name);
1437 }
1438
1439 for (cur_idx = 0, node = *node_match; node; ++cur_idx) {
1440 /* target */
1441 target_match = NULL;
1442 if ((name[0] == '.') || !value) {
1443 target_match = calloc(1, sizeof *target_match);
1444 target_match->dnode = node->dnode;
1445 } else if (resolve_data_nodeid(prefix, pref_len, name, nam_len, node->dnode, &target_match)) {
1446 return -parsed;
1447 }
1448
1449 /* check that we have the correct type */
1450 if (name[0] == '.') {
Radek Krejci76512572015-08-04 09:47:08 +02001451 if (node->dnode->schema->nodetype != LYS_LEAFLIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001452 goto remove_instid;
1453 }
1454 } else if (value) {
Radek Krejci76512572015-08-04 09:47:08 +02001455 if (node->dnode->schema->nodetype != LYS_LIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001456 goto remove_instid;
1457 }
1458 }
1459
1460 if ((value && (strncmp(((struct lyd_node_leaf *)target_match->dnode)->value_str, value, val_len)
1461 || ((struct lyd_node_leaf *)target_match->dnode)->value_str[val_len]))
1462 || (!value && (idx != cur_idx))) {
1463 goto remove_instid;
1464 }
1465
1466 while (target_match) {
1467 tmp = target_match->next;
1468 free(target_match);
1469 target_match = tmp;
1470 }
1471
1472 /* leafref is ok, continue check with next leafref */
1473 node_prev = node;
1474 node = node->next;
1475 continue;
1476
1477remove_instid:
1478 while (target_match) {
1479 tmp = target_match->next;
1480 free(target_match);
1481 target_match = tmp;
1482 }
1483
1484 /* does not fulfill conditions, remove leafref record */
1485 if (node_prev) {
1486 node_prev->next = node->next;
1487 free(node);
1488 node = node_prev->next;
1489 } else {
1490 node = (*node_match)->next;
1491 free(*node_match);
1492 *node_match = node;
1493 }
1494 }
1495 } while (has_predicate);
1496
1497 return parsed;
1498}
1499
Michal Vaskof02e3742015-08-05 16:27:02 +02001500/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001501int
Michal Vaskof02e3742015-08-05 16:27:02 +02001502resolve_instid(struct unres_data *unres, const char *path, int path_len, struct unres_data **ret)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001503{
1504 struct lyd_node *data;
Michal Vaskof02e3742015-08-05 16:27:02 +02001505 struct unres_data *riter = NULL, *raux;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001506 const char *apath = strndupa(path, path_len);
1507 const char *prefix, *name;
1508 int i, parsed, pref_len, nam_len, has_predicate;
1509
1510 parsed = 0;
1511
1512 /* we need root, absolute path */
1513 for (data = unres->dnode; data->parent; data = data->parent);
1514 for (; data->prev->next; data = data->prev);
1515
1516 /* searching for nodeset */
1517 do {
1518 if ((i = parse_instance_identifier(apath, &prefix, &pref_len, &name, &nam_len, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001519 LOGVAL(LYE_INCHAR, unres->line, apath[-i], apath-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001520 goto error;
1521 }
1522 parsed += i;
1523 apath += i;
1524
1525 if (resolve_data_nodeid(prefix, pref_len, name, nam_len, data, ret)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001526 LOGVAL(LYE_LINE, unres->line);
1527 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001528 goto error;
1529 }
1530
1531 if (has_predicate) {
1532 /* we have predicate, so the current results must be list or leaf-list */
1533 for (raux = NULL, riter = *ret; riter; ) {
Radek Krejci76512572015-08-04 09:47:08 +02001534 if ((riter->dnode->schema->nodetype == LYS_LIST &&
Radek Krejcib8048692015-08-05 13:36:34 +02001535 ((struct lys_node_list *)riter->dnode->schema)->keys)
Radek Krejci76512572015-08-04 09:47:08 +02001536 || (riter->dnode->schema->nodetype == LYS_LEAFLIST)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001537 /* instid is ok, continue check with next instid */
1538 raux = riter;
1539 riter = riter->next;
1540 continue;
1541 }
1542
1543 /* does not fulfill conditions, remove inst record */
1544 if (raux) {
1545 raux->next = riter->next;
1546 free(riter);
1547 riter = raux->next;
1548 } else {
1549 *ret = riter->next;
1550 free(riter);
1551 riter = *ret;
1552 }
1553 }
1554 if ((i = resolve_predicate(apath, ret)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001555 LOGVAL(LYE_INPRED, unres->line, apath-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001556 goto error;
1557 }
1558 parsed += i;
1559 apath += i;
1560
1561 if (!*ret) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001562 LOGVAL(LYE_LINE, unres->line);
1563 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001564 goto error;
1565 }
1566 }
1567 } while (apath[0] != '\0');
1568
Michal Vaskof02e3742015-08-05 16:27:02 +02001569 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001570
1571error:
1572 while (*ret) {
1573 raux = (*ret)->next;
1574 free(*ret);
1575 *ret = raux;
1576 }
1577
Michal Vaskof02e3742015-08-05 16:27:02 +02001578 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001579}
1580
Michal Vaskof02e3742015-08-05 16:27:02 +02001581/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001582static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001583inherit_config_flag(struct lys_node *node)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001584{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001585 LY_TREE_FOR(node, node) {
1586 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
1587 inherit_config_flag(node->child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001588 }
1589}
1590
Michal Vaskof02e3742015-08-05 16:27:02 +02001591/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001592static int
Michal Vasko2e1a7e42015-08-06 15:08:32 +02001593resolve_augment(struct lys_node_augment *aug, struct lys_node *siblings, struct lys_module *module)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001594{
Radek Krejci76512572015-08-04 09:47:08 +02001595 struct lys_node *sub, *aux;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001596
1597 assert(module);
1598
1599 /* resolve target node */
Michal Vasko2e1a7e42015-08-06 15:08:32 +02001600 aug->target = resolve_schema_nodeid(aug->target_name, siblings, module, LYS_AUGMENT);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001601 if (!aug->target) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001602 return EXIT_FAILURE;
1603 }
1604
1605 if (!aug->child) {
1606 /* nothing to do */
1607 return EXIT_SUCCESS;
1608 }
1609
1610 /* inherit config information from parent, augment does not have
1611 * config property, but we need to keep the information for subelements
1612 */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001613 aug->flags |= aug->target->flags & LYS_CONFIG_MASK;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001614 LY_TREE_FOR(aug->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001615 inherit_config_flag(sub);
1616 }
1617
Radek Krejci0acbe1b2015-08-04 09:33:49 +02001618 /* reconnect augmenting data into the target - add them to the target child list */
1619 if (aug->target->child) {
1620 aux = aug->target->child->prev; /* remember current target's last node */
1621 aux->next = aug->child; /* connect augmenting data after target's last node */
1622 aug->target->child->prev = aug->child->prev; /* new target's last node is last augmenting node */
1623 aug->child->prev = aux; /* finish connecting of both child lists */
1624 } else {
1625 aug->target->child = aug->child;
1626 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001627
1628 return EXIT_SUCCESS;
1629}
1630
Michal Vaskof02e3742015-08-05 16:27:02 +02001631/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001632int
Michal Vaskof02e3742015-08-05 16:27:02 +02001633resolve_uses(struct lys_node_uses *uses, struct unres_schema *unres, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001634{
1635 struct ly_ctx *ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001636 struct lys_node *node = NULL, *node_aux;
Radek Krejci76512572015-08-04 09:47:08 +02001637 struct lys_refine *rfn;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001638 struct lys_restr *newmust;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001639 int i, j;
1640 uint8_t size;
1641
1642 /* copy the data nodes from grouping into the uses context */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001643 LY_TREE_FOR(uses->grp->child, node) {
1644 node_aux = lys_node_dup(uses->module, node, uses->flags, 1, unres);
1645 if (!node_aux) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001646 LOGVAL(LYE_SPEC, line, "Copying data from grouping failed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001647 return EXIT_FAILURE;
1648 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001649 if (lys_node_addchild((struct lys_node *)uses, node_aux)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001650 /* error logged */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001651 lys_node_free(node_aux);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001652 return EXIT_FAILURE;
1653 }
1654 }
1655 ctx = uses->module->ctx;
1656
1657 /* apply refines */
1658 for (i = 0; i < uses->refine_size; i++) {
1659 rfn = &uses->refine[i];
Radek Krejci1d82ef62015-08-07 14:44:40 +02001660 node = resolve_schema_nodeid(rfn->target_name, uses->child, uses->module, LYS_LEAF);
1661 if (!node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001662 LOGVAL(LYE_INARG, line, rfn->target_name, "refine");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001663 return EXIT_FAILURE;
1664 }
1665
Radek Krejci1d82ef62015-08-07 14:44:40 +02001666 if (rfn->target_type && !(node->nodetype & rfn->target_type)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001667 LOGVAL(LYE_SPEC, line, "Refine substatements not applicable to the target-node.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001668 return EXIT_FAILURE;
1669 }
1670
1671 /* description on any nodetype */
1672 if (rfn->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001673 lydict_remove(ctx, node->dsc);
1674 node->dsc = lydict_insert(ctx, rfn->dsc, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001675 }
1676
1677 /* reference on any nodetype */
1678 if (rfn->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001679 lydict_remove(ctx, node->ref);
1680 node->ref = lydict_insert(ctx, rfn->ref, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001681 }
1682
1683 /* config on any nodetype */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001684 if (rfn->flags & LYS_CONFIG_MASK) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001685 node->flags &= ~LYS_CONFIG_MASK;
1686 node->flags |= (rfn->flags & LYS_CONFIG_MASK);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001687 }
1688
1689 /* default value ... */
1690 if (rfn->mod.dflt) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001691 if (node->nodetype == LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001692 /* leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001693 lydict_remove(ctx, ((struct lys_node_leaf *)node)->dflt);
1694 ((struct lys_node_leaf *)node)->dflt = lydict_insert(ctx, rfn->mod.dflt, 0);
1695 } else if (node->nodetype == LYS_CHOICE) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001696 /* choice */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001697 ((struct lys_node_choice *)node)->dflt = resolve_schema_nodeid(rfn->mod.dflt, node->child, node->module, LYS_CHOICE);
1698 if (!((struct lys_node_choice *)node)->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001699 LOGVAL(LYE_INARG, line, rfn->mod.dflt, "default");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001700 return EXIT_FAILURE;
1701 }
1702 }
1703 }
1704
1705 /* mandatory on leaf, anyxml or choice */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001706 if (rfn->flags & LYS_MAND_MASK) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001707 if (node->nodetype & (LYS_LEAF | LYS_ANYXML | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001708 /* remove current value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001709 node->flags &= ~LYS_MAND_MASK;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001710
1711 /* set new value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001712 node->flags |= (rfn->flags & LYS_MAND_MASK);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001713 }
1714 }
1715
1716 /* presence on container */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001717 if ((node->nodetype & LYS_CONTAINER) && rfn->mod.presence) {
1718 lydict_remove(ctx, ((struct lys_node_container *)node)->presence);
1719 ((struct lys_node_container *)node)->presence = lydict_insert(ctx, rfn->mod.presence, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001720 }
1721
1722 /* min/max-elements on list or leaf-list */
1723 /* magic - bit 3 in flags means min set, bit 4 says max set */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001724 if (node->nodetype == LYS_LIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001725 if (rfn->flags & 0x04) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 ((struct lys_node_list *)node)->min = rfn->mod.list.min;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001727 }
1728 if (rfn->flags & 0x08) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001729 ((struct lys_node_list *)node)->max = rfn->mod.list.max;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001730 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001731 } else if (node->nodetype == LYS_LEAFLIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001732 if (rfn->flags & 0x04) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001733 ((struct lys_node_leaflist *)node)->min = rfn->mod.list.min;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001734 }
1735 if (rfn->flags & 0x08) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001736 ((struct lys_node_leaflist *)node)->max = rfn->mod.list.max;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001737 }
1738 }
1739
1740 /* must in leaf, leaf-list, list, container or anyxml */
1741 if (rfn->must_size) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001742 size = ((struct lys_node_leaf *)node)->must_size + rfn->must_size;
1743 newmust = realloc(((struct lys_node_leaf *)node)->must, size * sizeof *rfn->must);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001744 if (!newmust) {
1745 LOGMEM;
1746 return EXIT_FAILURE;
1747 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001748 for (i = 0, j = ((struct lys_node_leaf *)node)->must_size; i < rfn->must_size; i++, j++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001749 newmust[j].expr = lydict_insert(ctx, rfn->must[i].expr, 0);
1750 newmust[j].dsc = lydict_insert(ctx, rfn->must[i].dsc, 0);
1751 newmust[j].ref = lydict_insert(ctx, rfn->must[i].ref, 0);
1752 newmust[j].eapptag = lydict_insert(ctx, rfn->must[i].eapptag, 0);
1753 newmust[j].emsg = lydict_insert(ctx, rfn->must[i].emsg, 0);
1754 }
1755
Radek Krejci1d82ef62015-08-07 14:44:40 +02001756 ((struct lys_node_leaf *)node)->must = newmust;
1757 ((struct lys_node_leaf *)node)->must_size = size;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001758 }
1759 }
1760
1761 /* apply augments */
1762 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko2e1a7e42015-08-06 15:08:32 +02001763 if (resolve_augment(&uses->augment[i], uses->child, uses->module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001764 LOGVAL(LYE_INRESOLV, line, "augment", uses->augment[i].target_name);
1765 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001766 }
1767 }
1768
1769 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001770}
1771
Michal Vaskof02e3742015-08-05 16:27:02 +02001772/* does not log */
Radek Krejcia52656e2015-08-05 13:41:50 +02001773static struct lys_ident *
1774resolve_base_ident_sub(struct lys_module *module, struct lys_ident *ident, const char *basename)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001775{
Michal Vaskof02e3742015-08-05 16:27:02 +02001776 uint32_t i, j;
Radek Krejcia52656e2015-08-05 13:41:50 +02001777 struct lys_ident *base_iter = NULL;
1778 struct lys_ident_der *der;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001779
1780 /* search module */
1781 for (i = 0; i < module->ident_size; i++) {
1782 if (!strcmp(basename, module->ident[i].name)) {
1783
1784 if (!ident) {
1785 /* just search for type, so do not modify anything, just return
1786 * the base identity pointer
1787 */
1788 return &module->ident[i];
1789 }
1790
1791 /* we are resolving identity definition, so now update structures */
1792 ident->base = base_iter = &module->ident[i];
1793
1794 break;
1795 }
1796 }
1797
1798 /* search submodules */
1799 if (!base_iter) {
1800 for (j = 0; j < module->inc_size; j++) {
1801 for (i = 0; i < module->inc[j].submodule->ident_size; i++) {
1802 if (!strcmp(basename, module->inc[j].submodule->ident[i].name)) {
1803
1804 if (!ident) {
1805 return &module->inc[j].submodule->ident[i];
1806 }
1807
1808 ident->base = base_iter = &module->inc[j].submodule->ident[i];
1809 break;
1810 }
1811 }
1812 }
1813 }
1814
1815 /* we found it somewhere */
1816 if (base_iter) {
1817 while (base_iter) {
1818 for (der = base_iter->der; der && der->next; der = der->next);
1819 if (der) {
1820 der->next = malloc(sizeof *der);
1821 der = der->next;
1822 } else {
1823 ident->base->der = der = malloc(sizeof *der);
1824 }
1825 der->next = NULL;
1826 der->ident = ident;
1827
1828 base_iter = base_iter->base;
1829 }
1830 return ident->base;
1831 }
1832
1833 return NULL;
1834}
1835
Michal Vaskof02e3742015-08-05 16:27:02 +02001836/* logs directly */
Radek Krejcia52656e2015-08-05 13:41:50 +02001837static struct lys_ident *
Michal Vaskof02e3742015-08-05 16:27:02 +02001838resolve_base_ident(struct lys_module *module, struct lys_ident *ident, const char *basename, const char* parent,
1839 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001840{
1841 const char *name;
Michal Vaskof02e3742015-08-05 16:27:02 +02001842 int i, prefix_len = 0;
Radek Krejcia52656e2015-08-05 13:41:50 +02001843 struct lys_ident *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001844
1845 /* search for the base identity */
1846 name = strchr(basename, ':');
1847 if (name) {
1848 /* set name to correct position after colon */
1849 prefix_len = name - basename;
1850 name++;
1851
1852 if (!strncmp(basename, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
1853 /* prefix refers to the current module, ignore it */
1854 prefix_len = 0;
1855 }
1856 } else {
1857 name = basename;
1858 }
1859
1860 if (prefix_len) {
1861 /* get module where to search */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001862 module = resolve_prefixed_module(module, basename, prefix_len);
1863 if (!module) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001864 /* identity refers unknown data model */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001865 LOGVAL(LYE_INPREF, line, basename);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001866 return NULL;
1867 }
1868 } else {
1869 /* search in submodules */
1870 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +02001871 result = resolve_base_ident_sub((struct lys_module *)module->inc[i].submodule, ident, name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001872 if (result) {
1873 return result;
1874 }
1875 }
1876 }
1877
1878 /* search in the identified module */
1879 result = resolve_base_ident_sub(module, ident, name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001880 if (!result) {
1881 LOGVAL(LYE_INARG, line, basename, parent);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001882 }
1883
1884 return result;
1885}
1886
Michal Vaskof02e3742015-08-05 16:27:02 +02001887/* does not log */
Radek Krejcia52656e2015-08-05 13:41:50 +02001888struct lys_ident *
1889resolve_identityref(struct lys_ident *base, const char *name, const char *ns)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001890{
Radek Krejcia52656e2015-08-05 13:41:50 +02001891 struct lys_ident_der *der;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001892
1893 if (!base || !name || !ns) {
1894 return NULL;
1895 }
1896
1897 for(der = base->der; der; der = der->next) {
1898 if (!strcmp(der->ident->name, name) && ns == der->ident->module->ns) {
1899 /* we have match */
1900 return der->ident;
1901 }
1902 }
1903
1904 /* not found */
1905 return NULL;
1906}
1907
Michal Vaskof02e3742015-08-05 16:27:02 +02001908/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001909static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001910resolve_unres_ident(struct lys_module *mod, struct lys_ident *ident, const char *base_name, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001911{
Michal Vaskof02e3742015-08-05 16:27:02 +02001912 if (resolve_base_ident(mod, ident, base_name, "ident", line)) {
1913 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001914 }
1915
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001916 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "identity", base_name);
1917 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001918}
1919
Michal Vaskof02e3742015-08-05 16:27:02 +02001920/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001921static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001922resolve_unres_type_identref(struct lys_module *mod, struct lys_type *type, const char *base_name, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001923{
Michal Vaskof02e3742015-08-05 16:27:02 +02001924 type->info.ident.ref = resolve_base_ident(mod, NULL, base_name, "type", line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001925 if (type->info.ident.ref) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001926 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001927 }
1928
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001929 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "identityref", base_name);
1930 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001931}
1932
Michal Vaskof02e3742015-08-05 16:27:02 +02001933/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001934static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001935resolve_unres_type_leafref(struct lys_module *mod, struct lys_type *type, struct lys_node *node, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001936{
Radek Krejcib1c12512015-08-11 11:22:04 +02001937 type->info.lref.target = (struct lys_node_leaf *)resolve_path_arg_schema(mod, type->info.lref.path, node, line);
1938 if (type->info.lref.target) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001939 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001940 }
1941
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001942 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "leafref", type->info.lref.path);
1943 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001944}
1945
Michal Vaskof02e3742015-08-05 16:27:02 +02001946/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001947static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001948resolve_unres_type_der(struct lys_module *mod, struct lys_type *type, const char *type_name, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001949{
Radek Krejci76512572015-08-04 09:47:08 +02001950 type->der = resolve_superior_type(type_name, type->prefix, mod, (struct lys_node *)type->der);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001951 if (type->der) {
Michal Vaskoa91333d2015-08-03 16:03:06 +02001952 type->base = type->der->type.base;
Michal Vaskof02e3742015-08-05 16:27:02 +02001953 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001954 }
1955
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001956 LOGVAL(LYE_INRESOLV, line, "type", type_name);
1957 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001958}
1959
Michal Vaskof02e3742015-08-05 16:27:02 +02001960/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001961static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001962resolve_unres_augment(struct lys_module *mod, struct lys_node_augment *aug, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001963{
Michal Vasko0d42e9f2015-08-06 10:07:28 +02001964 assert(!aug->parent || (aug->parent->nodetype != LYS_USES));
Michal Vasko49291b32015-08-06 09:49:41 +02001965
1966 if (!resolve_augment(aug, aug->parent, mod)) {
1967 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001968 }
1969
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001970 LOGVAL(LYE_INRESOLV, line, "augment", aug->target_name);
1971 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001972}
1973
Michal Vaskof02e3742015-08-05 16:27:02 +02001974/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001975static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001976resolve_unres_iffeature(struct lys_module *mod, struct lys_feature **feat_ptr, const char *feat_name, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001977{
Michal Vaskof02e3742015-08-05 16:27:02 +02001978 *feat_ptr = resolve_feature(feat_name, mod, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001979 if (*feat_ptr) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001980 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001981 }
1982
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001983 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "if-feature", feat_name);
1984 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001985}
1986
Michal Vaskof02e3742015-08-05 16:27:02 +02001987/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001988static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001989resolve_unres_uses(struct lys_node_uses *uses, struct unres_schema *unres, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001990{
Michal Vaskof02e3742015-08-05 16:27:02 +02001991 if (uses->grp || !resolve_grouping(uses->parent, uses, line)) {
1992 if (!resolve_uses(uses, unres, line)) {
1993 return EXIT_SUCCESS;
Michal Vasko12e30842015-08-04 11:54:00 +02001994 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 }
1996
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001997 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "uses", uses->name);
1998 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001999}
2000
Michal Vaskof02e3742015-08-05 16:27:02 +02002001/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002002static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002003resolve_unres_type_dflt(struct lys_type *type, const char *dflt, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002004{
Michal Vasko12e30842015-08-04 11:54:00 +02002005 if (!check_default(type, dflt)) {
Michal Vaskof02e3742015-08-05 16:27:02 +02002006 return EXIT_SUCCESS;
Michal Vasko12e30842015-08-04 11:54:00 +02002007 }
2008
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002009 LOGVAL(LYE_INRESOLV, line, "type default", dflt);
2010 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011}
2012
Michal Vaskof02e3742015-08-05 16:27:02 +02002013/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002014static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002015resolve_unres_choice_dflt(struct lys_node_choice *choice, const char *dflt, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002016{
Michal Vasko1f76a282015-08-04 16:16:53 +02002017 choice->dflt = resolve_child((struct lys_node *)choice, dflt, strlen(dflt), LYS_ANYXML | LYS_CASE
Radek Krejci76512572015-08-04 09:47:08 +02002018 | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002019 if (choice->dflt) {
Michal Vaskof02e3742015-08-05 16:27:02 +02002020 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002021 }
2022
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002023 LOGVAL(LYE_INRESOLV, line, "choice default", dflt);
2024 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002025}
2026
Michal Vaskof02e3742015-08-05 16:27:02 +02002027/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002028static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002029resolve_unres_list_keys(struct lys_node_list *list, const char *keys_str, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002030{
2031 int i, len;
2032 const char *value;
2033
2034 for (i = 0; i < list->keys_size; ++i) {
2035 /* get the key name */
2036 if ((value = strpbrk(keys_str, " \t\n"))) {
2037 len = value - keys_str;
2038 while (isspace(value[0])) {
2039 value++;
2040 }
2041 } else {
2042 len = strlen(keys_str);
2043 }
2044
Radek Krejcib8048692015-08-05 13:36:34 +02002045 list->keys[i] = (struct lys_node_leaf *)resolve_child((struct lys_node *)list, keys_str, len, LYS_LEAF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002046
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002047 if (check_key(list->keys[i], list->flags, list->keys, i, keys_str, len, line)) {
2048 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "list keys", keys_str);
2049 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002050 }
2051
2052 /* prepare for next iteration */
2053 while (value && isspace(value[0])) {
2054 value++;
2055 }
2056 keys_str = value;
2057 }
2058
Michal Vaskof02e3742015-08-05 16:27:02 +02002059 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002060}
2061
Michal Vaskof02e3742015-08-05 16:27:02 +02002062/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002063static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002064resolve_unres_list_uniq(struct lys_unique *uniq, const char *uniq_str, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002065{
Michal Vaskof02e3742015-08-05 16:27:02 +02002066 if (!resolve_unique((struct lys_node *)uniq->leafs, uniq_str, uniq, line)) {
2067 return EXIT_SUCCESS;
Michal Vasko12e30842015-08-04 11:54:00 +02002068 }
2069
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002070 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "list unique", uniq_str);
2071 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002072}
2073
2074static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002075resolve_unres_when(struct lys_when *UNUSED(when), struct lys_node *UNUSED(start), uint32_t UNUSED(line))
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002076{
2077 /* TODO */
Michal Vaskof02e3742015-08-05 16:27:02 +02002078 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002079}
2080
2081static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002082resolve_unres_must(struct lys_restr *UNUSED(must), struct lys_node *UNUSED(start), uint32_t UNUSED(line))
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002083{
2084 /* TODO */
Michal Vaskof02e3742015-08-05 16:27:02 +02002085 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002086}
2087
Michal Vaskof02e3742015-08-05 16:27:02 +02002088/* logs indirectly
2089 * line == -1 means do not log, 0 means unknown */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002090static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002091resolve_unres_item(struct lys_module *mod, void *item, enum UNRES_ITEM type, void *str_node, struct unres_schema *unres,
Michal Vaskof02e3742015-08-05 16:27:02 +02002092 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002093{
2094 int ret = EXIT_FAILURE, has_str = 0;
2095
2096 switch (type) {
2097 case UNRES_RESOLVED:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002098 LOGINT;
Michal Vasko45b42312015-08-05 09:30:11 +02002099 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002100 case UNRES_IDENT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002101 ret = resolve_unres_ident(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002102 has_str = 1;
2103 break;
2104 case UNRES_TYPE_IDENTREF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002105 ret = resolve_unres_type_identref(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002106 has_str = 1;
2107 break;
2108 case UNRES_TYPE_LEAFREF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002109 ret = resolve_unres_type_leafref(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002110 has_str = 0;
2111 break;
2112 case UNRES_TYPE_DER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002113 ret = resolve_unres_type_der(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002114 has_str = 1;
2115 break;
2116 case UNRES_AUGMENT:
2117 ret = resolve_unres_augment(mod, item, line);
2118 has_str = 0;
2119 break;
2120 case UNRES_IFFEAT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002121 ret = resolve_unres_iffeature(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002122 has_str = 1;
2123 break;
2124 case UNRES_USES:
Michal Vaskof02e3742015-08-05 16:27:02 +02002125 ret = resolve_unres_uses(item, unres, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002126 has_str = 0;
2127 break;
2128 case UNRES_TYPE_DFLT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002129 ret = resolve_unres_type_dflt(item, str_node, line);
2130 /* do not remove str_node (dflt), it's in a typedef */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002131 has_str = 0;
2132 break;
2133 case UNRES_CHOICE_DFLT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002134 ret = resolve_unres_choice_dflt(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002135 has_str = 1;
2136 break;
2137 case UNRES_LIST_KEYS:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002138 ret = resolve_unres_list_keys(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002139 has_str = 1;
2140 break;
2141 case UNRES_LIST_UNIQ:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002142 ret = resolve_unres_list_uniq(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002143 has_str = 1;
2144 break;
2145 case UNRES_WHEN:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002146 ret = resolve_unres_when(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002147 has_str = 0;
2148 break;
2149 case UNRES_MUST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002150 ret = resolve_unres_must(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002151 has_str = 0;
2152 break;
2153 }
2154
2155 if (has_str && !ret) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002156 lydict_remove(mod->ctx, str_node);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002157 }
2158
2159 return ret;
2160}
2161
Michal Vaskof02e3742015-08-05 16:27:02 +02002162/* logs directly */
2163static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02002164print_unres_item_fail(void *item, enum UNRES_ITEM type, void *str_node, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002165{
Michal Vaskof02e3742015-08-05 16:27:02 +02002166 char line_str[18];
2167
2168 if (line) {
2169 sprintf(line_str, " (line %u)", line);
2170 } else {
2171 line_str[0] = '\0';
2172 }
2173
2174 switch (type) {
2175 case UNRES_RESOLVED:
2176 LOGINT;
2177 break;
2178 case UNRES_IDENT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002179 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "identity", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002180 break;
2181 case UNRES_TYPE_IDENTREF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002182 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "identityref", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002183 break;
2184 case UNRES_TYPE_LEAFREF:
2185 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "leafref", ((struct lys_type *)item)->info.lref.path, line_str);
2186 break;
2187 case UNRES_TYPE_DER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002188 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "derived type", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002189 break;
2190 case UNRES_AUGMENT:
2191 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "augment target", ((struct lys_node_augment *)item)->target_name, line_str);
2192 break;
2193 case UNRES_IFFEAT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002194 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "if-feature", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002195 break;
2196 case UNRES_USES:
2197 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "uses", ((struct lys_node_uses *)item)->name, line_str);
2198 break;
2199 case UNRES_TYPE_DFLT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002200 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "type default", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002201 break;
2202 case UNRES_CHOICE_DFLT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002203 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "choice default", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002204 break;
2205 case UNRES_LIST_KEYS:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002206 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "list keys", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002207 break;
2208 case UNRES_LIST_UNIQ:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002209 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "list unique", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002210 break;
2211 case UNRES_WHEN:
2212 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "when", ((struct lys_when *)item)->cond, line_str);
2213 break;
2214 case UNRES_MUST:
2215 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "must", ((struct lys_restr *)item)->expr, line_str);
2216 break;
2217 }
2218}
2219
2220/* logs indirectly */
2221int
2222resolve_unres(struct lys_module *mod, struct unres_schema *unres)
2223{
2224 uint32_t i, resolved = 0;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002225
2226 assert(unres);
2227
2228 /* uses */
2229 for (i = 0; i < unres->count; ++i) {
2230 if (unres->type[i] != UNRES_USES) {
2231 continue;
2232 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002233 if (!resolve_unres_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres, unres->line[i])) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002234 unres->type[i] = UNRES_RESOLVED;
2235 ++resolved;
2236 }
2237 }
2238
2239 /* augment */
2240 for (i = 0; i < unres->count; ++i) {
2241 if (unres->type[i] != UNRES_AUGMENT) {
2242 continue;
2243 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002244 if (!resolve_unres_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres, unres->line[i])) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002245 unres->type[i] = UNRES_RESOLVED;
2246 ++resolved;
2247 }
2248 }
2249
2250 /* the rest */
2251 for (i = 0; i < unres->count; ++i) {
2252 if (unres->type[i] == UNRES_RESOLVED) {
2253 continue;
2254 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002255 if (!resolve_unres_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres, unres->line[i])) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002256 unres->type[i] = UNRES_RESOLVED;
2257 ++resolved;
2258 }
2259 }
2260
2261 if (resolved < unres->count) {
2262 return EXIT_FAILURE;
2263 }
2264
2265 return EXIT_SUCCESS;
2266}
2267
Michal Vaskof02e3742015-08-05 16:27:02 +02002268/* logs indirectly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002269void
Radek Krejci1d82ef62015-08-07 14:44:40 +02002270unres_add_str(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type, const char *str,
Michal Vaskof02e3742015-08-05 16:27:02 +02002271 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002272{
2273 str = lydict_insert(mod->ctx, str, 0);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002274 unres_add_node(mod, unres, item, type, (struct lys_node *)str, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002275}
2276
Michal Vaskof02e3742015-08-05 16:27:02 +02002277/* logs indirectly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002278void
Radek Krejci1d82ef62015-08-07 14:44:40 +02002279unres_add_node(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type,
2280 struct lys_node *node, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002281{
2282 assert(unres && item);
2283
Radek Krejci1d82ef62015-08-07 14:44:40 +02002284 if (!resolve_unres_item(mod, item, type, node, unres, UINT_MAX)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002285 return;
2286 }
2287
Radek Krejci1d82ef62015-08-07 14:44:40 +02002288 print_unres_item_fail(item, type, node, line);
Michal Vaskof02e3742015-08-05 16:27:02 +02002289
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002290 unres->count++;
2291 unres->item = realloc(unres->item, unres->count*sizeof *unres->item);
2292 unres->item[unres->count-1] = item;
2293 unres->type = realloc(unres->type, unres->count*sizeof *unres->type);
2294 unres->type[unres->count-1] = type;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002295 unres->str_snode = realloc(unres->str_snode, unres->count*sizeof *unres->str_snode);
2296 unres->str_snode[unres->count-1] = node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002297 unres->line = realloc(unres->line, unres->count*sizeof *unres->line);
2298 unres->line[unres->count-1] = line;
2299}
2300
Michal Vaskof02e3742015-08-05 16:27:02 +02002301/* logs indirectly */
Michal Vaskodad19402015-08-06 09:51:53 +02002302int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002303unres_dup(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type, void *new_item)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002304{
2305 int i;
2306
2307 if (!item || !new_item) {
Michal Vaskodad19402015-08-06 09:51:53 +02002308 LOGINT;
2309 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002310 }
2311
Radek Krejci1d82ef62015-08-07 14:44:40 +02002312 i = unres_find(unres, item, type);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002313
2314 if (i == -1) {
Michal Vaskodad19402015-08-06 09:51:53 +02002315 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002316 }
2317
2318 if ((type == UNRES_TYPE_LEAFREF) || (type == UNRES_AUGMENT) || (type == UNRES_USES) || (type == UNRES_TYPE_DFLT)
2319 || (type == UNRES_WHEN) || (type == UNRES_MUST)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002320 unres_add_node(mod, unres, new_item, type, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002321 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002322 unres_add_str(mod, unres, new_item, type, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002323 }
Michal Vaskodad19402015-08-06 09:51:53 +02002324
2325 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002326}
2327
Michal Vaskof02e3742015-08-05 16:27:02 +02002328/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002329int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002330unres_find(struct unres_schema *unres, void *item, enum UNRES_ITEM type)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002331{
2332 uint32_t ret = -1, i;
2333
2334 for (i = 0; i < unres->count; ++i) {
2335 if ((unres->item[i] == item) && (unres->type[i] == type)) {
2336 ret = i;
2337 break;
2338 }
2339 }
2340
2341 return ret;
2342}