blob: aa135a21a909aef5750a3f26bc3cfd4472036561 [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 */
Michal Vasko1f76a282015-08-04 16:16:53 +02001334static int
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);
Michal Vasko1f76a282015-08-04 16:16:53 +02001349 return EXIT_FAILURE;
1350 }
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 */
Michal Vasko1f76a282015-08-04 16:16:53 +02001364 return EXIT_FAILURE;
1365 }
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 */
Michal Vasko1f76a282015-08-04 16:16:53 +02001387 return EXIT_FAILURE;
1388 }
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 */
Michal Vasko1f76a282015-08-04 16:16:53 +02001396 return EXIT_FAILURE;
1397 }
1398
1399 if ((i = resolve_path_predicate_schema(id, mod, node, parent_node, line)) < 1) {
1400 return EXIT_FAILURE;
1401 }
1402 id += i;
1403 }
1404 } while (id[0]);
1405
1406 return EXIT_SUCCESS;
1407}
1408
Michal Vaskof02e3742015-08-05 16:27:02 +02001409/* does not log
1410 * ... /node[target = value] ... */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001411static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001412resolve_predicate(const char *pred, struct unres_data **node_match)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001413{
Michal Vaskof02e3742015-08-05 16:27:02 +02001414 struct unres_data *target_match, *node, *node_prev = NULL, *tmp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001415 const char *prefix, *name, *value;
1416 int pref_len, nam_len, val_len, i, has_predicate, cur_idx, idx, parsed;
1417
1418 idx = -1;
1419 parsed = 0;
1420
1421 do {
1422 if ((i = parse_predicate(pred, &prefix, &pref_len, &name, &nam_len, &value, &val_len, &has_predicate)) < 1) {
1423 return -parsed+i;
1424 }
1425 parsed += i;
1426 pred += i;
1427
1428 if (isdigit(name[0])) {
1429 idx = atoi(name);
1430 }
1431
1432 for (cur_idx = 0, node = *node_match; node; ++cur_idx) {
1433 /* target */
1434 target_match = NULL;
1435 if ((name[0] == '.') || !value) {
1436 target_match = calloc(1, sizeof *target_match);
1437 target_match->dnode = node->dnode;
1438 } else if (resolve_data_nodeid(prefix, pref_len, name, nam_len, node->dnode, &target_match)) {
1439 return -parsed;
1440 }
1441
1442 /* check that we have the correct type */
1443 if (name[0] == '.') {
Radek Krejci76512572015-08-04 09:47:08 +02001444 if (node->dnode->schema->nodetype != LYS_LEAFLIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001445 goto remove_instid;
1446 }
1447 } else if (value) {
Radek Krejci76512572015-08-04 09:47:08 +02001448 if (node->dnode->schema->nodetype != LYS_LIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001449 goto remove_instid;
1450 }
1451 }
1452
1453 if ((value && (strncmp(((struct lyd_node_leaf *)target_match->dnode)->value_str, value, val_len)
1454 || ((struct lyd_node_leaf *)target_match->dnode)->value_str[val_len]))
1455 || (!value && (idx != cur_idx))) {
1456 goto remove_instid;
1457 }
1458
1459 while (target_match) {
1460 tmp = target_match->next;
1461 free(target_match);
1462 target_match = tmp;
1463 }
1464
1465 /* leafref is ok, continue check with next leafref */
1466 node_prev = node;
1467 node = node->next;
1468 continue;
1469
1470remove_instid:
1471 while (target_match) {
1472 tmp = target_match->next;
1473 free(target_match);
1474 target_match = tmp;
1475 }
1476
1477 /* does not fulfill conditions, remove leafref record */
1478 if (node_prev) {
1479 node_prev->next = node->next;
1480 free(node);
1481 node = node_prev->next;
1482 } else {
1483 node = (*node_match)->next;
1484 free(*node_match);
1485 *node_match = node;
1486 }
1487 }
1488 } while (has_predicate);
1489
1490 return parsed;
1491}
1492
Michal Vaskof02e3742015-08-05 16:27:02 +02001493/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001494int
Michal Vaskof02e3742015-08-05 16:27:02 +02001495resolve_instid(struct unres_data *unres, const char *path, int path_len, struct unres_data **ret)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001496{
1497 struct lyd_node *data;
Michal Vaskof02e3742015-08-05 16:27:02 +02001498 struct unres_data *riter = NULL, *raux;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001499 const char *apath = strndupa(path, path_len);
1500 const char *prefix, *name;
1501 int i, parsed, pref_len, nam_len, has_predicate;
1502
1503 parsed = 0;
1504
1505 /* we need root, absolute path */
1506 for (data = unres->dnode; data->parent; data = data->parent);
1507 for (; data->prev->next; data = data->prev);
1508
1509 /* searching for nodeset */
1510 do {
1511 if ((i = parse_instance_identifier(apath, &prefix, &pref_len, &name, &nam_len, &has_predicate)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001512 LOGVAL(LYE_INCHAR, unres->line, apath[-i], apath-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001513 goto error;
1514 }
1515 parsed += i;
1516 apath += i;
1517
1518 if (resolve_data_nodeid(prefix, pref_len, name, nam_len, data, ret)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001519 LOGVAL(LYE_LINE, unres->line);
1520 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001521 goto error;
1522 }
1523
1524 if (has_predicate) {
1525 /* we have predicate, so the current results must be list or leaf-list */
1526 for (raux = NULL, riter = *ret; riter; ) {
Radek Krejci76512572015-08-04 09:47:08 +02001527 if ((riter->dnode->schema->nodetype == LYS_LIST &&
Radek Krejcib8048692015-08-05 13:36:34 +02001528 ((struct lys_node_list *)riter->dnode->schema)->keys)
Radek Krejci76512572015-08-04 09:47:08 +02001529 || (riter->dnode->schema->nodetype == LYS_LEAFLIST)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001530 /* instid is ok, continue check with next instid */
1531 raux = riter;
1532 riter = riter->next;
1533 continue;
1534 }
1535
1536 /* does not fulfill conditions, remove inst record */
1537 if (raux) {
1538 raux->next = riter->next;
1539 free(riter);
1540 riter = raux->next;
1541 } else {
1542 *ret = riter->next;
1543 free(riter);
1544 riter = *ret;
1545 }
1546 }
1547 if ((i = resolve_predicate(apath, ret)) < 1) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001548 LOGVAL(LYE_INPRED, unres->line, apath-i);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001549 goto error;
1550 }
1551 parsed += i;
1552 apath += i;
1553
1554 if (!*ret) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001555 LOGVAL(LYE_LINE, unres->line);
1556 /* general error, the one written later will suffice */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001557 goto error;
1558 }
1559 }
1560 } while (apath[0] != '\0');
1561
Michal Vaskof02e3742015-08-05 16:27:02 +02001562 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001563
1564error:
1565 while (*ret) {
1566 raux = (*ret)->next;
1567 free(*ret);
1568 *ret = raux;
1569 }
1570
Michal Vaskof02e3742015-08-05 16:27:02 +02001571 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001572}
1573
Michal Vaskof02e3742015-08-05 16:27:02 +02001574/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001575static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001576inherit_config_flag(struct lys_node *node)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001577{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001578 LY_TREE_FOR(node, node) {
1579 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
1580 inherit_config_flag(node->child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001581 }
1582}
1583
Michal Vaskof02e3742015-08-05 16:27:02 +02001584/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001585static int
Michal Vasko2e1a7e42015-08-06 15:08:32 +02001586resolve_augment(struct lys_node_augment *aug, struct lys_node *siblings, struct lys_module *module)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001587{
Radek Krejci76512572015-08-04 09:47:08 +02001588 struct lys_node *sub, *aux;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001589
1590 assert(module);
1591
1592 /* resolve target node */
Michal Vasko2e1a7e42015-08-06 15:08:32 +02001593 aug->target = resolve_schema_nodeid(aug->target_name, siblings, module, LYS_AUGMENT);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001594 if (!aug->target) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001595 return EXIT_FAILURE;
1596 }
1597
1598 if (!aug->child) {
1599 /* nothing to do */
1600 return EXIT_SUCCESS;
1601 }
1602
1603 /* inherit config information from parent, augment does not have
1604 * config property, but we need to keep the information for subelements
1605 */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001606 aug->flags |= aug->target->flags & LYS_CONFIG_MASK;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001607 LY_TREE_FOR(aug->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001608 inherit_config_flag(sub);
1609 }
1610
Radek Krejci0acbe1b2015-08-04 09:33:49 +02001611 /* reconnect augmenting data into the target - add them to the target child list */
1612 if (aug->target->child) {
1613 aux = aug->target->child->prev; /* remember current target's last node */
1614 aux->next = aug->child; /* connect augmenting data after target's last node */
1615 aug->target->child->prev = aug->child->prev; /* new target's last node is last augmenting node */
1616 aug->child->prev = aux; /* finish connecting of both child lists */
1617 } else {
1618 aug->target->child = aug->child;
1619 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001620
1621 return EXIT_SUCCESS;
1622}
1623
Michal Vaskof02e3742015-08-05 16:27:02 +02001624/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001625int
Michal Vaskof02e3742015-08-05 16:27:02 +02001626resolve_uses(struct lys_node_uses *uses, struct unres_schema *unres, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001627{
1628 struct ly_ctx *ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001629 struct lys_node *node = NULL, *node_aux;
Radek Krejci76512572015-08-04 09:47:08 +02001630 struct lys_refine *rfn;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001631 struct lys_restr *newmust;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001632 int i, j;
1633 uint8_t size;
1634
1635 /* copy the data nodes from grouping into the uses context */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001636 LY_TREE_FOR(uses->grp->child, node) {
1637 node_aux = lys_node_dup(uses->module, node, uses->flags, 1, unres);
1638 if (!node_aux) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001639 LOGVAL(LYE_SPEC, line, "Copying data from grouping failed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001640 return EXIT_FAILURE;
1641 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001642 if (lys_node_addchild((struct lys_node *)uses, node_aux)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001643 /* error logged */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001644 lys_node_free(node_aux);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001645 return EXIT_FAILURE;
1646 }
1647 }
1648 ctx = uses->module->ctx;
1649
1650 /* apply refines */
1651 for (i = 0; i < uses->refine_size; i++) {
1652 rfn = &uses->refine[i];
Radek Krejci1d82ef62015-08-07 14:44:40 +02001653 node = resolve_schema_nodeid(rfn->target_name, uses->child, uses->module, LYS_LEAF);
1654 if (!node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001655 LOGVAL(LYE_INARG, line, rfn->target_name, "refine");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001656 return EXIT_FAILURE;
1657 }
1658
Radek Krejci1d82ef62015-08-07 14:44:40 +02001659 if (rfn->target_type && !(node->nodetype & rfn->target_type)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001660 LOGVAL(LYE_SPEC, line, "Refine substatements not applicable to the target-node.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001661 return EXIT_FAILURE;
1662 }
1663
1664 /* description on any nodetype */
1665 if (rfn->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001666 lydict_remove(ctx, node->dsc);
1667 node->dsc = lydict_insert(ctx, rfn->dsc, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001668 }
1669
1670 /* reference on any nodetype */
1671 if (rfn->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001672 lydict_remove(ctx, node->ref);
1673 node->ref = lydict_insert(ctx, rfn->ref, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001674 }
1675
1676 /* config on any nodetype */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001677 if (rfn->flags & LYS_CONFIG_MASK) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001678 node->flags &= ~LYS_CONFIG_MASK;
1679 node->flags |= (rfn->flags & LYS_CONFIG_MASK);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001680 }
1681
1682 /* default value ... */
1683 if (rfn->mod.dflt) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001684 if (node->nodetype == LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001685 /* leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001686 lydict_remove(ctx, ((struct lys_node_leaf *)node)->dflt);
1687 ((struct lys_node_leaf *)node)->dflt = lydict_insert(ctx, rfn->mod.dflt, 0);
1688 } else if (node->nodetype == LYS_CHOICE) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001689 /* choice */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001690 ((struct lys_node_choice *)node)->dflt = resolve_schema_nodeid(rfn->mod.dflt, node->child, node->module, LYS_CHOICE);
1691 if (!((struct lys_node_choice *)node)->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001692 LOGVAL(LYE_INARG, line, rfn->mod.dflt, "default");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001693 return EXIT_FAILURE;
1694 }
1695 }
1696 }
1697
1698 /* mandatory on leaf, anyxml or choice */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001699 if (rfn->flags & LYS_MAND_MASK) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001700 if (node->nodetype & (LYS_LEAF | LYS_ANYXML | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001701 /* remove current value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001702 node->flags &= ~LYS_MAND_MASK;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001703
1704 /* set new value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001705 node->flags |= (rfn->flags & LYS_MAND_MASK);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001706 }
1707 }
1708
1709 /* presence on container */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001710 if ((node->nodetype & LYS_CONTAINER) && rfn->mod.presence) {
1711 lydict_remove(ctx, ((struct lys_node_container *)node)->presence);
1712 ((struct lys_node_container *)node)->presence = lydict_insert(ctx, rfn->mod.presence, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001713 }
1714
1715 /* min/max-elements on list or leaf-list */
1716 /* magic - bit 3 in flags means min set, bit 4 says max set */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001717 if (node->nodetype == LYS_LIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001718 if (rfn->flags & 0x04) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001719 ((struct lys_node_list *)node)->min = rfn->mod.list.min;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001720 }
1721 if (rfn->flags & 0x08) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001722 ((struct lys_node_list *)node)->max = rfn->mod.list.max;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001723 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001724 } else if (node->nodetype == LYS_LEAFLIST) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001725 if (rfn->flags & 0x04) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 ((struct lys_node_leaflist *)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_leaflist *)node)->max = rfn->mod.list.max;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001730 }
1731 }
1732
1733 /* must in leaf, leaf-list, list, container or anyxml */
1734 if (rfn->must_size) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001735 size = ((struct lys_node_leaf *)node)->must_size + rfn->must_size;
1736 newmust = realloc(((struct lys_node_leaf *)node)->must, size * sizeof *rfn->must);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001737 if (!newmust) {
1738 LOGMEM;
1739 return EXIT_FAILURE;
1740 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001741 for (i = 0, j = ((struct lys_node_leaf *)node)->must_size; i < rfn->must_size; i++, j++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001742 newmust[j].expr = lydict_insert(ctx, rfn->must[i].expr, 0);
1743 newmust[j].dsc = lydict_insert(ctx, rfn->must[i].dsc, 0);
1744 newmust[j].ref = lydict_insert(ctx, rfn->must[i].ref, 0);
1745 newmust[j].eapptag = lydict_insert(ctx, rfn->must[i].eapptag, 0);
1746 newmust[j].emsg = lydict_insert(ctx, rfn->must[i].emsg, 0);
1747 }
1748
Radek Krejci1d82ef62015-08-07 14:44:40 +02001749 ((struct lys_node_leaf *)node)->must = newmust;
1750 ((struct lys_node_leaf *)node)->must_size = size;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001751 }
1752 }
1753
1754 /* apply augments */
1755 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko2e1a7e42015-08-06 15:08:32 +02001756 if (resolve_augment(&uses->augment[i], uses->child, uses->module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001757 LOGVAL(LYE_INRESOLV, line, "augment", uses->augment[i].target_name);
1758 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001759 }
1760 }
1761
1762 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001763}
1764
Michal Vaskof02e3742015-08-05 16:27:02 +02001765/* does not log */
Radek Krejcia52656e2015-08-05 13:41:50 +02001766static struct lys_ident *
1767resolve_base_ident_sub(struct lys_module *module, struct lys_ident *ident, const char *basename)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001768{
Michal Vaskof02e3742015-08-05 16:27:02 +02001769 uint32_t i, j;
Radek Krejcia52656e2015-08-05 13:41:50 +02001770 struct lys_ident *base_iter = NULL;
1771 struct lys_ident_der *der;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001772
1773 /* search module */
1774 for (i = 0; i < module->ident_size; i++) {
1775 if (!strcmp(basename, module->ident[i].name)) {
1776
1777 if (!ident) {
1778 /* just search for type, so do not modify anything, just return
1779 * the base identity pointer
1780 */
1781 return &module->ident[i];
1782 }
1783
1784 /* we are resolving identity definition, so now update structures */
1785 ident->base = base_iter = &module->ident[i];
1786
1787 break;
1788 }
1789 }
1790
1791 /* search submodules */
1792 if (!base_iter) {
1793 for (j = 0; j < module->inc_size; j++) {
1794 for (i = 0; i < module->inc[j].submodule->ident_size; i++) {
1795 if (!strcmp(basename, module->inc[j].submodule->ident[i].name)) {
1796
1797 if (!ident) {
1798 return &module->inc[j].submodule->ident[i];
1799 }
1800
1801 ident->base = base_iter = &module->inc[j].submodule->ident[i];
1802 break;
1803 }
1804 }
1805 }
1806 }
1807
1808 /* we found it somewhere */
1809 if (base_iter) {
1810 while (base_iter) {
1811 for (der = base_iter->der; der && der->next; der = der->next);
1812 if (der) {
1813 der->next = malloc(sizeof *der);
1814 der = der->next;
1815 } else {
1816 ident->base->der = der = malloc(sizeof *der);
1817 }
1818 der->next = NULL;
1819 der->ident = ident;
1820
1821 base_iter = base_iter->base;
1822 }
1823 return ident->base;
1824 }
1825
1826 return NULL;
1827}
1828
Michal Vaskof02e3742015-08-05 16:27:02 +02001829/* logs directly */
Radek Krejcia52656e2015-08-05 13:41:50 +02001830static struct lys_ident *
Michal Vaskof02e3742015-08-05 16:27:02 +02001831resolve_base_ident(struct lys_module *module, struct lys_ident *ident, const char *basename, const char* parent,
1832 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001833{
1834 const char *name;
Michal Vaskof02e3742015-08-05 16:27:02 +02001835 int i, prefix_len = 0;
Radek Krejcia52656e2015-08-05 13:41:50 +02001836 struct lys_ident *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001837
1838 /* search for the base identity */
1839 name = strchr(basename, ':');
1840 if (name) {
1841 /* set name to correct position after colon */
1842 prefix_len = name - basename;
1843 name++;
1844
1845 if (!strncmp(basename, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
1846 /* prefix refers to the current module, ignore it */
1847 prefix_len = 0;
1848 }
1849 } else {
1850 name = basename;
1851 }
1852
1853 if (prefix_len) {
1854 /* get module where to search */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001855 module = resolve_prefixed_module(module, basename, prefix_len);
1856 if (!module) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001857 /* identity refers unknown data model */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001858 LOGVAL(LYE_INPREF, line, basename);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001859 return NULL;
1860 }
1861 } else {
1862 /* search in submodules */
1863 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +02001864 result = resolve_base_ident_sub((struct lys_module *)module->inc[i].submodule, ident, name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001865 if (result) {
1866 return result;
1867 }
1868 }
1869 }
1870
1871 /* search in the identified module */
1872 result = resolve_base_ident_sub(module, ident, name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001873 if (!result) {
1874 LOGVAL(LYE_INARG, line, basename, parent);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001875 }
1876
1877 return result;
1878}
1879
Michal Vaskof02e3742015-08-05 16:27:02 +02001880/* does not log */
Radek Krejcia52656e2015-08-05 13:41:50 +02001881struct lys_ident *
1882resolve_identityref(struct lys_ident *base, const char *name, const char *ns)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001883{
Radek Krejcia52656e2015-08-05 13:41:50 +02001884 struct lys_ident_der *der;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001885
1886 if (!base || !name || !ns) {
1887 return NULL;
1888 }
1889
1890 for(der = base->der; der; der = der->next) {
1891 if (!strcmp(der->ident->name, name) && ns == der->ident->module->ns) {
1892 /* we have match */
1893 return der->ident;
1894 }
1895 }
1896
1897 /* not found */
1898 return NULL;
1899}
1900
Michal Vaskof02e3742015-08-05 16:27:02 +02001901/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001902static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001903resolve_unres_ident(struct lys_module *mod, struct lys_ident *ident, const char *base_name, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001904{
Michal Vaskof02e3742015-08-05 16:27:02 +02001905 if (resolve_base_ident(mod, ident, base_name, "ident", line)) {
1906 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001907 }
1908
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001909 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "identity", base_name);
1910 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001911}
1912
Michal Vaskof02e3742015-08-05 16:27:02 +02001913/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001914static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001915resolve_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 +02001916{
Michal Vaskof02e3742015-08-05 16:27:02 +02001917 type->info.ident.ref = resolve_base_ident(mod, NULL, base_name, "type", line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001918 if (type->info.ident.ref) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001919 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001920 }
1921
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001922 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "identityref", base_name);
1923 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001924}
1925
Michal Vaskof02e3742015-08-05 16:27:02 +02001926/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001927static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001928resolve_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 +02001929{
Michal Vaskof02e3742015-08-05 16:27:02 +02001930 if (!resolve_path_arg_schema(mod, type->info.lref.path, node, line)) {
1931 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001932 }
1933
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001934 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "leafref", type->info.lref.path);
1935 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001936}
1937
Michal Vaskof02e3742015-08-05 16:27:02 +02001938/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001939static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001940resolve_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 +02001941{
Radek Krejci76512572015-08-04 09:47:08 +02001942 type->der = resolve_superior_type(type_name, type->prefix, mod, (struct lys_node *)type->der);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001943 if (type->der) {
Michal Vaskoa91333d2015-08-03 16:03:06 +02001944 type->base = type->der->type.base;
Michal Vaskof02e3742015-08-05 16:27:02 +02001945 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001946 }
1947
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001948 LOGVAL(LYE_INRESOLV, line, "type", type_name);
1949 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001950}
1951
Michal Vaskof02e3742015-08-05 16:27:02 +02001952/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001953static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001954resolve_unres_augment(struct lys_module *mod, struct lys_node_augment *aug, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001955{
Michal Vasko0d42e9f2015-08-06 10:07:28 +02001956 assert(!aug->parent || (aug->parent->nodetype != LYS_USES));
Michal Vasko49291b32015-08-06 09:49:41 +02001957
1958 if (!resolve_augment(aug, aug->parent, mod)) {
1959 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001960 }
1961
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001962 LOGVAL(LYE_INRESOLV, line, "augment", aug->target_name);
1963 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001964}
1965
Michal Vaskof02e3742015-08-05 16:27:02 +02001966/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001967static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001968resolve_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 +02001969{
Michal Vaskof02e3742015-08-05 16:27:02 +02001970 *feat_ptr = resolve_feature(feat_name, mod, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001971 if (*feat_ptr) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001972 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001973 }
1974
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001975 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "if-feature", feat_name);
1976 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001977}
1978
Michal Vaskof02e3742015-08-05 16:27:02 +02001979/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001980static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001981resolve_unres_uses(struct lys_node_uses *uses, struct unres_schema *unres, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001982{
Michal Vaskof02e3742015-08-05 16:27:02 +02001983 if (uses->grp || !resolve_grouping(uses->parent, uses, line)) {
1984 if (!resolve_uses(uses, unres, line)) {
1985 return EXIT_SUCCESS;
Michal Vasko12e30842015-08-04 11:54:00 +02001986 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001987 }
1988
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001989 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "uses", uses->name);
1990 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001991}
1992
Michal Vaskof02e3742015-08-05 16:27:02 +02001993/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001994static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001995resolve_unres_type_dflt(struct lys_type *type, const char *dflt, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001996{
Michal Vasko12e30842015-08-04 11:54:00 +02001997 if (!check_default(type, dflt)) {
Michal Vaskof02e3742015-08-05 16:27:02 +02001998 return EXIT_SUCCESS;
Michal Vasko12e30842015-08-04 11:54:00 +02001999 }
2000
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002001 LOGVAL(LYE_INRESOLV, line, "type default", dflt);
2002 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002003}
2004
Michal Vaskof02e3742015-08-05 16:27:02 +02002005/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002007resolve_unres_choice_dflt(struct lys_node_choice *choice, const char *dflt, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002008{
Michal Vasko1f76a282015-08-04 16:16:53 +02002009 choice->dflt = resolve_child((struct lys_node *)choice, dflt, strlen(dflt), LYS_ANYXML | LYS_CASE
Radek Krejci76512572015-08-04 09:47:08 +02002010 | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011 if (choice->dflt) {
Michal Vaskof02e3742015-08-05 16:27:02 +02002012 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002013 }
2014
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002015 LOGVAL(LYE_INRESOLV, line, "choice default", dflt);
2016 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002017}
2018
Michal Vaskof02e3742015-08-05 16:27:02 +02002019/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002020static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002021resolve_unres_list_keys(struct lys_node_list *list, const char *keys_str, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002022{
2023 int i, len;
2024 const char *value;
2025
2026 for (i = 0; i < list->keys_size; ++i) {
2027 /* get the key name */
2028 if ((value = strpbrk(keys_str, " \t\n"))) {
2029 len = value - keys_str;
2030 while (isspace(value[0])) {
2031 value++;
2032 }
2033 } else {
2034 len = strlen(keys_str);
2035 }
2036
Radek Krejcib8048692015-08-05 13:36:34 +02002037 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 +02002038
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002039 if (check_key(list->keys[i], list->flags, list->keys, i, keys_str, len, line)) {
2040 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "list keys", keys_str);
2041 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002042 }
2043
2044 /* prepare for next iteration */
2045 while (value && isspace(value[0])) {
2046 value++;
2047 }
2048 keys_str = value;
2049 }
2050
Michal Vaskof02e3742015-08-05 16:27:02 +02002051 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002052}
2053
Michal Vaskof02e3742015-08-05 16:27:02 +02002054/* logs directly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002055static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002056resolve_unres_list_uniq(struct lys_unique *uniq, const char *uniq_str, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002057{
Michal Vaskof02e3742015-08-05 16:27:02 +02002058 if (!resolve_unique((struct lys_node *)uniq->leafs, uniq_str, uniq, line)) {
2059 return EXIT_SUCCESS;
Michal Vasko12e30842015-08-04 11:54:00 +02002060 }
2061
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002062 LOGVAL(LYE_INRESOLV, (line == UINT_MAX ? line : 0), "list unique", uniq_str);
2063 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002064}
2065
2066static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002067resolve_unres_when(struct lys_when *UNUSED(when), struct lys_node *UNUSED(start), uint32_t UNUSED(line))
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002068{
2069 /* TODO */
Michal Vaskof02e3742015-08-05 16:27:02 +02002070 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002071}
2072
2073static int
Michal Vaskof02e3742015-08-05 16:27:02 +02002074resolve_unres_must(struct lys_restr *UNUSED(must), struct lys_node *UNUSED(start), uint32_t UNUSED(line))
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002075{
2076 /* TODO */
Michal Vaskof02e3742015-08-05 16:27:02 +02002077 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002078}
2079
Michal Vaskof02e3742015-08-05 16:27:02 +02002080/* logs indirectly
2081 * line == -1 means do not log, 0 means unknown */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002082static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002083resolve_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 +02002084 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002085{
2086 int ret = EXIT_FAILURE, has_str = 0;
2087
2088 switch (type) {
2089 case UNRES_RESOLVED:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002090 LOGINT;
Michal Vasko45b42312015-08-05 09:30:11 +02002091 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002092 case UNRES_IDENT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002093 ret = resolve_unres_ident(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002094 has_str = 1;
2095 break;
2096 case UNRES_TYPE_IDENTREF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002097 ret = resolve_unres_type_identref(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002098 has_str = 1;
2099 break;
2100 case UNRES_TYPE_LEAFREF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002101 ret = resolve_unres_type_leafref(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002102 has_str = 0;
2103 break;
2104 case UNRES_TYPE_DER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002105 ret = resolve_unres_type_der(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002106 has_str = 1;
2107 break;
2108 case UNRES_AUGMENT:
2109 ret = resolve_unres_augment(mod, item, line);
2110 has_str = 0;
2111 break;
2112 case UNRES_IFFEAT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002113 ret = resolve_unres_iffeature(mod, item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002114 has_str = 1;
2115 break;
2116 case UNRES_USES:
Michal Vaskof02e3742015-08-05 16:27:02 +02002117 ret = resolve_unres_uses(item, unres, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002118 has_str = 0;
2119 break;
2120 case UNRES_TYPE_DFLT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002121 ret = resolve_unres_type_dflt(item, str_node, line);
2122 /* do not remove str_node (dflt), it's in a typedef */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002123 has_str = 0;
2124 break;
2125 case UNRES_CHOICE_DFLT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002126 ret = resolve_unres_choice_dflt(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002127 has_str = 1;
2128 break;
2129 case UNRES_LIST_KEYS:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002130 ret = resolve_unres_list_keys(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002131 has_str = 1;
2132 break;
2133 case UNRES_LIST_UNIQ:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002134 ret = resolve_unres_list_uniq(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002135 has_str = 1;
2136 break;
2137 case UNRES_WHEN:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002138 ret = resolve_unres_when(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002139 has_str = 0;
2140 break;
2141 case UNRES_MUST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002142 ret = resolve_unres_must(item, str_node, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002143 has_str = 0;
2144 break;
2145 }
2146
2147 if (has_str && !ret) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002148 lydict_remove(mod->ctx, str_node);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002149 }
2150
2151 return ret;
2152}
2153
Michal Vaskof02e3742015-08-05 16:27:02 +02002154/* logs directly */
2155static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02002156print_unres_item_fail(void *item, enum UNRES_ITEM type, void *str_node, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002157{
Michal Vaskof02e3742015-08-05 16:27:02 +02002158 char line_str[18];
2159
2160 if (line) {
2161 sprintf(line_str, " (line %u)", line);
2162 } else {
2163 line_str[0] = '\0';
2164 }
2165
2166 switch (type) {
2167 case UNRES_RESOLVED:
2168 LOGINT;
2169 break;
2170 case UNRES_IDENT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002171 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "identity", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002172 break;
2173 case UNRES_TYPE_IDENTREF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002174 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "identityref", (char *)str_node, line_str);
Michal Vaskof02e3742015-08-05 16:27:02 +02002175 break;
2176 case UNRES_TYPE_LEAFREF:
2177 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "leafref", ((struct lys_type *)item)->info.lref.path, line_str);
2178 break;
2179 case UNRES_TYPE_DER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002180 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 +02002181 break;
2182 case UNRES_AUGMENT:
2183 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "augment target", ((struct lys_node_augment *)item)->target_name, line_str);
2184 break;
2185 case UNRES_IFFEAT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002186 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 +02002187 break;
2188 case UNRES_USES:
2189 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "uses", ((struct lys_node_uses *)item)->name, line_str);
2190 break;
2191 case UNRES_TYPE_DFLT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002192 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 +02002193 break;
2194 case UNRES_CHOICE_DFLT:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002195 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 +02002196 break;
2197 case UNRES_LIST_KEYS:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002198 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 +02002199 break;
2200 case UNRES_LIST_UNIQ:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002201 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 +02002202 break;
2203 case UNRES_WHEN:
2204 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "when", ((struct lys_when *)item)->cond, line_str);
2205 break;
2206 case UNRES_MUST:
2207 LOGVRB("Resolving %s \"%s\" failed, it will be attempted later%s.", "must", ((struct lys_restr *)item)->expr, line_str);
2208 break;
2209 }
2210}
2211
2212/* logs indirectly */
2213int
2214resolve_unres(struct lys_module *mod, struct unres_schema *unres)
2215{
2216 uint32_t i, resolved = 0;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002217
2218 assert(unres);
2219
2220 /* uses */
2221 for (i = 0; i < unres->count; ++i) {
2222 if (unres->type[i] != UNRES_USES) {
2223 continue;
2224 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002225 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 +02002226 unres->type[i] = UNRES_RESOLVED;
2227 ++resolved;
2228 }
2229 }
2230
2231 /* augment */
2232 for (i = 0; i < unres->count; ++i) {
2233 if (unres->type[i] != UNRES_AUGMENT) {
2234 continue;
2235 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002236 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 +02002237 unres->type[i] = UNRES_RESOLVED;
2238 ++resolved;
2239 }
2240 }
2241
2242 /* the rest */
2243 for (i = 0; i < unres->count; ++i) {
2244 if (unres->type[i] == UNRES_RESOLVED) {
2245 continue;
2246 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002247 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 +02002248 unres->type[i] = UNRES_RESOLVED;
2249 ++resolved;
2250 }
2251 }
2252
2253 if (resolved < unres->count) {
2254 return EXIT_FAILURE;
2255 }
2256
2257 return EXIT_SUCCESS;
2258}
2259
Michal Vaskof02e3742015-08-05 16:27:02 +02002260/* logs indirectly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002261void
Radek Krejci1d82ef62015-08-07 14:44:40 +02002262unres_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 +02002263 uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002264{
2265 str = lydict_insert(mod->ctx, str, 0);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002266 unres_add_node(mod, unres, item, type, (struct lys_node *)str, line);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002267}
2268
Michal Vaskof02e3742015-08-05 16:27:02 +02002269/* logs indirectly */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002270void
Radek Krejci1d82ef62015-08-07 14:44:40 +02002271unres_add_node(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type,
2272 struct lys_node *node, uint32_t line)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002273{
2274 assert(unres && item);
2275
Radek Krejci1d82ef62015-08-07 14:44:40 +02002276 if (!resolve_unres_item(mod, item, type, node, unres, UINT_MAX)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002277 return;
2278 }
2279
Radek Krejci1d82ef62015-08-07 14:44:40 +02002280 print_unres_item_fail(item, type, node, line);
Michal Vaskof02e3742015-08-05 16:27:02 +02002281
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002282 unres->count++;
2283 unres->item = realloc(unres->item, unres->count*sizeof *unres->item);
2284 unres->item[unres->count-1] = item;
2285 unres->type = realloc(unres->type, unres->count*sizeof *unres->type);
2286 unres->type[unres->count-1] = type;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002287 unres->str_snode = realloc(unres->str_snode, unres->count*sizeof *unres->str_snode);
2288 unres->str_snode[unres->count-1] = node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002289 unres->line = realloc(unres->line, unres->count*sizeof *unres->line);
2290 unres->line[unres->count-1] = line;
2291}
2292
Michal Vaskof02e3742015-08-05 16:27:02 +02002293/* logs indirectly */
Michal Vaskodad19402015-08-06 09:51:53 +02002294int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002295unres_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 +02002296{
2297 int i;
2298
2299 if (!item || !new_item) {
Michal Vaskodad19402015-08-06 09:51:53 +02002300 LOGINT;
2301 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002302 }
2303
Radek Krejci1d82ef62015-08-07 14:44:40 +02002304 i = unres_find(unres, item, type);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002305
2306 if (i == -1) {
Michal Vaskodad19402015-08-06 09:51:53 +02002307 return EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002308 }
2309
2310 if ((type == UNRES_TYPE_LEAFREF) || (type == UNRES_AUGMENT) || (type == UNRES_USES) || (type == UNRES_TYPE_DFLT)
2311 || (type == UNRES_WHEN) || (type == UNRES_MUST)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002312 unres_add_node(mod, unres, new_item, type, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002313 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002314 unres_add_str(mod, unres, new_item, type, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002315 }
Michal Vaskodad19402015-08-06 09:51:53 +02002316
2317 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002318}
2319
Michal Vaskof02e3742015-08-05 16:27:02 +02002320/* does not log */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002321int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002322unres_find(struct unres_schema *unres, void *item, enum UNRES_ITEM type)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002323{
2324 uint32_t ret = -1, i;
2325
2326 for (i = 0; i < unres->count; ++i) {
2327 if ((unres->item[i] == item) && (unres->type[i] == type)) {
2328 ret = i;
2329 break;
2330 }
2331 }
2332
2333 return ret;
2334}