blob: 91b2751dcde03e101a5020a8c97fb0c7c6e89cfa [file] [log] [blame]
Pavol Vican021488a2016-01-25 23:56:12 +01001/**
2 * @file parser_yang.c
3 * @author Pavol Vican
4 * @brief YANG parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Pavol Vican9a3a7212016-03-23 10:04:00 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
Pavol Vican021488a2016-01-25 23:56:12 +010013 */
14
Pavol Vican5de33492016-02-22 14:03:24 +010015#include <ctype.h>
Pavol Vican7313fc02016-11-14 01:10:31 +010016#include <assert.h>
Pavol Vican021488a2016-01-25 23:56:12 +010017#include "parser_yang.h"
Pavol Vican8e7110b2016-03-22 17:00:26 +010018#include "parser_yang_lex.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010019#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010020#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010021
Pavol Vican082afd02016-10-25 12:39:15 +020022static void yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size);
23static void yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size);
Pavol Vican7313fc02016-11-14 01:10:31 +010024static int yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node);
Pavol Vican05810b62016-11-23 14:07:22 +010025static void free_yang_common(struct lys_module *module, struct lys_node *node);
26void lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size);
Pavol Vican082afd02016-10-25 12:39:15 +020027
Michal Vaskofe7e5a72016-05-02 14:49:23 +020028static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010029yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010030{
Pavol Vicanbf805472016-01-26 14:24:56 +010031 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010032 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010033 free(value);
34 return 1;
35 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010036 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010037 return 0;
38 }
39}
40
Michal Vaskofe7e5a72016-05-02 14:49:23 +020041int
Pavol Vican5f0316a2016-04-05 21:21:11 +020042yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010043{
Pavol Vican6eb14e82016-02-03 12:27:13 +010044 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010045
46 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010047 case MODULE_KEYWORD:
48 module->name = lydict_insert_zc(module->ctx, value);
49 break;
50 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010051 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010052 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010053 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010054 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010055 break;
56 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010057 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010058 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +020059 default:
60 free(value);
61 LOGINT;
62 ret = EXIT_FAILURE;
63 break;
Pavol Vican2a064652016-02-02 22:54:34 +010064 }
65
Pavol Vican021488a2016-01-25 23:56:12 +010066 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010067}
68
Michal Vaskofe7e5a72016-05-02 14:49:23 +020069int
Pavol Vicand0b64c12016-07-15 09:56:19 +020070yang_check_version(struct lys_module *module, struct lys_submodule *submodule, char *value, int repeat)
71{
72 int ret = EXIT_SUCCESS;
73
74 if (repeat) {
Michal Vasko3767fb22016-07-21 12:10:57 +020075 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module");
76 ret = EXIT_FAILURE;
Pavol Vicand0b64c12016-07-15 09:56:19 +020077 } else {
78 if (!strcmp(value, "1")) {
79 if (submodule) {
80 if (module->version > 1) {
81 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
82 ret = EXIT_FAILURE;
83 }
84 } else {
85 module->version = 1;
86 }
87 } else if (!strcmp(value, "1.1")) {
88 if (submodule) {
89 if (module->version != 2) {
90 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
91 ret = EXIT_FAILURE;
92 }
93 } else {
94 module->version = 2;
95 }
96 } else {
97 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
98 ret = EXIT_FAILURE;
Michal Vasko3767fb22016-07-21 12:10:57 +020099 }
Pavol Vicand0b64c12016-07-15 09:56:19 +0200100 }
101 free(value);
102 return ret;
103}
104
105int
Pavol Vicane024ab72016-07-27 14:27:43 +0200106yang_read_prefix(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +0100107{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100108 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100109
Pavol Vican1cc4e192016-10-24 16:38:31 +0200110 if (!imp && lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100111 free(value);
112 return EXIT_FAILURE;
113 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200114
115 if (imp) {
116 ret = yang_check_string(module, &imp->prefix, "prefix", "import", value);
117 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100118 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100119 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100120
Pavol Vicanbf805472016-01-26 14:24:56 +0100121 return ret;
122}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100123
Pavol Vican1cc4e192016-10-24 16:38:31 +0200124static int
125yang_fill_import(struct lys_module *module, struct lys_import *imp_old, struct lys_import *imp_new, char *value)
Pavol Vican6eb14e82016-02-03 12:27:13 +0100126{
Pavol Vican0da132e2016-03-21 12:03:03 +0100127 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200128 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100129
Pavol Vican1cc4e192016-10-24 16:38:31 +0200130 if (!imp_old->prefix) {
Pavol Vicane024ab72016-07-27 14:27:43 +0200131 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "import");
Pavol Vican1cc4e192016-10-24 16:38:31 +0200132 goto error;
133 } else {
134 if (lyp_check_identifier(imp_old->prefix, LY_IDENT_PREFIX, module, NULL)) {
135 goto error;
136 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200137 }
Pavol Vican1cc4e192016-10-24 16:38:31 +0200138 memcpy(imp_new, imp_old, sizeof *imp_old);
Pavol Vican0da132e2016-03-21 12:03:03 +0100139 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican1cc4e192016-10-24 16:38:31 +0200140 rc = lyp_check_import(module, exp, imp_new);
Pavol Vican0da132e2016-03-21 12:03:03 +0100141 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200142 module->imp_size++;
Pavol Vican0da132e2016-03-21 12:03:03 +0100143 if (rc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200144 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100145 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100146
Pavol Vican6eb14e82016-02-03 12:27:13 +0100147 return EXIT_SUCCESS;
Pavol Vican1cc4e192016-10-24 16:38:31 +0200148
149error:
150 free(value);
151 lydict_remove(module->ctx, imp_old->dsc);
152 lydict_remove(module->ctx, imp_old->ref);
153 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100154}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100155
156int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100157yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100158{
159 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100160 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100161
162 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100163 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100164 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100165 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100166 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200167 } else if (!strcmp("import", where)){
168 ret = yang_check_string(module, &((struct lys_import *)node)->dsc, dsc, where, value);
169 } else if (!strcmp("include", where)){
170 ret = yang_check_string(module, &((struct lys_include *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100171 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100172 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100173 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100174 }
175 return ret;
176}
177
178int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100179yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100180{
181 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100182 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100183
184 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100185 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100186 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100187 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100188 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200189 } else if (!strcmp("import", where)){
190 ret = yang_check_string(module, &((struct lys_import *)node)->ref, ref, where, value);
191 } else if (!strcmp("include", where)){
192 ret = yang_check_string(module, &((struct lys_include *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100193 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100194 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100195 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100196 }
197 return ret;
198}
Pavol Vicanbedff692016-02-03 14:29:17 +0100199
Pavol Vican866d9912016-10-25 09:13:30 +0200200void
201yang_read_revision(struct lys_module *module, char *value, struct lys_revision *retval)
Pavol Vicanbedff692016-02-03 14:29:17 +0100202{
Pavol Vicanbedff692016-02-03 14:29:17 +0100203 /* first member of array is last revision */
Pavol Vican866d9912016-10-25 09:13:30 +0200204 if ((module->rev_size - 1) && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100205 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
206 memcpy(module->rev[0].date, value, LY_REV_SIZE);
207 retval->dsc = module->rev[0].dsc;
208 retval->ref = module->rev[0].ref;
209 retval = module->rev;
210 retval->dsc = NULL;
211 retval->ref = NULL;
212 } else {
213 memcpy(retval->date, value, LY_REV_SIZE);
214 }
Pavol Vicanbedff692016-02-03 14:29:17 +0100215 free(value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100216}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100217
218int
Pavol Vicana1827962016-02-29 15:39:42 +0100219yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100220{
Pavol Vican45ccc592016-03-09 18:53:48 +0100221 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100222 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
223 LOGMEM;
224 return EXIT_FAILURE;
225 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100226 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100227 }
228 }
229 (*size)++;
230 return EXIT_SUCCESS;
231}
Pavol Vicane1354e92016-02-09 14:02:09 +0100232
Pavol Vicane1354e92016-02-09 14:02:09 +0100233int
Pavol Vican5c8a9ad2016-11-22 11:50:54 +0100234yang_read_if_feature(struct lys_module *module, void *ptr, void *parent, char *value,
235 struct unres_schema *unres, enum yytokentype type)
Pavol Vicane1354e92016-02-09 14:02:09 +0100236{
237 const char *exp;
238 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100239 struct lys_feature *f;
Pavol Vican4df80542016-08-08 09:37:55 +0200240 struct lys_ident *i;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100241 struct lys_node *n;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200242 struct lys_type_enum *e;
243 struct lys_type_bit *b;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200244 struct lys_refine *r;
Pavol Vicane1354e92016-02-09 14:02:09 +0100245
Michal Vasko97b32be2016-07-25 10:59:53 +0200246 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
247 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
248 free(value);
249 return EXIT_FAILURE;
250 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100251
Michal Vasko56d082c2016-10-25 14:00:42 +0200252 if (!(exp = transform_iffeat_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100253 free(value);
254 return EXIT_FAILURE;
255 }
256 free(value);
257
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200258 switch (type) {
259 case FEATURE_KEYWORD:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100260 f = (struct lys_feature *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200261 ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, 1, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200262 f->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200263 break;
264 case IDENTITY_KEYWORD:
Pavol Vican4df80542016-08-08 09:37:55 +0200265 i = (struct lys_ident *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200266 ret = resolve_iffeature_compile(&i->iffeature[i->iffeature_size], exp, (struct lys_node *)i, 0, unres);
Pavol Vican4df80542016-08-08 09:37:55 +0200267 i->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200268 break;
269 case ENUM_KEYWORD:
Pavol Vican5c8a9ad2016-11-22 11:50:54 +0100270 e = (struct lys_type_enum *) ptr;
271 ret = resolve_iffeature_compile(&e->iffeature[e->iffeature_size], exp, (struct lys_node *) parent, 0, unres);
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200272 e->iffeature_size++;
273 break;
274 case BIT_KEYWORD:
Pavol Vican5c8a9ad2016-11-22 11:50:54 +0100275 b = (struct lys_type_bit *) ptr;
276 ret = resolve_iffeature_compile(&b->iffeature[b->iffeature_size], exp, (struct lys_node *) parent, 0, unres);
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200277 b->iffeature_size++;
278 break;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200279 case REFINE_KEYWORD:
280 r = &((struct lys_node_uses *)ptr)->refine[((struct lys_node_uses *)ptr)->refine_size - 1];
Radek Krejci9de2c042016-10-19 16:53:06 +0200281 ret = resolve_iffeature_compile(&r->iffeature[r->iffeature_size], exp, (struct lys_node *) ptr, 0, unres);
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200282 r->iffeature_size++;
283 break;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200284 default:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100285 n = (struct lys_node *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200286 ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, 0, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200287 n->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200288 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100289 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100290 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100291
Radek Krejci9ff0a922016-07-14 13:08:05 +0200292 if (ret) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100293 return EXIT_FAILURE;
294 }
295 return EXIT_SUCCESS;
296}
297
Pavol Vican4fb66c92016-03-17 10:32:27 +0100298int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200299yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100300{
301 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100302 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100303 return EXIT_FAILURE;
304 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200305 if (shortint) {
306 *((uint8_t *)flags) |= (uint8_t)value;
307 } else {
308 *flags |= value;
309 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100310 return EXIT_SUCCESS;
311 }
312}
313
Pavol Vicanbbdef532016-02-09 14:52:12 +0100314int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100315yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100316{
317 const char *exp;
318
Pavol Vican0adf01d2016-03-22 12:29:33 +0100319 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100320 free(value);
321 if (!exp) {
322 return EXIT_FAILURE;
323 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200324
Pavol Vican0adf01d2016-03-22 12:29:33 +0100325 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100326 lydict_remove(module->ctx, exp);
327 return EXIT_FAILURE;
328 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100329
Pavol Vicanbbdef532016-02-09 14:52:12 +0100330 lydict_remove(module->ctx, exp);
331 return EXIT_SUCCESS;
332}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100333
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100334int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100335yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100336{
337 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100338
Pavol Vicandde090a2016-08-30 15:12:14 +0200339 if (message == ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100340 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100341 } else {
Pavol Vicandde090a2016-08-30 15:12:14 +0200342 ret = yang_check_string(module, &save->emsg, "error_message", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100343 }
344 return ret;
345}
Pavol Vicanb5687112016-02-09 22:35:59 +0100346
347int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100348yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100349{
350 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100351 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100352 free(value);
353 return EXIT_FAILURE;
354 } else {
355 cont->presence = lydict_insert_zc(module->ctx, value);
356 return EXIT_SUCCESS;
357 }
358}
359
Pavol Vican235dbd42016-02-10 10:34:19 +0100360void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200361yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100362{
363 struct lys_when *retval;
364
365 retval = calloc(1, sizeof *retval);
366 if (!retval) {
367 LOGMEM;
368 free(value);
369 return NULL;
370 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100371 retval->cond = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200372 if (!retval->cond) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100373 goto error;
374 }
375 switch (type) {
376 case CONTAINER_KEYWORD:
377 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100378 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100379 goto error;
380 }
381 ((struct lys_node_container *)node)->when = retval;
382 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200383 case ANYDATA_KEYWORD:
Pavol Vican1f06ba82016-02-10 17:39:50 +0100384 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200385 if (((struct lys_node_anydata *)node)->when) {
Pavol Vicandb7489e2016-08-23 17:23:39 +0200386 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", (type == ANYXML_KEYWORD) ? "anyxml" : "anydata");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100387 goto error;
388 }
Radek Krejcibf2abff2016-08-23 15:51:52 +0200389 ((struct lys_node_anydata *)node)->when = retval;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100390 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100391 case CHOICE_KEYWORD:
392 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100393 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100394 goto error;
395 }
396 ((struct lys_node_choice *)node)->when = retval;
397 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100398 case CASE_KEYWORD:
399 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100400 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100401 goto error;
402 }
403 ((struct lys_node_case *)node)->when = retval;
404 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100405 case LEAF_KEYWORD:
406 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100407 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100408 goto error;
409 }
410 ((struct lys_node_leaf *)node)->when = retval;
411 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100412 case LEAF_LIST_KEYWORD:
413 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100414 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100415 goto error;
416 }
417 ((struct lys_node_leaflist *)node)->when = retval;
418 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100419 case LIST_KEYWORD:
420 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100421 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100422 goto error;
423 }
424 ((struct lys_node_list *)node)->when = retval;
425 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100426 case USES_KEYWORD:
427 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100428 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100429 goto error;
430 }
431 ((struct lys_node_uses *)node)->when = retval;
432 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100433 case AUGMENT_KEYWORD:
434 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100435 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100436 goto error;
437 }
438 ((struct lys_node_augment *)node)->when = retval;
439 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200440 default:
441 goto error;
442 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100443 }
444 free(value);
445 return retval;
446
447error:
448 free(value);
449 lys_when_free(module->ctx, retval);
450 return NULL;
451}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100452
453void *
Pavol Vican05810b62016-11-23 14:07:22 +0100454yang_read_node(struct lys_module *module, struct lys_node *parent, struct lys_node **root,
455 char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100456{
Pavol Vican05810b62016-11-23 14:07:22 +0100457 struct lys_node *node, **child;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100458
Pavol Vican7cadfe72016-02-11 12:33:34 +0100459 node = calloc(1, sizeof_struct);
460 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100461 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100462 LOGMEM;
463 return NULL;
464 }
Pavol Vican531a9132016-03-03 10:10:09 +0100465 if (value) {
466 node->name = lydict_insert_zc(module->ctx, value);
467 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100468 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100469 node->nodetype = nodetype;
Pavol Vicanc54a8f72016-11-23 16:45:55 +0100470 node->parent = parent;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100471
472 /* insert the node into the schema tree */
Pavol Vican05810b62016-11-23 14:07:22 +0100473 child = (parent) ? &parent->child : root;
474 if (*child) {
475 (*child)->prev->next = node;
476 (*child)->prev = node;
477 } else {
478 *child = node;
479 node->prev = node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100480 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100481 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100482}
483
Pavol Vican8c793992016-07-15 10:44:57 +0200484void *
Pavol Vican05810b62016-11-23 14:07:22 +0100485yang_read_action(struct lys_module *module, struct lys_node *parent, struct lys_node **root, char *value)
Pavol Vican8c793992016-07-15 10:44:57 +0200486{
487 struct lys_node *node;
488
Michal Vaskobb174852016-07-25 11:00:21 +0200489 if (module->version != 2) {
490 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
491 return NULL;
492 }
493
Pavol Vican8c793992016-07-15 10:44:57 +0200494 for (node = parent; node; node = lys_parent(node)) {
Radek Krejci24681f12016-10-06 10:42:21 +0200495 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Pavol Vicanbbe77822016-07-15 12:53:07 +0200496 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Pavol Vican8c793992016-07-15 10:44:57 +0200497 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
498 return NULL;
499 }
500 }
Pavol Vican05810b62016-11-23 14:07:22 +0100501 return yang_read_node(module, parent, root, value, LYS_ACTION, sizeof(struct lys_node_rpc_action));
Pavol Vican8c793992016-07-15 10:44:57 +0200502}
503
Pavol Vican8c82fa82016-02-10 13:13:24 +0100504int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200505yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100506{
507 int ret;
508
509 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100510 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100511 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100512 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100513 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100514 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100515 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200516 default:
517 free(value);
518 LOGINT;
519 ret = EXIT_FAILURE;
520 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100521 }
522 return ret;
523}
524
525int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200526yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100527{
528 int ret;
529
530 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100531 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100532 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100533 break;
534 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100535 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100536 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100537 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100538 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100539 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200540 default:
541 free(value);
542 LOGINT;
543 ret = EXIT_FAILURE;
544 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100545 }
546 return ret;
547}
Pavol Vican5de33492016-02-22 14:03:24 +0100548
549int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100550yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100551{
552 char *exp, *value;
Radek Krejci5c08a992016-11-02 13:30:04 +0100553 struct lys_node *node;
Pavol Vican5de33492016-02-22 14:03:24 +0100554
555 exp = value = (char *) list->keys;
556 while ((value = strpbrk(value, " \t\n"))) {
557 list->keys_size++;
558 while (isspace(*value)) {
559 value++;
560 }
561 }
562 list->keys_size++;
Radek Krejci5c08a992016-11-02 13:30:04 +0100563
564 list->keys_str = lydict_insert_zc(module->ctx, exp);
Pavol Vican5de33492016-02-22 14:03:24 +0100565 list->keys = calloc(list->keys_size, sizeof *list->keys);
566 if (!list->keys) {
567 LOGMEM;
Radek Krejci5c08a992016-11-02 13:30:04 +0100568 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100569 }
Radek Krejci5c08a992016-11-02 13:30:04 +0100570 for (node = list->parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
571 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
572 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100573 }
Pavol Vican5de33492016-02-22 14:03:24 +0100574 return EXIT_SUCCESS;
Pavol Vican5de33492016-02-22 14:03:24 +0100575}
576
577int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100578yang_fill_unique(struct lys_module *module, struct lys_node_list *list, struct lys_unique *unique, char *value, struct unres_schema *unres)
Pavol Vican85f12022016-03-05 16:30:35 +0100579{
580 int i, j;
581 char *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200582 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100583
584 /* count the number of unique leafs in the value */
585 vaux = value;
586 while ((vaux = strpbrk(vaux, " \t\n"))) {
587 unique->expr_size++;
588 while (isspace(*vaux)) {
589 vaux++;
590 }
591 }
592 unique->expr_size++;
593 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
594 if (!unique->expr) {
595 LOGMEM;
596 goto error;
597 }
598
599 for (i = 0; i < unique->expr_size; i++) {
600 vaux = strpbrk(value, " \t\n");
601 if (!vaux) {
602 /* the last token, lydict_insert() will count its size on its own */
603 vaux = value;
604 }
605
606 /* store token into unique structure */
607 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
608
609 /* check that the expression does not repeat */
610 for (j = 0; j < i; j++) {
611 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100612 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
613 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100614 goto error;
615 }
616 }
617 /* try to resolve leaf */
618 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200619 unique_info = malloc(sizeof *unique_info);
620 unique_info->list = (struct lys_node *)list;
621 unique_info->expr = unique->expr[i];
622 unique_info->trg_type = &unique->trg_type;
623 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200624 goto error;
625 }
Pavol Vican85f12022016-03-05 16:30:35 +0100626 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200627 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100628 goto error;
629 }
630 }
631
632 /* move to next token */
633 value = vaux;
634 while(isspace(*value)) {
635 value++;
636 }
637 }
638
639 return EXIT_SUCCESS;
640
641error:
642 return EXIT_FAILURE;
643}
644
645int
Pavol Vican5de33492016-02-22 14:03:24 +0100646yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
647{
648 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100649 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100650
651 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100652 str = (char *)list->unique[k].expr;
653 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100654 goto error;
655 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100656 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100657 }
658 return EXIT_SUCCESS;
659
660error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100661 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100662 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100663}
664
Pavol Vican07f220f2016-09-02 13:04:37 +0200665int
Pavol Vican81344ac2016-09-02 14:23:06 +0200666yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100667{
Pavol Vican81344ac2016-09-02 14:23:06 +0200668 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
669 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
670 goto error;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100671 }
Pavol Vican81344ac2016-09-02 14:23:06 +0200672 if (stype->type->info.lref.path) {
673 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
674 goto error;
675 }
676 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
677 stype->base = LY_TYPE_LEAFREF;
678 return EXIT_SUCCESS;
679
680error:
681 free(value);
682 return EXIT_FAILURE;
683}
684
685int
686yang_read_require_instance(struct yang_type *stype, int req)
687{
688 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
689 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
690 return EXIT_FAILURE;
691 }
692 if (stype->type->info.lref.req) {
693 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
694 return EXIT_FAILURE;
695 }
696 stype->type->info.lref.req = req;
697 stype->base = LY_TYPE_LEAFREF;
698 return EXIT_SUCCESS;
699}
700
701int
Pavol Vican07f220f2016-09-02 13:04:37 +0200702yang_read_identyref(struct lys_module *module, struct yang_type *stype, char *expr, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100703{
Pavol Vican07f220f2016-09-02 13:04:37 +0200704 const char *value;
705 int rc;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100706
Pavol Vican07f220f2016-09-02 13:04:37 +0200707 if (stype->base && stype->base != LY_TYPE_IDENT) {
708 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
709 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100710 }
Pavol Vican07f220f2016-09-02 13:04:37 +0200711
712 stype->base = LY_TYPE_IDENT;
713 /* store in the JSON format */
714 value = transform_schema2json(module, expr);
715 free(expr);
716
717 if (!value) {
718 return EXIT_FAILURE;
719 }
720 rc = unres_schema_add_str(module, unres, stype->type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100721 lydict_remove(module->ctx, value);
722
723 if (rc == -1) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200724 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100725 }
726
Pavol Vican07f220f2016-09-02 13:04:37 +0200727 return EXIT_SUCCESS;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100728}
729
Pavol Vican73e7c992016-02-24 12:18:05 +0100730int
Pavol Vican7313fc02016-11-14 01:10:31 +0100731yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct lys_type *type, int tpdftype, struct unres_schema *unres)
Pavol Vican73e7c992016-02-24 12:18:05 +0100732{
Pavol Vican81344ac2016-09-02 14:23:06 +0200733 int i, j, rc, ret = -1;
734 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100735 const char *name, *value;
Pavol Vican8bd72e42016-08-29 09:53:05 +0200736 LY_DATA_TYPE base = 0;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200737 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200738 struct lys_type *dertype;
739 struct lys_type_enum *enms_sc = NULL;
740 struct lys_type_bit *bits_sc = NULL;
741 struct lys_type_bit bit_tmp;
Pavol Vican73e7c992016-02-24 12:18:05 +0100742
Pavol Vican0adf01d2016-03-22 12:29:33 +0100743 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100744 if (!value) {
745 goto error;
746 }
747
748 i = parse_identifier(value);
749 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100750 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100751 lydict_remove(module->ctx, value);
752 goto error;
753 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200754 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100755 name = value;
756 if (value[i]) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100757 type->module_name = lydict_insert(module->ctx, value, i);
Pavol Vican73e7c992016-02-24 12:18:05 +0100758 name += i;
759 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100760 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100761 lydict_remove(module->ctx, value);
762 goto error;
763 }
764 ++name;
765 }
766
Pavol Vican7313fc02016-11-14 01:10:31 +0100767 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100768 if (rc == -1) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100769 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200770 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100771 goto error;
772
Michal Vasko01c6fd22016-05-20 11:43:05 +0200773 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100774 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200775 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200776 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100777 ret = EXIT_FAILURE;
778 goto error;
779 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200780 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200781
Pavol Vican7313fc02016-11-14 01:10:31 +0100782 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200783 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200784 * unresolved item left inside the grouping, LY_TYPE_ERR used as a flag for types inside a grouping. */
Radek Krejcic13db382016-08-16 10:52:42 +0200785 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
786 if (siter) {
787 if (!((struct lys_node_grp *)siter)->nacm) {
788 LOGINT;
789 goto error;
790 }
791 ((struct lys_node_grp *)siter)->nacm--;
792 } else {
793 LOGINT;
794 goto error;
795 }
796 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200797
798 /* check status */
Pavol Vican7313fc02016-11-14 01:10:31 +0100799 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
800 type->der->flags, type->der->module, type->der->name, parent)) {
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200801 goto error;
802 }
803
Pavol Vican8bd72e42016-08-29 09:53:05 +0200804 base = typ->base;
Pavol Vican7313fc02016-11-14 01:10:31 +0100805 type->base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100806 if (base == 0) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100807 base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100808 }
809 switch (base) {
810 case LY_TYPE_STRING:
Pavol Vican7313fc02016-11-14 01:10:31 +0100811 if (type->base == LY_TYPE_BINARY) {
812 if (type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100813 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100814 goto error;
815 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100816 type->info.binary.length = type->info.str.length;
817 if (type->info.binary.length && lyp_check_length_range(type->info.binary.length->expr, type)) {
818 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100819 goto error;
820 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100821 } else if (type->base == LY_TYPE_STRING) {
822 if (type->info.str.length && lyp_check_length_range(type->info.str.length->expr, type)) {
823 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100824 goto error;
825 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100826 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100827 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100828 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100829 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100830 break;
831 case LY_TYPE_DEC64:
Pavol Vican7313fc02016-11-14 01:10:31 +0100832 if (type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100833 /* mandatory sub-statement(s) check */
Pavol Vican7313fc02016-11-14 01:10:31 +0100834 if (!type->info.dec64.dig && !type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100835 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100836 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100837 goto error;
838 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100839 if (type->info.dec64.dig && type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100840 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100841 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100842 goto error;
843 }
Radek Krejci4800f652016-09-08 14:02:52 +0200844
845 /* copy fraction-digits specification from parent type for easier internal use */
Pavol Vican7313fc02016-11-14 01:10:31 +0100846 if (type->der->type.der) {
847 type->info.dec64.dig = type->der->type.info.dec64.dig;
848 type->info.dec64.div = type->der->type.info.dec64.div;
Radek Krejci4800f652016-09-08 14:02:52 +0200849 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100850 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
851 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.dec64.range->expr, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200852 goto error;
853 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100854 } else if (type->base >= LY_TYPE_INT8 && type->base <=LY_TYPE_UINT64) {
855 if (type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100856 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100857 goto error;
858 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100859 type->info.num.range = type->info.dec64.range;
860 if (type->info.num.range && lyp_check_length_range(type->info.num.range->expr, type)) {
861 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100862 goto error;
863 }
864 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100865 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100866 goto error;
867 }
868 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100869 case LY_TYPE_ENUM:
Pavol Vican7313fc02016-11-14 01:10:31 +0100870 if (type->base != LY_TYPE_ENUM) {
871 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100872 goto error;
873 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100874 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200875
876 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100877 if (!type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200878 /* type is derived directly from buit-in enumeartion type and enum statement is required */
879 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
880 goto error;
881 }
882 } else {
883 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100884 if (module->version < 2 && type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200885 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
886 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
887 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
888 goto error;
889 }
890
891 /* restricted enumeration type - the name MUST be used in the base type */
892 enms_sc = dertype->info.enums.enm;
Pavol Vican7313fc02016-11-14 01:10:31 +0100893 for(i = 0; i < type->info.enums.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200894 for (j = 0; j < dertype->info.enums.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100895 if (ly_strequal(enms_sc[j].name, type->info.enums.enm[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200896 break;
897 }
898 }
899 if (j == dertype->info.enums.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100900 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200901 goto error;
902 }
903
Pavol Vican7313fc02016-11-14 01:10:31 +0100904 if (type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200905 /* automatically assign value from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100906 type->info.enums.enm[i].value = enms_sc[j].value;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200907 } else {
908 /* check that the assigned value corresponds to the original
909 * value of the enum in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100910 if (type->info.enums.enm[i].value != enms_sc[j].value) {
911 /* type->info.enums.enm[i].value - assigned value in restricted enum
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200912 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100913 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, type->info.enums.enm[i].value,
914 type->info.enums.enm[i].name, enms_sc[j].value);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200915 goto error;
916 }
917 }
918 }
Pavol Vican79a763d2016-02-25 15:41:27 +0100919 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100920 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100921 case LY_TYPE_BITS:
Pavol Vican7313fc02016-11-14 01:10:31 +0100922 if (type->base != LY_TYPE_BITS) {
923 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100924 goto error;
925 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100926 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200927
928 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100929 if (!type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200930 /* type is derived directly from buit-in bits type and bit statement is required */
931 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
932 goto error;
933 }
934 } else {
935 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100936 if (module->version < 2 && type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200937 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
938 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
939 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
940 goto error;
941 }
942
943 bits_sc = dertype->info.bits.bit;
Pavol Vican7313fc02016-11-14 01:10:31 +0100944 for (i = 0; i < type->info.bits.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200945 for (j = 0; j < dertype->info.bits.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100946 if (ly_strequal(bits_sc[j].name, type->info.bits.bit[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200947 break;
948 }
949 }
950 if (j == dertype->info.bits.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100951 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200952 goto error;
953 }
954
955 /* restricted bits type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100956 if (type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200957 /* automatically assign position from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100958 type->info.bits.bit[i].pos = bits_sc[j].pos;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200959 } else {
960 /* check that the assigned position corresponds to the original
961 * position of the bit in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100962 if (type->info.bits.bit[i].pos != bits_sc[j].pos) {
963 /* type->info.bits.bit[i].pos - assigned position in restricted bits
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200964 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100965 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
966 type->info.bits.bit[i].name, bits_sc[j].pos);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200967 goto error;
968 }
969 }
970 }
Pavol Vican03a59442016-03-21 15:23:45 +0100971 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200972
Pavol Vican7313fc02016-11-14 01:10:31 +0100973 for (i = type->info.bits.count - 1; i > 0; i--) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200974 j = i;
975
976 /* keep them ordered by position */
Pavol Vican7313fc02016-11-14 01:10:31 +0100977 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200978 /* switch them */
Pavol Vican7313fc02016-11-14 01:10:31 +0100979 memcpy(&bit_tmp, &type->info.bits.bit[j], sizeof bit_tmp);
980 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit_tmp);
981 memcpy(&type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200982 j--;
983 }
Pavol Vican03a59442016-03-21 15:23:45 +0100984 }
985 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100986 case LY_TYPE_LEAFREF:
Pavol Vican7313fc02016-11-14 01:10:31 +0100987 if (type->base == LY_TYPE_INST) {
988 if (type->info.lref.path) {
Pavol Vican81344ac2016-09-02 14:23:06 +0200989 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
Pavol Vican1ff0e222016-02-26 12:27:01 +0100990 goto error;
991 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100992 if ((req = type->info.lref.req)) {
993 type->info.inst.req = req;
Pavol Vican81344ac2016-09-02 14:23:06 +0200994 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100995 } else if (type->base == LY_TYPE_LEAFREF) {
Pavol Vican92626d72016-09-21 09:36:09 +0200996 /* require-instance only YANG 1.1 */
Pavol Vican7313fc02016-11-14 01:10:31 +0100997 if (type->info.lref.req && (module->version < 2)) {
Pavol Vican92626d72016-09-21 09:36:09 +0200998 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
999 goto error;
1000 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001001 /* flag resolving for later use */
1002 if (!tpdftype) {
1003 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1004 if (siter) {
1005 /* just a flag - do not resolve */
1006 tpdftype = 1;
1007 }
1008 }
1009
Pavol Vican7313fc02016-11-14 01:10:31 +01001010 if (type->info.lref.path) {
1011 if (type->der->type.der) {
Pavol Vican894ee0f2016-08-30 15:29:46 +02001012 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
1013 goto error;
1014 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001015 value = type->info.lref.path;
Pavol Vican191613a2016-02-26 16:21:32 +01001016 /* store in the JSON format */
Pavol Vican7313fc02016-11-14 01:10:31 +01001017 type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +01001018 lydict_remove(module->ctx, value);
Pavol Vican7313fc02016-11-14 01:10:31 +01001019 if (!type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +01001020 goto error;
1021 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001022 /* try to resolve leafref path only when this is instantiated
1023 * leaf, so it is not:
1024 * - typedef's type,
1025 * - in grouping definition,
1026 * - just instantiated in a grouping definition,
1027 * because in those cases the nodes referenced in path might not be present
1028 * and it is not a bug. */
Pavol Vican7313fc02016-11-14 01:10:31 +01001029 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +01001030 goto error;
1031 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001032 } else if (!type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001033 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +01001034 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +02001035 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001036 /* copy leafref definition into the derived type */
Pavol Vican7313fc02016-11-14 01:10:31 +01001037 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +02001038 /* and resolve the path at the place we are (if not in grouping/typedef) */
Pavol Vican7313fc02016-11-14 01:10:31 +01001039 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001040 goto error;
1041 }
Radek Krejci742be352016-07-17 12:18:54 +02001042
Radek Krejci3a5501d2016-07-18 22:03:34 +02001043 /* add pointer to leafref target, only on leaves (not in typedefs) */
Pavol Vican7313fc02016-11-14 01:10:31 +01001044 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001045 goto error;
Radek Krejci742be352016-07-17 12:18:54 +02001046 }
Pavol Vican191613a2016-02-26 16:21:32 +01001047 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001048 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +01001049 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001050 goto error;
1051 }
1052 break;
1053 case LY_TYPE_IDENT:
Pavol Vican7313fc02016-11-14 01:10:31 +01001054 if (type->base != LY_TYPE_IDENT) {
1055 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001056 goto error;
1057 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001058 if (type->der->type.der) {
1059 if (type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +02001060 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1061 goto error;
1062 }
1063 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +01001064 if (!type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +02001065 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
1066 goto error;
1067 }
1068 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001069 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001070 case LY_TYPE_UNION:
Pavol Vican7313fc02016-11-14 01:10:31 +01001071 if (type->base != LY_TYPE_UNION) {
1072 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001073 goto error;
1074 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001075 if (!type->info.uni.types) {
1076 if (type->der->type.der) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001077 /* this is just a derived type with no additional type specified/required */
1078 break;
1079 }
Pavol Vican0adf01d2016-03-22 12:29:33 +01001080 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +01001081 goto error;
1082 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001083 for (i = 0; i < type->info.uni.count; i++) {
1084 type->info.uni.types[i].parent = type->parent;
1085 if (unres_schema_add_node(module, unres, &type->info.uni.types[i],
Michal Vasko5d631402016-07-21 13:15:15 +02001086 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001087 goto error;
1088 }
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001089 if (module->version < 2) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001090 if (type->info.uni.types[i].base == LY_TYPE_EMPTY) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001091 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
1092 goto error;
Pavol Vican7313fc02016-11-14 01:10:31 +01001093 } else if (type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001094 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
1095 goto error;
1096 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001097 }
1098 }
1099 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001100
1101 default:
1102 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001103 if (type->base != base) {
1104 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001105 goto error;
1106 }
1107 } else {
1108 LOGINT;
1109 goto error;
1110 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001111 }
1112 return EXIT_SUCCESS;
1113
1114error:
Pavol Vican7313fc02016-11-14 01:10:31 +01001115 if (type->module_name) {
1116 lydict_remove(module->ctx, type->module_name);
1117 type->module_name = NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001118 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001119 if (base) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001120 type->base = base;
Pavol Vican8bd72e42016-08-29 09:53:05 +02001121 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001122 return ret;
1123}
1124
1125void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001126yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001127{
1128 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001129 struct type_deviation *dev;
1130 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001131
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001132 typ = calloc(1, sizeof *typ);
1133 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001134 LOGMEM;
1135 return NULL;
1136 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001137
1138 typ->flags = LY_YANG_STRUCTURE_FLAG;
1139 switch (type) {
1140 case LEAF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001141 if (((struct lys_node_leaf *)parent)->type.der) {
1142 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf");
1143 goto error;
1144 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001145 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1146 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1147 typ->type = &((struct lys_node_leaf *)parent)->type;
1148 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001149 case LEAF_LIST_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001150 if (((struct lys_node_leaflist *)parent)->type.der) {
1151 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf-list");
1152 goto error;
1153 }
Pavol Vicana55992a2016-03-01 13:37:17 +01001154 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1155 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1156 typ->type = &((struct lys_node_leaflist *)parent)->type;
1157 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001158 case UNION_KEYWORD:
1159 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1160 typ->type = (struct lys_type *)parent;
1161 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001162 case TYPEDEF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001163 if (((struct lys_tpdf *)parent)->type.der) {
1164 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "typedef");
1165 goto error;
1166 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001167 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1168 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001169 break;
1170 case REPLACE_KEYWORD:
1171 /* deviation replace type*/
1172 dev = (struct type_deviation *)parent;
1173 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001174 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001175 goto error;
1176 }
1177 /* check target node type */
1178 if (dev->target->nodetype == LYS_LEAF) {
1179 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1180 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1181 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1182 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001183 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1184 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001185 goto error;
1186 }
1187
1188 /* remove type and initialize it */
1189 lys_type_free(module->ctx, typ->type);
1190 tmp_parent = typ->type->parent;
1191 memset(typ->type, 0, sizeof *typ->type);
1192 typ->type->parent = tmp_parent;
1193
1194 /* replace it with the value specified in deviation */
1195 /* HACK for unres */
1196 typ->type->der = (struct lys_tpdf *)typ;
1197 dev->deviate->type = typ->type;
1198 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001199 default:
1200 goto error;
1201 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001202 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001203 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001204 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001205
1206error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001207 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001208 free(typ);
1209 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001210}
1211
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001212void
1213yang_delete_type(struct lys_module *module, struct yang_type *stype)
1214{
1215 int i;
1216
Pavol Vican77a95e52016-08-15 09:49:26 +02001217 if (!stype) {
1218 return;
1219 }
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001220 stype->type->base = stype->base;
1221 stype->type->der = NULL;
1222 lydict_remove(module->ctx, stype->name);
1223 if (stype->base == LY_TYPE_UNION) {
1224 for (i = 0; i < stype->type->info.uni.count; i++) {
1225 if (stype->type->info.uni.types[i].der) {
1226 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1227 }
1228 }
1229 }
1230 free(stype);
1231}
1232
Pavol Vican73e7c992016-02-24 12:18:05 +01001233void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001234yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001235{
1236 struct lys_restr **length;
1237
Pavol Vican6b072512016-04-04 10:50:21 +02001238 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001239 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001240 typ->base = LY_TYPE_STRING;
1241 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001242 length = &typ->type->info.binary.length;
1243 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001244 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001245 goto error;
1246 }
1247
1248 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001249 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001250 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001251 }
1252 *length = calloc(1, sizeof **length);
1253 if (!*length) {
1254 LOGMEM;
1255 goto error;
1256 }
1257 (*length)->expr = lydict_insert_zc(module->ctx, value);
1258 return *length;
1259
1260error:
1261 free(value);
1262 return NULL;
1263
1264}
Pavol Vican1c203db2016-02-24 14:05:23 +01001265
Pavol Vican6eecf302016-08-10 11:09:05 +02001266int
1267yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001268{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001269 char *buf;
1270 size_t len;
1271
Michal Vasko0aee5c12016-06-17 14:27:26 +02001272 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001273 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001274 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001275 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001276
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001277 len = strlen(value);
1278 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001279
1280 if (!buf) {
1281 LOGMEM;
1282 free(value);
1283 return EXIT_FAILURE;
1284 }
1285
1286 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001287 strcpy(&buf[1], value);
1288 free(value);
1289
Pavol Vican6eecf302016-08-10 11:09:05 +02001290 pattern->expr = lydict_insert_zc(module->ctx, buf);
1291 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001292}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001293
1294void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001295yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001296{
Pavol Vican6b072512016-04-04 10:50:21 +02001297 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001298 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001299 goto error;
1300 }
Pavol Vican6b072512016-04-04 10:50:21 +02001301 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001302 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001303 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001304 goto error;
1305 }
1306 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1307 if (!typ->type->info.dec64.range) {
1308 LOGMEM;
1309 goto error;
1310 }
1311 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1312 return typ->type->info.dec64.range;
1313
1314error:
1315 free(value);
1316 return NULL;
1317}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001318
1319int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001320yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001321{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001322 unsigned int i;
1323
Pavol Vican6b072512016-04-04 10:50:21 +02001324 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1325 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001326 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001327 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001328 goto error;
1329 }
1330 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001331 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001332 goto error;
1333 }
1334 /* range check */
1335 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001336 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001337 goto error;
1338 }
1339 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001340 typ->type->info.dec64.div = 10;
1341 for (i = 1; i < value; i++) {
1342 typ->type->info.dec64.div *= 10;
1343 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001344 return EXIT_SUCCESS;
1345
1346error:
1347 return EXIT_FAILURE;
1348}
Pavol Vican79a763d2016-02-25 15:41:27 +01001349
Pavol Vican874715f2016-10-25 14:52:08 +02001350int
1351yang_read_enum(struct lys_module *module, struct yang_type *typ, struct lys_type_enum *enm, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001352{
Pavol Vican874715f2016-10-25 14:52:08 +02001353 int i, j;
Pavol Vican79a763d2016-02-25 15:41:27 +01001354
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01001355 typ->base = LY_TYPE_ENUM;
Pavol Vicanc6662412016-08-30 08:06:28 +02001356 if (!value[0]) {
1357 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1358 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1359 free(value);
1360 goto error;
1361 }
1362
Pavol Vican79a763d2016-02-25 15:41:27 +01001363 enm->name = lydict_insert_zc(module->ctx, value);
1364
1365 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1366 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001367 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001368 goto error;
1369 }
1370
Pavol Vican874715f2016-10-25 14:52:08 +02001371 j = typ->type->info.enums.count - 1;
Pavol Vican79a763d2016-02-25 15:41:27 +01001372 /* check the name uniqueness */
Pavol Vican874715f2016-10-25 14:52:08 +02001373 for (i = 0; i < j; i++) {
1374 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[j].name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001375 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001376 goto error;
1377 }
1378 }
1379
Pavol Vican874715f2016-10-25 14:52:08 +02001380 return EXIT_SUCCESS;
Pavol Vican79a763d2016-02-25 15:41:27 +01001381
1382error:
Pavol Vican874715f2016-10-25 14:52:08 +02001383 return EXIT_FAILURE;
Pavol Vican79a763d2016-02-25 15:41:27 +01001384}
1385
1386int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001387yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001388{
1389 int i, j;
1390
1391 if (!assign) {
1392 /* assign value automatically */
1393 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001394 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001395 goto error;
1396 }
1397 enm->value = *value;
1398 enm->flags |= LYS_AUTOASSIGNED;
1399 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001400 } else if (typ->type->info.enums.enm == enm) {
1401 /* change value, which is assigned automatically, if first enum has value. */
1402 *value = typ->type->info.enums.enm[0].value;
1403 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001404 }
1405
1406 /* check that the value is unique */
1407 j = typ->type->info.enums.count-1;
1408 for (i = 0; i < j; i++) {
1409 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001410 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001411 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1412 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001413 goto error;
1414 }
1415 }
1416
1417 return EXIT_SUCCESS;
1418
1419error:
1420 return EXIT_FAILURE;
1421}
Pavol Vican9887c682016-02-29 11:32:01 +01001422
Pavol Vican59e8dee2016-10-25 15:29:38 +02001423int
1424yang_read_bit(struct lys_module *module, struct yang_type *typ, struct lys_type_bit *bit, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001425{
Pavol Vican59e8dee2016-10-25 15:29:38 +02001426 int i, j;
Pavol Vican9887c682016-02-29 11:32:01 +01001427
Pavol Vican59e8dee2016-10-25 15:29:38 +02001428 bit->name = lydict_insert_zc(module->ctx, value);
1429 if (lyp_check_identifier(bit->name, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001430 free(value);
1431 goto error;
1432 }
Pavol Vican9887c682016-02-29 11:32:01 +01001433
Pavol Vican59e8dee2016-10-25 15:29:38 +02001434 j = typ->type->info.bits.count - 1;
Pavol Vican9887c682016-02-29 11:32:01 +01001435 /* check the name uniqueness */
Pavol Vican59e8dee2016-10-25 15:29:38 +02001436 for (i = 0; i < j; i++) {
Pavol Vican9887c682016-02-29 11:32:01 +01001437 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001438 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001439 goto error;
1440 }
1441 }
Pavol Vican59e8dee2016-10-25 15:29:38 +02001442 return EXIT_SUCCESS;
Pavol Vican9887c682016-02-29 11:32:01 +01001443
1444error:
Pavol Vican59e8dee2016-10-25 15:29:38 +02001445 return EXIT_FAILURE;
Pavol Vican9887c682016-02-29 11:32:01 +01001446}
1447
1448int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001449yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001450{
1451 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001452
1453 if (!assign) {
1454 /* assign value automatically */
1455 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001456 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001457 goto error;
1458 }
1459 bit->pos = (uint32_t)*value;
1460 bit->flags |= LYS_AUTOASSIGNED;
1461 (*value)++;
1462 }
1463
1464 j = typ->type->info.bits.count - 1;
1465 /* check that the value is unique */
1466 for (i = 0; i < j; i++) {
1467 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001468 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL, bit->pos, bit->name, typ->type->info.bits.bit[i].name);
Pavol Vican9887c682016-02-29 11:32:01 +01001469 goto error;
1470 }
1471 }
1472
Pavol Vican9887c682016-02-29 11:32:01 +01001473 return EXIT_SUCCESS;
1474
1475error:
1476 return EXIT_FAILURE;
1477}
Pavol Vican0df02b02016-03-01 10:28:50 +01001478
1479void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001480yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001481{
1482 struct lys_refine *rfn;
1483
1484 rfn = &uses->refine[uses->refine_size];
1485 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001486 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001487 free(value);
1488 if (!rfn->target_name) {
1489 return NULL;
1490 }
1491 return rfn;
1492}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001493
1494void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001495yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001496{
1497 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001498
1499 if (parent) {
1500 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1501 } else {
1502 aug = &module->augment[module->augment_size];
1503 }
1504 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001505 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001506 free(value);
1507 if (!aug->target_name) {
1508 return NULL;
1509 }
1510 aug->parent = parent;
1511 aug->module = module;
1512 if (parent) {
1513 ((struct lys_node_uses *)parent)->augment_size++;
1514 } else {
1515 module->augment_size++;
1516 }
1517 return aug;
1518}
Pavol Vican220e5a12016-03-03 14:19:43 +01001519
1520void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001521yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001522{
1523 struct lys_node *dev_target = NULL;
1524 struct lys_deviation *dev;
1525 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001526 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001527
Pavol Vican220e5a12016-03-03 14:19:43 +01001528 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001529 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001530 free(value);
1531 if (!dev->target_name) {
1532 goto error;
1533 }
1534
Pavol Vican974377b2016-03-23 00:38:53 +01001535 deviation = calloc(1, sizeof *deviation);
1536 if (!deviation) {
1537 LOGMEM;
1538 goto error;
1539 }
1540
Pavol Vican220e5a12016-03-03 14:19:43 +01001541 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01001542 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Pavol Vican220e5a12016-03-03 14:19:43 +01001543 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001544 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001545 goto error;
1546 }
Radek Krejcic4283442016-04-22 09:19:27 +02001547 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001548 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1549 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001550 goto error;
1551 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001552
Pavol Vican220e5a12016-03-03 14:19:43 +01001553 /*save pointer to the deviation and deviated target*/
1554 deviation->deviation = dev;
1555 deviation->target = dev_target;
1556
Pavol Vican38321d02016-08-16 14:56:02 +02001557 deviation->dflt_check = ly_set_new();
1558 if (!deviation->dflt_check) {
1559 LOGMEM;
1560 goto error;
1561 }
1562
Pavol Vican220e5a12016-03-03 14:19:43 +01001563 return deviation;
1564
1565error:
1566 free(deviation);
1567 lydict_remove(module->ctx, dev->target_name);
1568 return NULL;
1569}
Pavol Vican4c90c642016-03-03 15:06:47 +01001570
1571int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001572yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001573{
1574 int i;
1575
1576 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001577 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001578 return EXIT_FAILURE;
1579 }
1580 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1581
1582 /* you cannot remove a key leaf */
1583 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1584 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1585 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001586 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1587 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001588 return EXIT_FAILURE;
1589 }
1590 }
1591 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001592
Pavol Vican4c90c642016-03-03 15:06:47 +01001593 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001594 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001595 dev->deviation->orig_node = dev->target;
1596
1597 dev->deviation->deviate_size = 1;
1598 return EXIT_SUCCESS;
1599}
Pavol Vican85f12022016-03-05 16:30:35 +01001600
1601int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001602yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001603{
1604 struct unres_schema tmp_unres;
1605
1606 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1607 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1608 dev->deviation->deviate_size++;
Pavol Vican33884462016-09-27 21:04:26 +02001609 dev->trg_must_size = NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001610 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001611 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1612 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001613 return EXIT_FAILURE;
1614 }
1615
1616 /* store a shallow copy of the original node */
1617 if (!dev->deviation->orig_node) {
1618 memset(&tmp_unres, 0, sizeof tmp_unres);
Michal Vaskoe022a562016-09-27 14:24:15 +02001619 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, &tmp_unres, 1);
Pavol Vican85f12022016-03-05 16:30:35 +01001620 /* just to be safe */
1621 if (tmp_unres.count) {
1622 LOGINT;
1623 return EXIT_FAILURE;
1624 }
1625 }
1626
1627 return EXIT_SUCCESS;
1628}
1629
1630int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001631yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001632{
1633 const char **stritem;
1634
1635 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001636 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001637 free(value);
1638 goto error;
1639 }
1640
1641 /* check target node type */
1642 if (dev->target->nodetype == LYS_LEAFLIST) {
1643 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1644 } else if (dev->target->nodetype == LYS_LEAF) {
1645 stritem = &((struct lys_node_leaf *)dev->target)->units;
1646 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001647 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1648 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001649 free(value);
1650 goto error;
1651 }
1652
1653 dev->deviate->units = lydict_insert_zc(ctx, value);
1654
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001655 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1656 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001657 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001658 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1659 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001660 goto error;
1661 }
1662 /* remove current units value of the target */
1663 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001664 } else {
1665 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1666 /* check that there is no current value */
1667 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001668 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1669 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001670 goto error;
1671 }
1672 } else { /* replace */
1673 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001674 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1675 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001676 goto error;
1677 }
1678 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001679 /* remove current units value of the target ... */
1680 lydict_remove(ctx, *stritem);
1681
1682 /* ... and replace it with the value specified in deviation */
1683 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1684 }
1685
Pavol Vican85f12022016-03-05 16:30:35 +01001686 return EXIT_SUCCESS;
1687
1688error:
1689 return EXIT_FAILURE;
1690}
1691
1692int
Pavol Vican974377b2016-03-23 00:38:53 +01001693yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001694{
Pavol Vican85f12022016-03-05 16:30:35 +01001695 /* check target node type */
1696 switch (dev->target->nodetype) {
1697 case LYS_LEAF:
1698 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1699 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1700 break;
1701 case LYS_CONTAINER:
1702 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1703 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1704 break;
1705 case LYS_LEAFLIST:
1706 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1707 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1708 break;
1709 case LYS_LIST:
1710 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1711 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1712 break;
1713 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001714 case LYS_ANYDATA:
1715 dev->trg_must = &((struct lys_node_anydata *)dev->target)->must;
1716 dev->trg_must_size = &((struct lys_node_anydata *)dev->target)->must_size;
Pavol Vican85f12022016-03-05 16:30:35 +01001717 break;
1718 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001719 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1720 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001721 goto error;
1722 }
1723
Michal Vasko508a50d2016-09-07 14:50:33 +02001724 /* flag will be checked again, clear it for now */
Michal Vaskoe9914d12016-10-07 14:32:37 +02001725 dev->target->flags &= ~LYS_VALID_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02001726
Pavol Vican85f12022016-03-05 16:30:35 +01001727 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1728 /* reallocate the must array of the target */
1729 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1730 if (!dev->deviate->must) {
1731 LOGMEM;
1732 goto error;
1733 }
1734 *dev->trg_must = dev->deviate->must;
1735 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1736 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001737 } else {
1738 /* LY_DEVIATE_DEL */
1739 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1740 if (!dev->deviate->must) {
1741 LOGMEM;
1742 goto error;
1743 }
Pavol Vican85f12022016-03-05 16:30:35 +01001744 }
1745
1746 return EXIT_SUCCESS;
1747
1748error:
1749 return EXIT_FAILURE;
1750}
1751
1752int
Pavol Vican974377b2016-03-23 00:38:53 +01001753yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001754{
Pavol Vican85f12022016-03-05 16:30:35 +01001755 struct lys_node_list *list;
1756
1757 /* check target node type */
1758 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001759 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1760 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001761 goto error;
1762 }
1763
1764 list = (struct lys_node_list *)dev->target;
1765 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1766 /* reallocate the unique array of the target */
1767 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1768 if (!dev->deviate->unique) {
1769 LOGMEM;
1770 goto error;
1771 }
1772 list->unique = dev->deviate->unique;
1773 dev->deviate->unique = &list->unique[list->unique_size];
1774 dev->deviate->unique_size = c_uniq;
1775 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001776 } else {
1777 /* LY_DEVIATE_DEL */
1778 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1779 if (!dev->deviate->unique) {
1780 LOGMEM;
1781 goto error;
1782 }
Pavol Vican85f12022016-03-05 16:30:35 +01001783 }
1784
1785 return EXIT_SUCCESS;
1786
1787error:
1788 return EXIT_FAILURE;
1789}
1790
1791int
Pavol Vican38321d02016-08-16 14:56:02 +02001792yang_read_deviate_default(struct lys_module *module, struct type_deviation *dev, uint8_t c_dflt)
Pavol Vican85f12022016-03-05 16:30:35 +01001793{
Pavol Vican38321d02016-08-16 14:56:02 +02001794 int i;
1795 struct lys_node_leaflist *llist;
Pavol Vican85f12022016-03-05 16:30:35 +01001796
Pavol Vican38321d02016-08-16 14:56:02 +02001797 /* check target node type */
1798 if (module->version < 2 && dev->target->nodetype == LYS_LEAFLIST) {
1799 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1800 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1801 goto error;
1802 } else if (c_dflt > 1 && dev->target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1803 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1804 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1805 goto error;
1806 } else if (!(dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
1807 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1808 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001809 goto error;
1810 }
1811
Pavol Vican38321d02016-08-16 14:56:02 +02001812 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1813 /* check that there is no current value */
1814 if ((dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) ||
1815 (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt)) {
1816 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1817 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001818 goto error;
1819 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001820
Pavol Vican38321d02016-08-16 14:56:02 +02001821 /* check collision with mandatory/min-elements */
1822 if ((dev->target->flags & LYS_MAND_TRUE) ||
1823 (dev->target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev->target)->min)) {
1824 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
1825 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1826 "Adding the \"default\" statement is forbidden on %s statement.",
1827 (dev->target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
1828 goto error;
Pavol Vican85f12022016-03-05 16:30:35 +01001829 }
Pavol Vican38321d02016-08-16 14:56:02 +02001830 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1831 /* check that there was a value before */
1832 if (((dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev->target)->dflt) ||
1833 (dev->target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev->target)->dflt)) {
1834 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1835 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
1836 goto error;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001837 }
Pavol Vican38321d02016-08-16 14:56:02 +02001838 }
1839
1840 if (dev->target->nodetype == LYS_LEAFLIST) {
1841 /* reallocate default list in the target */
1842 llist = (struct lys_node_leaflist *)dev->target;
1843 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1844 /* reallocate (enlarge) the unique array of the target */
1845 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *dev->deviate->dflt);
1846 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1847 /* reallocate (replace) the unique array of the target */
1848 for (i = 0; i < llist->dflt_size; i++) {
1849 lydict_remove(llist->module->ctx, llist->dflt[i]);
1850 }
1851 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *dev->deviate->dflt);
1852 llist->dflt_size = 0;
1853 }
1854 }
1855
1856 dev->deviate->dflt = calloc(c_dflt, sizeof *dev->deviate->dflt);
1857 if (!dev->deviate->dflt) {
1858 LOGMEM;
Pavol Vican85f12022016-03-05 16:30:35 +01001859 goto error;
1860 }
1861
1862 return EXIT_SUCCESS;
1863
1864error:
1865 return EXIT_FAILURE;
1866}
1867
1868int
Pavol Vican38321d02016-08-16 14:56:02 +02001869yang_fill_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *exp)
1870{
1871 struct lys_node *node;
1872 struct lys_node_choice *choice;
1873 struct lys_node_leaf *leaf;
1874 struct lys_node_leaflist *llist;
1875 int rc, i;
1876 unsigned int u;
1877 const char *value;
1878
1879 value = lydict_insert_zc(ctx, exp);
1880 u = strlen(value);
1881 dev->deviate->dflt[dev->deviate->dflt_size++] = value;
1882
1883 if (dev->target->nodetype == LYS_CHOICE) {
1884 choice = (struct lys_node_choice *)dev->target;
1885 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
1886 if (rc || !node) {
1887 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1888 goto error;
1889 }
1890 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1891 if (!choice->dflt || (choice->dflt != node)) {
1892 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1893 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1894 goto error;
1895 }
1896 } else { /* add or replace */
1897 choice->dflt = node;
1898 if (!choice->dflt) {
1899 /* default branch not found */
1900 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1901 goto error;
1902 }
1903 }
1904 } else if (dev->target->nodetype == LYS_LEAF) {
1905 leaf = (struct lys_node_leaf *)dev->target;
1906 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1907 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
1908 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1909 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1910 goto error;
1911 }
1912 /* remove value */
1913 lydict_remove(ctx, leaf->dflt);
1914 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01001915 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001916 } else { /* add (already checked) and replace */
1917 /* remove value */
1918 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01001919 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001920
1921 /* set new value */
1922 leaf->dflt = lydict_insert(ctx, value, u);
1923
1924 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1925 ly_set_add(dev->dflt_check, dev->target, 0);
1926 }
1927 } else { /* LYS_LEAFLIST */
1928 llist = (struct lys_node_leaflist *)dev->target;
1929 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1930 /* find and remove the value in target list */
1931 for (i = 0; i < llist->dflt_size; i++) {
1932 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
1933 /* match, remove the value */
1934 lydict_remove(llist->module->ctx, llist->dflt[i]);
1935 llist->dflt[i] = NULL;
1936 break;
1937 }
1938 }
1939 if (i == llist->dflt_size) {
1940 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1941 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
1942 goto error;
1943 }
1944 } else {
1945 /* add or replace, anyway we place items into the deviate's list
1946 which propagates to the target */
1947 /* we just want to check that the value isn't already in the list */
1948 for (i = 0; i < llist->dflt_size; i++) {
1949 if (ly_strequal(llist->dflt[i], value, 1)) {
1950 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1951 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
1952 goto error;
1953 }
1954 }
1955 /* store it in target node */
1956 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
1957
1958 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1959 ly_set_add(dev->dflt_check, dev->target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01001960 llist->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001961 }
1962 }
1963
1964 return EXIT_SUCCESS;
1965error:
1966 return EXIT_FAILURE;
1967}
1968
1969
1970int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001971yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001972{
1973 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001974 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001975 goto error;
1976 }
1977
1978 /* for we deviate from RFC 6020 and allow config property even it is/is not
1979 * specified in the target explicitly since config property inherits. So we expect
1980 * that config is specified in every node. But for delete, we check that the value
1981 * is the same as here in deviation
1982 */
1983 dev->deviate->flags |= value;
1984
1985 /* add and replace are the same in this case */
1986 /* remove current config value of the target ... */
1987 dev->target->flags &= ~LYS_CONFIG_MASK;
1988
1989 /* ... and replace it with the value specified in deviation */
1990 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1991
1992 return EXIT_SUCCESS;
1993
1994error:
1995 return EXIT_FAILURE;
1996}
1997
1998int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001999yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002000{
Radek Krejcie00d2312016-08-12 15:27:49 +02002001 struct lys_node *parent;
2002
Pavol Vican85f12022016-03-05 16:30:35 +01002003 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002004 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002005 goto error;
2006 }
2007
2008 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002009 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002010 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2011 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002012 goto error;
2013 }
2014
2015 dev->deviate->flags |= value;
2016
2017 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2018 /* check that there is no current value */
2019 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002020 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2021 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002022 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02002023 } else {
2024 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
2025 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2026 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
2027 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2028 goto error;
2029 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
2030 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
2031 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
2032 goto error;
2033 }
Pavol Vican85f12022016-03-05 16:30:35 +01002034 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002035 } else { /* replace */
2036 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002037 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2038 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002039 goto error;
2040 }
Pavol Vican85f12022016-03-05 16:30:35 +01002041 }
2042
Pavol Vican85f12022016-03-05 16:30:35 +01002043 /* remove current mandatory value of the target ... */
2044 dev->target->flags &= ~LYS_MAND_MASK;
2045
2046 /* ... and replace it with the value specified in deviation */
2047 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2048
Radek Krejcie00d2312016-08-12 15:27:49 +02002049 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2050 for (parent = dev->target->parent;
2051 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2052 parent = parent->parent) {
2053 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2054 /* stop also on presence containers */
2055 break;
2056 }
2057 }
2058 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2059 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2060 if (lyp_check_mandatory_choice(parent)) {
2061 goto error;
2062 }
2063 }
2064
Pavol Vican85f12022016-03-05 16:30:35 +01002065 return EXIT_SUCCESS;
2066
2067error:
2068 return EXIT_FAILURE;
2069}
2070
2071int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002072yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002073{
Pavol Vican09adcc32016-08-25 10:51:36 +02002074 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01002075
2076 /* check target node type */
2077 if (dev->target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002078 max = &((struct lys_node_leaflist *)dev->target)->max;
2079 min = &((struct lys_node_leaflist *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002080 } else if (dev->target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002081 max = &((struct lys_node_list *)dev->target)->max;
2082 min = &((struct lys_node_list *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002083 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002084 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2085 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", (type) ? "max-elements" : "min-elements");
Pavol Vican85f12022016-03-05 16:30:35 +01002086 goto error;
2087 }
2088
2089 if (type) {
2090 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002091 dev->deviate->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002092 ui32val = max;
Pavol Vican85f12022016-03-05 16:30:35 +01002093 } else {
2094 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002095 dev->deviate->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002096 ui32val = min;
Pavol Vican85f12022016-03-05 16:30:35 +01002097 }
2098
2099 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2100 /* check that there is no current value */
2101 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002102 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2103 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002104 goto error;
2105 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002106 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2107 /* unfortunately, there is no way to check reliably that there
2108 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002109 }
2110
2111 /* add (already checked) and replace */
2112 /* set new value specified in deviation */
2113 *ui32val = value;
2114
Pavol Vican09adcc32016-08-25 10:51:36 +02002115 /* check min-elements is smaller than max-elements */
2116 if (*max && *min > *max) {
2117 if (type) {
2118 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
2119 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2120 } else {
2121 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
2122 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2123 }
2124 goto error;
2125 }
2126
Pavol Vican85f12022016-03-05 16:30:35 +01002127 return EXIT_SUCCESS;
2128
2129error:
2130 return EXIT_FAILURE;
2131}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002132
2133int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002134yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002135{
2136 int i;
2137
2138 /* find must to delete, we are ok with just matching conditions */
2139 for (i = 0; i < *dev->trg_must_size; i++) {
2140 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2141 /* we have a match, free the must structure ... */
2142 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2143 /* ... and maintain the array */
2144 (*dev->trg_must_size)--;
2145 if (i != *dev->trg_must_size) {
2146 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2147 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2148 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2149 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2150 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2151 }
2152 if (!(*dev->trg_must_size)) {
2153 free(*dev->trg_must);
2154 *dev->trg_must = NULL;
2155 } else {
2156 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2157 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2158 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2159 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2160 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2161 }
2162
2163 i = -1; /* set match flag */
2164 break;
2165 }
2166 }
2167 if (i != -1) {
2168 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002169 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2170 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002171 return EXIT_FAILURE;
2172 }
2173
2174 return EXIT_SUCCESS;
2175}
2176
2177int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002178yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002179{
2180 struct lys_node_list *list;
2181 int i, j;
2182
2183 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002184 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002185 dev->deviate->unique_size++;
2186 goto error;
2187 }
2188
2189 /* find unique structures to delete */
2190 for (i = 0; i < list->unique_size; i++) {
2191 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2192 continue;
2193 }
2194
2195 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2196 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2197 break;
2198 }
2199 }
2200
2201 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2202 /* we have a match, free the unique structure ... */
2203 for (j = 0; j < list->unique[i].expr_size; j++) {
2204 lydict_remove(module->ctx, list->unique[i].expr[j]);
2205 }
2206 free(list->unique[i].expr);
2207 /* ... and maintain the array */
2208 list->unique_size--;
2209 if (i != list->unique_size) {
2210 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2211 list->unique[i].expr = list->unique[list->unique_size].expr;
2212 }
2213
2214 if (!list->unique_size) {
2215 free(list->unique);
2216 list->unique = NULL;
2217 } else {
2218 list->unique[list->unique_size].expr_size = 0;
2219 list->unique[list->unique_size].expr = NULL;
2220 }
2221
2222 i = -1; /* set match flag */
2223 break;
2224 }
2225 }
2226 dev->deviate->unique_size++;
2227
2228 if (i != -1) {
2229 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002230 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2231 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002232 goto error;
2233 }
2234
2235 free(value);
2236 return EXIT_SUCCESS;
2237
2238error:
2239 free(value);
2240 return EXIT_FAILURE;
2241}
Pavol Vicane92421d2016-03-08 10:12:33 +01002242
2243int
Pavol Vican38321d02016-08-16 14:56:02 +02002244yang_check_deviation(struct lys_module *module, struct ly_set *dflt_check, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002245{
2246 int i, rc;
Pavol Vican38321d02016-08-16 14:56:02 +02002247 unsigned int u;
2248 const char *value, *target_name;
2249 struct lys_node_leaflist *llist;
2250 struct lys_node_leaf *leaf;
Pavol Vicane92421d2016-03-08 10:12:33 +01002251
Pavol Vican38321d02016-08-16 14:56:02 +02002252 /* now check whether default value, if any, matches the type */
2253 for (u = 0; u < dflt_check->number; ++u) {
2254 value = NULL;
2255 rc = EXIT_SUCCESS;
2256 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2257 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2258 target_name = leaf->name;
Radek Krejci51673202016-11-01 17:00:32 +01002259 value = leaf->dflt;
2260 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Pavol Vican38321d02016-08-16 14:56:02 +02002261 } else { /* LYS_LEAFLIST */
2262 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2263 target_name = llist->name;
2264 for (i = 0; i < llist->dflt_size; i++) {
Radek Krejci51673202016-11-01 17:00:32 +01002265 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2266 (struct lys_node *)(&llist->dflt[i]));
Pavol Vican38321d02016-08-16 14:56:02 +02002267 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002268 value = llist->dflt[i];
Pavol Vicane92421d2016-03-08 10:12:33 +01002269 break;
2270 }
2271 }
2272 }
Pavol Vican38321d02016-08-16 14:56:02 +02002273 if (rc == -1) {
2274 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2275 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2276 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2277 target_name);
2278 return EXIT_FAILURE;
2279 }
Pavol Vicane92421d2016-03-08 10:12:33 +01002280 }
Pavol Vican38321d02016-08-16 14:56:02 +02002281
Pavol Vicane92421d2016-03-08 10:12:33 +01002282 return EXIT_SUCCESS;
Pavol Vican38321d02016-08-16 14:56:02 +02002283
Pavol Vican9b89dda2016-03-09 15:36:55 +01002284}
2285
Pavol Vicanec423c92016-10-24 21:33:43 +02002286static int
2287yang_fill_include(struct lys_module *trg, char *value, struct lys_include *inc,
2288 struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002289{
Pavol Vicanec423c92016-10-24 21:33:43 +02002290 struct lys_submodule *submodule;
2291 struct lys_module *module;
Pavol Vican55870412016-03-10 12:36:21 +01002292 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002293 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002294 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002295
Pavol Vicanec423c92016-10-24 21:33:43 +02002296 str = lydict_insert_zc(trg->ctx, value);
2297 if (trg->version) {
2298 submodule = (struct lys_submodule *)trg;
2299 module = ((struct lys_submodule *)trg)->belongsto;
2300 } else {
2301 submodule = NULL;
2302 module = trg;
2303 }
Pavol Vicane024ab72016-07-27 14:27:43 +02002304 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002305 if (!rc) {
2306 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002307 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002308 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002309 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002310 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002311 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002312
Pavol Vicanec423c92016-10-24 21:33:43 +02002313 lydict_remove(trg->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002314 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002315}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002316
2317int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002318yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002319{
2320 char *prefix;
2321 char *identif;
2322 const char *ns = NULL;
2323 int i;
2324
Pavol Vicanf4717e62016-03-16 11:30:01 +01002325 /* check to the same pointer */
2326 if (data_node != actual) {
2327 return EXIT_SUCCESS;
2328 }
2329
Pavol Vicana302aa62016-03-17 10:45:35 +01002330 prefix = strdup(value);
2331 if (!prefix) {
2332 LOGMEM;
2333 goto error;
2334 }
2335 /* find prefix anf identificator*/
2336 identif = strchr(prefix, ':');
Pavol Vicanfbd02782016-08-29 11:14:45 +02002337 if (!identif) {
2338 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, prefix);
2339 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The extension must have prefix.");
2340 goto error;
2341 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002342 *identif = '\0';
2343 identif++;
2344
Pavol Vicanf4717e62016-03-16 11:30:01 +01002345 for(i = 0; i < module->imp_size; ++i) {
2346 if (!strcmp(module->imp[i].prefix, prefix)) {
2347 ns = module->imp[i].module->ns;
2348 break;
2349 }
2350 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002351 if (!ns && !strcmp(module->prefix, prefix)) {
2352 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2353 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002354 if (ns && !strcmp(ns, LY_NSNACM)) {
2355 if (!strcmp(identif, "default-deny-write")) {
2356 data_node->nacm |= LYS_NACM_DENYW;
2357 } else if (!strcmp(identif, "default-deny-all")) {
2358 data_node->nacm |= LYS_NACM_DENYA;
2359 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002360 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002361 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002362 }
2363 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002364 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002365 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002366
2367error:
2368 free(prefix);
2369 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002370}
2371
2372void
2373nacm_inherit(struct lys_module *module)
2374{
Pavol Vican10ffba52016-04-04 12:21:22 +02002375 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002376
2377 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002378 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002379 if (elem->parent) {
2380 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002381 case LYS_GROUPING:
2382 /* extension nacm not inherited*/
2383 break;
2384 case LYS_CHOICE:
2385 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002386 case LYS_ANYDATA:
Pavol Vican10ffba52016-04-04 12:21:22 +02002387 case LYS_USES:
2388 if (elem->parent->nodetype != LYS_GROUPING) {
2389 elem->nacm |= elem->parent->nacm;
2390 }
2391 break;
2392 case LYS_CONTAINER:
2393 case LYS_LIST:
2394 case LYS_CASE:
2395 case LYS_NOTIF:
2396 case LYS_RPC:
2397 case LYS_INPUT:
2398 case LYS_OUTPUT:
2399 case LYS_AUGMENT:
2400 elem->nacm |= elem->parent->nacm;
2401 break;
2402 case LYS_LEAF:
2403 case LYS_LEAFLIST:
2404 tmp_node = elem;
2405 tmp_child = elem->child;
2406 elem->child = NULL;
2407 default:
2408 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002409 }
2410 }
2411 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002412 if (tmp_node) {
2413 tmp_node->child = tmp_child;
2414 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002415 }
2416}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002417
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002418int
Pavol Vican1dac40c2016-09-28 11:39:26 +02002419store_flags(struct lys_node *node, uint8_t flags, int config_opt)
Pavol Vican4fb66c92016-03-17 10:32:27 +01002420{
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002421 struct lys_node *elem;
2422
Pavol Vican1dac40c2016-09-28 11:39:26 +02002423 node->flags |= (config_opt == CONFIG_IGNORE) ? flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET)): flags;
2424 if (config_opt == CONFIG_INHERIT_ENABLE) {
2425 if (!(node->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002426 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02002427 if (node->parent) {
2428 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002429 } else {
2430 /* default config is true */
2431 node->flags |= LYS_CONFIG_W;
2432 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002433 } else {
Pavol Vican1dac40c2016-09-28 11:39:26 +02002434 /* do we even care about config flags? */
2435 for (elem = node; elem && !(elem->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); elem = elem->parent);
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002436
Pavol Vican1dac40c2016-09-28 11:39:26 +02002437 if (!elem && (node->flags & LYS_CONFIG_W) && node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2438 LOGVAL(LYE_INARG, LY_VLOG_LYS, node, "true", "config");
2439 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "State nodes cannot have configuration nodes as children.");
2440 return EXIT_FAILURE;
2441 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002442 }
2443 }
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002444
2445 return EXIT_SUCCESS;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002446}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002447
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002448void
2449store_config_flag(struct lys_node *node, int config_opt)
2450{
2451 if (config_opt == CONFIG_IGNORE) {
2452 node->flags |= node->flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET));
2453 } else if (config_opt == CONFIG_INHERIT_ENABLE) {
2454 if (!(node->flags & LYS_CONFIG_MASK)) {
2455 /* get config flag from parent */
2456 if (node->parent) {
2457 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2458 } else {
2459 /* default config is true */
2460 node->flags |= LYS_CONFIG_W;
2461 }
2462 }
2463 }
2464}
2465
Pavol Vican9d50a772016-10-14 22:23:36 +02002466int
2467yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres,
2468 const char *data, unsigned int size_data, struct lys_node **node)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002469{
Pavol Vican9d50a772016-10-14 22:23:36 +02002470 unsigned int size;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002471 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002472 yyscan_t scanner = NULL;
Pavol Vican082afd02016-10-25 12:39:15 +02002473 int ret = EXIT_SUCCESS, remove_import = 1;
2474 struct lys_module *trg;
Pavol Vican1938d882016-04-10 13:36:31 +02002475
Pavol Vican9d50a772016-10-14 22:23:36 +02002476 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002477 yylex_init(&scanner);
2478 bp = yy_scan_buffer((char *)data, size, scanner);
2479 yy_switch_to_buffer(bp, scanner);
Pavol Vican082afd02016-10-25 12:39:15 +02002480 if (yyparse(scanner, NULL, module, submodule, unres, node, &remove_import)) {
2481 if (remove_import) {
2482 trg = (submodule) ? (struct lys_module *)submodule : module;
2483 yang_free_import(trg->ctx, trg->imp, 0, trg->imp_size);
2484 yang_free_include(trg->ctx, trg->inc, 0, trg->inc_size);
2485 trg->inc_size = 0;
2486 trg->imp_size = 0;
2487 }
Pavol Vican1938d882016-04-10 13:36:31 +02002488 ret = EXIT_FAILURE;
2489 }
2490 yy_delete_buffer(bp, scanner);
2491 yylex_destroy(scanner);
2492 return ret;
2493}
2494
Pavol Vican8e7110b2016-03-22 17:00:26 +01002495struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002496yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002497{
2498
Pavol Vican10ffba52016-04-04 12:21:22 +02002499 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002500 struct unres_schema *unres = NULL;
Pavol Vican9d50a772016-10-14 22:23:36 +02002501 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002502
2503 unres = calloc(1, sizeof *unres);
2504 if (!unres) {
2505 LOGMEM;
2506 goto error;
2507 }
2508
2509 module = calloc(1, sizeof *module);
2510 if (!module) {
2511 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002512 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002513 }
2514
2515 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002516 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002517 module->type = 0;
2518 module->implemented = (implement ? 1 : 0);
2519
Pavol Vican9d50a772016-10-14 22:23:36 +02002520 if (yang_parse_mem(module, NULL, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002521 free_yang_common(module, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002522 goto error;
2523 }
2524
2525 if (yang_check_sub_module(module, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002526 goto error;
2527 }
2528
2529 if (module && unres->count && resolve_unres_schema(module, unres)) {
2530 goto error;
2531 }
2532
2533 if (revision) {
2534 /* check revision of the parsed model */
2535 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2536 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2537 module->name, module->rev[0].date, revision);
2538 goto error;
2539 }
2540 }
2541
Pavol Vican10ffba52016-04-04 12:21:22 +02002542 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002543 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002544 goto error;
2545 }
2546
Pavol Vican10ffba52016-04-04 12:21:22 +02002547 if (module == tmp_module) {
2548 nacm_inherit(module);
2549 }
2550
Radek Krejci27fe55e2016-09-13 17:13:35 +02002551 if (module->deviation_size && !module->implemented) {
2552 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2553 /* deviations always causes target to be made implemented,
2554 * but augents and leafrefs not, so we have to apply them now */
2555 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002556 goto error;
2557 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002558 }
2559
Pavol Vican8e7110b2016-03-22 17:00:26 +01002560 unres_schema_free(NULL, &unres);
2561 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2562 return module;
2563
2564error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002565 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002566 unres_schema_free(module, &unres);
2567 if (!module || !module->name) {
2568 free(module);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01002569 if (ly_vecode != LYVE_SUBMODULE) {
2570 LOGERR(ly_errno, "Module parsing failed.");
2571 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002572 return NULL;
2573 }
2574
2575 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002576
2577 lys_sub_module_remove_devs_augs(module);
2578 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002579 return NULL;
2580}
2581
2582struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002583yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002584{
2585 struct lys_submodule *submodule;
Pavol Vican9d50a772016-10-14 22:23:36 +02002586 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002587
2588 submodule = calloc(1, sizeof *submodule);
2589 if (!submodule) {
2590 LOGMEM;
2591 goto error;
2592 }
2593
2594 submodule->ctx = module->ctx;
2595 submodule->type = 1;
2596 submodule->belongsto = module;
2597
Pavol Vican9d50a772016-10-14 22:23:36 +02002598 if (yang_parse_mem(module, submodule, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002599 free_yang_common((struct lys_module *)submodule, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002600 goto error;
2601 }
2602
2603 if (yang_check_sub_module((struct lys_module *)submodule, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002604 goto error;
2605 }
2606
Pavol Vican8e7110b2016-03-22 17:00:26 +01002607 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002608 return submodule;
2609
2610error:
2611 /* cleanup */
2612 unres_schema_free((struct lys_module *)submodule, &unres);
2613
2614 if (!submodule || !submodule->name) {
2615 free(submodule);
2616 LOGERR(ly_errno, "Submodule parsing failed.");
2617 return NULL;
2618 }
2619
2620 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2621
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002622 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2623 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002624 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002625 return NULL;
2626}
Pavol Vican8760bb72016-04-07 09:44:01 +02002627
2628static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002629read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2630{
2631 int k = 0, j;
2632
2633 while (in_index < size) {
2634 if (input[in_index] == ' ') {
2635 k++;
2636 } else if (input[in_index] == '\t') {
2637 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2638 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002639 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2640 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2641 k += 8;
2642 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002643 } else {
2644 break;
2645 }
2646 ++in_index;
2647 if (k >= indent) {
2648 for (j = k - indent; j > 0; --j) {
2649 output[*out_index] = ' ';
2650 ++(*out_index);
2651 }
2652 break;
2653 }
2654 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002655 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002656}
2657
2658char *
Pavol Vican3f598892016-09-28 15:41:07 +02002659yang_read_string(const char *input, char *output, int size, int offset, int indent, int version) {
2660 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002661
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002662 while (i < size) {
2663 switch (input[i]) {
2664 case '\n':
2665 out_index -= space;
2666 output[out_index] = '\n';
2667 space = 0;
2668 i = read_indent(input, indent, size, i + 1, &out_index, output);
2669 break;
2670 case ' ':
2671 case '\t':
2672 output[out_index] = input[i];
2673 ++space;
2674 break;
2675 case '\\':
2676 if (input[i + 1] == 'n') {
2677 out_index -= space;
2678 output[out_index] = '\n';
2679 space = 0;
2680 i = read_indent(input, indent, size, i + 2, &out_index, output);
2681 } else if (input[i + 1] == 't') {
2682 output[out_index] = '\t';
2683 ++i;
2684 ++space;
2685 } else if (input[i + 1] == '\\') {
2686 output[out_index] = '\\';
2687 ++i;
2688 } else if ((i + 1) != size && input[i + 1] == '"') {
2689 output[out_index] = '"';
2690 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002691 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002692 if (version < 2) {
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002693 output[out_index] = input[i];
Pavol Vican677b0132016-08-09 15:44:58 +02002694 } else {
2695 /* YANG 1.1 backslash must not be followed by any other character */
2696 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
Pavol Vican3f598892016-09-28 15:41:07 +02002697 return NULL;
Pavol Vican677b0132016-08-09 15:44:58 +02002698 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002699 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002700 break;
2701 default:
2702 output[out_index] = input[i];
2703 space = 0;
2704 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002705 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002706 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002707 ++out_index;
2708 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002709 output[out_index] = '\0';
2710 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002711 output = realloc(output, out_index + 1);
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002712 if (!output) {
2713 LOGMEM;
Pavol Vican3f598892016-09-28 15:41:07 +02002714 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002715 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002716 }
Pavol Vican3f598892016-09-28 15:41:07 +02002717 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002718}
Pavol Vican1cc4e192016-10-24 16:38:31 +02002719
2720/* free function */
2721
Pavol Vican7313fc02016-11-14 01:10:31 +01002722static void yang_type_free(struct ly_ctx *ctx, struct lys_type *type)
2723{
2724 struct yang_type *stype = (struct yang_type *)type->der;
2725 int i;
2726
2727 if (!stype) {
2728 return ;
2729 }
2730 lydict_remove(ctx, stype->name);
2731 type->base = stype->base;
2732 if (type->base == LY_TYPE_IDENT) {
2733 for (i = 0; i < type->info.ident.count; ++i) {
2734 free(type->info.ident.ref[i]);
2735 }
2736 }
2737 lys_type_free(ctx, type);
Pavol Vican36aff862016-11-26 17:07:05 +01002738 type->base = LY_TYPE_DER;
Pavol Vican7313fc02016-11-14 01:10:31 +01002739 free(stype);
2740}
2741
2742static void
2743yang_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf, uint8_t start, uint8_t size)
2744{
2745 uint8_t i;
2746
2747 assert(ctx);
2748 if (!tpdf) {
2749 return;
2750 }
2751
2752 for (i = start; i < size; ++i) {
Pavol Vicancee10802016-11-22 15:48:35 +01002753 lydict_remove(ctx, tpdf[i].name);
2754 lydict_remove(ctx, tpdf[i].dsc);
2755 lydict_remove(ctx, tpdf[i].ref);
Pavol Vican7313fc02016-11-14 01:10:31 +01002756
Pavol Vicancee10802016-11-22 15:48:35 +01002757 yang_type_free(ctx, &tpdf[i].type);
Pavol Vican7313fc02016-11-14 01:10:31 +01002758
Pavol Vicancee10802016-11-22 15:48:35 +01002759 lydict_remove(ctx, tpdf[i].units);
2760 lydict_remove(ctx, tpdf[i].dflt);
Pavol Vican7313fc02016-11-14 01:10:31 +01002761 }
2762}
2763
Pavol Vican1cc4e192016-10-24 16:38:31 +02002764static void
2765yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size)
2766{
2767 uint8_t i;
2768
2769 for (i = start; i < size; ++i){
2770 free((char *)imp[i].module);
2771 lydict_remove(ctx, imp[i].prefix);
2772 lydict_remove(ctx, imp[i].dsc);
2773 lydict_remove(ctx, imp[i].ref);
2774 }
2775}
2776
Pavol Vicanec423c92016-10-24 21:33:43 +02002777static void
2778yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size)
2779{
2780 uint8_t i;
2781
2782 for (i = start; i < size; ++i){
2783 free((char *)inc[i].submodule);
2784 lydict_remove(ctx, inc[i].dsc);
2785 lydict_remove(ctx, inc[i].ref);
2786 }
2787}
2788
Pavol Vican36e27272016-11-22 15:47:28 +01002789static void
2790yang_free_ident_base(struct lys_ident *ident, uint32_t start, uint32_t size)
2791{
2792 uint32_t i;
2793 uint8_t j;
2794
2795 /* free base name */
2796 for (i = start; i < size; ++i) {
2797 for (j = 0; j < ident[i].base_size; ++j) {
2798 free(ident[i].base[j]);
2799 }
2800 }
2801}
2802
Pavol Vican05810b62016-11-23 14:07:22 +01002803static void
2804yang_free_grouping(struct ly_ctx *ctx, struct lys_node_grp * grp)
2805{
2806 yang_tpdf_free(ctx, grp->tpdf, 0, grp->tpdf_size);
2807 free(grp->tpdf);
2808}
2809
2810static void
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002811yang_free_container(struct ly_ctx *ctx, struct lys_node_container * cont)
2812{
2813 uint8_t i;
2814
2815 yang_tpdf_free(ctx, cont->tpdf, 0, cont->tpdf_size);
2816 free(cont->tpdf);
2817 lydict_remove(ctx, cont->presence);
2818
2819 for (i = 0; cont->must_size; ++i) {
2820 lys_restr_free(ctx, &cont->must[i]);
2821 }
2822 free(cont->must);
2823
2824 lys_when_free(ctx, cont->when);
2825}
2826
2827static void
Pavol Vicana69aff22016-11-24 18:23:50 +01002828yang_free_leaf(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
2829{
2830 uint8_t i;
2831
2832 for (i = 0; i < leaf->must_size; i++) {
2833 lys_restr_free(ctx, &leaf->must[i]);
2834 }
2835 free(leaf->must);
2836
2837 lys_when_free(ctx, leaf->when);
2838
2839 yang_type_free(ctx, &leaf->type);
2840 lydict_remove(ctx, leaf->units);
2841 lydict_remove(ctx, leaf->dflt);
2842}
2843
2844static void
Pavol Vican36aff862016-11-26 17:07:05 +01002845yang_free_leaflist(struct ly_ctx *ctx, struct lys_node_leaflist *leaflist)
2846{
2847 uint8_t i;
2848
2849 for (i = 0; i < leaflist->must_size; i++) {
2850 lys_restr_free(ctx, &leaflist->must[i]);
2851 }
2852 free(leaflist->must);
2853
2854 for (i = 0; i < leaflist->dflt_size; i++) {
2855 lydict_remove(ctx, leaflist->dflt[i]);
2856 }
2857 free(leaflist->dflt);
2858
2859 lys_when_free(ctx, leaflist->when);
2860
2861 yang_type_free(ctx, &leaflist->type);
2862 lydict_remove(ctx, leaflist->units);
2863}
2864
2865static void
Pavol Vicand8136a42016-11-27 13:28:04 +01002866yang_free_list(struct ly_ctx *ctx, struct lys_node_list *list)
2867{
2868 uint8_t i;
2869
2870 yang_tpdf_free(ctx, list->tpdf, 0, list->tpdf_size);
2871 free(list->tpdf);
2872
2873 for (i = 0; i < list->must_size; ++i) {
2874 lys_restr_free(ctx, &list->must[i]);
2875 }
2876 free(list->must);
2877
2878 lys_when_free(ctx, list->when);
2879
2880 for (i = 0; i < list->unique_size; ++i) {
2881 free(list->unique[i].expr);
2882 }
2883 free(list->unique);
2884
2885 free(list->keys);
2886}
2887
2888static void
Pavol Vican36ace102016-11-28 11:46:59 +01002889yang_free_choice(struct ly_ctx *ctx, struct lys_node_choice *choice)
2890{
2891 free(choice->dflt);
2892 lys_when_free(ctx, choice->when);
2893}
2894
2895static void
Pavol Vican05810b62016-11-23 14:07:22 +01002896yang_free_nodes(struct ly_ctx *ctx, struct lys_node *node)
2897{
2898 struct lys_node *tmp, *child, *sibling;
2899
2900 if (!node) {
2901 return;
2902 }
2903 tmp = node;
Pavol Vican05810b62016-11-23 14:07:22 +01002904
2905 while (tmp) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01002906 child = tmp->child;
Pavol Vican05810b62016-11-23 14:07:22 +01002907 sibling = tmp->next;
2908 /* common part */
2909 lydict_remove(ctx, tmp->name);
2910 if (!(tmp->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01002911 lys_iffeature_free(tmp->iffeature, tmp->iffeature_size);
2912 lydict_remove(ctx, tmp->dsc);
2913 lydict_remove(ctx, tmp->ref);
Pavol Vican05810b62016-11-23 14:07:22 +01002914 }
2915
2916 switch (tmp->nodetype) {
2917 case LYS_GROUPING:
2918 yang_free_grouping(ctx, (struct lys_node_grp *)tmp);
2919 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002920 case LYS_CONTAINER:
2921 yang_free_container(ctx, (struct lys_node_container *)tmp);
2922 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01002923 case LYS_LEAF:
2924 yang_free_leaf(ctx, (struct lys_node_leaf *)tmp);
2925 break;
Pavol Vican36aff862016-11-26 17:07:05 +01002926 case LYS_LEAFLIST:
2927 yang_free_leaflist(ctx, (struct lys_node_leaflist *)tmp);
2928 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01002929 case LYS_LIST:
2930 yang_free_list(ctx, (struct lys_node_list *)tmp);
2931 break;
Pavol Vican36ace102016-11-28 11:46:59 +01002932 case LYS_CHOICE:
2933 yang_free_choice(ctx, (struct lys_node_choice *)tmp);
2934 break;
Pavol Vican05810b62016-11-23 14:07:22 +01002935 default:
2936 break;
2937 }
2938
2939 yang_free_nodes(ctx, child);
2940 free(tmp);
2941 tmp = sibling;
2942 }
2943}
2944
Pavol Vican7313fc02016-11-14 01:10:31 +01002945/* free common item from module and submodule */
2946static void
Pavol Vican05810b62016-11-23 14:07:22 +01002947free_yang_common(struct lys_module *module, struct lys_node *node)
Pavol Vican7313fc02016-11-14 01:10:31 +01002948{
2949 yang_tpdf_free(module->ctx, module->tpdf, 0, module->tpdf_size);
2950 module->tpdf_size = 0;
Pavol Vican36e27272016-11-22 15:47:28 +01002951 yang_free_ident_base(module->ident, 0, module->ident_size);
Pavol Vican05810b62016-11-23 14:07:22 +01002952 yang_free_nodes(module->ctx, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002953}
2954
Pavol Vican1cc4e192016-10-24 16:38:31 +02002955/* check function*/
2956
2957int
Pavol Vicanec423c92016-10-24 21:33:43 +02002958yang_check_imports(struct lys_module *module, struct unres_schema *unres)
Pavol Vican1cc4e192016-10-24 16:38:31 +02002959{
2960 struct lys_import *imp;
Pavol Vicanec423c92016-10-24 21:33:43 +02002961 struct lys_include *inc;
2962 uint8_t imp_size, inc_size, j = 0, i = 0;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002963 size_t size;
2964 char *s;
2965
2966 imp = module->imp;
2967 imp_size = module->imp_size;
Pavol Vicanec423c92016-10-24 21:33:43 +02002968 inc = module->inc;
2969 inc_size = module->inc_size;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002970
2971 if (imp_size) {
2972 size = (imp_size * sizeof *module->imp) + sizeof(void*);
2973 module->imp_size = 0;
2974 module->imp = calloc(1, size);
2975 if (!module->imp) {
2976 LOGMEM;
2977 goto error;
2978 }
2979 /* set stop block for possible realloc */
2980 module->imp[imp_size].module = (void*)0x1;
Pavol Vicanec423c92016-10-24 21:33:43 +02002981 }
Pavol Vican1cc4e192016-10-24 16:38:31 +02002982
Pavol Vicanec423c92016-10-24 21:33:43 +02002983 if (inc_size) {
2984 size = (inc_size * sizeof *module->inc) + sizeof(void*);
2985 module->inc_size = 0;
2986 module->inc = calloc(1, size);
2987 if (!module->inc) {
2988 LOGMEM;
2989 goto error;
2990 }
2991 /* set stop block for possible realloc */
2992 module->inc[inc_size].submodule = (void*)0x1;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002993 }
2994
2995 for (i = 0; i < imp_size; ++i) {
2996 s = (char *) imp[i].module;
2997 imp[i].module = NULL;
2998 if (yang_fill_import(module, &imp[i], &module->imp[module->imp_size], s)) {
2999 ++i;
3000 goto error;
3001 }
3002 }
Pavol Vicanec423c92016-10-24 21:33:43 +02003003 for (j = 0; j < inc_size; ++j) {
3004 s = (char *) inc[i].submodule;
3005 inc[i].submodule = NULL;
3006 if (yang_fill_include(module, s, &inc[i], unres)) {
3007 ++i;
3008 goto error;
3009 }
3010 }
3011 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003012 free(imp);
3013
3014 return EXIT_SUCCESS;
3015
3016error:
3017 yang_free_import(module->ctx, imp, i, imp_size);
Pavol Vicanec423c92016-10-24 21:33:43 +02003018 yang_free_include(module->ctx, inc, j, inc_size);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003019 free(imp);
Pavol Vicanec423c92016-10-24 21:33:43 +02003020 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003021 return EXIT_FAILURE;
3022}
Pavol Vican7313fc02016-11-14 01:10:31 +01003023
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003024static int
3025yang_check_type_iffeature(struct lys_module *module, struct unres_schema *unres, struct lys_type *type)
3026{
3027 uint i, j, size;
3028 uint8_t iffeature_size;
3029 LY_DATA_TYPE stype;
3030
3031 if (((struct yang_type *)type->der)->base == LY_TYPE_ENUM) {
3032 stype = LY_TYPE_ENUM;
3033 size = type->info.enums.count;
3034 } else if (((struct yang_type *)type->der)->base == LY_TYPE_BITS) {
3035 stype = LY_TYPE_ENUM;
3036 size = type->info.enums.count;
3037 } else {
3038 return EXIT_SUCCESS;
3039 }
3040
3041 for (i = 0; i < size; ++i) {
3042 if (stype == LY_TYPE_ENUM) {
3043 iffeature_size = type->info.enums.enm[i].iffeature_size;
3044 type->info.enums.enm[i].iffeature_size = 0;
3045 for (j = 0; j < iffeature_size; ++j) {
3046 if (yang_read_if_feature(module, &type->info.enums.enm[i], type->parent,
3047 (char *)type->info.enums.enm[i].iffeature[j].features, unres, ENUM_KEYWORD)) {
3048 goto error;
3049 }
3050 }
3051 } else {
3052 iffeature_size = type->info.bits.bit[i].iffeature_size;
3053 type->info.bits.bit[i].iffeature_size = 0;
3054 for (j = 0; j < iffeature_size; ++j) {
3055 if (yang_read_if_feature(module, &type->info.bits.bit[i], type->parent,
3056 (char *)type->info.bits.bit[i].iffeature[j].features, unres, BIT_KEYWORD)) {
3057 goto error;
3058 }
3059 }
3060 }
3061 }
3062
3063 return EXIT_SUCCESS;
3064error:
3065 return EXIT_FAILURE;
3066}
3067
Pavol Vican7313fc02016-11-14 01:10:31 +01003068int
3069yang_check_typedef(struct lys_module *module, struct lys_node *parent, struct unres_schema *unres)
3070{
3071 struct lys_tpdf *tpdf;
3072 uint8_t i, tpdf_size, *ptr_tpdf_size;
3073 int ret = EXIT_SUCCESS;
3074
3075 if (!parent) {
3076 tpdf = module->tpdf;
3077 ptr_tpdf_size = &module->tpdf_size;
Pavol Vican05810b62016-11-23 14:07:22 +01003078 } else {
3079 switch (parent->nodetype) {
3080 case LYS_GROUPING:
3081 tpdf = ((struct lys_node_grp *)parent)->tpdf;
3082 ptr_tpdf_size = &((struct lys_node_grp *)parent)->tpdf_size;
3083 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003084 case LYS_CONTAINER:
3085 tpdf = ((struct lys_node_container *)parent)->tpdf;
3086 ptr_tpdf_size = &((struct lys_node_container *)parent)->tpdf_size;
3087 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003088 case LYS_LIST:
3089 tpdf = ((struct lys_node_list *)parent)->tpdf;
3090 ptr_tpdf_size = &((struct lys_node_list *)parent)->tpdf_size;
3091 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003092 default:
3093 LOGINT;
3094 return EXIT_FAILURE;
3095 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003096 }
3097
3098 tpdf_size = *ptr_tpdf_size;
3099 *ptr_tpdf_size = 0;
3100
3101 for (i = 0; i < tpdf_size; ++i) {
3102 tpdf[i].type.parent = &tpdf[i];
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003103 if (yang_check_type_iffeature(module, unres, &tpdf[i].type)) {
3104 ret = EXIT_FAILURE;
3105 break;
3106 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003107 if (unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPE_DER_TPDF, parent) == -1) {
3108 ret = EXIT_FAILURE;
3109 break;
3110 }
3111
3112 /* check default value*/
3113 if (tpdf[i].dflt && unres_schema_add_str(module, unres, &tpdf[i].type, UNRES_TYPE_DFLT, tpdf[i].dflt) == -1) {
3114 ++i;
3115 ret = EXIT_FAILURE;
3116 break;
3117 }
3118 (*ptr_tpdf_size)++;
3119 }
3120 if (i < tpdf_size) {
3121 yang_tpdf_free(module->ctx, tpdf, i, tpdf_size);
3122 }
3123
3124 return ret;
3125}
3126
3127static int
Pavol Vican36e27272016-11-22 15:47:28 +01003128yang_check_identities(struct lys_module *module, struct unres_schema *unres)
3129{
3130 uint32_t i, size, base_size;
3131 uint8_t j;
3132
3133 size = module->ident_size;
3134 module->ident_size = 0;
3135 for (i = 0; i < size; ++i) {
3136 base_size = module->ident[i].base_size;
3137 module->ident[i].base_size = 0;
3138 for (j = 0; j < base_size; ++j) {
3139 if (yang_read_base(module, &module->ident[i], (char *)module->ident[i].base[j], unres)) {
3140 ++j;
3141 module->ident_size = size;
3142 goto error;
3143 }
3144 }
3145 module->ident_size++;
3146 }
3147
3148 return EXIT_SUCCESS;
3149
3150error:
3151 for (; j< module->ident[i].base_size; ++j) {
3152 free(module->ident[i].base[j]);
3153 }
3154 yang_free_ident_base(module->ident, i + 1, size);
3155 return EXIT_FAILURE;
3156}
3157
3158static int
Pavol Vican05810b62016-11-23 14:07:22 +01003159yang_check_grouping(struct lys_module *module, struct lys_node_grp *node, struct unres_schema *unres)
3160{
3161 uint8_t i, size;
3162
3163 if (yang_check_typedef(module, (struct lys_node *)node, unres)) {
3164 goto error;
3165 }
3166
3167 size = node->iffeature_size;
3168 node->iffeature_size = 0;
3169 for (i = 0; i < size; ++i) {
3170 if (yang_read_if_feature(module, node, NULL, (char *)node->iffeature[i].features, unres, GROUPING_KEYWORD)) {
3171 node->iffeature_size = size;
3172 goto error;
3173 }
3174 }
3175
3176 return EXIT_SUCCESS;
3177
3178error:
3179 return EXIT_FAILURE;
3180}
3181
3182static int
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003183yang_check_container(struct lys_module *module, struct lys_node_container *node, struct unres_schema *unres)
3184{
3185 uint8_t i, size;
3186
3187 if (yang_check_typedef(module, (struct lys_node *)node, unres)) {
3188 goto error;
3189 }
3190
3191 size = node->iffeature_size;
3192 node->iffeature_size = 0;
3193 for (i = 0; i < size; ++i) {
3194 if (yang_read_if_feature(module, node, NULL, (char *)node->iffeature[i].features, unres, CONTAINER_KEYWORD)) {
3195 node->iffeature_size = size;
3196 goto error;
3197 }
3198 }
3199
3200 /* check XPath dependencies */
3201 if ((node->when || node->must_size) && (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1)) {
3202 goto error;
3203 }
3204
3205 return EXIT_SUCCESS;
3206error:
3207 return EXIT_FAILURE;
3208}
3209
3210static int
Pavol Vicana69aff22016-11-24 18:23:50 +01003211yang_check_leaf(struct lys_module *module, struct lys_node_leaf *leaf, struct unres_schema *unres)
3212{
3213 uint8_t i, size;
3214
3215 if (yang_check_type_iffeature(module, unres, &leaf->type)) {
3216 yang_type_free(module->ctx, &leaf->type);
3217 goto error;
3218 }
3219
3220 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER_TPDF, (struct lys_node *)leaf) == -1) {
3221 yang_type_free(module->ctx, &leaf->type);
3222 goto error;
3223 }
3224
3225 if (leaf->dflt && unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)leaf->dflt) == -1) {
3226 goto error;
3227 }
3228
3229 size = leaf->iffeature_size;
3230 leaf->iffeature_size = 0;
3231 for (i = 0; i < size; ++i) {
3232 if (yang_read_if_feature(module, leaf, NULL, (char *)leaf->iffeature[i].features, unres, LEAF_KEYWORD)) {
3233 leaf->iffeature_size = size;
3234 goto error;
3235 }
3236 }
3237
3238 /* check XPath dependencies */
3239 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, leaf, UNRES_XPATH, NULL) == -1)) {
3240 goto error;
3241 }
3242
3243 return EXIT_SUCCESS;
3244error:
3245 return EXIT_FAILURE;
3246}
3247
3248static int
Pavol Vican36aff862016-11-26 17:07:05 +01003249yang_check_leaflist(struct lys_module *module, struct lys_node_leaflist *leaflist, struct unres_schema *unres)
3250{
3251 uint8_t i, size;
3252
3253 if (yang_check_type_iffeature(module, unres, &leaflist->type)) {
3254 yang_type_free(module->ctx, &leaflist->type);
3255 goto error;
3256 }
3257
3258 if (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DER_TPDF, (struct lys_node *)leaflist) == -1) {
3259 yang_type_free(module->ctx, &leaflist->type);
3260 goto error;
3261 }
3262
3263 /* check default value (if not defined, there still could be some restrictions
3264 * that need to be checked against a default value from a derived type) */
3265 for (i = 0; i < leaflist->dflt_size; ++i) {
3266 if (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaflist->dflt[i])) == -1) {
3267 goto error;
3268 }
3269 }
3270
3271 size = leaflist->iffeature_size;
3272 leaflist->iffeature_size = 0;
3273 for (i = 0; i < size; ++i) {
3274 if (yang_read_if_feature(module, leaflist, NULL, (char *)leaflist->iffeature[i].features, unres, LEAF_LIST_KEYWORD)) {
3275 leaflist->iffeature_size = size;
3276 goto error;
3277 }
3278 }
3279
3280 /* check XPath dependencies */
3281 if ((leaflist->when || leaflist->must_size) && (unres_schema_add_node(module, unres, leaflist, UNRES_XPATH, NULL) == -1)) {
3282 goto error;
3283 }
3284
3285 return EXIT_SUCCESS;
3286error:
3287 return EXIT_FAILURE;
3288}
3289
3290static int
Pavol Vicand8136a42016-11-27 13:28:04 +01003291yang_check_list(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
3292{
3293 uint8_t size, i;
3294
3295 if (yang_check_typedef(module, (struct lys_node *)list, unres)) {
3296 goto error;
3297 }
3298
3299 size = list->iffeature_size;
3300 list->iffeature_size = 0;
3301 for (i = 0; i < size; ++i) {
3302 if (yang_read_if_feature(module, list, NULL, (char *)list->iffeature[i].features, unres, LIST_KEYWORD)) {
3303 list->iffeature_size = size;
3304 goto error;
3305 }
3306 }
3307
3308 if (list->keys && yang_read_key(module, list, unres)) {
3309 goto error;
3310 }
3311
3312 if (yang_read_unique(module, list, unres)) {
3313 goto error;
3314 }
3315
3316 /* check XPath dependencies */
3317 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, list, UNRES_XPATH, NULL) == -1)) {
3318 goto error;
3319 }
3320
3321 return EXIT_SUCCESS;
3322error:
3323 return EXIT_FAILURE;
3324}
3325
3326static int
Pavol Vican36ace102016-11-28 11:46:59 +01003327yang_check_choice(struct lys_module *module, struct lys_node_choice *choice, struct unres_schema *unres)
3328{
3329 char *value;
3330 uint8_t size, i;
3331
3332 if (choice->dflt) {
3333 value = (char *)choice->dflt;
3334 choice->dflt = NULL;
3335 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
3336 free(value);
3337 goto error;
3338 }
3339 free(value);
3340 }
3341
3342 size = choice->iffeature_size;
3343 choice->iffeature_size = 0;
3344 for (i = 0; i < size; ++i) {
3345 if (yang_read_if_feature(module, choice, NULL, (char *)choice->iffeature[i].features, unres, CHOICE_KEYWORD)) {
3346 choice->iffeature_size = size;
3347 goto error;
3348 }
3349 }
3350
3351 /* check XPath dependencies */
3352 if ((choice->when) && (unres_schema_add_node(module, unres, choice, UNRES_XPATH, NULL) == -1)) {
3353 goto error;
3354 }
3355
3356 return EXIT_SUCCESS;
3357error:
3358 return EXIT_FAILURE;
3359}
3360
3361static int
Pavol Vican05810b62016-11-23 14:07:22 +01003362yang_check_nodes(struct lys_module *module, struct lys_node *nodes, struct unres_schema *unres)
3363{
3364 struct lys_node *node = nodes, *sibling, *child;
3365
3366 while (node) {
3367 sibling = node->next;
3368 child = node->child;
3369 node->next = NULL;
3370 node->child = NULL;
3371 node->prev = node;
3372
3373 if (lys_node_addchild(node->parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
3374 sibling = node;
3375 child = NULL;
3376 goto error;
3377 }
3378 switch (node->nodetype) {
3379 case LYS_GROUPING:
3380 if (yang_check_grouping(module, (struct lys_node_grp *)node, unres)) {
3381 goto error;
3382 }
3383 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003384 case LYS_CONTAINER:
3385 if (yang_check_container(module, (struct lys_node_container *)node, unres)) {
3386 goto error;
3387 }
3388 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01003389 case LYS_LEAF:
3390 if (yang_check_leaf(module, (struct lys_node_leaf *)node, unres)) {
3391 goto error;
3392 }
3393 break;
Pavol Vican36aff862016-11-26 17:07:05 +01003394 case LYS_LEAFLIST:
3395 if (yang_check_leaflist(module, (struct lys_node_leaflist *)node, unres)) {
3396 goto error;
3397 }
3398 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003399 case LYS_LIST:
3400 if (yang_check_list(module, (struct lys_node_list *)node, unres)) {
3401 goto error;
3402 }
3403 break;
Pavol Vican36ace102016-11-28 11:46:59 +01003404 case LYS_CHOICE:
3405 if (yang_check_choice(module, (struct lys_node_choice *)node, unres)) {
3406 goto error;
3407 }
3408 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003409 default:
3410 LOGINT;
3411 sibling = node;
3412 child = NULL;
3413 goto error;
3414 }
3415 if (yang_check_nodes(module, child, unres)) {
3416 child = NULL;
3417 goto error;
3418 }
3419 node = sibling;
3420 }
3421
3422 return EXIT_SUCCESS;
3423error:
3424 yang_free_nodes(module->ctx, sibling);
3425 yang_free_nodes(module->ctx, child);
3426 return EXIT_FAILURE;
3427}
3428
3429static int
Pavol Vican7313fc02016-11-14 01:10:31 +01003430yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node)
3431{
Pavol Vican05810b62016-11-23 14:07:22 +01003432 uint8_t i, j, size, erase_identities = 1, erase_nodes = 1;
Pavol Vican7a7916f2016-11-21 23:38:30 +01003433 struct lys_feature *feature; /* shortcut */
3434 char *s;
3435
Pavol Vican7313fc02016-11-14 01:10:31 +01003436 if (yang_check_typedef(module, NULL, unres)) {
3437 goto error;
3438 }
3439
Pavol Vican7a7916f2016-11-21 23:38:30 +01003440 /* check features */
3441 for (i = 0; i < module->features_size; ++i) {
3442 feature = &module->features[i];
3443 size = feature->iffeature_size;
3444 feature->iffeature_size = 0;
3445 for (j = 0; j < size; ++j) {
3446 s = (char *)feature->iffeature[j].features;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003447 if (yang_read_if_feature(module, feature, NULL, s, unres, FEATURE_KEYWORD)) {
Pavol Vican7a7916f2016-11-21 23:38:30 +01003448 goto error;
3449 }
3450 if (unres_schema_add_node(module, unres, feature, UNRES_FEATURE, NULL) == -1) {
3451 goto error;
3452 }
3453 }
3454 }
Pavol Vican36e27272016-11-22 15:47:28 +01003455 erase_identities = 0;
3456 if (yang_check_identities(module, unres)) {
3457 goto error;
3458 }
Pavol Vican05810b62016-11-23 14:07:22 +01003459 erase_nodes = 0;
3460 if (yang_check_nodes(module, node, unres)) {
3461 goto error;
3462 }
Pavol Vican7a7916f2016-11-21 23:38:30 +01003463
Pavol Vican7313fc02016-11-14 01:10:31 +01003464 return EXIT_SUCCESS;
3465error:
Pavol Vican36e27272016-11-22 15:47:28 +01003466 if (erase_identities) {
3467 yang_free_ident_base(module->ident, 0, module->ident_size);
3468 }
Pavol Vican05810b62016-11-23 14:07:22 +01003469 if (erase_nodes) {
3470 yang_free_nodes(module->ctx, node);
3471 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003472 return EXIT_FAILURE;
3473}