blob: 8cebff3a106259aa70a5f71cdb995d19d9365fa1 [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
Radek Krejcib8048692015-08-05 13:36:34 +0200609 uniq_s->leafs[i] = (struct lys_node_leaf *)resolve_schema_nodeid(start, parent, parent->module, LYS_USES);
Radek Krejci76512572015-08-04 09:47:08 +0200610 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 Krejci76512572015-08-04 09:47:08 +0200645 struct lys_node *mnode, *mnode_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
684 LY_TREE_FOR(searchmod->data, mnode) {
Radek Krejci76512572015-08-04 09:47:08 +0200685 if (mnode->nodetype == LYS_GROUPING && !strcmp(mnode->name, name)) {
Radek Krejcib8048692015-08-05 13:36:34 +0200686 uses->grp = (struct lys_node_grp *)mnode;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200687 return EXIT_SUCCESS;
688 }
689 }
690 } else {
691 /* in local tree hierarchy */
692 for (mnode_aux = parent; mnode_aux; mnode_aux = mnode_aux->parent) {
693 LY_TREE_FOR(mnode_aux->child, mnode) {
Radek Krejci76512572015-08-04 09:47:08 +0200694 if (mnode->nodetype == LYS_GROUPING && !strcmp(mnode->name, name)) {
Radek Krejcib8048692015-08-05 13:36:34 +0200695 uses->grp = (struct lys_node_grp *)mnode;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200696 return EXIT_SUCCESS;
697 }
698 }
699 }
700
701 /* search in top level of the current module */
702 LY_TREE_FOR(module->data, mnode) {
Radek Krejci76512572015-08-04 09:47:08 +0200703 if (mnode->nodetype == LYS_GROUPING && !strcmp(mnode->name, name)) {
Radek Krejcib8048692015-08-05 13:36:34 +0200704 uses->grp = (struct lys_node_grp *)mnode;
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++) {
711 LY_TREE_FOR(module->inc[i].submodule->data, mnode) {
Radek Krejci76512572015-08-04 09:47:08 +0200712 if (mnode->nodetype == LYS_GROUPING && !strcmp(mnode->name, name)) {
Radek Krejcib8048692015-08-05 13:36:34 +0200713 uses->grp = (struct lys_node_grp *)mnode;
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)
817 * - LYS_USES (only descendant-schema-nodeid allowed, ".." not allowed)
818 * - LYS_CHOICE (search only start->child, only descendant-schema-nodeid allowed)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200819 */
Radek Krejci76512572015-08-04 09:47:08 +0200820struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +0200821resolve_schema_nodeid(const char *id, struct lys_node *start, struct lys_module *mod, LYS_NODE node_type)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200822{
Michal Vaskocc9e12e2015-08-04 16:14:37 +0200823 const char *name, *prefix;
Radek Krejci76512572015-08-04 09:47:08 +0200824 struct lys_node *sibling;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200825 int ret, nam_len, pref_len, is_relative = -1;
Radek Krejcib8048692015-08-05 13:36:34 +0200826 struct lys_module *prefix_mod, *start_mod;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200827 /* 0 - in module, 1 - in 1st submodule, 2 - in 2nd submodule, ... */
828 uint8_t in_submod = 0;
Michal Vaskocc9e12e2015-08-04 16:14:37 +0200829 /* 0 - in data, 1 - in RPCs, 2 - in notifications (relevant only with LYS_AUGMENT) */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200830 uint8_t in_mod_part = 0;
831
832 assert(mod);
833 assert(id);
834
835 if ((ret = parse_schema_nodeid(id, &prefix, &pref_len, &name, &nam_len, &is_relative)) < 1) {
836 return NULL;
837 }
838 id += ret;
839
Radek Krejci76512572015-08-04 09:47:08 +0200840 if (!is_relative && (node_type & (LYS_USES | LYS_CHOICE))) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200841 return NULL;
842 }
843
844 /* absolute-schema-nodeid */
845 if (!is_relative) {
846 if (prefix) {
847 start_mod = resolve_prefixed_module(mod, prefix, pref_len);
848 if (!start_mod) {
849 return NULL;
850 }
851 start = start_mod->data;
852 } else {
853 start = mod->data;
854 start_mod = mod;
855 }
856 /* descendant-schema-nodeid */
857 } else {
858 assert(start);
859 start = start->child;
860 start_mod = start->module;
861 }
862
863 while (1) {
Michal Vasko1e989c02015-08-04 12:33:00 +0200864 sibling = NULL;
865 LY_TREE_FOR(start, sibling) {
866 /* name match */
867 if ((sibling->name && !strncmp(name, sibling->name, nam_len) && !sibling->name[nam_len])
868 || (!strncmp(name, "input", 5) && (nam_len == 5) && (sibling->nodetype == LYS_INPUT))
869 || (!strncmp(name, "output", 6) && (nam_len == 6) && (sibling->nodetype == LYS_OUTPUT))) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200870
Michal Vasko1e989c02015-08-04 12:33:00 +0200871 /* prefix match check */
872 if (prefix) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200873
Michal Vasko1e989c02015-08-04 12:33:00 +0200874 prefix_mod = resolve_prefixed_module(mod, prefix, pref_len);
875 if (!prefix_mod) {
876 return NULL;
877 }
878
879 if (!sibling->module->type) {
880 if (prefix_mod != sibling->module) {
881 continue;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200882 }
Michal Vasko1e989c02015-08-04 12:33:00 +0200883 } else {
Radek Krejcib8048692015-08-05 13:36:34 +0200884 if (prefix_mod != ((struct lys_submodule *)sibling->module)->belongsto) {
Michal Vasko1e989c02015-08-04 12:33:00 +0200885 continue;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200886 }
887 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200888 }
Michal Vasko1e989c02015-08-04 12:33:00 +0200889
Michal Vasko1e989c02015-08-04 12:33:00 +0200890 /* the result node? */
891 if (!id[0]) {
892 return sibling;
893 }
894
895 /* check for shorthand cases - then 'start' does not change */
896 if (!sibling->parent || (sibling->parent->nodetype != LYS_CHOICE)
897 || (sibling->nodetype == LYS_CASE)) {
898 start = sibling->child;
899 }
900 break;
901 }
902 }
903
904 /* we did not find the case in direct siblings */
905 if (node_type == LYS_CHOICE) {
906 return NULL;
907 }
908
909 /* no match */
910 if (!sibling) {
911 /* on augment search also RPCs and notifications, if we are in top-level */
912 if ((node_type == LYS_AUGMENT) && (!start || !start->parent)) {
913 /* we have searched all the data nodes */
914 if (in_mod_part == 0) {
915 if (!in_submod) {
916 start = start_mod->rpc;
917 } else {
918 start = start_mod->inc[in_submod-1].submodule->rpc;
919 }
920 in_mod_part = 1;
921 continue;
922 }
923 /* we have searched all the RPCs */
924 if (in_mod_part == 1) {
925 if (!in_submod) {
926 start = start_mod->notif;
927 } else {
928 start = start_mod->inc[in_submod-1].submodule->notif;
929 }
930 in_mod_part = 2;
931 continue;
932 }
933 /* we have searched all the notifications, nothing else to search in this module */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200934 }
935
Michal Vasko1e989c02015-08-04 12:33:00 +0200936 /* are we done with the included submodules as well? */
937 if (in_submod == start_mod->inc_size) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200938 return NULL;
939 }
940
Michal Vasko1e989c02015-08-04 12:33:00 +0200941 /* we aren't, check the next one */
942 ++in_submod;
943 in_mod_part = 0;
944 start = start_mod->inc[in_submod-1].submodule->data;
945 continue;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200946 }
947
948 /* we found our submodule */
949 if (in_submod) {
Radek Krejcib8048692015-08-05 13:36:34 +0200950 start_mod = (struct lys_module *)start_mod->inc[in_submod-1].submodule;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200951 in_submod = 0;
952 }
953
954 if ((ret = parse_schema_nodeid(id, &prefix, &pref_len, &name, &nam_len, &is_relative)) < 1) {
955 return NULL;
956 }
957 id += ret;
958 }
959
960 /* cannot get here */
961 return NULL;
962}
963
Michal Vaskof02e3742015-08-05 16:27:02 +0200964/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200965static int
966resolve_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 +0200967 struct unres_data **parents)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200968{
969 int flag;
Radek Krejcib8048692015-08-05 13:36:34 +0200970 struct lys_module *mod;
Michal Vaskof02e3742015-08-05 16:27:02 +0200971 struct unres_data *item, *par_iter;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200972 struct lyd_node *node;
973
974 if (prefix) {
975 /* we have prefix, find appropriate module */
976 mod = resolve_prefixed_module(data_source->schema->module, prefix, pref_len);
977 if (!mod) {
978 /* invalid prefix */
Michal Vaskof02e3742015-08-05 16:27:02 +0200979 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200980 }
981 } else {
982 /* no prefix, module is the same as of current node */
983 mod = data_source->schema->module;
984 }
985
986 if (!*parents) {
987 *parents = malloc(sizeof **parents);
988 (*parents)->dnode = NULL;
989 (*parents)->next = NULL;
990 }
991 for (par_iter = *parents; par_iter; par_iter = par_iter->next) {
Radek Krejci76512572015-08-04 09:47:08 +0200992 if (par_iter->dnode && (par_iter->dnode->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200993 /* skip */
994 continue;
995 }
996 flag = 0;
997 LY_TREE_FOR(par_iter->dnode ? par_iter->dnode->child : data_source, node) {
998 if (node->schema->module == mod && !strncmp(node->schema->name, name, nam_len)
999 && node->schema->name[nam_len] == '\0') {
1000 /* matching target */
1001 if (!flag) {
1002 /* replace leafref instead of the current parent */
1003 par_iter->dnode = node;
1004 flag = 1;
1005 } else {
1006 /* multiple matching, so create new leafref structure */
1007 item = malloc(sizeof *item);
1008 item->dnode = node;
1009 item->next = par_iter->next;
1010 par_iter->next = item;
1011 par_iter = par_iter->next;
1012 }
1013 }
1014 }
1015 }
1016
1017 return !flag;
1018}
1019
Michal Vaskof02e3742015-08-05 16:27:02 +02001020/* logs directly
1021 * ... /node[source = destination] ... */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001022static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001023resolve_path_predicate_data(const char *pred, struct unres_data **node_match, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001024{
Michal Vaskof02e3742015-08-05 16:27:02 +02001025 struct unres_data *source_match, *dest_match, *node, *node_prev = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001026 const char *path_key_expr, *source, *sour_pref, *dest, *dest_pref;
1027 int pke_len, sour_len, sour_pref_len, dest_len, dest_pref_len, parsed = 0, pke_parsed = 0;
1028 int has_predicate, dest_parent_times, i;
1029
1030 do {
1031 if ((i = parse_path_predicate(pred, &sour_pref, &sour_pref_len, &source, &sour_len, &path_key_expr,
1032 &pke_len, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001033 LOGVAL(LYE_INCHAR, line, pred[-i], pred-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001034 return -parsed+i;
1035 }
1036 parsed += i;
1037 pred += i;
1038
1039 for (node = *node_match; node;) {
1040 /* source */
1041 source_match = NULL;
1042 /* must be leaf (key of a list) */
1043 if (resolve_data_nodeid(sour_pref, sour_pref_len, source, sour_len, node->dnode, &source_match)
1044 || !source_match || source_match->next
Radek Krejci76512572015-08-04 09:47:08 +02001045 || (source_match->dnode->schema->nodetype != LYS_LEAF)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001046 LOGVAL(LYE_LINE, line);
1047 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001048 return -parsed;
1049 }
1050
1051 /* destination */
1052 dest_match = calloc(1, sizeof *dest_match);
1053 dest_match->dnode = node->dnode;
1054 if ((i = parse_path_key_expr(path_key_expr, &dest_pref, &dest_pref_len, &dest, &dest_len,
1055 &dest_parent_times)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001056 LOGVAL(LYE_INCHAR, line, path_key_expr[-i], path_key_expr-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001057 return -parsed+i;
1058 }
1059 pke_parsed += i;
1060 for (i = 0; i < dest_parent_times; ++i) {
1061 dest_match->dnode = dest_match->dnode->parent;
1062 if (!dest_match->dnode) {
1063 free(dest_match);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001064 LOGVAL(LYE_LINE, line);
1065 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001066 return -parsed;
1067 }
1068 }
1069 while (1) {
1070 if (resolve_data_nodeid(dest_pref, dest_pref_len, dest, dest_len, dest_match->dnode, &dest_match)
Michal Vasko1f76a282015-08-04 16:16:53 +02001071 || !dest_match->dnode || dest_match->next) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001072 free(dest_match);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001073 LOGVAL(LYE_LINE, line);
1074 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001075 return -parsed;
1076 }
1077
1078 if (pke_len == pke_parsed) {
1079 break;
1080 }
Michal Vasko1f76a282015-08-04 16:16:53 +02001081 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 +02001082 &dest_parent_times)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001083 LOGVAL(LYE_INCHAR, line, path_key_expr[-i], path_key_expr-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001084 return -parsed+i;
1085 }
1086 pke_parsed += i;
1087 }
1088
1089 /* check match between source and destination nodes */
Radek Krejcib8048692015-08-05 13:36:34 +02001090 if (((struct lys_node_leaf *)source_match->dnode->schema)->type.base
1091 != ((struct lys_node_leaf *)dest_match->dnode->schema)->type.base) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001092 goto remove_leafref;
1093 }
1094
1095 if (((struct lyd_node_leaf *)source_match->dnode)->value_str
1096 != ((struct lyd_node_leaf *)dest_match->dnode)->value_str) {
1097 goto remove_leafref;
1098 }
1099
1100 /* leafref is ok, continue check with next leafref */
1101 node_prev = node;
1102 node = node->next;
1103 continue;
1104
1105remove_leafref:
1106 /* does not fulfill conditions, remove leafref record */
1107 if (node_prev) {
1108 node_prev->next = node->next;
1109 free(node);
1110 node = node_prev->next;
1111 } else {
1112 node = (*node_match)->next;
1113 free(*node_match);
1114 *node_match = node;
1115 }
1116 }
1117 } while (has_predicate);
1118
1119 return parsed;
1120}
1121
Michal Vaskof02e3742015-08-05 16:27:02 +02001122/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001123int
Michal Vaskof02e3742015-08-05 16:27:02 +02001124resolve_path_arg_data(struct unres_data *unres, const char *path, struct unres_data **ret)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001125{
1126 struct lyd_node *data;
Michal Vaskof02e3742015-08-05 16:27:02 +02001127 struct unres_data *riter = NULL, *raux;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001128 const char *prefix, *name;
Michal Vasko1f76a282015-08-04 16:16:53 +02001129 int pref_len, nam_len, has_predicate, parent_times, i;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001130
1131 *ret = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001132 parent_times = 0;
1133
1134 /* searching for nodeset */
1135 do {
1136 if ((i = parse_path_arg(path, &prefix, &pref_len, &name, &nam_len, &parent_times, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001137 LOGVAL(LYE_INCHAR, unres->line, path[-i], path-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001138 goto error;
1139 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001140 path += i;
1141
1142 if (!*ret) {
1143 *ret = calloc(1, sizeof **ret);
1144 for (i = 0; i < parent_times; ++i) {
1145 /* relative path */
1146 if (!*ret) {
1147 /* error, too many .. */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001148 LOGVAL(LYE_INVAL, unres->line, path, unres->dnode->schema->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001149 goto error;
1150 } else if (!(*ret)->dnode) {
1151 /* first .. */
1152 (*ret)->dnode = unres->dnode->parent;
1153 } else if (!(*ret)->dnode->parent) {
1154 /* we are in root */
1155 free(*ret);
1156 *ret = NULL;
1157 } else {
1158 /* multiple .. */
1159 (*ret)->dnode = (*ret)->dnode->parent;
1160 }
1161 }
1162
1163 /* absolute path */
1164 if (parent_times == -1) {
1165 for (data = unres->dnode; data->parent; data = data->parent);
1166 for (; data->prev->next; data = data->prev);
1167 }
1168 }
1169
1170 /* node identifier */
1171 if (resolve_data_nodeid(prefix, pref_len, name, nam_len, data, ret)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001172 LOGVAL(LYE_INELEM_LEN, unres->line, nam_len, name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001173 goto error;
1174 }
1175
1176 if (has_predicate) {
1177 /* we have predicate, so the current results must be lists */
1178 for (raux = NULL, riter = *ret; riter; ) {
Radek Krejci76512572015-08-04 09:47:08 +02001179 if (riter->dnode->schema->nodetype == LYS_LIST &&
Radek Krejcib8048692015-08-05 13:36:34 +02001180 ((struct lys_node_list *)riter->dnode->schema)->keys) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001181 /* leafref is ok, continue check with next leafref */
1182 raux = riter;
1183 riter = riter->next;
1184 continue;
1185 }
1186
1187 /* does not fulfill conditions, remove leafref record */
1188 if (raux) {
1189 raux->next = riter->next;
1190 free(riter);
1191 riter = raux->next;
1192 } else {
1193 *ret = riter->next;
1194 free(riter);
1195 riter = *ret;
1196 }
1197 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001198 if ((i = resolve_path_predicate_data(path, ret, unres->line)) < 1) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001199 goto error;
1200 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001201 path += i;
1202
1203 if (!*ret) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001204 LOGVAL(LYE_LINE, unres->line);
1205 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001206 goto error;
1207 }
1208 }
1209 } while (path[0] != '\0');
1210
Michal Vaskof02e3742015-08-05 16:27:02 +02001211 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001212
1213error:
1214
1215 while (*ret) {
1216 raux = (*ret)->next;
1217 free(*ret);
1218 *ret = raux;
1219 }
1220
Michal Vaskof02e3742015-08-05 16:27:02 +02001221 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001222}
1223
Michal Vaskof02e3742015-08-05 16:27:02 +02001224/* logs directly */
Michal Vasko1f76a282015-08-04 16:16:53 +02001225static int
Radek Krejcib8048692015-08-05 13:36:34 +02001226resolve_path_predicate_schema(const char *pred, struct lys_module *mod, struct lys_node *source_node,
Michal Vaskof02e3742015-08-05 16:27:02 +02001227 struct lys_node *dest_node, uint32_t line)
Michal Vasko1f76a282015-08-04 16:16:53 +02001228{
1229 struct lys_node *src_node, *dst_node;
1230 const char *path_key_expr, *source, *sour_pref, *dest, *dest_pref;
1231 int pke_len, sour_len, sour_pref_len, dest_len, dest_pref_len, parsed = 0, pke_parsed = 0;
1232 int has_predicate, dest_parent_times = 0, i;
1233
1234 do {
1235 if ((i = parse_path_predicate(pred, &sour_pref, &sour_pref_len, &source, &sour_len, &path_key_expr,
1236 &pke_len, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001237 LOGVAL(LYE_INCHAR, line, pred[-i], pred-i);
Michal Vasko1f76a282015-08-04 16:16:53 +02001238 return -parsed+i;
1239 }
1240 parsed += i;
1241 pred += i;
1242
1243 /* source (must be leaf, from the same module) */
1244 if (sour_pref && (resolve_prefixed_module(mod, sour_pref, sour_pref_len) != mod)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001245 LOGVAL(LYE_INPREF_LEN, line, sour_pref_len, sour_pref);
Michal Vasko1f76a282015-08-04 16:16:53 +02001246 return -parsed;
1247 }
1248
1249 src_node = resolve_child(source_node, source, sour_len, LYS_LEAF);
1250 if (!src_node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001251 LOGVAL(LYE_LINE, line);
1252 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001253 return -parsed;
1254 }
1255
1256 /* destination */
1257 if ((i = parse_path_key_expr(path_key_expr, &dest_pref, &dest_pref_len, &dest, &dest_len,
1258 &dest_parent_times)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001259 LOGVAL(LYE_INCHAR, line, path_key_expr[-i], path_key_expr-i);
Michal Vasko1f76a282015-08-04 16:16:53 +02001260 return -parsed;
1261 }
1262 pke_parsed += i;
1263
1264 /* dest_node is actually the parent of this leaf, so skip the first ".." */
1265 dst_node = dest_node;
1266 for (i = 1; i < dest_parent_times; ++i) {
1267 dst_node = dst_node->parent;
1268 if (!dst_node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001269 LOGVAL(LYE_LINE, line);
1270 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001271 return -parsed;
1272 }
1273 }
1274 while (1) {
1275 if (dest_pref && (resolve_prefixed_module(mod, dest_pref, dest_pref_len) != mod)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001276 LOGVAL(LYE_INPREF_LEN, line, dest_pref_len, dest_pref);
Michal Vasko1f76a282015-08-04 16:16:53 +02001277 return -parsed;
1278 }
1279 dst_node = resolve_child(dst_node, dest, dest_len, LYS_CONTAINER | LYS_LIST | LYS_LEAF);
1280 if (!dst_node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001281 LOGVAL(LYE_LINE, line);
1282 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001283 return -parsed;
1284 }
1285
1286 if (pke_len == pke_parsed) {
1287 break;
1288 }
1289
1290 if ((i = parse_path_key_expr(path_key_expr+pke_parsed, &dest_pref, &dest_pref_len, &dest, &dest_len,
1291 &dest_parent_times)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001292 LOGVAL(LYE_INCHAR, line, (path_key_expr+pke_parsed)[-i], (path_key_expr+pke_parsed)-i);
Michal Vasko1f76a282015-08-04 16:16:53 +02001293 return -parsed;
1294 }
1295 pke_parsed += i;
1296 }
1297
1298 /* check source - dest match */
Radek Krejcib8048692015-08-05 13:36:34 +02001299 if ((dst_node->nodetype != LYS_LEAF) || ((struct lys_node_leaf *)dst_node)->type.base
1300 != ((struct lys_node_leaf *)src_node)->type.base) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001301 LOGVAL(LYE_LINE, line);
1302 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001303 return -parsed;
1304 }
1305 } while (has_predicate);
1306
1307 return parsed;
1308}
1309
Michal Vaskof02e3742015-08-05 16:27:02 +02001310/* logs indirectly */
Michal Vasko1f76a282015-08-04 16:16:53 +02001311static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001312resolve_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 +02001313{
1314 struct lys_node *child, *node;
1315 const char *id, *prefix, *name;
1316 int pref_len, nam_len, parent_times, has_predicate;
1317 int i, first;
1318
1319 first = 1;
1320 parent_times = 0;
1321 id = path;
1322
1323 do {
1324 if ((i = parse_path_arg(id, &prefix, &pref_len, &name, &nam_len, &parent_times, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001325 LOGVAL(LYE_INCHAR, line, id[-i], id-i);
Michal Vasko1f76a282015-08-04 16:16:53 +02001326 return EXIT_FAILURE;
1327 }
1328 id += i;
1329
1330 if (first) {
1331 if (parent_times == -1) {
1332 node = mod->data;
1333 } else if (parent_times > 0) {
1334 node = parent_node;
1335 for (i = 0; i < parent_times; ++i) {
1336 node = node->parent;
1337 if (!node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001338 LOGVAL(LYE_LINE, line);
1339 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001340 return EXIT_FAILURE;
1341 }
1342 }
1343 node = node->child;
1344 }
1345 first = 0;
1346 } else {
1347 node = node->child;
1348 }
1349
1350 /* node identifier */
1351 LY_TREE_FOR(node, child) {
1352 if (child->nodetype == LYS_GROUPING) {
1353 continue;
1354 }
1355
1356 if (!strncmp(child->name, name, nam_len) && !child->name[nam_len]) {
1357 break;
1358 }
1359 }
1360 if (!child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001361 LOGVAL(LYE_LINE, line);
1362 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001363 return EXIT_FAILURE;
1364 }
1365 node = child;
1366
1367 if (has_predicate) {
1368 /* we have predicate, so the current result must be list */
1369 if (node->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001370 LOGVAL(LYE_LINE, line);
1371 /* general error, the one written later will suffice */
Michal Vasko1f76a282015-08-04 16:16:53 +02001372 return EXIT_FAILURE;
1373 }
1374
1375 if ((i = resolve_path_predicate_schema(id, mod, node, parent_node, line)) < 1) {
1376 return EXIT_FAILURE;
1377 }
1378 id += i;
1379 }
1380 } while (id[0]);
1381
1382 return EXIT_SUCCESS;
1383}
1384
Michal Vaskof02e3742015-08-05 16:27:02 +02001385/* does not log
1386 * ... /node[target = value] ... */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001387static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001388resolve_predicate(const char *pred, struct unres_data **node_match)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001389{
Michal Vaskof02e3742015-08-05 16:27:02 +02001390 struct unres_data *target_match, *node, *node_prev = NULL, *tmp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001391 const char *prefix, *name, *value;
1392 int pref_len, nam_len, val_len, i, has_predicate, cur_idx, idx, parsed;
1393
1394 idx = -1;
1395 parsed = 0;
1396
1397 do {
1398 if ((i = parse_predicate(pred, &prefix, &pref_len, &name, &nam_len, &value, &val_len, &has_predicate)) < 1) {
1399 return -parsed+i;
1400 }
1401 parsed += i;
1402 pred += i;
1403
1404 if (isdigit(name[0])) {
1405 idx = atoi(name);
1406 }
1407
1408 for (cur_idx = 0, node = *node_match; node; ++cur_idx) {
1409 /* target */
1410 target_match = NULL;
1411 if ((name[0] == '.') || !value) {
1412 target_match = calloc(1, sizeof *target_match);
1413 target_match->dnode = node->dnode;
1414 } else if (resolve_data_nodeid(prefix, pref_len, name, nam_len, node->dnode, &target_match)) {
1415 return -parsed;
1416 }
1417
1418 /* check that we have the correct type */
1419 if (name[0] == '.') {
Radek Krejci76512572015-08-04 09:47:08 +02001420 if (node->dnode->schema->nodetype != LYS_LEAFLIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001421 goto remove_instid;
1422 }
1423 } else if (value) {
Radek Krejci76512572015-08-04 09:47:08 +02001424 if (node->dnode->schema->nodetype != LYS_LIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001425 goto remove_instid;
1426 }
1427 }
1428
1429 if ((value && (strncmp(((struct lyd_node_leaf *)target_match->dnode)->value_str, value, val_len)
1430 || ((struct lyd_node_leaf *)target_match->dnode)->value_str[val_len]))
1431 || (!value && (idx != cur_idx))) {
1432 goto remove_instid;
1433 }
1434
1435 while (target_match) {
1436 tmp = target_match->next;
1437 free(target_match);
1438 target_match = tmp;
1439 }
1440
1441 /* leafref is ok, continue check with next leafref */
1442 node_prev = node;
1443 node = node->next;
1444 continue;
1445
1446remove_instid:
1447 while (target_match) {
1448 tmp = target_match->next;
1449 free(target_match);
1450 target_match = tmp;
1451 }
1452
1453 /* does not fulfill conditions, remove leafref record */
1454 if (node_prev) {
1455 node_prev->next = node->next;
1456 free(node);
1457 node = node_prev->next;
1458 } else {
1459 node = (*node_match)->next;
1460 free(*node_match);
1461 *node_match = node;
1462 }
1463 }
1464 } while (has_predicate);
1465
1466 return parsed;
1467}
1468
Michal Vaskof02e3742015-08-05 16:27:02 +02001469/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001470int
Michal Vaskof02e3742015-08-05 16:27:02 +02001471resolve_instid(struct unres_data *unres, const char *path, int path_len, struct unres_data **ret)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001472{
1473 struct lyd_node *data;
Michal Vaskof02e3742015-08-05 16:27:02 +02001474 struct unres_data *riter = NULL, *raux;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001475 const char *apath = strndupa(path, path_len);
1476 const char *prefix, *name;
1477 int i, parsed, pref_len, nam_len, has_predicate;
1478
1479 parsed = 0;
1480
1481 /* we need root, absolute path */
1482 for (data = unres->dnode; data->parent; data = data->parent);
1483 for (; data->prev->next; data = data->prev);
1484
1485 /* searching for nodeset */
1486 do {
1487 if ((i = parse_instance_identifier(apath, &prefix, &pref_len, &name, &nam_len, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001488 LOGVAL(LYE_INCHAR, unres->line, apath[-i], apath-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001489 goto error;
1490 }
1491 parsed += i;
1492 apath += i;
1493
1494 if (resolve_data_nodeid(prefix, pref_len, name, nam_len, data, ret)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001495 LOGVAL(LYE_LINE, unres->line);
1496 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001497 goto error;
1498 }
1499
1500 if (has_predicate) {
1501 /* we have predicate, so the current results must be list or leaf-list */
1502 for (raux = NULL, riter = *ret; riter; ) {
Radek Krejci76512572015-08-04 09:47:08 +02001503 if ((riter->dnode->schema->nodetype == LYS_LIST &&
Radek Krejcib8048692015-08-05 13:36:34 +02001504 ((struct lys_node_list *)riter->dnode->schema)->keys)
Radek Krejci76512572015-08-04 09:47:08 +02001505 || (riter->dnode->schema->nodetype == LYS_LEAFLIST)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001506 /* instid is ok, continue check with next instid */
1507 raux = riter;
1508 riter = riter->next;
1509 continue;
1510 }
1511
1512 /* does not fulfill conditions, remove inst record */
1513 if (raux) {
1514 raux->next = riter->next;
1515 free(riter);
1516 riter = raux->next;
1517 } else {
1518 *ret = riter->next;
1519 free(riter);
1520 riter = *ret;
1521 }
1522 }
1523 if ((i = resolve_predicate(apath, ret)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001524 LOGVAL(LYE_INPRED, unres->line, apath-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001525 goto error;
1526 }
1527 parsed += i;
1528 apath += i;
1529
1530 if (!*ret) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001531 LOGVAL(LYE_LINE, unres->line);
1532 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001533 goto error;
1534 }
1535 }
1536 } while (apath[0] != '\0');
1537
Michal Vaskof02e3742015-08-05 16:27:02 +02001538 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001539
1540error:
1541 while (*ret) {
1542 raux = (*ret)->next;
1543 free(*ret);
1544 *ret = raux;
1545 }
1546
Michal Vaskof02e3742015-08-05 16:27:02 +02001547 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001548}
1549
Michal Vaskof02e3742015-08-05 16:27:02 +02001550/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001551static void
Radek Krejci76512572015-08-04 09:47:08 +02001552inherit_config_flag(struct lys_node *mnode)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001553{
1554 LY_TREE_FOR(mnode, mnode) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001555 mnode->flags |= mnode->parent->flags & LYS_CONFIG_MASK;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001556 inherit_config_flag(mnode->child);
1557 }
1558}
1559
Michal Vaskof02e3742015-08-05 16:27:02 +02001560/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001561static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001562resolve_augment(struct lys_node_augment *aug, struct lys_node *parent, struct lys_module *module)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001563{
Radek Krejci76512572015-08-04 09:47:08 +02001564 struct lys_node *sub, *aux;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001565
1566 assert(module);
1567
1568 /* resolve target node */
Radek Krejci76512572015-08-04 09:47:08 +02001569 aug->target = resolve_schema_nodeid(aug->target_name, parent, module, LYS_AUGMENT);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001570 if (!aug->target) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001571 return EXIT_FAILURE;
1572 }
1573
1574 if (!aug->child) {
1575 /* nothing to do */
1576 return EXIT_SUCCESS;
1577 }
1578
1579 /* inherit config information from parent, augment does not have
1580 * config property, but we need to keep the information for subelements
1581 */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001582 aug->flags |= aug->target->flags & LYS_CONFIG_MASK;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001583 LY_TREE_FOR(aug->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001584 inherit_config_flag(sub);
1585 }
1586
Radek Krejci0acbe1b2015-08-04 09:33:49 +02001587 /* reconnect augmenting data into the target - add them to the target child list */
1588 if (aug->target->child) {
1589 aux = aug->target->child->prev; /* remember current target's last node */
1590 aux->next = aug->child; /* connect augmenting data after target's last node */
1591 aug->target->child->prev = aug->child->prev; /* new target's last node is last augmenting node */
1592 aug->child->prev = aux; /* finish connecting of both child lists */
1593 } else {
1594 aug->target->child = aug->child;
1595 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001596
1597 return EXIT_SUCCESS;
1598}
1599
Michal Vaskof02e3742015-08-05 16:27:02 +02001600/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001601int
Michal Vaskof02e3742015-08-05 16:27:02 +02001602resolve_uses(struct lys_node_uses *uses, struct unres_schema *unres, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001603{
1604 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001605 struct lys_node *mnode = NULL, *mnode_aux;
1606 struct lys_refine *rfn;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001607 struct lys_restr *newmust;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001608 int i, j;
1609 uint8_t size;
1610
1611 /* copy the data nodes from grouping into the uses context */
1612 LY_TREE_FOR(uses->grp->child, mnode) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001613 mnode_aux = ly_mnode_dup(uses->module, mnode, uses->flags, 1, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001614 if (!mnode_aux) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001615 LOGVAL(LYE_SPEC, line, "Copying data from grouping failed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001616 return EXIT_FAILURE;
1617 }
Radek Krejci76512572015-08-04 09:47:08 +02001618 if (ly_mnode_addchild((struct lys_node *)uses, mnode_aux)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001619 /* error logged */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001620 ly_mnode_free(mnode_aux);
1621 return EXIT_FAILURE;
1622 }
1623 }
1624 ctx = uses->module->ctx;
1625
1626 /* apply refines */
1627 for (i = 0; i < uses->refine_size; i++) {
1628 rfn = &uses->refine[i];
Radek Krejci76512572015-08-04 09:47:08 +02001629 mnode = resolve_schema_nodeid(rfn->target_name, (struct lys_node *)uses, uses->module, LYS_USES);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001630 if (!mnode) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001631 LOGVAL(LYE_INARG, line, rfn->target_name, "refine");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001632 return EXIT_FAILURE;
1633 }
1634
1635 if (rfn->target_type && !(mnode->nodetype & rfn->target_type)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001636 LOGVAL(LYE_SPEC, line, "Refine substatements not applicable to the target-node.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001637 return EXIT_FAILURE;
1638 }
1639
1640 /* description on any nodetype */
1641 if (rfn->dsc) {
1642 lydict_remove(ctx, mnode->dsc);
1643 mnode->dsc = lydict_insert(ctx, rfn->dsc, 0);
1644 }
1645
1646 /* reference on any nodetype */
1647 if (rfn->ref) {
1648 lydict_remove(ctx, mnode->ref);
1649 mnode->ref = lydict_insert(ctx, rfn->ref, 0);
1650 }
1651
1652 /* config on any nodetype */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001653 if (rfn->flags & LYS_CONFIG_MASK) {
1654 mnode->flags &= ~LYS_CONFIG_MASK;
1655 mnode->flags |= (rfn->flags & LYS_CONFIG_MASK);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001656 }
1657
1658 /* default value ... */
1659 if (rfn->mod.dflt) {
Radek Krejci76512572015-08-04 09:47:08 +02001660 if (mnode->nodetype == LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001661 /* leaf */
Radek Krejcib8048692015-08-05 13:36:34 +02001662 lydict_remove(ctx, ((struct lys_node_leaf *)mnode)->dflt);
1663 ((struct lys_node_leaf *)mnode)->dflt = lydict_insert(ctx, rfn->mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001664 } else if (mnode->nodetype == LYS_CHOICE) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001665 /* choice */
Radek Krejcib8048692015-08-05 13:36:34 +02001666 ((struct lys_node_choice *)mnode)->dflt = resolve_schema_nodeid(rfn->mod.dflt, mnode, mnode->module, LYS_CHOICE);
1667 if (!((struct lys_node_choice *)mnode)->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001668 LOGVAL(LYE_INARG, line, rfn->mod.dflt, "default");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001669 return EXIT_FAILURE;
1670 }
1671 }
1672 }
1673
1674 /* mandatory on leaf, anyxml or choice */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001675 if (rfn->flags & LYS_MAND_MASK) {
Radek Krejci76512572015-08-04 09:47:08 +02001676 if (mnode->nodetype & (LYS_LEAF | LYS_ANYXML | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001677 /* remove current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001678 mnode->flags &= ~LYS_MAND_MASK;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001679
1680 /* set new value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001681 mnode->flags |= (rfn->flags & LYS_MAND_MASK);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001682 }
1683 }
1684
1685 /* presence on container */
Radek Krejci76512572015-08-04 09:47:08 +02001686 if ((mnode->nodetype & LYS_CONTAINER) && rfn->mod.presence) {
Radek Krejcib8048692015-08-05 13:36:34 +02001687 lydict_remove(ctx, ((struct lys_node_container *)mnode)->presence);
1688 ((struct lys_node_container *)mnode)->presence = lydict_insert(ctx, rfn->mod.presence, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001689 }
1690
1691 /* min/max-elements on list or leaf-list */
1692 /* magic - bit 3 in flags means min set, bit 4 says max set */
Radek Krejci76512572015-08-04 09:47:08 +02001693 if (mnode->nodetype == LYS_LIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001694 if (rfn->flags & 0x04) {
Radek Krejcib8048692015-08-05 13:36:34 +02001695 ((struct lys_node_list *)mnode)->min = rfn->mod.list.min;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001696 }
1697 if (rfn->flags & 0x08) {
Radek Krejcib8048692015-08-05 13:36:34 +02001698 ((struct lys_node_list *)mnode)->max = rfn->mod.list.max;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001699 }
Radek Krejci76512572015-08-04 09:47:08 +02001700 } else if (mnode->nodetype == LYS_LEAFLIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001701 if (rfn->flags & 0x04) {
Radek Krejcib8048692015-08-05 13:36:34 +02001702 ((struct lys_node_leaflist *)mnode)->min = rfn->mod.list.min;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001703 }
1704 if (rfn->flags & 0x08) {
Radek Krejcib8048692015-08-05 13:36:34 +02001705 ((struct lys_node_leaflist *)mnode)->max = rfn->mod.list.max;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001706 }
1707 }
1708
1709 /* must in leaf, leaf-list, list, container or anyxml */
1710 if (rfn->must_size) {
Radek Krejcib8048692015-08-05 13:36:34 +02001711 size = ((struct lys_node_leaf *)mnode)->must_size + rfn->must_size;
1712 newmust = realloc(((struct lys_node_leaf *)mnode)->must, size * sizeof *rfn->must);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001713 if (!newmust) {
1714 LOGMEM;
1715 return EXIT_FAILURE;
1716 }
Radek Krejcib8048692015-08-05 13:36:34 +02001717 for (i = 0, j = ((struct lys_node_leaf *)mnode)->must_size; i < rfn->must_size; i++, j++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001718 newmust[j].expr = lydict_insert(ctx, rfn->must[i].expr, 0);
1719 newmust[j].dsc = lydict_insert(ctx, rfn->must[i].dsc, 0);
1720 newmust[j].ref = lydict_insert(ctx, rfn->must[i].ref, 0);
1721 newmust[j].eapptag = lydict_insert(ctx, rfn->must[i].eapptag, 0);
1722 newmust[j].emsg = lydict_insert(ctx, rfn->must[i].emsg, 0);
1723 }
1724
Radek Krejcib8048692015-08-05 13:36:34 +02001725 ((struct lys_node_leaf *)mnode)->must = newmust;
1726 ((struct lys_node_leaf *)mnode)->must_size = size;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001727 }
1728 }
1729
1730 /* apply augments */
1731 for (i = 0; i < uses->augment_size; i++) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001732 if (resolve_augment(&uses->augment[i], (struct lys_node *)uses, uses->module)) {
1733 LOGVAL(LYE_INRESOLV, line, "augment", uses->augment[i].target_name);
1734 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001735 }
1736 }
1737
1738 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001739}
1740
Michal Vaskof02e3742015-08-05 16:27:02 +02001741/* does not log */
Radek Krejcia52656e2015-08-05 13:41:50 +02001742static struct lys_ident *
1743resolve_base_ident_sub(struct lys_module *module, struct lys_ident *ident, const char *basename)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001744{
Michal Vaskof02e3742015-08-05 16:27:02 +02001745 uint32_t i, j;
Radek Krejcia52656e2015-08-05 13:41:50 +02001746 struct lys_ident *base_iter = NULL;
1747 struct lys_ident_der *der;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001748
1749 /* search module */
1750 for (i = 0; i < module->ident_size; i++) {
1751 if (!strcmp(basename, module->ident[i].name)) {
1752
1753 if (!ident) {
1754 /* just search for type, so do not modify anything, just return
1755 * the base identity pointer
1756 */
1757 return &module->ident[i];
1758 }
1759
1760 /* we are resolving identity definition, so now update structures */
1761 ident->base = base_iter = &module->ident[i];
1762
1763 break;
1764 }
1765 }
1766
1767 /* search submodules */
1768 if (!base_iter) {
1769 for (j = 0; j < module->inc_size; j++) {
1770 for (i = 0; i < module->inc[j].submodule->ident_size; i++) {
1771 if (!strcmp(basename, module->inc[j].submodule->ident[i].name)) {
1772
1773 if (!ident) {
1774 return &module->inc[j].submodule->ident[i];
1775 }
1776
1777 ident->base = base_iter = &module->inc[j].submodule->ident[i];
1778 break;
1779 }
1780 }
1781 }
1782 }
1783
1784 /* we found it somewhere */
1785 if (base_iter) {
1786 while (base_iter) {
1787 for (der = base_iter->der; der && der->next; der = der->next);
1788 if (der) {
1789 der->next = malloc(sizeof *der);
1790 der = der->next;
1791 } else {
1792 ident->base->der = der = malloc(sizeof *der);
1793 }
1794 der->next = NULL;
1795 der->ident = ident;
1796
1797 base_iter = base_iter->base;
1798 }
1799 return ident->base;
1800 }
1801
1802 return NULL;
1803}
1804
Michal Vaskof02e3742015-08-05 16:27:02 +02001805/* logs directly */
Radek Krejcia52656e2015-08-05 13:41:50 +02001806static struct lys_ident *
Michal Vaskof02e3742015-08-05 16:27:02 +02001807resolve_base_ident(struct lys_module *module, struct lys_ident *ident, const char *basename, const char* parent,
1808 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001809{
1810 const char *name;
Michal Vaskof02e3742015-08-05 16:27:02 +02001811 int i, prefix_len = 0;
Radek Krejcia52656e2015-08-05 13:41:50 +02001812 struct lys_ident *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001813
1814 /* search for the base identity */
1815 name = strchr(basename, ':');
1816 if (name) {
1817 /* set name to correct position after colon */
1818 prefix_len = name - basename;
1819 name++;
1820
1821 if (!strncmp(basename, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
1822 /* prefix refers to the current module, ignore it */
1823 prefix_len = 0;
1824 }
1825 } else {
1826 name = basename;
1827 }
1828
1829 if (prefix_len) {
1830 /* get module where to search */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001831 module = resolve_prefixed_module(module, basename, prefix_len);
1832 if (!module) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001833 /* identity refers unknown data model */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001834 LOGVAL(LYE_INPREF, line, basename);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001835 return NULL;
1836 }
1837 } else {
1838 /* search in submodules */
1839 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +02001840 result = resolve_base_ident_sub((struct lys_module *)module->inc[i].submodule, ident, name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001841 if (result) {
1842 return result;
1843 }
1844 }
1845 }
1846
1847 /* search in the identified module */
1848 result = resolve_base_ident_sub(module, ident, name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001849 if (!result) {
1850 LOGVAL(LYE_INARG, line, basename, parent);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001851 }
1852
1853 return result;
1854}
1855
Michal Vaskof02e3742015-08-05 16:27:02 +02001856/* does not log */
Radek Krejcia52656e2015-08-05 13:41:50 +02001857struct lys_ident *
1858resolve_identityref(struct lys_ident *base, const char *name, const char *ns)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001859{
Radek Krejcia52656e2015-08-05 13:41:50 +02001860 struct lys_ident_der *der;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001861
1862 if (!base || !name || !ns) {
1863 return NULL;
1864 }
1865
1866 for(der = base->der; der; der = der->next) {
1867 if (!strcmp(der->ident->name, name) && ns == der->ident->module->ns) {
1868 /* we have match */
1869 return der->ident;
1870 }
1871 }
1872
1873 /* not found */
1874 return NULL;
1875}
1876
Michal Vaskof02e3742015-08-05 16:27:02 +02001877/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001878static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001879resolve_unres_ident(struct lys_module *mod, struct lys_ident *ident, const char *base_name, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001880{
Michal Vaskof02e3742015-08-05 16:27:02 +02001881 if (resolve_base_ident(mod, ident, base_name, "ident", line)) {
1882 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001883 }
1884
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001885 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "identity", base_name);
1886 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001887}
1888
Michal Vaskof02e3742015-08-05 16:27:02 +02001889/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001890static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001891resolve_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 +02001892{
Michal Vaskof02e3742015-08-05 16:27:02 +02001893 type->info.ident.ref = resolve_base_ident(mod, NULL, base_name, "type", line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001894 if (type->info.ident.ref) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001895 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001896 }
1897
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001898 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "identityref", base_name);
1899 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001900}
1901
Michal Vaskof02e3742015-08-05 16:27:02 +02001902/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001903static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001904resolve_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 +02001905{
Michal Vaskof02e3742015-08-05 16:27:02 +02001906 if (!resolve_path_arg_schema(mod, type->info.lref.path, node, line)) {
1907 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001908 }
1909
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001910 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "leafref", type->info.lref.path);
1911 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001912}
1913
Michal Vaskof02e3742015-08-05 16:27:02 +02001914/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001915static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001916resolve_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 +02001917{
Radek Krejci76512572015-08-04 09:47:08 +02001918 type->der = resolve_superior_type(type_name, type->prefix, mod, (struct lys_node *)type->der);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001919 if (type->der) {
Michal Vaskoa91333d2015-08-03 16:03:06 +02001920 type->base = type->der->type.base;
Michal Vaskof02e3742015-08-05 16:27:02 +02001921 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001922 }
1923
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001924 LOGVAL(LYE_INRESOLV, line, "type", type_name);
1925 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001926}
1927
Michal Vaskof02e3742015-08-05 16:27:02 +02001928/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001929static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001930resolve_unres_augment(struct lys_module *mod, struct lys_node_augment *aug, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001931{
Radek Krejci76512572015-08-04 09:47:08 +02001932 if (aug->parent->nodetype == LYS_USES) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001933 if ((aug->target_name[0] != '/')
Radek Krejci76512572015-08-04 09:47:08 +02001934 && resolve_schema_nodeid(aug->target_name, aug->parent->child, mod, LYS_AUGMENT)) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001935 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001936 }
1937 } else {
1938 if ((aug->target_name[0] == '/')
Radek Krejci76512572015-08-04 09:47:08 +02001939 && resolve_schema_nodeid(aug->target_name, mod->data, mod, LYS_AUGMENT)) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001940 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001941 }
1942 }
1943
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001944 LOGVAL(LYE_INRESOLV, line, "augment", aug->target_name);
1945 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001946}
1947
Michal Vaskof02e3742015-08-05 16:27:02 +02001948/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001949static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001950resolve_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 +02001951{
Michal Vaskof02e3742015-08-05 16:27:02 +02001952 *feat_ptr = resolve_feature(feat_name, mod, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001953 if (*feat_ptr) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001954 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001955 }
1956
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001957 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "if-feature", feat_name);
1958 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001959}
1960
Michal Vaskof02e3742015-08-05 16:27:02 +02001961/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001962static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001963resolve_unres_uses(struct lys_node_uses *uses, struct unres_schema *unres, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001964{
Michal Vaskof02e3742015-08-05 16:27:02 +02001965 if (uses->grp || !resolve_grouping(uses->parent, uses, line)) {
1966 if (!resolve_uses(uses, unres, line)) {
1967 return EXIT_SUCCESS;
Michal Vasko12e30842015-08-04 11:54:00 +02001968 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001969 }
1970
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001971 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "uses", uses->name);
1972 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001973}
1974
Michal Vaskof02e3742015-08-05 16:27:02 +02001975/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001976static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001977resolve_unres_type_dflt(struct lys_type *type, const char *dflt, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001978{
Michal Vasko12e30842015-08-04 11:54:00 +02001979 if (!check_default(type, dflt)) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001980 return EXIT_SUCCESS;
Michal Vasko12e30842015-08-04 11:54:00 +02001981 }
1982
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001983 LOGVAL(LYE_INRESOLV, line, "type default", dflt);
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_choice_dflt(struct lys_node_choice *choice, const char *dflt, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001990{
Michal Vasko1f76a282015-08-04 16:16:53 +02001991 choice->dflt = resolve_child((struct lys_node *)choice, dflt, strlen(dflt), LYS_ANYXML | LYS_CASE
Radek Krejci76512572015-08-04 09:47:08 +02001992 | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001993 if (choice->dflt) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001994 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 }
1996
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001997 LOGVAL(LYE_INRESOLV, line, "choice default", dflt);
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_list_keys(struct lys_node_list *list, const char *keys_str, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002004{
2005 int i, len;
2006 const char *value;
2007
2008 for (i = 0; i < list->keys_size; ++i) {
2009 /* get the key name */
2010 if ((value = strpbrk(keys_str, " \t\n"))) {
2011 len = value - keys_str;
2012 while (isspace(value[0])) {
2013 value++;
2014 }
2015 } else {
2016 len = strlen(keys_str);
2017 }
2018
Radek Krejcib8048692015-08-05 13:36:34 +02002019 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 +02002020
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002021 if (check_key(list->keys[i], list->flags, list->keys, i, keys_str, len, line)) {
2022 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "list keys", keys_str);
2023 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002024 }
2025
2026 /* prepare for next iteration */
2027 while (value && isspace(value[0])) {
2028 value++;
2029 }
2030 keys_str = value;
2031 }
2032
Michal Vaskof02e3742015-08-05 16:27:02 +02002033 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002034}
2035
Michal Vaskof02e3742015-08-05 16:27:02 +02002036/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002037static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002038resolve_unres_list_uniq(struct lys_unique *uniq, const char *uniq_str, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002039{
Michal Vaskof02e3742015-08-05 16:27:02 +02002040 if (!resolve_unique((struct lys_node *)uniq->leafs, uniq_str, uniq, line)) {
2041 return EXIT_SUCCESS;
Michal Vasko12e30842015-08-04 11:54:00 +02002042 }
2043
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002044 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "list unique", uniq_str);
2045 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002046}
2047
2048static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002049resolve_unres_when(struct lys_when *UNUSED(when), struct lys_node *UNUSED(start), uint32_t UNUSED(line))
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002050{
2051 /* TODO */
Michal Vaskof02e3742015-08-05 16:27:02 +02002052 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002053}
2054
2055static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002056resolve_unres_must(struct lys_restr *UNUSED(must), struct lys_node *UNUSED(start), uint32_t UNUSED(line))
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002057{
2058 /* TODO */
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 indirectly
2063 * line == -1 means do not log, 0 means unknown */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002064static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002065resolve_unres_item(struct lys_module *mod, void *item, enum UNRES_ITEM type, void *str_mnode, struct unres_schema *unres,
2066 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002067{
2068 int ret = EXIT_FAILURE, has_str = 0;
2069
2070 switch (type) {
2071 case UNRES_RESOLVED:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002072 LOGINT;
Michal Vasko45b42312015-08-05 09:30:11 +02002073 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002074 case UNRES_IDENT:
2075 ret = resolve_unres_ident(mod, item, str_mnode, line);
2076 has_str = 1;
2077 break;
2078 case UNRES_TYPE_IDENTREF:
2079 ret = resolve_unres_type_identref(mod, item, str_mnode, line);
2080 has_str = 1;
2081 break;
2082 case UNRES_TYPE_LEAFREF:
2083 ret = resolve_unres_type_leafref(mod, item, str_mnode, line);
2084 has_str = 0;
2085 break;
2086 case UNRES_TYPE_DER:
2087 ret = resolve_unres_type_der(mod, item, str_mnode, line);
2088 has_str = 1;
2089 break;
2090 case UNRES_AUGMENT:
2091 ret = resolve_unres_augment(mod, item, line);
2092 has_str = 0;
2093 break;
2094 case UNRES_IFFEAT:
2095 ret = resolve_unres_iffeature(mod, item, str_mnode, line);
2096 has_str = 1;
2097 break;
2098 case UNRES_USES:
Michal Vaskof02e3742015-08-05 16:27:02 +02002099 ret = resolve_unres_uses(item, unres, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002100 has_str = 0;
2101 break;
2102 case UNRES_TYPE_DFLT:
2103 ret = resolve_unres_type_dflt(item, str_mnode, line);
2104 /* do not remove str_mnode (dflt), it's in a typedef */
2105 has_str = 0;
2106 break;
2107 case UNRES_CHOICE_DFLT:
Michal Vasko12e30842015-08-04 11:54:00 +02002108 ret = resolve_unres_choice_dflt(item, str_mnode, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002109 has_str = 1;
2110 break;
2111 case UNRES_LIST_KEYS:
2112 ret = resolve_unres_list_keys(item, str_mnode, line);
2113 has_str = 1;
2114 break;
2115 case UNRES_LIST_UNIQ:
2116 ret = resolve_unres_list_uniq(item, str_mnode, line);
2117 has_str = 1;
2118 break;
2119 case UNRES_WHEN:
2120 ret = resolve_unres_when(item, str_mnode, line);
2121 has_str = 0;
2122 break;
2123 case UNRES_MUST:
2124 ret = resolve_unres_must(item, str_mnode, line);
2125 has_str = 0;
2126 break;
2127 }
2128
2129 if (has_str && !ret) {
2130 lydict_remove(mod->ctx, str_mnode);
2131 }
2132
2133 return ret;
2134}
2135
Michal Vaskof02e3742015-08-05 16:27:02 +02002136/* logs directly */
2137static void
2138print_unres_item_fail(void *item, enum UNRES_ITEM type, void *str_mnode, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002139{
Michal Vaskof02e3742015-08-05 16:27:02 +02002140 char line_str[18];
2141
2142 if (line) {
2143 sprintf(line_str, " (line %u)", line);
2144 } else {
2145 line_str[0] = '\0';
2146 }
2147
2148 switch (type) {
2149 case UNRES_RESOLVED:
2150 LOGINT;
2151 break;
2152 case UNRES_IDENT:
2153 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "identity", (char *)str_mnode, line_str);
2154 break;
2155 case UNRES_TYPE_IDENTREF:
2156 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "identityref", (char *)str_mnode, line_str);
2157 break;
2158 case UNRES_TYPE_LEAFREF:
2159 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "leafref", ((struct lys_type *)item)->info.lref.path, line_str);
2160 break;
2161 case UNRES_TYPE_DER:
2162 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "derived type", (char *)str_mnode, line_str);
2163 break;
2164 case UNRES_AUGMENT:
2165 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "augment target", ((struct lys_node_augment *)item)->target_name, line_str);
2166 break;
2167 case UNRES_IFFEAT:
2168 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "if-feature", (char *)str_mnode, line_str);
2169 break;
2170 case UNRES_USES:
2171 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "uses", ((struct lys_node_uses *)item)->name, line_str);
2172 break;
2173 case UNRES_TYPE_DFLT:
2174 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "type default", (char *)str_mnode, line_str);
2175 break;
2176 case UNRES_CHOICE_DFLT:
2177 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "choice default", (char *)str_mnode, line_str);
2178 break;
2179 case UNRES_LIST_KEYS:
2180 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "list keys", (char *)str_mnode, line_str);
2181 break;
2182 case UNRES_LIST_UNIQ:
2183 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "list unique", (char *)str_mnode, line_str);
2184 break;
2185 case UNRES_WHEN:
2186 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "when", ((struct lys_when *)item)->cond, line_str);
2187 break;
2188 case UNRES_MUST:
2189 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "must", ((struct lys_restr *)item)->expr, line_str);
2190 break;
2191 }
2192}
2193
2194/* logs indirectly */
2195int
2196resolve_unres(struct lys_module *mod, struct unres_schema *unres)
2197{
2198 uint32_t i, resolved = 0;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002199
2200 assert(unres);
2201
2202 /* uses */
2203 for (i = 0; i < unres->count; ++i) {
2204 if (unres->type[i] != UNRES_USES) {
2205 continue;
2206 }
Michal Vaskof02e3742015-08-05 16:27:02 +02002207 if (!resolve_unres_item(mod, unres->item[i], unres->type[i], unres->str_mnode[i], unres, unres->line[i])) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002208 unres->type[i] = UNRES_RESOLVED;
2209 ++resolved;
2210 }
2211 }
2212
2213 /* augment */
2214 for (i = 0; i < unres->count; ++i) {
2215 if (unres->type[i] != UNRES_AUGMENT) {
2216 continue;
2217 }
Michal Vaskof02e3742015-08-05 16:27:02 +02002218 if (!resolve_unres_item(mod, unres->item[i], unres->type[i], unres->str_mnode[i], unres, unres->line[i])) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002219 unres->type[i] = UNRES_RESOLVED;
2220 ++resolved;
2221 }
2222 }
2223
2224 /* the rest */
2225 for (i = 0; i < unres->count; ++i) {
2226 if (unres->type[i] == UNRES_RESOLVED) {
2227 continue;
2228 }
Michal Vaskof02e3742015-08-05 16:27:02 +02002229 if (!resolve_unres_item(mod, unres->item[i], unres->type[i], unres->str_mnode[i], unres, unres->line[i])) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002230 unres->type[i] = UNRES_RESOLVED;
2231 ++resolved;
2232 }
2233 }
2234
2235 if (resolved < unres->count) {
2236 return EXIT_FAILURE;
2237 }
2238
2239 return EXIT_SUCCESS;
2240}
2241
Michal Vaskof02e3742015-08-05 16:27:02 +02002242/* logs indirectly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002243void
Michal Vaskof02e3742015-08-05 16:27:02 +02002244add_unres_str(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type, const char *str,
2245 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002246{
2247 str = lydict_insert(mod->ctx, str, 0);
Radek Krejci76512572015-08-04 09:47:08 +02002248 add_unres_mnode(mod, unres, item, type, (struct lys_node *)str, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002249}
2250
Michal Vaskof02e3742015-08-05 16:27:02 +02002251/* logs indirectly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002252void
Michal Vaskof02e3742015-08-05 16:27:02 +02002253add_unres_mnode(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type,
2254 struct lys_node *mnode, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002255{
2256 assert(unres && item);
2257
Michal Vaskof02e3742015-08-05 16:27:02 +02002258 if (!resolve_unres_item(mod, item, type, mnode, unres, UINT_MAX)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002259 return;
2260 }
2261
Michal Vaskof02e3742015-08-05 16:27:02 +02002262 print_unres_item_fail(item, type, mnode, line);
2263
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002264 unres->count++;
2265 unres->item = realloc(unres->item, unres->count*sizeof *unres->item);
2266 unres->item[unres->count-1] = item;
2267 unres->type = realloc(unres->type, unres->count*sizeof *unres->type);
2268 unres->type[unres->count-1] = type;
2269 unres->str_mnode = realloc(unres->str_mnode, unres->count*sizeof *unres->str_mnode);
2270 unres->str_mnode[unres->count-1] = mnode;
2271 unres->line = realloc(unres->line, unres->count*sizeof *unres->line);
2272 unres->line[unres->count-1] = line;
2273}
2274
Michal Vaskof02e3742015-08-05 16:27:02 +02002275/* logs indirectly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002276void
Michal Vaskof02e3742015-08-05 16:27:02 +02002277dup_unres(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type, void *new_item)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002278{
2279 int i;
2280
2281 if (!item || !new_item) {
2282 return;
2283 }
2284
2285 i = find_unres(unres, item, type);
2286
2287 if (i == -1) {
2288 return;
2289 }
2290
2291 if ((type == UNRES_TYPE_LEAFREF) || (type == UNRES_AUGMENT) || (type == UNRES_USES) || (type == UNRES_TYPE_DFLT)
2292 || (type == UNRES_WHEN) || (type == UNRES_MUST)) {
2293 add_unres_mnode(mod, unres, new_item, type, unres->str_mnode[i], 0);
2294 } else {
2295 add_unres_str(mod, unres, new_item, type, unres->str_mnode[i], 0);
2296 }
2297}
2298
Michal Vaskof02e3742015-08-05 16:27:02 +02002299/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002300int
Michal Vaskof02e3742015-08-05 16:27:02 +02002301find_unres(struct unres_schema *unres, void *item, enum UNRES_ITEM type)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002302{
2303 uint32_t ret = -1, i;
2304
2305 for (i = 0; i < unres->count; ++i) {
2306 if ((unres->item[i] == item) && (unres->type[i] == type)) {
2307 ret = i;
2308 break;
2309 }
2310 }
2311
2312 return ret;
2313}