blob: a8ec395b384f8093586e9c51c83bbdfbfba55cfa [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);
PavolVican6f000922017-02-10 12:56:59 +010023static int yang_check_must(struct lys_module *module, struct lys_restr *must, uint size, struct unres_schema *unres);
Pavol Vican082afd02016-10-25 12:39:15 +020024static 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 +010025static int yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node);
Pavol Vican05810b62016-11-23 14:07:22 +010026static void free_yang_common(struct lys_module *module, struct lys_node *node);
Pavol Vican3ad50f82016-12-04 15:00:36 +010027static int yang_check_nodes(struct lys_module *module, struct lys_node *parent, struct lys_node *nodes,
Radek Krejci7212e0a2017-03-08 15:58:22 +010028 int options, struct unres_schema *unres);
PavolVican5334c892017-02-15 16:29:09 +010029static int yang_fill_ext_substm_index(struct lys_ext_instance_complex *ext, LY_STMT stmt, enum yytokentype keyword);
PavolVicanf3091bf2017-02-19 18:27:01 +010030static void yang_free_nodes(struct ly_ctx *ctx, struct lys_node *node);
Radek Krejci5138e9f2017-04-12 13:10:46 +020031void lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size,
32 void (*private_destructor)(const struct lys_node *node, void *priv));
Pavol Vican082afd02016-10-25 12:39:15 +020033
Michal Vaskofe7e5a72016-05-02 14:49:23 +020034static int
PavolVican196694c2017-01-27 10:33:09 +010035yang_check_string(struct lys_module *module, const char **target, char *what,
36 char *where, char *value, struct lys_node *node)
Pavol Vican2a064652016-02-02 22:54:34 +010037{
Pavol Vicanbf805472016-01-26 14:24:56 +010038 if (*target) {
PavolVican196694c2017-01-27 10:33:09 +010039 LOGVAL(LYE_TOOMANY, (node) ? LY_VLOG_LYS : LY_VLOG_NONE, node, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010040 free(value);
41 return 1;
42 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010043 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010044 return 0;
45 }
46}
47
Michal Vaskofe7e5a72016-05-02 14:49:23 +020048int
Pavol Vican5f0316a2016-04-05 21:21:11 +020049yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010050{
Pavol Vican6eb14e82016-02-03 12:27:13 +010051 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010052
53 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010054 case MODULE_KEYWORD:
55 module->name = lydict_insert_zc(module->ctx, value);
56 break;
57 case NAMESPACE_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +010058 ret = yang_check_string(module, &module->ns, "namespace", "module", value, NULL);
Pavol Vican2a064652016-02-02 22:54:34 +010059 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010060 case ORGANIZATION_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +010061 ret = yang_check_string(module, &module->org, "organization", "module", value, NULL);
Pavol Vican1ca072c2016-02-03 13:03:56 +010062 break;
63 case CONTACT_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +010064 ret = yang_check_string(module, &module->contact, "contact", "module", value, NULL);
Pavol Vican1ca072c2016-02-03 13:03:56 +010065 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +020066 default:
67 free(value);
68 LOGINT;
69 ret = EXIT_FAILURE;
70 break;
Pavol Vican2a064652016-02-02 22:54:34 +010071 }
72
Pavol Vican021488a2016-01-25 23:56:12 +010073 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010074}
75
Michal Vaskofe7e5a72016-05-02 14:49:23 +020076int
Pavol Vicand0b64c12016-07-15 09:56:19 +020077yang_check_version(struct lys_module *module, struct lys_submodule *submodule, char *value, int repeat)
78{
79 int ret = EXIT_SUCCESS;
80
81 if (repeat) {
Michal Vasko3767fb22016-07-21 12:10:57 +020082 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module");
83 ret = EXIT_FAILURE;
Pavol Vicand0b64c12016-07-15 09:56:19 +020084 } else {
85 if (!strcmp(value, "1")) {
86 if (submodule) {
87 if (module->version > 1) {
88 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
89 ret = EXIT_FAILURE;
90 }
Radek Krejci29eac3d2017-06-01 16:50:02 +020091 submodule->version = 1;
Pavol Vicand0b64c12016-07-15 09:56:19 +020092 } else {
93 module->version = 1;
94 }
95 } else if (!strcmp(value, "1.1")) {
96 if (submodule) {
97 if (module->version != 2) {
98 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
99 ret = EXIT_FAILURE;
100 }
Radek Krejci29eac3d2017-06-01 16:50:02 +0200101 submodule->version = 2;
Pavol Vicand0b64c12016-07-15 09:56:19 +0200102 } else {
103 module->version = 2;
104 }
105 } else {
106 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
107 ret = EXIT_FAILURE;
Michal Vasko3767fb22016-07-21 12:10:57 +0200108 }
Pavol Vicand0b64c12016-07-15 09:56:19 +0200109 }
110 free(value);
111 return ret;
112}
113
114int
Pavol Vicane024ab72016-07-27 14:27:43 +0200115yang_read_prefix(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +0100116{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100117 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100118
Pavol Vican1cc4e192016-10-24 16:38:31 +0200119 if (!imp && lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100120 free(value);
121 return EXIT_FAILURE;
122 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200123
124 if (imp) {
PavolVican196694c2017-01-27 10:33:09 +0100125 ret = yang_check_string(module, &imp->prefix, "prefix", "import", value, NULL);
Pavol Vicane024ab72016-07-27 14:27:43 +0200126 } else {
PavolVican196694c2017-01-27 10:33:09 +0100127 ret = yang_check_string(module, &module->prefix, "prefix", "module", value, NULL);
Pavol Vican2a064652016-02-02 22:54:34 +0100128 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100129
Pavol Vicanbf805472016-01-26 14:24:56 +0100130 return ret;
131}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100132
Pavol Vican1cc4e192016-10-24 16:38:31 +0200133static int
PavolVican7d0b5ab2017-02-01 13:06:53 +0100134yang_fill_import(struct lys_module *module, struct lys_import *imp_old, struct lys_import *imp_new,
135 char *value, struct unres_schema *unres)
Pavol Vican6eb14e82016-02-03 12:27:13 +0100136{
Pavol Vican0da132e2016-03-21 12:03:03 +0100137 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200138 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100139
Pavol Vican1cc4e192016-10-24 16:38:31 +0200140 if (!imp_old->prefix) {
Pavol Vicane024ab72016-07-27 14:27:43 +0200141 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "import");
Pavol Vican1cc4e192016-10-24 16:38:31 +0200142 goto error;
143 } else {
144 if (lyp_check_identifier(imp_old->prefix, LY_IDENT_PREFIX, module, NULL)) {
145 goto error;
146 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200147 }
Pavol Vican1cc4e192016-10-24 16:38:31 +0200148 memcpy(imp_new, imp_old, sizeof *imp_old);
Pavol Vican0da132e2016-03-21 12:03:03 +0100149 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican1cc4e192016-10-24 16:38:31 +0200150 rc = lyp_check_import(module, exp, imp_new);
Pavol Vican0da132e2016-03-21 12:03:03 +0100151 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200152 module->imp_size++;
PavolVican7d0b5ab2017-02-01 13:06:53 +0100153 if (rc || yang_check_ext_instance(module, &imp_new->ext, imp_new->ext_size, imp_new, unres)) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200154 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100155 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100156
Pavol Vican6eb14e82016-02-03 12:27:13 +0100157 return EXIT_SUCCESS;
Pavol Vican1cc4e192016-10-24 16:38:31 +0200158
159error:
160 free(value);
161 lydict_remove(module->ctx, imp_old->dsc);
162 lydict_remove(module->ctx, imp_old->ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +0200163 lys_extension_instances_free(module->ctx, imp_old->ext, imp_old->ext_size, NULL);
Pavol Vican1cc4e192016-10-24 16:38:31 +0200164 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100165}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100166
167int
PavolVican196694c2017-01-27 10:33:09 +0100168yang_read_description(struct lys_module *module, void *node, char *value, char *where, enum yytokentype type)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100169{
170 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100171 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100172
PavolVican196694c2017-01-27 10:33:09 +0100173 switch (type) {
174 case MODULE_KEYWORD:
175 ret = yang_check_string(module, &module->dsc, dsc, "module", value, NULL);
176 break;
177 case REVISION_KEYWORD:
178 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value, NULL);
179 break;
180 case IMPORT_KEYWORD:
181 ret = yang_check_string(module, &((struct lys_import *)node)->dsc, dsc, where, value, NULL);
182 break;
183 case INCLUDE_KEYWORD:
184 ret = yang_check_string(module, &((struct lys_include *)node)->dsc, dsc, where, value, NULL);
185 break;
186 case NODE_PRINT:
187 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value, node);
188 break;
189 default:
190 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value, NULL);
191 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +0100192 }
193 return ret;
194}
195
196int
PavolVican196694c2017-01-27 10:33:09 +0100197yang_read_reference(struct lys_module *module, void *node, char *value, char *where, enum yytokentype type)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100198{
199 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100200 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100201
PavolVican196694c2017-01-27 10:33:09 +0100202 switch (type) {
203 case MODULE_KEYWORD:
204 ret = yang_check_string(module, &module->ref, ref, "module", value, NULL);
205 break;
206 case REVISION_KEYWORD:
207 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value, NULL);
208 break;
209 case IMPORT_KEYWORD:
210 ret = yang_check_string(module, &((struct lys_import *)node)->ref, ref, where, value, NULL);
211 break;
212 case INCLUDE_KEYWORD:
213 ret = yang_check_string(module, &((struct lys_include *)node)->ref, ref, where, value, NULL);
214 break;
215 case NODE_PRINT:
216 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value, node);
217 break;
218 default:
219 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value, NULL);
220 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +0100221 }
222 return ret;
223}
Pavol Vicanbedff692016-02-03 14:29:17 +0100224
Pavol Vican1eeb1992016-02-09 11:10:45 +0100225int
Pavol Vicandf9a95c2016-12-02 23:34:51 +0100226yang_fill_iffeature(struct lys_module *module, struct lys_iffeature *iffeature, void *parent,
227 char *value, struct unres_schema *unres, int parent_is_feature)
Pavol Vicane1354e92016-02-09 14:02:09 +0100228{
229 const char *exp;
230 int ret;
231
Michal Vasko97b32be2016-07-25 10:59:53 +0200232 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
233 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
234 free(value);
235 return EXIT_FAILURE;
236 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100237
Michal Vasko56d082c2016-10-25 14:00:42 +0200238 if (!(exp = transform_iffeat_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100239 free(value);
240 return EXIT_FAILURE;
241 }
242 free(value);
243
Pavol Vicandf9a95c2016-12-02 23:34:51 +0100244 ret = resolve_iffeature_compile(iffeature, exp, (struct lys_node *)parent, parent_is_feature, unres);
Pavol Vicane1354e92016-02-09 14:02:09 +0100245 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100246
Pavol Vicandf9a95c2016-12-02 23:34:51 +0100247 return (ret) ? EXIT_FAILURE : EXIT_SUCCESS;
Pavol Vicane1354e92016-02-09 14:02:09 +0100248}
249
Pavol Vican4fb66c92016-03-17 10:32:27 +0100250int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100251yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100252{
253 const char *exp;
254
Pavol Vican0adf01d2016-03-22 12:29:33 +0100255 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100256 free(value);
257 if (!exp) {
258 return EXIT_FAILURE;
259 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200260
Pavol Vican0adf01d2016-03-22 12:29:33 +0100261 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100262 lydict_remove(module->ctx, exp);
263 return EXIT_FAILURE;
264 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100265
Pavol Vicanbbdef532016-02-09 14:52:12 +0100266 lydict_remove(module->ctx, exp);
267 return EXIT_SUCCESS;
268}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100269
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100270int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100271yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100272{
273 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100274
Pavol Vicandde090a2016-08-30 15:12:14 +0200275 if (message == ERROR_APP_TAG_KEYWORD) {
PavolVican196694c2017-01-27 10:33:09 +0100276 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value, NULL);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100277 } else {
PavolVican196694c2017-01-27 10:33:09 +0100278 ret = yang_check_string(module, &save->emsg, "error_message", what, value, NULL);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100279 }
280 return ret;
281}
Pavol Vicanb5687112016-02-09 22:35:59 +0100282
283int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100284yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100285{
286 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100287 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100288 free(value);
289 return EXIT_FAILURE;
290 } else {
291 cont->presence = lydict_insert_zc(module->ctx, value);
292 return EXIT_SUCCESS;
293 }
294}
295
Pavol Vican235dbd42016-02-10 10:34:19 +0100296void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200297yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100298{
299 struct lys_when *retval;
300
301 retval = calloc(1, sizeof *retval);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200302 LY_CHECK_ERR_RETURN(!retval, LOGMEM; free(value), NULL);
Pavol Vican0adf01d2016-03-22 12:29:33 +0100303 retval->cond = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200304 if (!retval->cond) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100305 goto error;
306 }
307 switch (type) {
308 case CONTAINER_KEYWORD:
309 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100310 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100311 goto error;
312 }
313 ((struct lys_node_container *)node)->when = retval;
314 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200315 case ANYDATA_KEYWORD:
Pavol Vican1f06ba82016-02-10 17:39:50 +0100316 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200317 if (((struct lys_node_anydata *)node)->when) {
Pavol Vicandb7489e2016-08-23 17:23:39 +0200318 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", (type == ANYXML_KEYWORD) ? "anyxml" : "anydata");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100319 goto error;
320 }
Radek Krejcibf2abff2016-08-23 15:51:52 +0200321 ((struct lys_node_anydata *)node)->when = retval;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100322 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100323 case CHOICE_KEYWORD:
324 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100325 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100326 goto error;
327 }
328 ((struct lys_node_choice *)node)->when = retval;
329 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100330 case CASE_KEYWORD:
331 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100332 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100333 goto error;
334 }
335 ((struct lys_node_case *)node)->when = retval;
336 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100337 case LEAF_KEYWORD:
338 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100339 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100340 goto error;
341 }
342 ((struct lys_node_leaf *)node)->when = retval;
343 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100344 case LEAF_LIST_KEYWORD:
345 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100346 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100347 goto error;
348 }
349 ((struct lys_node_leaflist *)node)->when = retval;
350 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100351 case LIST_KEYWORD:
352 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100353 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100354 goto error;
355 }
356 ((struct lys_node_list *)node)->when = retval;
357 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100358 case USES_KEYWORD:
359 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100360 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100361 goto error;
362 }
363 ((struct lys_node_uses *)node)->when = retval;
364 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100365 case AUGMENT_KEYWORD:
366 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100367 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100368 goto error;
369 }
370 ((struct lys_node_augment *)node)->when = retval;
371 break;
PavolVicanb0317082017-02-19 01:29:22 +0100372 case EXTENSION_INSTANCE:
373 *(struct lys_when **)node = retval;
374 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200375 default:
376 goto error;
377 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100378 }
379 free(value);
380 return retval;
381
382error:
383 free(value);
PavolVicanb0317082017-02-19 01:29:22 +0100384 lydict_remove(module->ctx, retval->cond);
385 free(retval);
Pavol Vican235dbd42016-02-10 10:34:19 +0100386 return NULL;
387}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100388
389void *
Pavol Vican05810b62016-11-23 14:07:22 +0100390yang_read_node(struct lys_module *module, struct lys_node *parent, struct lys_node **root,
391 char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100392{
Pavol Vican05810b62016-11-23 14:07:22 +0100393 struct lys_node *node, **child;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100394
Pavol Vican7cadfe72016-02-11 12:33:34 +0100395 node = calloc(1, sizeof_struct);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200396 LY_CHECK_ERR_RETURN(!node, LOGMEM; free(value), NULL);
397
Michal Vasko3e3228d2017-02-24 14:55:32 +0100398 LOGDBG(LY_LDGYANG, "parsing %s statement \"%s\"", strnodetype(nodetype), value);
PavolVican196694c2017-01-27 10:33:09 +0100399 node->name = lydict_insert_zc(module->ctx, value);
Pavol Vican7cadfe72016-02-11 12:33:34 +0100400 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100401 node->nodetype = nodetype;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100402
403 /* insert the node into the schema tree */
Pavol Vican05810b62016-11-23 14:07:22 +0100404 child = (parent) ? &parent->child : root;
405 if (*child) {
406 (*child)->prev->next = node;
407 (*child)->prev = node;
408 } else {
409 *child = node;
410 node->prev = node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100411 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100412 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100413}
414
415int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200416yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100417{
418 int ret;
419
420 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100421 case LEAF_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100422 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value, node);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100423 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100424 case TYPEDEF_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100425 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value, NULL);
Pavol Vican0df02b02016-03-01 10:28:50 +0100426 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200427 default:
428 free(value);
429 LOGINT;
430 ret = EXIT_FAILURE;
431 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100432 }
433 return ret;
434}
435
436int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200437yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100438{
439 int ret;
440
441 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100442 case LEAF_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100443 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value, node);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100444 break;
445 case LEAF_LIST_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100446 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value, node);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100447 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100448 case TYPEDEF_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100449 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value, NULL);
Pavol Vican0df02b02016-03-01 10:28:50 +0100450 break;
PavolVican75af21d2016-12-29 20:04:07 +0100451 case ADD_KEYWORD:
452 case REPLACE_KEYWORD:
PavolVican6f000922017-02-10 12:56:59 +0100453 case DELETE_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100454 ret = yang_check_string(module, &((struct lys_deviate *) node)->units, "units", "deviate", value, NULL);
Pavol Vican021488a2016-01-25 23:56:12 +0100455 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200456 default:
457 free(value);
458 LOGINT;
459 ret = EXIT_FAILURE;
460 break;
Pavol Vican021488a2016-01-25 23:56:12 +0100461 }
462 return ret;
463}
Pavol Vican5de33492016-02-22 14:03:24 +0100464
465int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100466yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100467{
468 char *exp, *value;
Radek Krejci5c08a992016-11-02 13:30:04 +0100469 struct lys_node *node;
Pavol Vican5de33492016-02-22 14:03:24 +0100470
471 exp = value = (char *) list->keys;
472 while ((value = strpbrk(value, " \t\n"))) {
473 list->keys_size++;
474 while (isspace(*value)) {
475 value++;
476 }
477 }
478 list->keys_size++;
Radek Krejci5c08a992016-11-02 13:30:04 +0100479
480 list->keys_str = lydict_insert_zc(module->ctx, exp);
Pavol Vican5de33492016-02-22 14:03:24 +0100481 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200482 LY_CHECK_ERR_RETURN(!list->keys, LOGMEM, EXIT_FAILURE);
483
Radek Krejci5c08a992016-11-02 13:30:04 +0100484 for (node = list->parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
485 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
486 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100487 }
Pavol Vican5de33492016-02-22 14:03:24 +0100488 return EXIT_SUCCESS;
Pavol Vican5de33492016-02-22 14:03:24 +0100489}
490
491int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100492yang_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 +0100493{
494 int i, j;
Radek Krejci1a9c3612017-04-24 14:49:43 +0200495 char *vaux, c;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200496 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100497
498 /* count the number of unique leafs in the value */
499 vaux = value;
500 while ((vaux = strpbrk(vaux, " \t\n"))) {
501 unique->expr_size++;
502 while (isspace(*vaux)) {
503 vaux++;
504 }
505 }
506 unique->expr_size++;
507 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200508 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM, error);
Pavol Vican85f12022016-03-05 16:30:35 +0100509
510 for (i = 0; i < unique->expr_size; i++) {
511 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +0200512 if (vaux) {
513 c = *vaux;
514 *vaux = '\0';
Pavol Vican85f12022016-03-05 16:30:35 +0100515 }
516
Radek Krejci1a9c3612017-04-24 14:49:43 +0200517 /* store token into unique structure (includes converting prefix to the module name) */
518 unique->expr[i] = transform_schema2json(module, value);
519 if (vaux) {
520 *vaux = c;
521 }
Pavol Vican85f12022016-03-05 16:30:35 +0100522
523 /* check that the expression does not repeat */
524 for (j = 0; j < i; j++) {
525 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100526 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
PavolVican196694c2017-01-27 10:33:09 +0100527 LOGVAL(LYE_SPEC, LY_VLOG_LYS, list, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100528 goto error;
529 }
530 }
531 /* try to resolve leaf */
532 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200533 unique_info = malloc(sizeof *unique_info);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200534 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM, error);
Radek Krejcid09d1a52016-08-11 14:05:45 +0200535 unique_info->list = (struct lys_node *)list;
536 unique_info->expr = unique->expr[i];
537 unique_info->trg_type = &unique->trg_type;
538 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200539 goto error;
540 }
Pavol Vican85f12022016-03-05 16:30:35 +0100541 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200542 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100543 goto error;
544 }
545 }
546
547 /* move to next token */
548 value = vaux;
Radek Krejci1a9c3612017-04-24 14:49:43 +0200549 while(value && isspace(*value)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100550 value++;
551 }
552 }
553
554 return EXIT_SUCCESS;
555
556error:
557 return EXIT_FAILURE;
558}
559
560int
Pavol Vican5de33492016-02-22 14:03:24 +0100561yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
562{
563 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100564 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100565
566 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100567 str = (char *)list->unique[k].expr;
568 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100569 goto error;
570 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100571 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100572 }
573 return EXIT_SUCCESS;
574
575error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100576 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100577 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100578}
579
Pavol Vican07f220f2016-09-02 13:04:37 +0200580int
Pavol Vican81344ac2016-09-02 14:23:06 +0200581yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100582{
Pavol Vican81344ac2016-09-02 14:23:06 +0200583 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
584 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
585 goto error;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100586 }
Pavol Vican81344ac2016-09-02 14:23:06 +0200587 if (stype->type->info.lref.path) {
588 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
589 goto error;
590 }
591 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
592 stype->base = LY_TYPE_LEAFREF;
593 return EXIT_SUCCESS;
594
595error:
596 free(value);
597 return EXIT_FAILURE;
598}
599
600int
601yang_read_require_instance(struct yang_type *stype, int req)
602{
603 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
604 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
605 return EXIT_FAILURE;
606 }
607 if (stype->type->info.lref.req) {
608 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
609 return EXIT_FAILURE;
610 }
611 stype->type->info.lref.req = req;
612 stype->base = LY_TYPE_LEAFREF;
613 return EXIT_SUCCESS;
614}
615
616int
Pavol Vican7313fc02016-11-14 01:10:31 +0100617yang_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 +0100618{
Pavol Vican81344ac2016-09-02 14:23:06 +0200619 int i, j, rc, ret = -1;
620 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100621 const char *name, *value;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100622 LY_DATA_TYPE base = 0, base_tmp;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200623 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200624 struct lys_type *dertype;
625 struct lys_type_enum *enms_sc = NULL;
626 struct lys_type_bit *bits_sc = NULL;
627 struct lys_type_bit bit_tmp;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100628 struct yang_type *yang;
Pavol Vican73e7c992016-02-24 12:18:05 +0100629
Pavol Vican0adf01d2016-03-22 12:29:33 +0100630 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100631 if (!value) {
632 goto error;
633 }
634
635 i = parse_identifier(value);
636 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100637 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100638 lydict_remove(module->ctx, value);
639 goto error;
640 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200641 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100642 name = value;
643 if (value[i]) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100644 type->module_name = lydict_insert(module->ctx, value, i);
Pavol Vican73e7c992016-02-24 12:18:05 +0100645 name += i;
646 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100647 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100648 lydict_remove(module->ctx, value);
649 goto error;
650 }
651 ++name;
652 }
653
Pavol Vican7313fc02016-11-14 01:10:31 +0100654 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100655 if (rc == -1) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100656 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200657 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100658 goto error;
659
Michal Vasko01c6fd22016-05-20 11:43:05 +0200660 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100661 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200662 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200663 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100664 ret = EXIT_FAILURE;
665 goto error;
666 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200667 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200668
Pavol Vican7313fc02016-11-14 01:10:31 +0100669 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200670 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200671 * 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 +0200672 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
673 if (siter) {
Radek Krejci93def382017-05-24 15:33:48 +0200674 assert(((struct lys_node_grp *)siter)->unres_count);
675 ((struct lys_node_grp *)siter)->unres_count--;
Radek Krejcic13db382016-08-16 10:52:42 +0200676 } else {
677 LOGINT;
678 goto error;
679 }
680 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200681
682 /* check status */
Pavol Vican7313fc02016-11-14 01:10:31 +0100683 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
684 type->der->flags, type->der->module, type->der->name, parent)) {
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200685 goto error;
686 }
687
Pavol Vican8bd72e42016-08-29 09:53:05 +0200688 base = typ->base;
PavolVicane87cb932016-12-30 15:36:18 +0100689 base_tmp = type->base;
Pavol Vican7313fc02016-11-14 01:10:31 +0100690 type->base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100691 if (base == 0) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100692 base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100693 }
694 switch (base) {
695 case LY_TYPE_STRING:
Pavol Vican7313fc02016-11-14 01:10:31 +0100696 if (type->base == LY_TYPE_BINARY) {
697 if (type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100698 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100699 goto error;
700 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100701 type->info.binary.length = type->info.str.length;
702 if (type->info.binary.length && lyp_check_length_range(type->info.binary.length->expr, type)) {
703 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100704 goto error;
705 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100706 } else if (type->base == LY_TYPE_STRING) {
707 if (type->info.str.length && lyp_check_length_range(type->info.str.length->expr, type)) {
708 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100709 goto error;
710 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100711 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100712 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100713 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100714 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100715 break;
716 case LY_TYPE_DEC64:
Pavol Vican7313fc02016-11-14 01:10:31 +0100717 if (type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100718 /* mandatory sub-statement(s) check */
Pavol Vican7313fc02016-11-14 01:10:31 +0100719 if (!type->info.dec64.dig && !type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100720 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100721 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100722 goto error;
723 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100724 if (type->info.dec64.dig && type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100725 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100726 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100727 goto error;
728 }
Radek Krejci4800f652016-09-08 14:02:52 +0200729
730 /* copy fraction-digits specification from parent type for easier internal use */
Pavol Vican7313fc02016-11-14 01:10:31 +0100731 if (type->der->type.der) {
732 type->info.dec64.dig = type->der->type.info.dec64.dig;
733 type->info.dec64.div = type->der->type.info.dec64.div;
Radek Krejci4800f652016-09-08 14:02:52 +0200734 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100735 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
736 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.dec64.range->expr, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200737 goto error;
738 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100739 } else if (type->base >= LY_TYPE_INT8 && type->base <=LY_TYPE_UINT64) {
740 if (type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100741 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100742 goto error;
743 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100744 type->info.num.range = type->info.dec64.range;
745 if (type->info.num.range && lyp_check_length_range(type->info.num.range->expr, type)) {
746 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100747 goto error;
748 }
749 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100750 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100751 goto error;
752 }
753 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100754 case LY_TYPE_ENUM:
Pavol Vican7313fc02016-11-14 01:10:31 +0100755 if (type->base != LY_TYPE_ENUM) {
756 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100757 goto error;
758 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100759 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200760
761 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100762 if (!type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200763 /* type is derived directly from buit-in enumeartion type and enum statement is required */
764 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
765 goto error;
766 }
767 } else {
768 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100769 if (module->version < 2 && type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200770 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
771 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
772 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
773 goto error;
774 }
775
776 /* restricted enumeration type - the name MUST be used in the base type */
777 enms_sc = dertype->info.enums.enm;
Pavol Vican7313fc02016-11-14 01:10:31 +0100778 for(i = 0; i < type->info.enums.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200779 for (j = 0; j < dertype->info.enums.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100780 if (ly_strequal(enms_sc[j].name, type->info.enums.enm[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200781 break;
782 }
783 }
784 if (j == dertype->info.enums.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100785 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200786 goto error;
787 }
788
Pavol Vican7313fc02016-11-14 01:10:31 +0100789 if (type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200790 /* automatically assign value from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100791 type->info.enums.enm[i].value = enms_sc[j].value;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200792 } else {
793 /* check that the assigned value corresponds to the original
794 * value of the enum in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100795 if (type->info.enums.enm[i].value != enms_sc[j].value) {
796 /* type->info.enums.enm[i].value - assigned value in restricted enum
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200797 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100798 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, type->info.enums.enm[i].value,
799 type->info.enums.enm[i].name, enms_sc[j].value);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200800 goto error;
801 }
802 }
803 }
Pavol Vican79a763d2016-02-25 15:41:27 +0100804 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100805 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100806 case LY_TYPE_BITS:
Pavol Vican7313fc02016-11-14 01:10:31 +0100807 if (type->base != LY_TYPE_BITS) {
808 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100809 goto error;
810 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100811 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200812
813 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100814 if (!type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200815 /* type is derived directly from buit-in bits type and bit statement is required */
816 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
817 goto error;
818 }
819 } else {
820 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100821 if (module->version < 2 && type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200822 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
823 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
824 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
825 goto error;
826 }
827
828 bits_sc = dertype->info.bits.bit;
Pavol Vican7313fc02016-11-14 01:10:31 +0100829 for (i = 0; i < type->info.bits.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200830 for (j = 0; j < dertype->info.bits.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100831 if (ly_strequal(bits_sc[j].name, type->info.bits.bit[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200832 break;
833 }
834 }
835 if (j == dertype->info.bits.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100836 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200837 goto error;
838 }
839
840 /* restricted bits type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100841 if (type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200842 /* automatically assign position from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100843 type->info.bits.bit[i].pos = bits_sc[j].pos;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200844 } else {
845 /* check that the assigned position corresponds to the original
846 * position of the bit in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100847 if (type->info.bits.bit[i].pos != bits_sc[j].pos) {
848 /* type->info.bits.bit[i].pos - assigned position in restricted bits
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200849 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100850 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
851 type->info.bits.bit[i].name, bits_sc[j].pos);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200852 goto error;
853 }
854 }
855 }
Pavol Vican03a59442016-03-21 15:23:45 +0100856 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200857
Pavol Vican7313fc02016-11-14 01:10:31 +0100858 for (i = type->info.bits.count - 1; i > 0; i--) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200859 j = i;
860
861 /* keep them ordered by position */
Pavol Vican7313fc02016-11-14 01:10:31 +0100862 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200863 /* switch them */
Pavol Vican7313fc02016-11-14 01:10:31 +0100864 memcpy(&bit_tmp, &type->info.bits.bit[j], sizeof bit_tmp);
865 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit_tmp);
866 memcpy(&type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200867 j--;
868 }
Pavol Vican03a59442016-03-21 15:23:45 +0100869 }
870 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100871 case LY_TYPE_LEAFREF:
Pavol Vican7313fc02016-11-14 01:10:31 +0100872 if (type->base == LY_TYPE_INST) {
873 if (type->info.lref.path) {
Pavol Vican81344ac2016-09-02 14:23:06 +0200874 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
Pavol Vican1ff0e222016-02-26 12:27:01 +0100875 goto error;
876 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100877 if ((req = type->info.lref.req)) {
878 type->info.inst.req = req;
Pavol Vican81344ac2016-09-02 14:23:06 +0200879 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100880 } else if (type->base == LY_TYPE_LEAFREF) {
Pavol Vican92626d72016-09-21 09:36:09 +0200881 /* require-instance only YANG 1.1 */
Pavol Vican7313fc02016-11-14 01:10:31 +0100882 if (type->info.lref.req && (module->version < 2)) {
Pavol Vican92626d72016-09-21 09:36:09 +0200883 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
884 goto error;
885 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200886 /* flag resolving for later use */
887 if (!tpdftype) {
888 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
889 if (siter) {
890 /* just a flag - do not resolve */
891 tpdftype = 1;
892 }
893 }
894
Pavol Vican7313fc02016-11-14 01:10:31 +0100895 if (type->info.lref.path) {
896 if (type->der->type.der) {
Pavol Vican894ee0f2016-08-30 15:29:46 +0200897 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
898 goto error;
899 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100900 value = type->info.lref.path;
Pavol Vican191613a2016-02-26 16:21:32 +0100901 /* store in the JSON format */
Pavol Vican7313fc02016-11-14 01:10:31 +0100902 type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +0100903 lydict_remove(module->ctx, value);
Pavol Vican7313fc02016-11-14 01:10:31 +0100904 if (!type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +0100905 goto error;
906 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200907 /* try to resolve leafref path only when this is instantiated
908 * leaf, so it is not:
909 * - typedef's type,
910 * - in grouping definition,
911 * - just instantiated in a grouping definition,
912 * because in those cases the nodes referenced in path might not be present
913 * and it is not a bug. */
Pavol Vican7313fc02016-11-14 01:10:31 +0100914 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +0100915 goto error;
916 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100917 } else if (!type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100918 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +0100919 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200920 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +0200921 /* copy leafref definition into the derived type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100922 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +0200923 /* and resolve the path at the place we are (if not in grouping/typedef) */
Pavol Vican7313fc02016-11-14 01:10:31 +0100924 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200925 goto error;
926 }
Pavol Vican191613a2016-02-26 16:21:32 +0100927 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100928 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100929 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100930 goto error;
931 }
932 break;
933 case LY_TYPE_IDENT:
Pavol Vican7313fc02016-11-14 01:10:31 +0100934 if (type->base != LY_TYPE_IDENT) {
935 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100936 goto error;
937 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100938 if (type->der->type.der) {
939 if (type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200940 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
941 goto error;
942 }
943 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100944 if (!type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200945 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
946 goto error;
947 }
948 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100949 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100950 case LY_TYPE_UNION:
Pavol Vican7313fc02016-11-14 01:10:31 +0100951 if (type->base != LY_TYPE_UNION) {
952 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100953 goto error;
954 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100955 if (!type->info.uni.types) {
956 if (type->der->type.der) {
Pavol Vicana4f045a2016-02-29 15:01:20 +0100957 /* this is just a derived type with no additional type specified/required */
958 break;
959 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100960 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +0100961 goto error;
962 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100963 for (i = 0; i < type->info.uni.count; i++) {
PavolVican811f03b2016-12-29 23:03:20 +0100964 dertype = &type->info.uni.types[i];
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100965 if (dertype->base == LY_TYPE_DER || dertype->base == LY_TYPE_ERR) {
966 yang = (struct yang_type *)dertype->der;
967 dertype->der = NULL;
PavolVicane87cb932016-12-30 15:36:18 +0100968 dertype->parent = type->parent;
969 if (yang_check_type(module, parent, yang, dertype, tpdftype, unres)) {
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100970 dertype->der = (struct lys_tpdf *)yang;
971 ret = EXIT_FAILURE;
PavolVican811f03b2016-12-29 23:03:20 +0100972 type->base = base_tmp;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100973 base = 0;
974 goto error;
975 } else {
976 lydict_remove(module->ctx, yang->name);
977 free(yang);
978 }
Pavol Vicana4f045a2016-02-29 15:01:20 +0100979 }
Pavol Vican8e00e7a2016-09-20 11:07:48 +0200980 if (module->version < 2) {
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100981 if (dertype->base == LY_TYPE_EMPTY) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +0200982 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
983 goto error;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100984 } else if (dertype->base == LY_TYPE_LEAFREF) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +0200985 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
986 goto error;
987 }
Pavol Vicana4f045a2016-02-29 15:01:20 +0100988 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100989 if ((dertype->base == LY_TYPE_INST) || (dertype->base == LY_TYPE_LEAFREF)
990 || ((dertype->base == LY_TYPE_UNION) && dertype->info.uni.has_ptr_type)) {
Radek Krejcia726f9b2017-02-28 09:56:44 +0100991 type->info.uni.has_ptr_type = 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100992 }
Pavol Vicana4f045a2016-02-29 15:01:20 +0100993 }
994 break;
Pavol Vicana1827962016-02-29 15:39:42 +0100995
996 default:
997 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100998 if (type->base != base) {
999 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001000 goto error;
1001 }
1002 } else {
1003 LOGINT;
1004 goto error;
1005 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001006 }
1007 return EXIT_SUCCESS;
1008
1009error:
Pavol Vican7313fc02016-11-14 01:10:31 +01001010 if (type->module_name) {
1011 lydict_remove(module->ctx, type->module_name);
1012 type->module_name = NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001013 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001014 if (base) {
PavolVicane87cb932016-12-30 15:36:18 +01001015 type->base = base_tmp;
Pavol Vican8bd72e42016-08-29 09:53:05 +02001016 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001017 return ret;
1018}
1019
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001020void
1021yang_free_type_union(struct ly_ctx *ctx, struct lys_type *type)
1022{
1023 struct lys_type *stype;
1024 struct yang_type *yang;
1025 int i;
1026
1027 for (i = 0; i < type->info.uni.count; ++i) {
1028 stype = &type->info.uni.types[i];
1029 if (stype->base == LY_TYPE_DER || stype->base == LY_TYPE_ERR) {
1030 yang = (struct yang_type *)stype->der;
1031 stype->base = yang->base;
1032 lydict_remove(ctx, yang->name);
1033 free(yang);
1034 } else if (stype->base == LY_TYPE_UNION) {
1035 yang_free_type_union(ctx, stype);
1036 }
1037 }
1038}
1039
Pavol Vican73e7c992016-02-24 12:18:05 +01001040void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001041yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001042{
1043 struct yang_type *typ;
PavolVican75af21d2016-12-29 20:04:07 +01001044 struct lys_deviate *dev;
Pavol Vican73e7c992016-02-24 12:18:05 +01001045
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001046 typ = calloc(1, sizeof *typ);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001047 LY_CHECK_ERR_RETURN(!typ, LOGMEM, NULL);
Pavol Vican73e7c992016-02-24 12:18:05 +01001048
1049 typ->flags = LY_YANG_STRUCTURE_FLAG;
1050 switch (type) {
1051 case LEAF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001052 if (((struct lys_node_leaf *)parent)->type.der) {
1053 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf");
1054 goto error;
1055 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001056 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1057 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1058 typ->type = &((struct lys_node_leaf *)parent)->type;
1059 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001060 case LEAF_LIST_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001061 if (((struct lys_node_leaflist *)parent)->type.der) {
1062 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf-list");
1063 goto error;
1064 }
Pavol Vicana55992a2016-03-01 13:37:17 +01001065 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1066 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1067 typ->type = &((struct lys_node_leaflist *)parent)->type;
1068 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001069 case UNION_KEYWORD:
1070 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1071 typ->type = (struct lys_type *)parent;
1072 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001073 case TYPEDEF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001074 if (((struct lys_tpdf *)parent)->type.der) {
1075 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "typedef");
1076 goto error;
1077 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001078 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1079 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001080 break;
1081 case REPLACE_KEYWORD:
1082 /* deviation replace type*/
PavolVican75af21d2016-12-29 20:04:07 +01001083 dev = (struct lys_deviate *)parent;
1084 if (dev->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001085 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001086 goto error;
1087 }
PavolVican75af21d2016-12-29 20:04:07 +01001088 dev->type = calloc(1, sizeof *dev->type);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001089 LY_CHECK_ERR_GOTO(!dev->type, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001090 dev->type->der = (struct lys_tpdf *)typ;
1091 typ->type = dev->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001092 break;
PavolVicana0fdbf32017-02-15 17:59:02 +01001093 case EXTENSION_INSTANCE:
1094 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1095 typ->type = parent;
1096 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001097 default:
1098 goto error;
1099 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001100 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001101 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001102 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001103
1104error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001105 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001106 free(typ);
1107 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001108}
1109
1110void *
PavolVicaneef1d912017-02-19 00:19:15 +01001111yang_read_length(struct lys_module *module, struct yang_type *stype, char *value, int is_ext_instance)
Pavol Vican73e7c992016-02-24 12:18:05 +01001112{
PavolVicaneef1d912017-02-19 00:19:15 +01001113 struct lys_restr *length;
Pavol Vican73e7c992016-02-24 12:18:05 +01001114
PavolVicaneef1d912017-02-19 00:19:15 +01001115 if (is_ext_instance) {
1116 length = (struct lys_restr *)stype;
Pavol Vican73e7c992016-02-24 12:18:05 +01001117 } else {
PavolVicaneef1d912017-02-19 00:19:15 +01001118 if (stype->base == 0 || stype->base == LY_TYPE_STRING) {
1119 stype->base = LY_TYPE_STRING;
1120 } else {
1121 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
1122 goto error;
1123 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001124
PavolVicaneef1d912017-02-19 00:19:15 +01001125 if (stype->type->info.str.length) {
1126 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
1127 goto error;
1128 }
1129 length = calloc(1, sizeof *length);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001130 LY_CHECK_ERR_GOTO(!length, LOGMEM, error);
PavolVicaneef1d912017-02-19 00:19:15 +01001131 stype->type->info.str.length = length;
Pavol Vican73e7c992016-02-24 12:18:05 +01001132 }
PavolVicaneef1d912017-02-19 00:19:15 +01001133 length->expr = lydict_insert_zc(module->ctx, value);
1134 return length;
Pavol Vican73e7c992016-02-24 12:18:05 +01001135
1136error:
1137 free(value);
1138 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001139}
Pavol Vican1c203db2016-02-24 14:05:23 +01001140
Pavol Vican6eecf302016-08-10 11:09:05 +02001141int
1142yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001143{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001144 char *buf;
1145 size_t len;
1146
Michal Vasko0aee5c12016-06-17 14:27:26 +02001147 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001148 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001149 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001150 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001151
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001152 len = strlen(value);
1153 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Radek Krejcia8d111f2017-05-31 13:57:37 +02001154 LY_CHECK_ERR_RETURN(!buf, LOGMEM; free(value), EXIT_FAILURE);
Pavol Vican6eecf302016-08-10 11:09:05 +02001155
1156 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001157 strcpy(&buf[1], value);
1158 free(value);
1159
Pavol Vican6eecf302016-08-10 11:09:05 +02001160 pattern->expr = lydict_insert_zc(module->ctx, buf);
1161 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001162}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001163
1164void *
PavolVicaneef1d912017-02-19 00:19:15 +01001165yang_read_range(struct lys_module *module, struct yang_type *stype, char *value, int is_ext_instance)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001166{
PavolVicaneef1d912017-02-19 00:19:15 +01001167 struct lys_restr * range;
1168
1169 if (is_ext_instance) {
1170 range = (struct lys_restr *)stype;
1171 } else {
1172 if (stype->base != 0 && stype->base != LY_TYPE_DEC64) {
1173 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
1174 goto error;
1175 }
1176 stype->base = LY_TYPE_DEC64;
1177 if (stype->type->info.dec64.range) {
1178 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
1179 goto error;
1180 }
1181 range = calloc(1, sizeof *range);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001182 LY_CHECK_ERR_GOTO(!range, LOGMEM, error);
PavolVicaneef1d912017-02-19 00:19:15 +01001183 stype->type->info.dec64.range = range;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001184 }
PavolVicaneef1d912017-02-19 00:19:15 +01001185 range->expr = lydict_insert_zc(module->ctx, value);
1186 return range;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001187
1188error:
1189 free(value);
1190 return NULL;
1191}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001192
1193int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001194yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001195{
Pavol Vican6b072512016-04-04 10:50:21 +02001196 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1197 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001198 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001199 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001200 goto error;
1201 }
1202 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001203 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001204 goto error;
1205 }
1206 /* range check */
1207 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001208 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001209 goto error;
1210 }
1211 typ->type->info.dec64.dig = value;
1212 return EXIT_SUCCESS;
1213
1214error:
1215 return EXIT_FAILURE;
1216}
Pavol Vican79a763d2016-02-25 15:41:27 +01001217
Pavol Vican874715f2016-10-25 14:52:08 +02001218int
1219yang_read_enum(struct lys_module *module, struct yang_type *typ, struct lys_type_enum *enm, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001220{
Pavol Vican874715f2016-10-25 14:52:08 +02001221 int i, j;
Pavol Vican79a763d2016-02-25 15:41:27 +01001222
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01001223 typ->base = LY_TYPE_ENUM;
Pavol Vicanc6662412016-08-30 08:06:28 +02001224 if (!value[0]) {
1225 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1226 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1227 free(value);
1228 goto error;
1229 }
1230
Pavol Vican79a763d2016-02-25 15:41:27 +01001231 enm->name = lydict_insert_zc(module->ctx, value);
1232
1233 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1234 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001235 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001236 goto error;
1237 }
1238
Pavol Vican874715f2016-10-25 14:52:08 +02001239 j = typ->type->info.enums.count - 1;
Pavol Vican79a763d2016-02-25 15:41:27 +01001240 /* check the name uniqueness */
Pavol Vican874715f2016-10-25 14:52:08 +02001241 for (i = 0; i < j; i++) {
PavolVican4b80d042017-02-23 14:30:27 +01001242 if (ly_strequal(typ->type->info.enums.enm[i].name, enm->name, 1)) {
1243 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001244 goto error;
1245 }
1246 }
1247
Pavol Vican874715f2016-10-25 14:52:08 +02001248 return EXIT_SUCCESS;
Pavol Vican79a763d2016-02-25 15:41:27 +01001249
1250error:
Pavol Vican874715f2016-10-25 14:52:08 +02001251 return EXIT_FAILURE;
Pavol Vican79a763d2016-02-25 15:41:27 +01001252}
1253
1254int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001255yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001256{
1257 int i, j;
1258
1259 if (!assign) {
1260 /* assign value automatically */
1261 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001262 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001263 goto error;
1264 }
1265 enm->value = *value;
1266 enm->flags |= LYS_AUTOASSIGNED;
1267 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001268 } else if (typ->type->info.enums.enm == enm) {
1269 /* change value, which is assigned automatically, if first enum has value. */
1270 *value = typ->type->info.enums.enm[0].value;
1271 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001272 }
1273
1274 /* check that the value is unique */
1275 j = typ->type->info.enums.count-1;
1276 for (i = 0; i < j; i++) {
1277 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001278 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001279 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1280 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001281 goto error;
1282 }
1283 }
1284
1285 return EXIT_SUCCESS;
1286
1287error:
1288 return EXIT_FAILURE;
1289}
Pavol Vican9887c682016-02-29 11:32:01 +01001290
Pavol Vican59e8dee2016-10-25 15:29:38 +02001291int
1292yang_read_bit(struct lys_module *module, struct yang_type *typ, struct lys_type_bit *bit, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001293{
Pavol Vican59e8dee2016-10-25 15:29:38 +02001294 int i, j;
Pavol Vican9887c682016-02-29 11:32:01 +01001295
PavolVicane87cb932016-12-30 15:36:18 +01001296 typ->base = LY_TYPE_BITS;
Pavol Vican59e8dee2016-10-25 15:29:38 +02001297 bit->name = lydict_insert_zc(module->ctx, value);
1298 if (lyp_check_identifier(bit->name, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001299 goto error;
1300 }
Pavol Vican9887c682016-02-29 11:32:01 +01001301
Pavol Vican59e8dee2016-10-25 15:29:38 +02001302 j = typ->type->info.bits.count - 1;
Pavol Vican9887c682016-02-29 11:32:01 +01001303 /* check the name uniqueness */
Pavol Vican59e8dee2016-10-25 15:29:38 +02001304 for (i = 0; i < j; i++) {
PavolVican4b80d042017-02-23 14:30:27 +01001305 if (ly_strequal(typ->type->info.bits.bit[i].name, bit->name, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001306 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001307 goto error;
1308 }
1309 }
Pavol Vican59e8dee2016-10-25 15:29:38 +02001310 return EXIT_SUCCESS;
Pavol Vican9887c682016-02-29 11:32:01 +01001311
1312error:
Pavol Vican59e8dee2016-10-25 15:29:38 +02001313 return EXIT_FAILURE;
Pavol Vican9887c682016-02-29 11:32:01 +01001314}
1315
1316int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001317yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001318{
1319 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001320
1321 if (!assign) {
1322 /* assign value automatically */
1323 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001324 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001325 goto error;
1326 }
1327 bit->pos = (uint32_t)*value;
1328 bit->flags |= LYS_AUTOASSIGNED;
1329 (*value)++;
1330 }
1331
1332 j = typ->type->info.bits.count - 1;
1333 /* check that the value is unique */
1334 for (i = 0; i < j; i++) {
1335 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001336 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 +01001337 goto error;
1338 }
1339 }
1340
Pavol Vican9887c682016-02-29 11:32:01 +01001341 return EXIT_SUCCESS;
1342
1343error:
1344 return EXIT_FAILURE;
1345}
Pavol Vican0df02b02016-03-01 10:28:50 +01001346
Pavol Vican3ad50f82016-12-04 15:00:36 +01001347int
1348yang_read_augment(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *aug, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001349{
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001350 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001351 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001352 free(value);
1353 if (!aug->target_name) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01001354 return EXIT_FAILURE;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001355 }
1356 aug->parent = parent;
1357 aug->module = module;
Pavol Vican3ad50f82016-12-04 15:00:36 +01001358 return EXIT_SUCCESS;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001359}
Pavol Vican220e5a12016-03-03 14:19:43 +01001360
PavolVican6f000922017-02-10 12:56:59 +01001361void *
PavolVican75af21d2016-12-29 20:04:07 +01001362yang_read_deviate_unsupported(struct lys_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001363{
PavolVican75af21d2016-12-29 20:04:07 +01001364 if (dev->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001365 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
PavolVican6f000922017-02-10 12:56:59 +01001366 return NULL;
Pavol Vican220e5a12016-03-03 14:19:43 +01001367 }
PavolVican75af21d2016-12-29 20:04:07 +01001368 dev->deviate = calloc(1, sizeof *dev->deviate);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001369 LY_CHECK_ERR_RETURN(!dev->deviate, LOGMEM, NULL);
PavolVican75af21d2016-12-29 20:04:07 +01001370 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1371 dev->deviate_size = 1;
PavolVican6f000922017-02-10 12:56:59 +01001372 return dev->deviate;
Pavol Vican220e5a12016-03-03 14:19:43 +01001373}
1374
1375void *
PavolVican75af21d2016-12-29 20:04:07 +01001376yang_read_deviate(struct lys_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican220e5a12016-03-03 14:19:43 +01001377{
PavolVican75af21d2016-12-29 20:04:07 +01001378 struct lys_deviate *deviate;
Pavol Vican220e5a12016-03-03 14:19:43 +01001379
PavolVican4b80d042017-02-23 14:30:27 +01001380 if (dev->deviate_size && dev->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001381 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1382 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
PavolVican75af21d2016-12-29 20:04:07 +01001383 return NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001384 }
PavolVican75af21d2016-12-29 20:04:07 +01001385 if (!(dev->deviate_size % LY_YANG_ARRAY_SIZE)) {
1386 deviate = realloc(dev->deviate, (LY_YANG_ARRAY_SIZE + dev->deviate_size) * sizeof *deviate);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001387 LY_CHECK_ERR_RETURN(!deviate, LOGMEM, NULL);
PavolVican75af21d2016-12-29 20:04:07 +01001388 memset(deviate + dev->deviate_size, 0, LY_YANG_ARRAY_SIZE * sizeof *deviate);
1389 dev->deviate = deviate;
Pavol Vican85f12022016-03-05 16:30:35 +01001390 }
PavolVican75af21d2016-12-29 20:04:07 +01001391 dev->deviate[dev->deviate_size].mod = mod;
1392 return &dev->deviate[dev->deviate_size++];
Pavol Vican85f12022016-03-05 16:30:35 +01001393}
1394
1395int
PavolVican75af21d2016-12-29 20:04:07 +01001396yang_read_deviate_units(struct ly_ctx *ctx, struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vican85f12022016-03-05 16:30:35 +01001397{
1398 const char **stritem;
PavolVican6f000922017-02-10 12:56:59 +01001399 int j;
Pavol Vican85f12022016-03-05 16:30:35 +01001400
Pavol Vican85f12022016-03-05 16:30:35 +01001401 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001402 if (dev_target->nodetype == LYS_LEAFLIST) {
1403 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1404 } else if (dev_target->nodetype == LYS_LEAF) {
1405 stritem = &((struct lys_node_leaf *)dev_target)->units;
Pavol Vican85f12022016-03-05 16:30:35 +01001406 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001407 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1408 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001409 goto error;
1410 }
1411
PavolVican75af21d2016-12-29 20:04:07 +01001412 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001413 /* check values */
PavolVican75af21d2016-12-29 20:04:07 +01001414 if (!ly_strequal(*stritem, deviate->units, 1)) {
1415 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, deviate->units, "units");
Pavol Vican0adf01d2016-03-22 12:29:33 +01001416 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001417 goto error;
1418 }
1419 /* remove current units value of the target */
1420 lydict_remove(ctx, *stritem);
PavolVican6f000922017-02-10 12:56:59 +01001421 *stritem = NULL;
1422 /* remove its extensions */
1423 j = -1;
1424 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
1425 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
1426 --j;
1427 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001428 } else {
PavolVican75af21d2016-12-29 20:04:07 +01001429 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican4766aca2016-03-07 12:42:36 +01001430 /* check that there is no current value */
1431 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001432 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1433 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001434 goto error;
1435 }
1436 } else { /* replace */
1437 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001438 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1439 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001440 goto error;
1441 }
1442 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001443 /* remove current units value of the target ... */
1444 lydict_remove(ctx, *stritem);
1445
1446 /* ... and replace it with the value specified in deviation */
PavolVican75af21d2016-12-29 20:04:07 +01001447 *stritem = lydict_insert(ctx, deviate->units, 0);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001448 }
1449
Pavol Vican85f12022016-03-05 16:30:35 +01001450 return EXIT_SUCCESS;
1451
1452error:
1453 return EXIT_FAILURE;
1454}
1455
1456int
PavolVican75af21d2016-12-29 20:04:07 +01001457yang_read_deviate_unique(struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vican85f12022016-03-05 16:30:35 +01001458{
Pavol Vican85f12022016-03-05 16:30:35 +01001459 struct lys_node_list *list;
PavolVican75af21d2016-12-29 20:04:07 +01001460 struct lys_unique *unique;
Pavol Vican85f12022016-03-05 16:30:35 +01001461
1462 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001463 if (dev_target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001464 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1465 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001466 goto error;
1467 }
1468
PavolVican75af21d2016-12-29 20:04:07 +01001469 list = (struct lys_node_list *)dev_target;
1470 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican85f12022016-03-05 16:30:35 +01001471 /* reallocate the unique array of the target */
PavolVican75af21d2016-12-29 20:04:07 +01001472 unique = ly_realloc(list->unique, (deviate->unique_size + list->unique_size) * sizeof *unique);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001473 LY_CHECK_ERR_GOTO(!unique, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001474 list->unique = unique;
1475 memset(unique + list->unique_size, 0, deviate->unique_size * sizeof *unique);
Pavol Vican85f12022016-03-05 16:30:35 +01001476 }
1477
1478 return EXIT_SUCCESS;
1479
1480error:
1481 return EXIT_FAILURE;
1482}
1483
1484int
PavolVican75af21d2016-12-29 20:04:07 +01001485yang_fill_deviate_default(struct ly_ctx *ctx, struct lys_deviate *deviate, struct lys_node *dev_target,
1486 struct ly_set *dflt_check, const char *value)
Pavol Vican38321d02016-08-16 14:56:02 +02001487{
1488 struct lys_node *node;
1489 struct lys_node_choice *choice;
1490 struct lys_node_leaf *leaf;
1491 struct lys_node_leaflist *llist;
PavolVican6f000922017-02-10 12:56:59 +01001492 int rc, i, j;
Pavol Vican38321d02016-08-16 14:56:02 +02001493 unsigned int u;
Pavol Vican38321d02016-08-16 14:56:02 +02001494
Pavol Vican38321d02016-08-16 14:56:02 +02001495 u = strlen(value);
PavolVican75af21d2016-12-29 20:04:07 +01001496 if (dev_target->nodetype == LYS_CHOICE) {
1497 choice = (struct lys_node_choice *)dev_target;
Pavol Vican38321d02016-08-16 14:56:02 +02001498 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
1499 if (rc || !node) {
1500 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1501 goto error;
1502 }
PavolVican75af21d2016-12-29 20:04:07 +01001503 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vican38321d02016-08-16 14:56:02 +02001504 if (!choice->dflt || (choice->dflt != node)) {
1505 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1506 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1507 goto error;
1508 }
PavolVican6f000922017-02-10 12:56:59 +01001509 choice->dflt = NULL;
1510 /* remove extensions of this default instance from the target node */
1511 j = -1;
1512 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
1513 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
1514 --j;
1515 }
Pavol Vican38321d02016-08-16 14:56:02 +02001516 } else { /* add or replace */
1517 choice->dflt = node;
1518 if (!choice->dflt) {
1519 /* default branch not found */
1520 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1521 goto error;
1522 }
1523 }
PavolVican75af21d2016-12-29 20:04:07 +01001524 } else if (dev_target->nodetype == LYS_LEAF) {
1525 leaf = (struct lys_node_leaf *)dev_target;
1526 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vican38321d02016-08-16 14:56:02 +02001527 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
1528 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1529 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1530 goto error;
1531 }
1532 /* remove value */
1533 lydict_remove(ctx, leaf->dflt);
1534 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01001535 leaf->flags &= ~LYS_DFLTJSON;
PavolVican6f000922017-02-10 12:56:59 +01001536 /* remove extensions of this default instance from the target node */
1537 j = -1;
1538 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
1539 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
1540 --j;
1541 }
Pavol Vican38321d02016-08-16 14:56:02 +02001542 } else { /* add (already checked) and replace */
1543 /* remove value */
1544 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01001545 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001546
1547 /* set new value */
1548 leaf->dflt = lydict_insert(ctx, value, u);
1549
1550 /* remember to check it later (it may not fit now, but the type can be deviated too) */
PavolVican75af21d2016-12-29 20:04:07 +01001551 ly_set_add(dflt_check, dev_target, 0);
Pavol Vican38321d02016-08-16 14:56:02 +02001552 }
1553 } else { /* LYS_LEAFLIST */
PavolVican75af21d2016-12-29 20:04:07 +01001554 llist = (struct lys_node_leaflist *)dev_target;
1555 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vican38321d02016-08-16 14:56:02 +02001556 /* find and remove the value in target list */
1557 for (i = 0; i < llist->dflt_size; i++) {
1558 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
1559 /* match, remove the value */
1560 lydict_remove(llist->module->ctx, llist->dflt[i]);
1561 llist->dflt[i] = NULL;
PavolVican6f000922017-02-10 12:56:59 +01001562 /* remove extensions of this default instance from the target node */
1563 j = -1;
1564 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
1565 if (dev_target->ext[j]->insubstmt_index == i) {
1566 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
1567 --j;
1568 } else if (dev_target->ext[j]->insubstmt_index > i) {
1569 /* decrease the substatement index of the extension because of the changed array of defaults */
1570 dev_target->ext[j]->insubstmt_index--;
1571 }
1572 }
Pavol Vican38321d02016-08-16 14:56:02 +02001573 break;
1574 }
1575 }
1576 if (i == llist->dflt_size) {
1577 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1578 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
1579 goto error;
1580 }
1581 } else {
1582 /* add or replace, anyway we place items into the deviate's list
1583 which propagates to the target */
1584 /* we just want to check that the value isn't already in the list */
1585 for (i = 0; i < llist->dflt_size; i++) {
1586 if (ly_strequal(llist->dflt[i], value, 1)) {
1587 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1588 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
1589 goto error;
1590 }
1591 }
1592 /* store it in target node */
1593 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
1594
1595 /* remember to check it later (it may not fit now, but the type can be deviated too) */
PavolVican75af21d2016-12-29 20:04:07 +01001596 ly_set_add(dflt_check, dev_target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01001597 llist->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001598 }
1599 }
1600
1601 return EXIT_SUCCESS;
1602error:
1603 return EXIT_FAILURE;
1604}
1605
Pavol Vican38321d02016-08-16 14:56:02 +02001606int
PavolVican75af21d2016-12-29 20:04:07 +01001607yang_read_deviate_default(struct lys_module *module, struct lys_deviate *deviate,
1608 struct lys_node *dev_target, struct ly_set * dflt_check)
Pavol Vican85f12022016-03-05 16:30:35 +01001609{
PavolVican75af21d2016-12-29 20:04:07 +01001610 int i;
1611 struct lys_node_leaflist *llist;
1612 const char **dflt;
1613
1614 /* check target node type */
1615 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
1616 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1617 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1618 goto error;
1619 } else if (deviate->dflt_size > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1620 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1621 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1622 goto error;
1623 } else if (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
1624 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1625 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001626 goto error;
1627 }
1628
PavolVican75af21d2016-12-29 20:04:07 +01001629 if (deviate->mod == LY_DEVIATE_ADD) {
1630 /* check that there is no current value */
1631 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
1632 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
1633 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1634 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
1635 goto error;
1636 }
Pavol Vican85f12022016-03-05 16:30:35 +01001637
PavolVican75af21d2016-12-29 20:04:07 +01001638 /* check collision with mandatory/min-elements */
1639 if ((dev_target->flags & LYS_MAND_TRUE) ||
1640 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
1641 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
1642 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1643 "Adding the \"default\" statement is forbidden on %s statement.",
1644 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
1645 goto error;
1646 }
1647 } else if (deviate->mod == LY_DEVIATE_RPL) {
1648 /* check that there was a value before */
1649 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
1650 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
1651 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1652 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
1653 goto error;
1654 }
1655 }
Pavol Vican85f12022016-03-05 16:30:35 +01001656
PavolVican75af21d2016-12-29 20:04:07 +01001657 if (dev_target->nodetype == LYS_LEAFLIST) {
1658 /* reallocate default list in the target */
1659 llist = (struct lys_node_leaflist *)dev_target;
1660 if (deviate->mod == LY_DEVIATE_ADD) {
1661 /* reallocate (enlarge) the unique array of the target */
1662 dflt = realloc(llist->dflt, (deviate->dflt_size + llist->dflt_size) * sizeof *dflt);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001663 LY_CHECK_ERR_GOTO(!dflt, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001664 llist->dflt = dflt;
1665 } else if (deviate->mod == LY_DEVIATE_RPL) {
1666 /* reallocate (replace) the unique array of the target */
1667 for (i = 0; i < llist->dflt_size; i++) {
1668 lydict_remove(llist->module->ctx, llist->dflt[i]);
1669 }
1670 dflt = realloc(llist->dflt, deviate->dflt_size * sizeof *dflt);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001671 LY_CHECK_ERR_GOTO(!dflt, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001672 llist->dflt = dflt;
1673 llist->dflt_size = 0;
1674 }
1675 }
1676
1677 for (i = 0; i < deviate->dflt_size; ++i) {
1678 if (yang_fill_deviate_default(module->ctx, deviate, dev_target, dflt_check, deviate->dflt[i])) {
1679 goto error;
1680 }
1681 }
Pavol Vican85f12022016-03-05 16:30:35 +01001682
1683 return EXIT_SUCCESS;
1684
1685error:
1686 return EXIT_FAILURE;
1687}
1688
1689int
PavolVican75af21d2016-12-29 20:04:07 +01001690yang_check_deviate_mandatory(struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vican85f12022016-03-05 16:30:35 +01001691{
Radek Krejcie00d2312016-08-12 15:27:49 +02001692 struct lys_node *parent;
1693
Pavol Vican85f12022016-03-05 16:30:35 +01001694 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001695 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001696 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1697 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001698 goto error;
1699 }
1700
PavolVican75af21d2016-12-29 20:04:07 +01001701 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican85f12022016-03-05 16:30:35 +01001702 /* check that there is no current value */
PavolVican75af21d2016-12-29 20:04:07 +01001703 if (dev_target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001704 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1705 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001706 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001707 } else {
PavolVican75af21d2016-12-29 20:04:07 +01001708 if (dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) {
Pavol Vican321a02e2016-04-05 16:11:59 +02001709 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1710 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
1711 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
1712 goto error;
PavolVican75af21d2016-12-29 20:04:07 +01001713 } else if (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt) {
Pavol Vican321a02e2016-04-05 16:11:59 +02001714 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
1715 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
1716 goto error;
1717 }
Pavol Vican85f12022016-03-05 16:30:35 +01001718 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001719 } else { /* replace */
PavolVican75af21d2016-12-29 20:04:07 +01001720 if (!(dev_target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001721 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1722 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001723 goto error;
1724 }
Pavol Vican85f12022016-03-05 16:30:35 +01001725 }
1726
Pavol Vican85f12022016-03-05 16:30:35 +01001727 /* remove current mandatory value of the target ... */
PavolVican75af21d2016-12-29 20:04:07 +01001728 dev_target->flags &= ~LYS_MAND_MASK;
Pavol Vican85f12022016-03-05 16:30:35 +01001729
1730 /* ... and replace it with the value specified in deviation */
PavolVican75af21d2016-12-29 20:04:07 +01001731 dev_target->flags |= deviate->flags & LYS_MAND_MASK;
Pavol Vican85f12022016-03-05 16:30:35 +01001732
Radek Krejcie00d2312016-08-12 15:27:49 +02001733 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
PavolVican75af21d2016-12-29 20:04:07 +01001734 for (parent = dev_target->parent;
Radek Krejcie00d2312016-08-12 15:27:49 +02001735 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
1736 parent = parent->parent) {
1737 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
1738 /* stop also on presence containers */
1739 break;
1740 }
1741 }
1742 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
1743 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
1744 if (lyp_check_mandatory_choice(parent)) {
1745 goto error;
1746 }
1747 }
1748
Pavol Vican85f12022016-03-05 16:30:35 +01001749 return EXIT_SUCCESS;
1750
1751error:
1752 return EXIT_FAILURE;
1753}
1754
1755int
PavolVican75af21d2016-12-29 20:04:07 +01001756yang_read_deviate_minmax(struct lys_deviate *deviate, struct lys_node *dev_target, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01001757{
Pavol Vican09adcc32016-08-25 10:51:36 +02001758 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01001759
1760 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001761 if (dev_target->nodetype == LYS_LEAFLIST) {
1762 max = &((struct lys_node_leaflist *)dev_target)->max;
1763 min = &((struct lys_node_leaflist *)dev_target)->min;
1764 } else if (dev_target->nodetype == LYS_LIST) {
1765 max = &((struct lys_node_list *)dev_target)->max;
1766 min = &((struct lys_node_list *)dev_target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01001767 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001768 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1769 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 +01001770 goto error;
1771 }
1772
PavolVican75af21d2016-12-29 20:04:07 +01001773 ui32val = (type) ? max : min;
1774 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican85f12022016-03-05 16:30:35 +01001775 /* check that there is no current value */
1776 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001777 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1778 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001779 goto error;
1780 }
PavolVican75af21d2016-12-29 20:04:07 +01001781 } else if (deviate->mod == LY_DEVIATE_RPL) {
Pavol Vican4766aca2016-03-07 12:42:36 +01001782 /* unfortunately, there is no way to check reliably that there
1783 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01001784 }
1785
1786 /* add (already checked) and replace */
1787 /* set new value specified in deviation */
1788 *ui32val = value;
1789
Pavol Vican09adcc32016-08-25 10:51:36 +02001790 /* check min-elements is smaller than max-elements */
1791 if (*max && *min > *max) {
1792 if (type) {
1793 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
1794 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1795 } else {
1796 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
1797 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1798 }
1799 goto error;
1800 }
1801
Pavol Vican85f12022016-03-05 16:30:35 +01001802 return EXIT_SUCCESS;
1803
1804error:
1805 return EXIT_FAILURE;
1806}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001807
1808int
PavolVican75af21d2016-12-29 20:04:07 +01001809yang_check_deviate_must(struct lys_module *module, struct unres_schema *unres,
1810 struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001811{
PavolVican75af21d2016-12-29 20:04:07 +01001812 int i, j, erase_must = 1;
1813 struct lys_restr **trg_must, *must;
PavolVican214408f2017-02-03 11:54:05 +01001814 uint8_t *trg_must_size;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001815
PavolVican75af21d2016-12-29 20:04:07 +01001816 /* check target node type */
1817 switch (dev_target->nodetype) {
1818 case LYS_LEAF:
1819 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1820 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001821 break;
PavolVican75af21d2016-12-29 20:04:07 +01001822 case LYS_CONTAINER:
1823 trg_must = &((struct lys_node_container *)dev_target)->must;
1824 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
1825 break;
1826 case LYS_LEAFLIST:
1827 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1828 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
1829 break;
1830 case LYS_LIST:
1831 trg_must = &((struct lys_node_list *)dev_target)->must;
1832 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
1833 break;
1834 case LYS_ANYXML:
1835 case LYS_ANYDATA:
1836 trg_must = &((struct lys_node_anydata *)dev_target)->must;
1837 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
1838 break;
1839 default:
1840 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1841 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
1842 goto error;
1843 }
1844
1845 /* flag will be checked again, clear it for now */
PavolVicancec18782017-01-26 21:48:46 +01001846 dev_target->flags &= ~LYS_XPATH_DEP;
PavolVican75af21d2016-12-29 20:04:07 +01001847
1848 if (deviate->mod == LY_DEVIATE_ADD) {
1849 /* reallocate the must array of the target */
1850 must = ly_realloc(*trg_must, (deviate->must_size + *trg_must_size) * sizeof *must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001851 LY_CHECK_ERR_GOTO(!must, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001852 *trg_must = must;
PavolVican214408f2017-02-03 11:54:05 +01001853 memcpy(&(*trg_must)[*trg_must_size], deviate->must, deviate->must_size * sizeof *must);
PavolVican75af21d2016-12-29 20:04:07 +01001854 free(deviate->must);
1855 deviate->must = &must[*trg_must_size];
PavolVican214408f2017-02-03 11:54:05 +01001856 *trg_must_size = *trg_must_size + deviate->must_size;
PavolVican75af21d2016-12-29 20:04:07 +01001857 erase_must = 0;
1858 } else if (deviate->mod == LY_DEVIATE_DEL) {
1859 /* find must to delete, we are ok with just matching conditions */
1860 for (j = 0; j < deviate->must_size; ++j) {
1861 for (i = 0; i < *trg_must_size; i++) {
1862 if (ly_strequal(deviate->must[j].expr, (*trg_must)[i].expr, 1)) {
1863 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02001864 lys_restr_free(module->ctx, &((*trg_must)[i]), NULL);
PavolVican75af21d2016-12-29 20:04:07 +01001865 /* ... and maintain the array */
1866 (*trg_must_size)--;
1867 if (i != *trg_must_size) {
PavolVican214408f2017-02-03 11:54:05 +01001868 memcpy(&(*trg_must)[i], &(*trg_must)[*trg_must_size], sizeof *must);
PavolVican75af21d2016-12-29 20:04:07 +01001869 }
1870 if (!(*trg_must_size)) {
1871 free(*trg_must);
1872 *trg_must = NULL;
1873 } else {
PavolVican214408f2017-02-03 11:54:05 +01001874 memset(&(*trg_must)[*trg_must_size], 0, sizeof *must);
PavolVican75af21d2016-12-29 20:04:07 +01001875 }
1876
1877 i = -1; /* set match flag */
1878 break;
1879 }
1880 }
1881 if (i != -1) {
1882 /* no match found */
1883 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, deviate->must[j].expr, "must");
1884 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
1885 goto error;
1886 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001887 }
1888 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001889
PavolVican6f000922017-02-10 12:56:59 +01001890 if (yang_check_must(module, deviate->must, deviate->must_size, unres)) {
1891 goto error;
1892 }
PavolVican75af21d2016-12-29 20:04:07 +01001893 /* check XPath dependencies */
1894 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001895 goto error;
1896 }
1897
PavolVican75af21d2016-12-29 20:04:07 +01001898 return EXIT_SUCCESS;
1899error:
1900 if (deviate->mod == LY_DEVIATE_ADD && erase_must) {
1901 for (i = 0; i < deviate->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001902 lys_restr_free(module->ctx, &deviate->must[i], NULL);
PavolVican75af21d2016-12-29 20:04:07 +01001903 }
1904 free(deviate->must);
1905 }
1906 return EXIT_FAILURE;
1907}
1908
1909int
1910yang_deviate_delete_unique(struct lys_module *module, struct lys_deviate *deviate,
1911 struct lys_node_list *list, int index, char * value)
1912{
PavolVican6f000922017-02-10 12:56:59 +01001913 int i, j, k;
PavolVican75af21d2016-12-29 20:04:07 +01001914
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001915 /* find unique structures to delete */
1916 for (i = 0; i < list->unique_size; i++) {
PavolVican75af21d2016-12-29 20:04:07 +01001917 if (list->unique[i].expr_size != deviate->unique[index].expr_size) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001918 continue;
1919 }
1920
PavolVican75af21d2016-12-29 20:04:07 +01001921 for (j = 0; j < deviate->unique[index].expr_size; j++) {
1922 if (!ly_strequal(list->unique[i].expr[j], deviate->unique[index].expr[j], 1)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001923 break;
1924 }
1925 }
1926
PavolVican75af21d2016-12-29 20:04:07 +01001927 if (j == deviate->unique[index].expr_size) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001928 /* we have a match, free the unique structure ... */
1929 for (j = 0; j < list->unique[i].expr_size; j++) {
1930 lydict_remove(module->ctx, list->unique[i].expr[j]);
1931 }
1932 free(list->unique[i].expr);
1933 /* ... and maintain the array */
1934 list->unique_size--;
1935 if (i != list->unique_size) {
1936 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1937 list->unique[i].expr = list->unique[list->unique_size].expr;
1938 }
1939
1940 if (!list->unique_size) {
1941 free(list->unique);
1942 list->unique = NULL;
1943 } else {
1944 list->unique[list->unique_size].expr_size = 0;
1945 list->unique[list->unique_size].expr = NULL;
1946 }
1947
PavolVican6f000922017-02-10 12:56:59 +01001948 k = i; /* remember index for removing extensions */
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001949 i = -1; /* set match flag */
1950 break;
1951 }
1952 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001953
1954 if (i != -1) {
1955 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001956 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
1957 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
PavolVican75af21d2016-12-29 20:04:07 +01001958 return EXIT_FAILURE;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001959 }
1960
PavolVican6f000922017-02-10 12:56:59 +01001961 /* remove extensions of this unique instance from the target node */
1962 j = -1;
1963 while ((j = lys_ext_iter(list->ext, list->ext_size, j + 1, LYEXT_SUBSTMT_UNIQUE)) != -1) {
1964 if (list->ext[j]->insubstmt_index == k) {
1965 lyp_ext_instance_rm(module->ctx, &list->ext, &list->ext_size, j);
1966 --j;
1967 } else if (list->ext[j]->insubstmt_index > k) {
1968 /* decrease the substatement index of the extension because of the changed array of uniques */
1969 list->ext[j]->insubstmt_index--;
1970 }
1971 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001972 return EXIT_SUCCESS;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001973}
Pavol Vican021488a2016-01-25 23:56:12 +01001974
PavolVican75af21d2016-12-29 20:04:07 +01001975int yang_check_deviate_unique(struct lys_module *module, struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vicane92421d2016-03-08 10:12:33 +01001976{
PavolVican75af21d2016-12-29 20:04:07 +01001977 struct lys_node_list *list;
1978 char *str;
PavolVican4b80d042017-02-23 14:30:27 +01001979 uint i = 0;
1980 struct lys_unique *last_unique = NULL;
Pavol Vicane92421d2016-03-08 10:12:33 +01001981
PavolVican75af21d2016-12-29 20:04:07 +01001982 if (yang_read_deviate_unique(deviate, dev_target)) {
1983 goto error;
1984 }
1985 list = (struct lys_node_list *)dev_target;
1986 last_unique = &list->unique[list->unique_size];
1987 for (i = 0; i < deviate->unique_size; ++i) {
1988 str = (char *) deviate->unique[i].expr;
1989 if (deviate->mod == LY_DEVIATE_ADD) {
1990 if (yang_fill_unique(module, list, &list->unique[list->unique_size], str, NULL)) {
1991 free(str);
1992 goto error;
1993 }
1994 list->unique_size++;
1995 } else if (deviate->mod == LY_DEVIATE_DEL) {
1996 if (yang_fill_unique(module, list, &deviate->unique[i], str, NULL)) {
1997 free(str);
1998 goto error;
1999 }
2000 if (yang_deviate_delete_unique(module, deviate, list, i, str)) {
2001 free(str);
2002 goto error;
Pavol Vicane92421d2016-03-08 10:12:33 +01002003 }
2004 }
PavolVican75af21d2016-12-29 20:04:07 +01002005 free(str);
2006 }
2007 if (deviate->mod == LY_DEVIATE_ADD) {
2008 free(deviate->unique);
2009 deviate->unique = last_unique;
Pavol Vicane92421d2016-03-08 10:12:33 +01002010 }
Pavol Vican38321d02016-08-16 14:56:02 +02002011
Pavol Vican38321d02016-08-16 14:56:02 +02002012
PavolVican75af21d2016-12-29 20:04:07 +01002013 return EXIT_SUCCESS;
Pavol Vican021488a2016-01-25 23:56:12 +01002014error:
PavolVican75af21d2016-12-29 20:04:07 +01002015 if (deviate->mod == LY_DEVIATE_ADD) {
2016 for (i = i + 1; i < deviate->unique_size; ++i) {
2017 free(deviate->unique[i].expr);
2018 }
2019 free(deviate->unique);
2020 deviate->unique = last_unique;
2021
2022 }
Pavol Vican021488a2016-01-25 23:56:12 +01002023 return EXIT_FAILURE;
2024}
2025
Pavol Vicanec423c92016-10-24 21:33:43 +02002026static int
2027yang_fill_include(struct lys_module *trg, char *value, struct lys_include *inc,
2028 struct unres_schema *unres)
Pavol Vican021488a2016-01-25 23:56:12 +01002029{
Pavol Vican55870412016-03-10 12:36:21 +01002030 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002031 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002032 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002033
Pavol Vicanec423c92016-10-24 21:33:43 +02002034 str = lydict_insert_zc(trg->ctx, value);
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01002035 rc = lyp_check_include(trg, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002036 if (!rc) {
2037 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002038 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
PavolVican7d0b5ab2017-02-01 13:06:53 +01002039 if (yang_check_ext_instance(trg, &trg->inc[trg->inc_size].ext, trg->inc[trg->inc_size].ext_size,
2040 &trg->inc[trg->inc_size], unres)) {
2041 ret = -1;
2042 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02002043 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002044 } else if (rc == -1) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002045 lys_extension_instances_free(trg->ctx, inc->ext, inc->ext_size, NULL);
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002046 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002047 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002048
Pavol Vicanec423c92016-10-24 21:33:43 +02002049 lydict_remove(trg->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002050 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002051}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002052
PavolVicanc1807262017-01-31 18:00:27 +01002053struct lys_ext_instance *
PavolVican22e88682017-02-14 22:38:18 +01002054yang_ext_instance(void *node, enum yytokentype type, int is_ext_instance)
PavolVicanc1807262017-01-31 18:00:27 +01002055{
2056 struct lys_ext_instance ***ext, **tmp, *instance = NULL;
2057 LYEXT_PAR parent_type;
2058 uint8_t *size;
2059
2060 switch (type) {
2061 case MODULE_KEYWORD:
PavolVicane6fa67b2017-02-01 11:06:57 +01002062 case SUBMODULE_KEYWORD:
PavolVicanc1807262017-01-31 18:00:27 +01002063 ext = &((struct lys_module *)node)->ext;
2064 size = &((struct lys_module *)node)->ext_size;
2065 parent_type = LYEXT_PAR_MODULE;
2066 break;
PavolVican22e88682017-02-14 22:38:18 +01002067 case BELONGS_TO_KEYWORD:
2068 if (is_ext_instance) {
2069 ext = &((struct lys_ext_instance *)node)->ext;
2070 size = &((struct lys_ext_instance *)node)->ext_size;
2071 parent_type = LYEXT_PAR_EXTINST;
2072 } else {
2073 ext = &((struct lys_module *)node)->ext;
2074 size = &((struct lys_module *)node)->ext_size;
2075 parent_type = LYEXT_PAR_MODULE;
2076 }
2077 break;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002078 case IMPORT_KEYWORD:
2079 ext = &((struct lys_import *)node)->ext;
2080 size = &((struct lys_import *)node)->ext_size;
2081 parent_type = LYEXT_PAR_IMPORT;
2082 break;
2083 case INCLUDE_KEYWORD:
2084 ext = &((struct lys_include *)node)->ext;
2085 size = &((struct lys_include *)node)->ext_size;
2086 parent_type = LYEXT_PAR_INCLUDE;
2087 break;
PavolVican171717d2017-02-01 14:49:55 +01002088 case REVISION_KEYWORD:
2089 ext = &((struct lys_revision *)node)->ext;
2090 size = &((struct lys_revision *)node)->ext_size;
2091 parent_type = LYEXT_PAR_REVISION;
2092 break;
PavolVican70ce7452017-02-01 15:39:39 +01002093 case GROUPING_KEYWORD:
PavolVican59af9be2017-02-01 16:04:37 +01002094 case CONTAINER_KEYWORD:
PavolVicana6c3ac92017-02-03 13:15:13 +01002095 case LEAF_KEYWORD:
2096 case LEAF_LIST_KEYWORD:
2097 case LIST_KEYWORD:
PavolVican91eb04a2017-02-03 13:45:52 +01002098 case CHOICE_KEYWORD:
2099 case CASE_KEYWORD:
2100 case ANYXML_KEYWORD:
2101 case ANYDATA_KEYWORD:
PavolVican07596382017-02-03 14:05:12 +01002102 case USES_KEYWORD:
2103 case AUGMENT_KEYWORD:
PavolVican97d1e6f2017-02-03 14:39:52 +01002104 case ACTION_KEYWORD:
2105 case RPC_KEYWORD:
2106 case INPUT_KEYWORD:
2107 case OUTPUT_KEYWORD:
2108 case NOTIFICATION_KEYWORD:
PavolVican70ce7452017-02-01 15:39:39 +01002109 ext = &((struct lys_node *)node)->ext;
2110 size = &((struct lys_node *)node)->ext_size;
2111 parent_type = LYEXT_PAR_NODE;
2112 break;
PavolVican19dc6152017-02-06 12:04:15 +01002113 case ARGUMENT_KEYWORD:
PavolVican50809742017-02-18 21:22:54 +01002114 if (is_ext_instance) {
2115 ext = &((struct lys_ext_instance *)node)->ext;
2116 size = &((struct lys_ext_instance *)node)->ext_size;
2117 parent_type = LYEXT_PAR_EXTINST;
2118 } else {
2119 ext = &((struct lys_ext *)node)->ext;
2120 size = &((struct lys_ext *)node)->ext_size;
2121 parent_type = LYEXT_PAR_EXT;
2122 }
2123 break;
PavolVican19dc6152017-02-06 12:04:15 +01002124 case EXTENSION_KEYWORD:
2125 ext = &((struct lys_ext *)node)->ext;
2126 size = &((struct lys_ext *)node)->ext_size;
2127 parent_type = LYEXT_PAR_EXT;
2128 break;
PavolVican5393d3f2017-02-06 23:30:55 +01002129 case FEATURE_KEYWORD:
2130 ext = &((struct lys_feature *)node)->ext;
2131 size = &((struct lys_feature *)node)->ext_size;
2132 parent_type = LYEXT_PAR_FEATURE;
2133 break;
PavolVican8fa31242017-02-07 11:04:26 +01002134 case IDENTITY_KEYWORD:
2135 ext = &((struct lys_ident *)node)->ext;
2136 size = &((struct lys_ident *)node)->ext_size;
2137 parent_type = LYEXT_PAR_IDENT;
2138 break;
2139 case IF_FEATURE_KEYWORD:
2140 ext = &((struct lys_iffeature *)node)->ext;
2141 size = &((struct lys_iffeature *)node)->ext_size;
2142 parent_type = LYEXT_PAR_IFFEATURE;
2143 break;
PavolVicandf9e7972017-02-07 11:41:38 +01002144 case TYPEDEF_KEYWORD:
2145 ext = &((struct lys_tpdf *)node)->ext;
2146 size = &((struct lys_tpdf *)node)->ext_size;
2147 parent_type = LYEXT_PAR_TPDF;
2148 break;
PavolVican056fcd12017-02-07 15:36:53 +01002149 case TYPE_KEYWORD:
2150 ext = &((struct yang_type *)node)->type->ext;
2151 size = &((struct yang_type *)node)->type->ext_size;
2152 parent_type = LYEXT_PAR_TYPE;
2153 break;
2154 case LENGTH_KEYWORD:
2155 case PATTERN_KEYWORD:
2156 case RANGE_KEYWORD:
PavolVican38104a32017-02-08 12:25:23 +01002157 case MUST_KEYWORD:
PavolVican056fcd12017-02-07 15:36:53 +01002158 ext = &((struct lys_restr *)node)->ext;
2159 size = &((struct lys_restr *)node)->ext_size;
2160 parent_type = LYEXT_PAR_RESTR;
2161 break;
PavolVican59ba4602017-02-08 11:53:32 +01002162 case WHEN_KEYWORD:
2163 ext = &((struct lys_when *)node)->ext;
2164 size = &((struct lys_when *)node)->ext_size;
2165 parent_type = LYEXT_PAR_RESTR;
2166 break;
PavolVican056fcd12017-02-07 15:36:53 +01002167 case ENUM_KEYWORD:
2168 ext = &((struct lys_type_enum *)node)->ext;
2169 size = &((struct lys_type_enum *)node)->ext_size;
2170 parent_type = LYEXT_PAR_TYPE_ENUM;
2171 break;
2172 case BIT_KEYWORD:
2173 ext = &((struct lys_type_bit *)node)->ext;
2174 size = &((struct lys_type_bit *)node)->ext_size;
2175 parent_type = LYEXT_PAR_TYPE_BIT;
2176 break;
PavolVican77374ee2017-02-08 15:18:45 +01002177 case REFINE_KEYWORD:
2178 ext = &((struct lys_type_bit *)node)->ext;
2179 size = &((struct lys_type_bit *)node)->ext_size;
2180 parent_type = LYEXT_PAR_REFINE;
2181 break;
PavolVican6f000922017-02-10 12:56:59 +01002182 case DEVIATION_KEYWORD:
2183 ext = &((struct lys_deviation *)node)->ext;
2184 size = &((struct lys_deviation *)node)->ext_size;
2185 parent_type = LYEXT_PAR_DEVIATION;
2186 break;
2187 case NOT_SUPPORTED_KEYWORD:
2188 case ADD_KEYWORD:
2189 case DELETE_KEYWORD:
2190 case REPLACE_KEYWORD:
2191 ext = &((struct lys_deviate *)node)->ext;
2192 size = &((struct lys_deviate *)node)->ext_size;
2193 parent_type = LYEXT_PAR_DEVIATE;
2194 break;
PavolVicandefa4852017-02-10 13:13:23 +01002195 case EXTENSION_INSTANCE:
2196 ext = &((struct lys_ext_instance *)node)->ext;
2197 size = &((struct lys_ext_instance *)node)->ext_size;
2198 parent_type = LYEXT_PAR_EXTINST;
2199 break;
PavolVicanc1807262017-01-31 18:00:27 +01002200 default:
2201 LOGINT;
2202 return NULL;
2203 }
2204
2205 instance = calloc(1, sizeof *instance);
2206 if (!instance) {
2207 goto error;
2208 }
2209 instance->parent_type = parent_type;
2210 tmp = realloc(*ext, (*size + 1) * sizeof *tmp);
2211 if (!tmp) {
2212 goto error;
2213 }
2214 tmp[*size] = instance;
2215 *ext = tmp;
2216 (*size)++;
2217 return instance;
2218
2219error:
2220 LOGMEM;
2221 free(instance);
2222 return NULL;
2223}
2224
2225void *
2226yang_read_ext(struct lys_module *module, void *actual, char *ext_name, char *ext_arg,
PavolVican22e88682017-02-14 22:38:18 +01002227 enum yytokentype actual_type, enum yytokentype backup_type, int is_ext_instance)
PavolVicanc1807262017-01-31 18:00:27 +01002228{
2229 struct lys_ext_instance *instance;
PavolVican5334c892017-02-15 16:29:09 +01002230 LY_STMT stmt = LY_STMT_UNKNOWN;
PavolVicanc1807262017-01-31 18:00:27 +01002231
2232 if (backup_type != NODE) {
PavolVican4b80d042017-02-23 14:30:27 +01002233 instance = yang_ext_instance(actual, backup_type, is_ext_instance);
PavolVicane6fa67b2017-02-01 11:06:57 +01002234 if (!instance) {
2235 return NULL;
2236 }
PavolVicanc1807262017-01-31 18:00:27 +01002237 switch (actual_type) {
PavolVicana4b79bc2017-02-08 13:47:00 +01002238 case YANG_VERSION_KEYWORD:
2239 instance->insubstmt = LYEXT_SUBSTMT_VERSION;
PavolVican5334c892017-02-15 16:29:09 +01002240 stmt = LY_STMT_VERSION;
PavolVicana4b79bc2017-02-08 13:47:00 +01002241 break;
PavolVicanc1807262017-01-31 18:00:27 +01002242 case NAMESPACE_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002243 instance->insubstmt = LYEXT_SUBSTMT_NAMESPACE;
PavolVican5334c892017-02-15 16:29:09 +01002244 stmt = LY_STMT_NAMESPACE;
PavolVicanc1807262017-01-31 18:00:27 +01002245 break;
PavolVicane6fa67b2017-02-01 11:06:57 +01002246 case PREFIX_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002247 instance->insubstmt = LYEXT_SUBSTMT_PREFIX;
PavolVican5334c892017-02-15 16:29:09 +01002248 stmt = LY_STMT_PREFIX;
PavolVicane6fa67b2017-02-01 11:06:57 +01002249 break;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002250 case REVISION_DATE_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002251 instance->insubstmt = LYEXT_SUBSTMT_REVISIONDATE;
PavolVican5334c892017-02-15 16:29:09 +01002252 stmt = LY_STMT_REVISIONDATE;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002253 break;
2254 case DESCRIPTION_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002255 instance->insubstmt = LYEXT_SUBSTMT_DESCRIPTION;
PavolVican5334c892017-02-15 16:29:09 +01002256 stmt = LY_STMT_DESCRIPTION;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002257 break;
2258 case REFERENCE_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002259 instance->insubstmt = LYEXT_SUBSTMT_REFERENCE;
PavolVican5334c892017-02-15 16:29:09 +01002260 stmt = LY_STMT_REFERENCE;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002261 break;
PavolVican171717d2017-02-01 14:49:55 +01002262 case CONTACT_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002263 instance->insubstmt = LYEXT_SUBSTMT_CONTACT;
PavolVican5334c892017-02-15 16:29:09 +01002264 stmt = LY_STMT_CONTACT;
PavolVican171717d2017-02-01 14:49:55 +01002265 break;
2266 case ORGANIZATION_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002267 instance->insubstmt = LYEXT_SUBSTMT_ORGANIZATION;
PavolVican5334c892017-02-15 16:29:09 +01002268 stmt = LY_STMT_ORGANIZATION;
PavolVican171717d2017-02-01 14:49:55 +01002269 break;
PavolVican19dc6152017-02-06 12:04:15 +01002270 case YIN_ELEMENT_KEYWORD:
2271 instance->insubstmt = LYEXT_SUBSTMT_YINELEM;
PavolVican5334c892017-02-15 16:29:09 +01002272 stmt = LY_STMT_YINELEM;
PavolVican19dc6152017-02-06 12:04:15 +01002273 break;
2274 case STATUS_KEYWORD:
2275 instance->insubstmt = LYEXT_SUBSTMT_STATUS;
PavolVican5334c892017-02-15 16:29:09 +01002276 stmt = LY_STMT_STATUS;
PavolVican19dc6152017-02-06 12:04:15 +01002277 break;
PavolVican8fa31242017-02-07 11:04:26 +01002278 case BASE_KEYWORD:
2279 instance->insubstmt = LYEXT_SUBSTMT_BASE;
PavolVican5334c892017-02-15 16:29:09 +01002280 stmt = LY_STMT_BASE;
PavolVican056fcd12017-02-07 15:36:53 +01002281 if (backup_type == IDENTITY_KEYWORD) {
2282 instance->insubstmt_index = ((struct lys_ident *)actual)->base_size;
PavolVican5334c892017-02-15 16:29:09 +01002283 } else if (backup_type == TYPE_KEYWORD) {
PavolVican056fcd12017-02-07 15:36:53 +01002284 instance->insubstmt_index = ((struct yang_type *)actual)->type->info.ident.count;
2285 }
PavolVican8fa31242017-02-07 11:04:26 +01002286 break;
PavolVicandf9e7972017-02-07 11:41:38 +01002287 case DEFAULT_KEYWORD:
2288 instance->insubstmt = LYEXT_SUBSTMT_DEFAULT;
PavolVican5334c892017-02-15 16:29:09 +01002289 stmt = LY_STMT_DEFAULT;
PavolVican6f000922017-02-10 12:56:59 +01002290 switch (backup_type) {
2291 case LEAF_LIST_KEYWORD:
PavolVican3feb2f92017-02-08 13:44:39 +01002292 instance->insubstmt_index = ((struct lys_node_leaflist *)actual)->dflt_size;
PavolVican6f000922017-02-10 12:56:59 +01002293 break;
2294 case REFINE_KEYWORD:
PavolVican77374ee2017-02-08 15:18:45 +01002295 instance->insubstmt_index = ((struct lys_refine *)actual)->dflt_size;
PavolVican6f000922017-02-10 12:56:59 +01002296 break;
2297 case ADD_KEYWORD:
2298 instance->insubstmt_index = ((struct lys_deviate *)actual)->dflt_size;
2299 break;
2300 default:
2301 /* nothing changes */
2302 break;
PavolVican3feb2f92017-02-08 13:44:39 +01002303 }
PavolVicandf9e7972017-02-07 11:41:38 +01002304 break;
2305 case UNITS_KEYWORD:
2306 instance->insubstmt = LYEXT_SUBSTMT_UNITS;
PavolVican5334c892017-02-15 16:29:09 +01002307 stmt = LY_STMT_UNITS;
PavolVicandf9e7972017-02-07 11:41:38 +01002308 break;
PavolVican056fcd12017-02-07 15:36:53 +01002309 case REQUIRE_INSTANCE_KEYWORD:
2310 instance->insubstmt = LYEXT_SUBSTMT_REQINSTANCE;
PavolVican5334c892017-02-15 16:29:09 +01002311 stmt = LY_STMT_REQINSTANCE;
PavolVican056fcd12017-02-07 15:36:53 +01002312 break;
2313 case PATH_KEYWORD:
2314 instance->insubstmt = LYEXT_SUBSTMT_PATH;
PavolVican5334c892017-02-15 16:29:09 +01002315 stmt = LY_STMT_PATH;
PavolVican056fcd12017-02-07 15:36:53 +01002316 break;
2317 case ERROR_MESSAGE_KEYWORD:
2318 instance->insubstmt = LYEXT_SUBSTMT_ERRMSG;
PavolVican5334c892017-02-15 16:29:09 +01002319 stmt = LY_STMT_ERRMSG;
PavolVican056fcd12017-02-07 15:36:53 +01002320 break;
2321 case ERROR_APP_TAG_KEYWORD:
2322 instance->insubstmt = LYEXT_SUBSTMT_ERRTAG;
PavolVican5334c892017-02-15 16:29:09 +01002323 stmt = LY_STMT_ERRTAG;
PavolVican056fcd12017-02-07 15:36:53 +01002324 break;
2325 case MODIFIER_KEYWORD:
2326 instance->insubstmt = LYEXT_SUBSTMT_MODIFIER;
PavolVican5334c892017-02-15 16:29:09 +01002327 stmt = LY_STMT_MODIFIER;
PavolVican056fcd12017-02-07 15:36:53 +01002328 break;
2329 case FRACTION_DIGITS_KEYWORD:
2330 instance->insubstmt = LYEXT_SUBSTMT_DIGITS;
PavolVican5334c892017-02-15 16:29:09 +01002331 stmt = LY_STMT_DIGITS;
PavolVican056fcd12017-02-07 15:36:53 +01002332 break;
2333 case VALUE_KEYWORD:
2334 instance->insubstmt = LYEXT_SUBSTMT_VALUE;
PavolVican5334c892017-02-15 16:29:09 +01002335 stmt = LY_STMT_VALUE;
PavolVican056fcd12017-02-07 15:36:53 +01002336 break;
2337 case POSITION_KEYWORD:
2338 instance->insubstmt = LYEXT_SUBSTMT_POSITION;
PavolVican5334c892017-02-15 16:29:09 +01002339 stmt = LY_STMT_POSITION;
PavolVican056fcd12017-02-07 15:36:53 +01002340 break;
PavolVican5b910842017-02-08 13:08:47 +01002341 case PRESENCE_KEYWORD:
2342 instance->insubstmt = LYEXT_SUBSTMT_PRESENCE;
PavolVican5334c892017-02-15 16:29:09 +01002343 stmt = LY_STMT_PRESENCE;
PavolVican5b910842017-02-08 13:08:47 +01002344 break;
2345 case CONFIG_KEYWORD:
2346 instance->insubstmt = LYEXT_SUBSTMT_CONFIG;
PavolVican5334c892017-02-15 16:29:09 +01002347 stmt = LY_STMT_CONFIG;
PavolVican5b910842017-02-08 13:08:47 +01002348 break;
PavolVican3feb2f92017-02-08 13:44:39 +01002349 case MANDATORY_KEYWORD:
2350 instance->insubstmt = LYEXT_SUBSTMT_MANDATORY;
PavolVican5334c892017-02-15 16:29:09 +01002351 stmt = LY_STMT_MANDATORY;
PavolVican3feb2f92017-02-08 13:44:39 +01002352 break;
2353 case MIN_ELEMENTS_KEYWORD:
2354 instance->insubstmt = LYEXT_SUBSTMT_MIN;
PavolVican5334c892017-02-15 16:29:09 +01002355 stmt = LY_STMT_MIN;
PavolVican3feb2f92017-02-08 13:44:39 +01002356 break;
2357 case MAX_ELEMENTS_KEYWORD:
2358 instance->insubstmt = LYEXT_SUBSTMT_MAX;
PavolVican5334c892017-02-15 16:29:09 +01002359 stmt = LY_STMT_MAX;
PavolVican3feb2f92017-02-08 13:44:39 +01002360 break;
2361 case ORDERED_BY_KEYWORD:
2362 instance->insubstmt = LYEXT_SUBSTMT_ORDEREDBY;
PavolVican5334c892017-02-15 16:29:09 +01002363 stmt = LY_STMT_ORDEREDBY;
PavolVican3feb2f92017-02-08 13:44:39 +01002364 break;
2365 case KEY_KEYWORD:
2366 instance->insubstmt = LYEXT_SUBSTMT_KEY;
PavolVican5334c892017-02-15 16:29:09 +01002367 stmt = LY_STMT_KEY;
PavolVican3feb2f92017-02-08 13:44:39 +01002368 break;
2369 case UNIQUE_KEYWORD:
2370 instance->insubstmt = LYEXT_SUBSTMT_UNIQUE;
PavolVican5334c892017-02-15 16:29:09 +01002371 stmt = LY_STMT_UNIQUE;
2372 switch (backup_type) {
2373 case LIST_KEYWORD:
PavolVican6f000922017-02-10 12:56:59 +01002374 instance->insubstmt_index = ((struct lys_node_list *)actual)->unique_size;
PavolVican5334c892017-02-15 16:29:09 +01002375 break;
2376 case ADD_KEYWORD:
2377 case DELETE_KEYWORD:
2378 case REPLACE_KEYWORD:
PavolVican6f000922017-02-10 12:56:59 +01002379 instance->insubstmt_index = ((struct lys_deviate *)actual)->unique_size;
PavolVican5334c892017-02-15 16:29:09 +01002380 break;
2381 default:
2382 /* nothing changes */
2383 break;
PavolVican6f000922017-02-10 12:56:59 +01002384 }
PavolVican3feb2f92017-02-08 13:44:39 +01002385 break;
PavolVicanc1807262017-01-31 18:00:27 +01002386 default:
2387 LOGINT;
2388 return NULL;
2389 }
2390 } else {
PavolVican4b80d042017-02-23 14:30:27 +01002391 instance = yang_ext_instance(actual, actual_type, is_ext_instance);
PavolVicane6fa67b2017-02-01 11:06:57 +01002392 if (!instance) {
2393 return NULL;
2394 }
Radek Krejcifebdad72017-02-06 11:35:51 +01002395 instance->insubstmt = LYEXT_SUBSTMT_SELF;
PavolVican19dc6152017-02-06 12:04:15 +01002396 switch (actual_type) {
2397 case ARGUMENT_KEYWORD:
2398 instance->insubstmt = LYEXT_SUBSTMT_ARGUMENT;
PavolVican5334c892017-02-15 16:29:09 +01002399 stmt = LY_STMT_ARGUMENT;
PavolVican19dc6152017-02-06 12:04:15 +01002400 break;
PavolVicanfaa49702017-02-06 12:10:59 +01002401 case BELONGS_TO_KEYWORD:
2402 instance->insubstmt = LYEXT_SUBSTMT_BELONGSTO;
PavolVican5334c892017-02-15 16:29:09 +01002403 stmt = LY_STMT_BELONGSTO;
PavolVicanfaa49702017-02-06 12:10:59 +01002404 break;
PavolVican19dc6152017-02-06 12:04:15 +01002405 default:
2406 instance->insubstmt = LYEXT_SUBSTMT_SELF;
2407 break;
2408 }
PavolVicanc1807262017-01-31 18:00:27 +01002409 }
2410 instance->flags |= LYEXT_OPT_YANG;
2411 instance->def = (struct lys_ext *)ext_name; /* hack for UNRES */
2412 instance->arg_value = lydict_insert_zc(module->ctx, ext_arg);
PavolVican5334c892017-02-15 16:29:09 +01002413 if (is_ext_instance && stmt != LY_STMT_UNKNOWN && instance->parent_type == LYEXT_PAR_EXTINST) {
2414 instance->insubstmt_index = yang_fill_ext_substm_index(actual, stmt, backup_type);
2415 }
PavolVicanc1807262017-01-31 18:00:27 +01002416 return instance;
2417}
2418
Pavol Vicanf4717e62016-03-16 11:30:01 +01002419int
Radek Krejci7212e0a2017-03-08 15:58:22 +01002420store_config_flag(struct lys_node *node, int options)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002421{
Pavol Vicanec598812016-11-30 14:13:38 +01002422 switch (node->nodetype) {
2423 case LYS_CONTAINER:
2424 case LYS_LEAF:
2425 case LYS_LEAFLIST:
2426 case LYS_LIST:
2427 case LYS_CHOICE:
2428 case LYS_ANYDATA:
2429 case LYS_ANYXML:
Radek Krejci7212e0a2017-03-08 15:58:22 +01002430 if (options & LYS_PARSE_OPT_CFG_IGNORE) {
Pavol Vicanec598812016-11-30 14:13:38 +01002431 node->flags |= node->flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET));
Radek Krejci7212e0a2017-03-08 15:58:22 +01002432 } else if (!(options & LYS_PARSE_OPT_CFG_NOINHERIT)) {
Pavol Vicanec598812016-11-30 14:13:38 +01002433 if (!(node->flags & LYS_CONFIG_MASK)) {
2434 /* get config flag from parent */
2435 if (node->parent) {
2436 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2437 } else {
2438 /* default config is true */
2439 node->flags |= LYS_CONFIG_W;
2440 }
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002441 }
2442 }
Pavol Vicanec598812016-11-30 14:13:38 +01002443 break;
2444 case LYS_CASE:
Radek Krejci7212e0a2017-03-08 15:58:22 +01002445 if (!(options & (LYS_PARSE_OPT_CFG_IGNORE | LYS_PARSE_OPT_CFG_NOINHERIT))) {
Pavol Vicanec598812016-11-30 14:13:38 +01002446 if (!(node->flags & LYS_CONFIG_MASK)) {
2447 /* get config flag from parent */
2448 if (node->parent) {
2449 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2450 } else {
2451 /* default config is true */
2452 node->flags |= LYS_CONFIG_W;
2453 }
2454 }
2455 }
2456 break;
Pavol Vicanec598812016-11-30 14:13:38 +01002457 default:
2458 break;
Pavol Vican1938d882016-04-10 13:36:31 +02002459 }
Pavol Vicanec598812016-11-30 14:13:38 +01002460
Radek Krejci7212e0a2017-03-08 15:58:22 +01002461 return EXIT_SUCCESS;
Pavol Vican1938d882016-04-10 13:36:31 +02002462}
2463
2464int
Pavol Vican9d50a772016-10-14 22:23:36 +02002465yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres,
2466 const char *data, unsigned int size_data, struct lys_node **node)
Pavol Vican1938d882016-04-10 13:36:31 +02002467{
Pavol Vican974377b2016-03-23 00:38:53 +01002468 unsigned int size;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002469 YY_BUFFER_STATE bp;
2470 yyscan_t scanner = NULL;
PavolVican9e81c6a2017-02-09 13:09:07 +01002471 int ret = 0;
Pavol Vican082afd02016-10-25 12:39:15 +02002472 struct lys_module *trg;
PavolVican196694c2017-01-27 10:33:09 +01002473 struct yang_parameter param;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002474
Pavol Vican8e7110b2016-03-22 17:00:26 +01002475 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002476 yylex_init(&scanner);
2477 bp = yy_scan_buffer((char *)data, size, scanner);
2478 yy_switch_to_buffer(bp, scanner);
PavolVican22e88682017-02-14 22:38:18 +01002479 memset(&param, 0, sizeof param);
PavolVican196694c2017-01-27 10:33:09 +01002480 param.module = module;
2481 param.submodule = submodule;
2482 param.unres = unres;
2483 param.node = node;
PavolVican22e88682017-02-14 22:38:18 +01002484 param.flags |= YANG_REMOVE_IMPORT;
PavolVican196694c2017-01-27 10:33:09 +01002485 if (yyparse(scanner, &param)) {
PavolVican22e88682017-02-14 22:38:18 +01002486 if (param.flags & YANG_REMOVE_IMPORT) {
Pavol Vican082afd02016-10-25 12:39:15 +02002487 trg = (submodule) ? (struct lys_module *)submodule : module;
2488 yang_free_import(trg->ctx, trg->imp, 0, trg->imp_size);
2489 yang_free_include(trg->ctx, trg->inc, 0, trg->inc_size);
2490 trg->inc_size = 0;
2491 trg->imp_size = 0;
2492 }
PavolVican22e88682017-02-14 22:38:18 +01002493 ret = (param.flags & YANG_EXIST_MODULE) ? 1 : -1;
2494 }
2495 yy_delete_buffer(bp, scanner);
2496 yylex_destroy(scanner);
2497 return ret;
2498}
2499
2500int
2501yang_parse_ext_substatement(struct lys_module *module, struct unres_schema *unres, const char *data,
2502 char *ext_name, struct lys_ext_instance_complex *ext)
2503{
2504 unsigned int size;
2505 YY_BUFFER_STATE bp;
2506 yyscan_t scanner = NULL;
2507 int ret = 0;
2508 struct yang_parameter param;
PavolVicanf3091bf2017-02-19 18:27:01 +01002509 struct lys_node *node = NULL;
PavolVican22e88682017-02-14 22:38:18 +01002510
PavolVicandb0e8172017-02-20 00:46:09 +01002511 if (!data) {
2512 return EXIT_SUCCESS;
2513 }
PavolVican22e88682017-02-14 22:38:18 +01002514 size = strlen(data) + 2;
2515 yylex_init(&scanner);
2516 bp = yy_scan_buffer((char *)data, size, scanner);
2517 yy_switch_to_buffer(bp, scanner);
2518 memset(&param, 0, sizeof param);
2519 param.module = module;
2520 param.unres = unres;
PavolVicanf3091bf2017-02-19 18:27:01 +01002521 param.node = &node;
PavolVican22e88682017-02-14 22:38:18 +01002522 param.actual_node = (void **)ext;
2523 param.data_node = (void **)ext_name;
2524 param.flags |= EXT_INSTANCE_SUBSTMT;
2525 if (yyparse(scanner, &param)) {
PavolVicanf3091bf2017-02-19 18:27:01 +01002526 yang_free_nodes(module->ctx, node);
PavolVican22e88682017-02-14 22:38:18 +01002527 ret = -1;
PavolVicanf3091bf2017-02-19 18:27:01 +01002528 } else {
2529 /* success parse, but it needs some sematic controls */
Radek Krejci7212e0a2017-03-08 15:58:22 +01002530 if (node && yang_check_nodes(module, (struct lys_node *)ext, node, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) {
PavolVicanf3091bf2017-02-19 18:27:01 +01002531 ret = -1;
2532 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002533 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002534 yy_delete_buffer(bp, scanner);
2535 yylex_destroy(scanner);
Pavol Vican1938d882016-04-10 13:36:31 +02002536 return ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002537}
2538
2539struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002540yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002541{
2542
PavolVican9e81c6a2017-02-09 13:09:07 +01002543 struct lys_module *module = NULL, *tmp_mod;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002544 struct unres_schema *unres = NULL;
Pavol Vican9d50a772016-10-14 22:23:36 +02002545 struct lys_node *node = NULL;
PavolVican9e81c6a2017-02-09 13:09:07 +01002546 int ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002547
2548 unres = calloc(1, sizeof *unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002549 LY_CHECK_ERR_GOTO(!unres, LOGMEM, error);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002550
2551 module = calloc(1, sizeof *module);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002552 LY_CHECK_ERR_GOTO(!module, LOGMEM, error);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002553
2554 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002555 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002556 module->type = 0;
2557 module->implemented = (implement ? 1 : 0);
2558
Radek Krejci9e757e02017-03-08 17:18:09 +01002559 /* add into the list of processed modules */
2560 if (lyp_check_circmod_add(module)) {
2561 goto error;
2562 }
2563
PavolVican9e81c6a2017-02-09 13:09:07 +01002564 ret = yang_parse_mem(module, NULL, unres, data, size, &node);
2565 if (ret == -1) {
Pavol Vican05810b62016-11-23 14:07:22 +01002566 free_yang_common(module, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002567 goto error;
Michal Vasko7b460e52017-02-10 14:50:26 +01002568 } else if (ret == 1) {
PavolVican9e81c6a2017-02-09 13:09:07 +01002569 assert(!unres->count);
2570 } else {
2571 if (yang_check_sub_module(module, unres, node)) {
2572 goto error;
2573 }
Pavol Vican7313fc02016-11-14 01:10:31 +01002574
Michal Vasko7b460e52017-02-10 14:50:26 +01002575 if (unres->count && resolve_unres_schema(module, unres)) {
PavolVican9e81c6a2017-02-09 13:09:07 +01002576 goto error;
2577 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002578 }
2579
PavolVicanfe83b152017-02-19 03:19:29 +01002580 lyp_sort_revisions(module);
2581
Pavol Vican8e7110b2016-03-22 17:00:26 +01002582 if (revision) {
2583 /* check revision of the parsed model */
2584 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2585 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2586 module->name, module->rev[0].date, revision);
2587 goto error;
2588 }
2589 }
2590
PavolVican9e81c6a2017-02-09 13:09:07 +01002591 /* add into context if not already there */
2592 if (!ret) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01002593 /* check correctness of includes */
2594 if (lyp_check_include_missing(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002595 goto error;
2596 }
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01002597
PavolVicanfd6f6952017-02-14 00:09:42 +01002598 /* remove our submodules from the parsed submodules list */
2599 lyp_del_includedup(module);
2600
2601
PavolVican6f000922017-02-10 12:56:59 +01002602 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01002603 goto error;
2604 }
2605
PavolVican9e81c6a2017-02-09 13:09:07 +01002606 if (lyp_ctx_add_module(module)) {
Michal Vasko7da5b0b2016-05-02 16:36:59 +02002607 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002608 }
PavolVican9e81c6a2017-02-09 13:09:07 +01002609
2610 if (module->deviation_size && !module->implemented) {
2611 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2612 /* deviations always causes target to be made implemented,
2613 * but augents and leafrefs not, so we have to apply them now */
2614 if (lys_set_implemented(module)) {
2615 goto error;
2616 }
2617 }
2618 } else {
2619 tmp_mod = module;
2620
2621 /* get the model from the context */
2622 module = (struct lys_module *)ly_ctx_get_module(ctx, module->name, revision);
2623 assert(module);
2624
2625 /* free what was parsed */
2626 lys_free(tmp_mod, NULL, 0);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002627 }
2628
Michal Vasko44ab1462017-05-18 13:18:36 +02002629 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01002630 lyp_check_circmod_pop(ctx);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002631 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2632 return module;
2633
2634error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002635 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02002636 unres_schema_free(module, &unres, 1);
Radek Krejcif505cd12017-06-13 10:32:48 +02002637 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01002638 if (ly_vecode != LYVE_SUBMODULE) {
2639 LOGERR(ly_errno, "Module parsing failed.");
2640 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002641 return NULL;
2642 }
2643
Radek Krejcif505cd12017-06-13 10:32:48 +02002644 if (module->name) {
2645 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
2646 } else {
2647 LOGERR(ly_errno, "Module parsing failed.");
2648 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002649
Radek Krejci9e757e02017-03-08 17:18:09 +01002650 lyp_check_circmod_pop(ctx);
Michal Vaskocf0489e2017-02-13 11:57:45 +01002651 lyp_del_includedup(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002652 lys_sub_module_remove_devs_augs(module);
2653 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002654 return NULL;
2655}
2656
2657struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002658yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002659{
2660 struct lys_submodule *submodule;
Pavol Vican9d50a772016-10-14 22:23:36 +02002661 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002662
2663 submodule = calloc(1, sizeof *submodule);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002664 LY_CHECK_ERR_GOTO(!submodule, LOGMEM, error);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002665
2666 submodule->ctx = module->ctx;
2667 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02002668 submodule->implemented = module->implemented;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002669 submodule->belongsto = module;
2670
Radek Krejci9e757e02017-03-08 17:18:09 +01002671 /* add into the list of processed modules */
2672 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
2673 goto error;
2674 }
2675
PavolVican9e81c6a2017-02-09 13:09:07 +01002676 /* module cannot be changed in this case and 1 cannot be returned */
Pavol Vican9d50a772016-10-14 22:23:36 +02002677 if (yang_parse_mem(module, submodule, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002678 free_yang_common((struct lys_module *)submodule, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002679 goto error;
2680 }
2681
PavolVicanfe83b152017-02-19 03:19:29 +01002682 lyp_sort_revisions((struct lys_module *)submodule);
2683
Pavol Vican7313fc02016-11-14 01:10:31 +01002684 if (yang_check_sub_module((struct lys_module *)submodule, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002685 goto error;
2686 }
2687
Radek Krejci9e757e02017-03-08 17:18:09 +01002688 lyp_check_circmod_pop(module->ctx);
2689
Pavol Vican8e7110b2016-03-22 17:00:26 +01002690 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002691 return submodule;
2692
2693error:
2694 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02002695 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002696
2697 if (!submodule || !submodule->name) {
2698 free(submodule);
2699 LOGERR(ly_errno, "Submodule parsing failed.");
2700 return NULL;
2701 }
2702
2703 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2704
Radek Krejci9e757e02017-03-08 17:18:09 +01002705 lyp_check_circmod_pop(module->ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002706 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2707 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002708 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002709 return NULL;
2710}
Pavol Vican8760bb72016-04-07 09:44:01 +02002711
2712static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002713read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2714{
2715 int k = 0, j;
2716
2717 while (in_index < size) {
2718 if (input[in_index] == ' ') {
2719 k++;
2720 } else if (input[in_index] == '\t') {
2721 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2722 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002723 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2724 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2725 k += 8;
2726 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002727 } else {
2728 break;
2729 }
2730 ++in_index;
2731 if (k >= indent) {
2732 for (j = k - indent; j > 0; --j) {
2733 output[*out_index] = ' ';
Pavol Vicana7bf3372016-12-01 15:58:18 +01002734 if (j > 1) {
2735 ++(*out_index);
2736 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002737 }
2738 break;
2739 }
2740 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002741 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002742}
2743
2744char *
PavolVican1bc22062017-01-19 15:09:04 +01002745yang_read_string(const char *input, char *output, int size, int offset, int indent) {
Pavol Vican3f598892016-09-28 15:41:07 +02002746 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002747
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002748 while (i < size) {
2749 switch (input[i]) {
2750 case '\n':
2751 out_index -= space;
2752 output[out_index] = '\n';
2753 space = 0;
2754 i = read_indent(input, indent, size, i + 1, &out_index, output);
2755 break;
2756 case ' ':
2757 case '\t':
2758 output[out_index] = input[i];
2759 ++space;
2760 break;
2761 case '\\':
2762 if (input[i + 1] == 'n') {
2763 out_index -= space;
2764 output[out_index] = '\n';
2765 space = 0;
2766 i = read_indent(input, indent, size, i + 2, &out_index, output);
2767 } else if (input[i + 1] == 't') {
2768 output[out_index] = '\t';
2769 ++i;
2770 ++space;
2771 } else if (input[i + 1] == '\\') {
2772 output[out_index] = '\\';
2773 ++i;
2774 } else if ((i + 1) != size && input[i + 1] == '"') {
2775 output[out_index] = '"';
2776 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002777 } else {
PavolVican1bc22062017-01-19 15:09:04 +01002778 /* backslash must not be followed by any other character */
2779 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
2780 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002781 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002782 break;
2783 default:
2784 output[out_index] = input[i];
2785 space = 0;
2786 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002787 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002788 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002789 ++out_index;
2790 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002791 output[out_index] = '\0';
2792 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002793 output = realloc(output, out_index + 1);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002794 LY_CHECK_ERR_RETURN(!output, LOGMEM, NULL);
Pavol Vican8760bb72016-04-07 09:44:01 +02002795 }
Pavol Vican3f598892016-09-28 15:41:07 +02002796 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002797}
Pavol Vican1cc4e192016-10-24 16:38:31 +02002798
2799/* free function */
2800
PavolVicana0fdbf32017-02-15 17:59:02 +01002801void
2802yang_type_free(struct ly_ctx *ctx, struct lys_type *type)
Pavol Vican7313fc02016-11-14 01:10:31 +01002803{
2804 struct yang_type *stype = (struct yang_type *)type->der;
2805 int i;
2806
2807 if (!stype) {
2808 return ;
2809 }
PavolVicane87cb932016-12-30 15:36:18 +01002810 if (type->base == LY_TYPE_DER || type->base == LY_TYPE_ERR || type->base == LY_TYPE_UNION) {
2811 lydict_remove(ctx, stype->name);
2812 if (stype->base == LY_TYPE_IDENT && (!(stype->flags & LYS_NO_ERASE_IDENTITY))) {
2813 for (i = 0; i < type->info.ident.count; ++i) {
2814 free(type->info.ident.ref[i]);
2815 }
Pavol Vican7313fc02016-11-14 01:10:31 +01002816 }
PavolVicane87cb932016-12-30 15:36:18 +01002817 if (stype->base == LY_TYPE_UNION) {
2818 for (i = 0; i < type->info.uni.count; ++i) {
2819 yang_type_free(ctx, &type->info.uni.types[i]);
2820 }
2821 free(type->info.uni.types);
2822 type->base = LY_TYPE_DER;
2823 } else {
2824 type->base = stype->base;
2825 }
2826 free(stype);
2827 type->der = NULL;
Pavol Vican7313fc02016-11-14 01:10:31 +01002828 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02002829 lys_type_free(ctx, type, NULL);
Pavol Vican36aff862016-11-26 17:07:05 +01002830 type->base = LY_TYPE_DER;
PavolVican575a9342017-02-15 18:14:39 +01002831 type->ext_size = 0;
2832 type->ext = NULL;
Pavol Vican7313fc02016-11-14 01:10:31 +01002833}
2834
2835static void
2836yang_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf, uint8_t start, uint8_t size)
2837{
2838 uint8_t i;
2839
2840 assert(ctx);
2841 if (!tpdf) {
2842 return;
2843 }
2844
2845 for (i = start; i < size; ++i) {
Pavol Vicancee10802016-11-22 15:48:35 +01002846 lydict_remove(ctx, tpdf[i].name);
2847 lydict_remove(ctx, tpdf[i].dsc);
2848 lydict_remove(ctx, tpdf[i].ref);
Pavol Vican7313fc02016-11-14 01:10:31 +01002849
Pavol Vicancee10802016-11-22 15:48:35 +01002850 yang_type_free(ctx, &tpdf[i].type);
Pavol Vican7313fc02016-11-14 01:10:31 +01002851
Pavol Vicancee10802016-11-22 15:48:35 +01002852 lydict_remove(ctx, tpdf[i].units);
2853 lydict_remove(ctx, tpdf[i].dflt);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002854 lys_extension_instances_free(ctx, tpdf[i].ext, tpdf[i].ext_size, NULL);
Pavol Vican7313fc02016-11-14 01:10:31 +01002855 }
2856}
2857
Pavol Vican1cc4e192016-10-24 16:38:31 +02002858static void
2859yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size)
2860{
2861 uint8_t i;
2862
2863 for (i = start; i < size; ++i){
2864 free((char *)imp[i].module);
2865 lydict_remove(ctx, imp[i].prefix);
2866 lydict_remove(ctx, imp[i].dsc);
2867 lydict_remove(ctx, imp[i].ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002868 lys_extension_instances_free(ctx, imp[i].ext, imp[i].ext_size, NULL);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002869 }
2870}
2871
Pavol Vicanec423c92016-10-24 21:33:43 +02002872static void
2873yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size)
2874{
2875 uint8_t i;
2876
2877 for (i = start; i < size; ++i){
2878 free((char *)inc[i].submodule);
2879 lydict_remove(ctx, inc[i].dsc);
2880 lydict_remove(ctx, inc[i].ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002881 lys_extension_instances_free(ctx, inc[i].ext, inc[i].ext_size, NULL);
Pavol Vicanec423c92016-10-24 21:33:43 +02002882 }
2883}
2884
Pavol Vican36e27272016-11-22 15:47:28 +01002885static void
2886yang_free_ident_base(struct lys_ident *ident, uint32_t start, uint32_t size)
2887{
2888 uint32_t i;
2889 uint8_t j;
2890
2891 /* free base name */
2892 for (i = start; i < size; ++i) {
2893 for (j = 0; j < ident[i].base_size; ++j) {
2894 free(ident[i].base[j]);
2895 }
2896 }
2897}
2898
Pavol Vican05810b62016-11-23 14:07:22 +01002899static void
2900yang_free_grouping(struct ly_ctx *ctx, struct lys_node_grp * grp)
2901{
2902 yang_tpdf_free(ctx, grp->tpdf, 0, grp->tpdf_size);
2903 free(grp->tpdf);
2904}
2905
2906static void
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002907yang_free_container(struct ly_ctx *ctx, struct lys_node_container * cont)
2908{
2909 uint8_t i;
2910
2911 yang_tpdf_free(ctx, cont->tpdf, 0, cont->tpdf_size);
2912 free(cont->tpdf);
2913 lydict_remove(ctx, cont->presence);
2914
Pavol Vicanfda8c802016-12-03 02:00:42 +01002915 for (i = 0; i < cont->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002916 lys_restr_free(ctx, &cont->must[i], NULL);
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002917 }
2918 free(cont->must);
2919
Radek Krejci5138e9f2017-04-12 13:10:46 +02002920 lys_when_free(ctx, cont->when, NULL);
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002921}
2922
2923static void
Pavol Vicana69aff22016-11-24 18:23:50 +01002924yang_free_leaf(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
2925{
2926 uint8_t i;
2927
2928 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002929 lys_restr_free(ctx, &leaf->must[i], NULL);
Pavol Vicana69aff22016-11-24 18:23:50 +01002930 }
2931 free(leaf->must);
2932
Radek Krejci5138e9f2017-04-12 13:10:46 +02002933 lys_when_free(ctx, leaf->when, NULL);
Pavol Vicana69aff22016-11-24 18:23:50 +01002934
2935 yang_type_free(ctx, &leaf->type);
2936 lydict_remove(ctx, leaf->units);
2937 lydict_remove(ctx, leaf->dflt);
2938}
2939
2940static void
Pavol Vican36aff862016-11-26 17:07:05 +01002941yang_free_leaflist(struct ly_ctx *ctx, struct lys_node_leaflist *leaflist)
2942{
2943 uint8_t i;
2944
2945 for (i = 0; i < leaflist->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002946 lys_restr_free(ctx, &leaflist->must[i], NULL);
Pavol Vican36aff862016-11-26 17:07:05 +01002947 }
2948 free(leaflist->must);
2949
2950 for (i = 0; i < leaflist->dflt_size; i++) {
2951 lydict_remove(ctx, leaflist->dflt[i]);
2952 }
2953 free(leaflist->dflt);
2954
Radek Krejci5138e9f2017-04-12 13:10:46 +02002955 lys_when_free(ctx, leaflist->when, NULL);
Pavol Vican36aff862016-11-26 17:07:05 +01002956
2957 yang_type_free(ctx, &leaflist->type);
2958 lydict_remove(ctx, leaflist->units);
2959}
2960
2961static void
Pavol Vicand8136a42016-11-27 13:28:04 +01002962yang_free_list(struct ly_ctx *ctx, struct lys_node_list *list)
2963{
2964 uint8_t i;
2965
2966 yang_tpdf_free(ctx, list->tpdf, 0, list->tpdf_size);
2967 free(list->tpdf);
2968
2969 for (i = 0; i < list->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002970 lys_restr_free(ctx, &list->must[i], NULL);
Pavol Vicand8136a42016-11-27 13:28:04 +01002971 }
2972 free(list->must);
2973
Radek Krejci5138e9f2017-04-12 13:10:46 +02002974 lys_when_free(ctx, list->when, NULL);
Pavol Vicand8136a42016-11-27 13:28:04 +01002975
2976 for (i = 0; i < list->unique_size; ++i) {
2977 free(list->unique[i].expr);
2978 }
2979 free(list->unique);
2980
2981 free(list->keys);
2982}
2983
2984static void
Pavol Vican36ace102016-11-28 11:46:59 +01002985yang_free_choice(struct ly_ctx *ctx, struct lys_node_choice *choice)
2986{
2987 free(choice->dflt);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002988 lys_when_free(ctx, choice->when, NULL);
Pavol Vican36ace102016-11-28 11:46:59 +01002989}
2990
2991static void
Pavol Vicanbfa1a582016-11-28 15:35:59 +01002992yang_free_anydata(struct ly_ctx *ctx, struct lys_node_anydata *anydata)
2993{
2994 uint8_t i;
2995
2996 for (i = 0; i < anydata->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002997 lys_restr_free(ctx, &anydata->must[i], NULL);
Pavol Vicanbfa1a582016-11-28 15:35:59 +01002998 }
2999 free(anydata->must);
3000
Radek Krejci5138e9f2017-04-12 13:10:46 +02003001 lys_when_free(ctx, anydata->when, NULL);
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003002}
3003
3004static void
Pavol Vican78729392016-11-28 17:18:22 +01003005yang_free_inout(struct ly_ctx *ctx, struct lys_node_inout *inout)
3006{
3007 uint8_t i;
3008
3009 yang_tpdf_free(ctx, inout->tpdf, 0, inout->tpdf_size);
3010 free(inout->tpdf);
3011
3012 for (i = 0; i < inout->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003013 lys_restr_free(ctx, &inout->must[i], NULL);
Pavol Vican78729392016-11-28 17:18:22 +01003014 }
3015 free(inout->must);
3016}
3017
3018static void
Pavol Vican29bf8802016-11-28 20:44:57 +01003019yang_free_notif(struct ly_ctx *ctx, struct lys_node_notif *notif)
3020{
3021 uint8_t i;
3022
3023 yang_tpdf_free(ctx, notif->tpdf, 0, notif->tpdf_size);
3024 free(notif->tpdf);
3025
3026 for (i = 0; i < notif->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003027 lys_restr_free(ctx, &notif->must[i], NULL);
Pavol Vican29bf8802016-11-28 20:44:57 +01003028 }
3029 free(notif->must);
3030}
3031
3032static void
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003033yang_free_uses(struct ly_ctx *ctx, struct lys_node_uses *uses)
3034{
3035 int i, j;
3036
3037 for (i = 0; i < uses->refine_size; i++) {
3038 lydict_remove(ctx, uses->refine[i].target_name);
3039 lydict_remove(ctx, uses->refine[i].dsc);
3040 lydict_remove(ctx, uses->refine[i].ref);
3041
3042 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003043 lys_restr_free(ctx, &uses->refine[i].must[j], NULL);
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003044 }
3045 free(uses->refine[i].must);
3046
3047 for (j = 0; j < uses->refine[i].dflt_size; j++) {
3048 lydict_remove(ctx, uses->refine[i].dflt[j]);
3049 }
3050 free(uses->refine[i].dflt);
3051
3052 if (uses->refine[i].target_type & LYS_CONTAINER) {
3053 lydict_remove(ctx, uses->refine[i].mod.presence);
3054 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02003055 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size, NULL);
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003056 }
3057 free(uses->refine);
3058
Radek Krejci5138e9f2017-04-12 13:10:46 +02003059 lys_when_free(ctx, uses->when, NULL);
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003060}
3061
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003062static void
Pavol Vican05810b62016-11-23 14:07:22 +01003063yang_free_nodes(struct ly_ctx *ctx, struct lys_node *node)
3064{
3065 struct lys_node *tmp, *child, *sibling;
3066
3067 if (!node) {
3068 return;
3069 }
3070 tmp = node;
Pavol Vican05810b62016-11-23 14:07:22 +01003071
3072 while (tmp) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01003073 child = tmp->child;
Pavol Vican05810b62016-11-23 14:07:22 +01003074 sibling = tmp->next;
3075 /* common part */
3076 lydict_remove(ctx, tmp->name);
3077 if (!(tmp->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003078 lys_iffeature_free(ctx, tmp->iffeature, tmp->iffeature_size, NULL);
Pavol Vicane87ff8d2016-11-24 18:25:01 +01003079 lydict_remove(ctx, tmp->dsc);
3080 lydict_remove(ctx, tmp->ref);
Pavol Vican05810b62016-11-23 14:07:22 +01003081 }
3082
3083 switch (tmp->nodetype) {
3084 case LYS_GROUPING:
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003085 case LYS_RPC:
3086 case LYS_ACTION:
Pavol Vican05810b62016-11-23 14:07:22 +01003087 yang_free_grouping(ctx, (struct lys_node_grp *)tmp);
3088 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003089 case LYS_CONTAINER:
3090 yang_free_container(ctx, (struct lys_node_container *)tmp);
3091 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01003092 case LYS_LEAF:
3093 yang_free_leaf(ctx, (struct lys_node_leaf *)tmp);
3094 break;
Pavol Vican36aff862016-11-26 17:07:05 +01003095 case LYS_LEAFLIST:
3096 yang_free_leaflist(ctx, (struct lys_node_leaflist *)tmp);
3097 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003098 case LYS_LIST:
3099 yang_free_list(ctx, (struct lys_node_list *)tmp);
3100 break;
Pavol Vican36ace102016-11-28 11:46:59 +01003101 case LYS_CHOICE:
3102 yang_free_choice(ctx, (struct lys_node_choice *)tmp);
3103 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01003104 case LYS_CASE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02003105 lys_when_free(ctx, ((struct lys_node_case *)tmp)->when, NULL);
Pavol Vicana420bac2016-11-28 14:51:54 +01003106 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003107 case LYS_ANYXML:
3108 case LYS_ANYDATA:
3109 yang_free_anydata(ctx, (struct lys_node_anydata *)tmp);
3110 break;
Pavol Vican78729392016-11-28 17:18:22 +01003111 case LYS_INPUT:
3112 case LYS_OUTPUT:
3113 yang_free_inout(ctx, (struct lys_node_inout *)tmp);
3114 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01003115 case LYS_NOTIF:
3116 yang_free_notif(ctx, (struct lys_node_notif *)tmp);
3117 break;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003118 case LYS_USES:
3119 yang_free_uses(ctx, (struct lys_node_uses *)tmp);
3120 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003121 default:
3122 break;
3123 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02003124 lys_extension_instances_free(ctx, tmp->ext, tmp->ext_size, NULL);
Pavol Vican05810b62016-11-23 14:07:22 +01003125 yang_free_nodes(ctx, child);
3126 free(tmp);
3127 tmp = sibling;
3128 }
3129}
3130
Pavol Vican3ad50f82016-12-04 15:00:36 +01003131static void
3132yang_free_augment(struct ly_ctx *ctx, struct lys_node_augment *aug)
3133{
3134 lydict_remove(ctx, aug->target_name);
3135 lydict_remove(ctx, aug->dsc);
3136 lydict_remove(ctx, aug->ref);
3137
Radek Krejci5138e9f2017-04-12 13:10:46 +02003138 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size, NULL);
3139 lys_when_free(ctx, aug->when, NULL);
Pavol Vican3ad50f82016-12-04 15:00:36 +01003140 yang_free_nodes(ctx, aug->child);
Radek Krejci5138e9f2017-04-12 13:10:46 +02003141 lys_extension_instances_free(ctx, aug->ext, aug->ext_size, NULL);
Pavol Vican3ad50f82016-12-04 15:00:36 +01003142}
3143
PavolVican75af21d2016-12-29 20:04:07 +01003144static void
3145yang_free_deviate(struct ly_ctx *ctx, struct lys_deviation *dev, uint index)
3146{
3147 uint i, j;
3148
3149 for (i = index; i < dev->deviate_size; ++i) {
3150 lydict_remove(ctx, dev->deviate[i].units);
3151
3152 if (dev->deviate[i].type) {
3153 yang_type_free(ctx, dev->deviate[i].type);
3154 }
3155
3156 for (j = 0; j < dev->deviate[i].dflt_size; ++j) {
3157 lydict_remove(ctx, dev->deviate[i].dflt[j]);
3158 }
3159 free(dev->deviate[i].dflt);
3160
3161 for (j = 0; j < dev->deviate[i].must_size; ++j) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003162 lys_restr_free(ctx, &dev->deviate[i].must[j], NULL);
PavolVican75af21d2016-12-29 20:04:07 +01003163 }
3164 free(dev->deviate[i].must);
3165
3166 for (j = 0; j < dev->deviate[i].unique_size; ++j) {
3167 free(dev->deviate[i].unique[j].expr);
3168 }
3169 free(dev->deviate[i].unique);
Radek Krejci5138e9f2017-04-12 13:10:46 +02003170 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size, NULL);
PavolVican75af21d2016-12-29 20:04:07 +01003171 }
3172}
3173
PavolVicandb0e8172017-02-20 00:46:09 +01003174void
3175yang_free_ext_data(struct yang_ext_substmt *substmt)
3176{
3177 int i;
3178
3179 if (!substmt) {
3180 return;
3181 }
3182
3183 free(substmt->ext_substmt);
3184 if (substmt->ext_modules) {
3185 for (i = 0; substmt->ext_modules[i]; ++i) {
3186 free(substmt->ext_modules[i]);
3187 }
3188 free(substmt->ext_modules);
3189 }
3190 free(substmt);
3191}
3192
Pavol Vican7313fc02016-11-14 01:10:31 +01003193/* free common item from module and submodule */
3194static void
Pavol Vican05810b62016-11-23 14:07:22 +01003195free_yang_common(struct lys_module *module, struct lys_node *node)
Pavol Vican7313fc02016-11-14 01:10:31 +01003196{
PavolVican75af21d2016-12-29 20:04:07 +01003197 uint i;
Pavol Vican7313fc02016-11-14 01:10:31 +01003198 yang_tpdf_free(module->ctx, module->tpdf, 0, module->tpdf_size);
3199 module->tpdf_size = 0;
Pavol Vican36e27272016-11-22 15:47:28 +01003200 yang_free_ident_base(module->ident, 0, module->ident_size);
Pavol Vican05810b62016-11-23 14:07:22 +01003201 yang_free_nodes(module->ctx, node);
PavolVican75af21d2016-12-29 20:04:07 +01003202 for (i = 0; i < module->augment_size; ++i) {
3203 yang_free_augment(module->ctx, &module->augment[i]);
3204 }
3205 module->augment_size = 0;
3206 for (i = 0; i < module->deviation_size; ++i) {
3207 yang_free_deviate(module->ctx, &module->deviation[i], 0);
3208 free(module->deviation[i].deviate);
3209 }
3210 module->deviation_size = 0;
Pavol Vican7313fc02016-11-14 01:10:31 +01003211}
3212
Pavol Vican1cc4e192016-10-24 16:38:31 +02003213/* check function*/
3214
3215int
PavolVicanc1807262017-01-31 18:00:27 +01003216yang_check_ext_instance(struct lys_module *module, struct lys_ext_instance ***ext, uint size,
3217 void *parent, struct unres_schema *unres)
3218{
3219 struct unres_ext *info;
3220 uint i;
3221
3222 for (i = 0; i < size; ++i) {
3223 info = malloc(sizeof *info);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003224 LY_CHECK_ERR_RETURN(!info, LOGMEM, EXIT_FAILURE);
PavolVicanc1807262017-01-31 18:00:27 +01003225 info->data.yang = (*ext)[i]->parent;
3226 info->datatype = LYS_IN_YANG;
3227 info->parent = parent;
3228 info->mod = module;
3229 info->parent_type = (*ext)[i]->parent_type;
Radek Krejcifebdad72017-02-06 11:35:51 +01003230 info->substmt = (*ext)[i]->insubstmt;
3231 info->substmt_index = (*ext)[i]->insubstmt_index;
PavolVicanc1807262017-01-31 18:00:27 +01003232 info->ext_index = i;
3233 if (unres_schema_add_node(module, unres, ext, UNRES_EXT, (struct lys_node *)info) == -1) {
3234 return EXIT_FAILURE;
3235 }
3236 }
3237
3238 return EXIT_SUCCESS;
3239}
3240
3241int
Pavol Vicanec423c92016-10-24 21:33:43 +02003242yang_check_imports(struct lys_module *module, struct unres_schema *unres)
Pavol Vican1cc4e192016-10-24 16:38:31 +02003243{
3244 struct lys_import *imp;
Pavol Vicanec423c92016-10-24 21:33:43 +02003245 struct lys_include *inc;
3246 uint8_t imp_size, inc_size, j = 0, i = 0;
Pavol Vican1cc4e192016-10-24 16:38:31 +02003247 char *s;
3248
3249 imp = module->imp;
3250 imp_size = module->imp_size;
Pavol Vicanec423c92016-10-24 21:33:43 +02003251 inc = module->inc;
3252 inc_size = module->inc_size;
Pavol Vican1cc4e192016-10-24 16:38:31 +02003253
3254 if (imp_size) {
PavolVican5144fd82017-03-07 19:45:06 +01003255 module->imp = calloc(imp_size, sizeof *module->imp);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003256 module->imp_size = 0;
Radek Krejcia8d111f2017-05-31 13:57:37 +02003257 LY_CHECK_ERR_GOTO(!module->imp, LOGMEM, error);
Pavol Vicanec423c92016-10-24 21:33:43 +02003258 }
Pavol Vican1cc4e192016-10-24 16:38:31 +02003259
Pavol Vicanec423c92016-10-24 21:33:43 +02003260 if (inc_size) {
PavolVican5144fd82017-03-07 19:45:06 +01003261 module->inc = calloc(inc_size, sizeof *module->inc);
Pavol Vicanec423c92016-10-24 21:33:43 +02003262 module->inc_size = 0;
Radek Krejcia8d111f2017-05-31 13:57:37 +02003263 LY_CHECK_ERR_GOTO(!module->inc, LOGMEM, error);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003264 }
3265
3266 for (i = 0; i < imp_size; ++i) {
3267 s = (char *) imp[i].module;
3268 imp[i].module = NULL;
PavolVican7d0b5ab2017-02-01 13:06:53 +01003269 if (yang_fill_import(module, &imp[i], &module->imp[module->imp_size], s, unres)) {
Pavol Vican1cc4e192016-10-24 16:38:31 +02003270 ++i;
3271 goto error;
3272 }
3273 }
Pavol Vicanec423c92016-10-24 21:33:43 +02003274 for (j = 0; j < inc_size; ++j) {
Pavol Vicanfda8c802016-12-03 02:00:42 +01003275 s = (char *) inc[j].submodule;
3276 inc[j].submodule = NULL;
3277 if (yang_fill_include(module, s, &inc[j], unres)) {
3278 ++j;
Pavol Vicanec423c92016-10-24 21:33:43 +02003279 goto error;
3280 }
3281 }
3282 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003283 free(imp);
3284
3285 return EXIT_SUCCESS;
3286
3287error:
3288 yang_free_import(module->ctx, imp, i, imp_size);
Pavol Vicanec423c92016-10-24 21:33:43 +02003289 yang_free_include(module->ctx, inc, j, inc_size);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003290 free(imp);
Pavol Vicanec423c92016-10-24 21:33:43 +02003291 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003292 return EXIT_FAILURE;
3293}
Pavol Vican7313fc02016-11-14 01:10:31 +01003294
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003295static int
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003296yang_check_iffeatures(struct lys_module *module, void *ptr, void *parent, enum yytokentype type, struct unres_schema *unres)
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003297{
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003298 struct lys_iffeature *iffeature;
3299 uint8_t *ptr_size, size, i;
3300 char *s;
3301 int parent_is_feature = 0;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003302
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003303 switch (type) {
3304 case FEATURE_KEYWORD:
3305 iffeature = ((struct lys_feature *)parent)->iffeature;
3306 size = ((struct lys_feature *)parent)->iffeature_size;
3307 ptr_size = &((struct lys_feature *)parent)->iffeature_size;
3308 parent_is_feature = 1;
3309 break;
3310 case IDENTITY_KEYWORD:
3311 iffeature = ((struct lys_ident *)parent)->iffeature;
3312 size = ((struct lys_ident *)parent)->iffeature_size;
3313 ptr_size = &((struct lys_ident *)parent)->iffeature_size;
3314 break;
3315 case ENUM_KEYWORD:
3316 iffeature = ((struct lys_type_enum *)ptr)->iffeature;
3317 size = ((struct lys_type_enum *)ptr)->iffeature_size;
3318 ptr_size = &((struct lys_type_enum *)ptr)->iffeature_size;
3319 break;
3320 case BIT_KEYWORD:
3321 iffeature = ((struct lys_type_bit *)ptr)->iffeature;
3322 size = ((struct lys_type_bit *)ptr)->iffeature_size;
3323 ptr_size = &((struct lys_type_bit *)ptr)->iffeature_size;
3324 break;
3325 case REFINE_KEYWORD:
3326 iffeature = ((struct lys_refine *)ptr)->iffeature;
3327 size = ((struct lys_refine *)ptr)->iffeature_size;
3328 ptr_size = &((struct lys_refine *)ptr)->iffeature_size;
3329 break;
3330 default:
3331 iffeature = ((struct lys_node *)parent)->iffeature;
3332 size = ((struct lys_node *)parent)->iffeature_size;
3333 ptr_size = &((struct lys_node *)parent)->iffeature_size;
3334 break;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003335 }
3336
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003337 *ptr_size = 0;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003338 for (i = 0; i < size; ++i) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003339 s = (char *)iffeature[i].features;
3340 iffeature[i].features = NULL;
3341 if (yang_fill_iffeature(module, &iffeature[i], parent, s, unres, parent_is_feature)) {
3342 *ptr_size = size;
3343 return EXIT_FAILURE;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003344 }
PavolVican8fa31242017-02-07 11:04:26 +01003345 if (yang_check_ext_instance(module, &iffeature[i].ext, iffeature[i].ext_size, &iffeature[i], unres)) {
3346 *ptr_size = size;
3347 return EXIT_FAILURE;
3348 }
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003349 (*ptr_size)++;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003350 }
3351
3352 return EXIT_SUCCESS;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003353}
3354
Pavol Vicanb60a1d12016-12-03 01:56:55 +01003355static int
3356yang_check_identityref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres)
3357{
3358 uint size, i;
3359 int rc;
3360 struct lys_ident **ref;
3361 const char *value;
3362 char *expr;
3363
3364 ref = type->info.ident.ref;
3365 size = type->info.ident.count;
3366 type->info.ident.count = 0;
3367 type->info.ident.ref = NULL;
3368 ((struct yang_type *)type->der)->flags |= LYS_NO_ERASE_IDENTITY;
3369
3370 for (i = 0; i < size; ++i) {
3371 expr = (char *)ref[i];
3372 /* store in the JSON format */
3373 value = transform_schema2json(module, expr);
3374 free(expr);
3375
3376 if (!value) {
3377 goto error;
3378 }
3379 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
3380 lydict_remove(module->ctx, value);
3381
3382 if (rc == -1) {
3383 goto error;
3384 }
3385 }
3386 free(ref);
3387
3388 return EXIT_SUCCESS;
3389error:
3390 for (i = i+1; i < size; ++i) {
3391 free(ref[i]);
3392 }
3393 free(ref);
3394 return EXIT_FAILURE;
3395}
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003396
Pavol Vican7313fc02016-11-14 01:10:31 +01003397int
PavolVican056fcd12017-02-07 15:36:53 +01003398yang_fill_type(struct lys_module *module, struct lys_type *type, struct yang_type *stype,
3399 void *parent, struct unres_schema *unres)
3400{
3401 int i;
3402
3403 type->parent = parent;
3404 if (yang_check_ext_instance(module, &type->ext, type->ext_size, type, unres)) {
3405 return EXIT_FAILURE;
3406 }
3407 switch (stype->base) {
3408 case LY_TYPE_ENUM:
3409 for (i = 0; i < type->info.enums.count; ++i) {
3410 if (yang_check_iffeatures(module, &type->info.enums.enm[i], parent, ENUM_KEYWORD, unres)) {
3411 return EXIT_FAILURE;
3412 }
3413 if (yang_check_ext_instance(module, &type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size,
3414 &type->info.enums.enm[i], unres)) {
3415 return EXIT_FAILURE;
3416 }
3417 }
3418 break;
3419 case LY_TYPE_BITS:
3420 for (i = 0; i < type->info.bits.count; ++i) {
3421 if (yang_check_iffeatures(module, &type->info.bits.bit[i], parent, BIT_KEYWORD, unres)) {
3422 return EXIT_FAILURE;
3423 }
3424 if (yang_check_ext_instance(module, &type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size,
3425 &type->info.bits.bit[i], unres)) {
3426 return EXIT_FAILURE;
3427 }
3428 }
3429 break;
3430 case LY_TYPE_IDENT:
3431 if (yang_check_identityref(module, type, unres)) {
3432 return EXIT_FAILURE;
3433 }
3434 break;
3435 case LY_TYPE_STRING:
3436 if (type->info.str.length && yang_check_ext_instance(module, &type->info.str.length->ext,
3437 type->info.str.length->ext_size, type->info.str.length, unres)) {
3438 return EXIT_FAILURE;
3439 }
3440 for (i = 0; i < type->info.str.pat_count; ++i) {
3441 if (yang_check_ext_instance(module, &type->info.str.patterns[i].ext, type->info.str.patterns[i].ext_size,
3442 &type->info.str.patterns[i], unres)) {
3443 return EXIT_FAILURE;
3444 }
3445 }
3446 break;
3447 case LY_TYPE_DEC64:
3448 if (type->info.dec64.range && yang_check_ext_instance(module, &type->info.dec64.range->ext,
3449 type->info.dec64.range->ext_size, type->info.dec64.range, unres)) {
3450 return EXIT_FAILURE;
3451 }
3452 break;
3453 case LY_TYPE_UNION:
3454 for (i = 0; i < type->info.uni.count; ++i) {
3455 if (yang_fill_type(module, &type->info.uni.types[i], (struct yang_type *)type->info.uni.types[i].der,
3456 parent, unres)) {
3457 return EXIT_FAILURE;
3458 }
3459 }
Radek Krejci57b41682017-03-07 12:33:24 +01003460 break;
PavolVican056fcd12017-02-07 15:36:53 +01003461 default:
3462 /* nothing checks */
3463 break;
3464 }
3465 return EXIT_SUCCESS;
3466}
3467
3468int
Pavol Vican7313fc02016-11-14 01:10:31 +01003469yang_check_typedef(struct lys_module *module, struct lys_node *parent, struct unres_schema *unres)
3470{
3471 struct lys_tpdf *tpdf;
PavolVican056fcd12017-02-07 15:36:53 +01003472 uint8_t i, tpdf_size, *ptr_tpdf_size;
Pavol Vican7313fc02016-11-14 01:10:31 +01003473
3474 if (!parent) {
3475 tpdf = module->tpdf;
3476 ptr_tpdf_size = &module->tpdf_size;
Pavol Vican05810b62016-11-23 14:07:22 +01003477 } else {
3478 switch (parent->nodetype) {
3479 case LYS_GROUPING:
3480 tpdf = ((struct lys_node_grp *)parent)->tpdf;
3481 ptr_tpdf_size = &((struct lys_node_grp *)parent)->tpdf_size;
3482 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003483 case LYS_CONTAINER:
3484 tpdf = ((struct lys_node_container *)parent)->tpdf;
3485 ptr_tpdf_size = &((struct lys_node_container *)parent)->tpdf_size;
3486 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003487 case LYS_LIST:
3488 tpdf = ((struct lys_node_list *)parent)->tpdf;
3489 ptr_tpdf_size = &((struct lys_node_list *)parent)->tpdf_size;
3490 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003491 case LYS_RPC:
3492 case LYS_ACTION:
3493 tpdf = ((struct lys_node_rpc_action *)parent)->tpdf;
3494 ptr_tpdf_size = &((struct lys_node_rpc_action *)parent)->tpdf_size;
3495 break;
Pavol Vican78729392016-11-28 17:18:22 +01003496 case LYS_INPUT:
3497 case LYS_OUTPUT:
3498 tpdf = ((struct lys_node_inout *)parent)->tpdf;
3499 ptr_tpdf_size = &((struct lys_node_inout *)parent)->tpdf_size;
3500 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01003501 case LYS_NOTIF:
3502 tpdf = ((struct lys_node_notif *)parent)->tpdf;
3503 ptr_tpdf_size = &((struct lys_node_notif *)parent)->tpdf_size;
3504 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003505 default:
3506 LOGINT;
3507 return EXIT_FAILURE;
3508 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003509 }
3510
3511 tpdf_size = *ptr_tpdf_size;
3512 *ptr_tpdf_size = 0;
3513
3514 for (i = 0; i < tpdf_size; ++i) {
Pavol Vicanfda8c802016-12-03 02:00:42 +01003515 if (lyp_check_identifier(tpdf[i].name, LY_IDENT_TYPE, module, parent)) {
3516 goto error;
3517 }
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003518
PavolVican056fcd12017-02-07 15:36:53 +01003519 if (yang_fill_type(module, &tpdf[i].type, (struct yang_type *)tpdf[i].type.der, &tpdf[i], unres)) {
3520 goto error;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003521 }
PavolVicandf9e7972017-02-07 11:41:38 +01003522 if (yang_check_ext_instance(module, &tpdf[i].ext, tpdf[i].ext_size, &tpdf[i], unres)) {
3523 goto error;
3524 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003525 if (unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003526 goto error;
Pavol Vican7313fc02016-11-14 01:10:31 +01003527 }
3528
PavolVicane87cb932016-12-30 15:36:18 +01003529 (*ptr_tpdf_size)++;
Pavol Vican7313fc02016-11-14 01:10:31 +01003530 /* check default value*/
Radek Krejciab08f0f2017-03-09 16:37:15 +01003531 if (unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPEDEF_DFLT,
3532 (struct lys_node *)(&tpdf[i].dflt)) == -1) {
Pavol Vican7313fc02016-11-14 01:10:31 +01003533 ++i;
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003534 goto error;
Pavol Vican7313fc02016-11-14 01:10:31 +01003535 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003536 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003537
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003538 return EXIT_SUCCESS;
3539
3540error:
3541 yang_tpdf_free(module->ctx, tpdf, i, tpdf_size);
3542 return EXIT_FAILURE;
Pavol Vican7313fc02016-11-14 01:10:31 +01003543}
3544
3545static int
Pavol Vican36e27272016-11-22 15:47:28 +01003546yang_check_identities(struct lys_module *module, struct unres_schema *unres)
3547{
3548 uint32_t i, size, base_size;
3549 uint8_t j;
3550
3551 size = module->ident_size;
3552 module->ident_size = 0;
3553 for (i = 0; i < size; ++i) {
3554 base_size = module->ident[i].base_size;
3555 module->ident[i].base_size = 0;
3556 for (j = 0; j < base_size; ++j) {
3557 if (yang_read_base(module, &module->ident[i], (char *)module->ident[i].base[j], unres)) {
3558 ++j;
3559 module->ident_size = size;
3560 goto error;
3561 }
3562 }
3563 module->ident_size++;
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003564 if (yang_check_iffeatures(module, NULL, &module->ident[i], IDENTITY_KEYWORD, unres)) {
3565 goto error;
3566 }
PavolVican8fa31242017-02-07 11:04:26 +01003567 if (yang_check_ext_instance(module, &module->ident[i].ext, module->ident[i].ext_size, &module->ident[i], unres)) {
3568 goto error;
3569 }
Pavol Vican36e27272016-11-22 15:47:28 +01003570 }
3571
PavolVican8fa31242017-02-07 11:04:26 +01003572
Pavol Vican36e27272016-11-22 15:47:28 +01003573 return EXIT_SUCCESS;
3574
3575error:
3576 for (; j< module->ident[i].base_size; ++j) {
3577 free(module->ident[i].base[j]);
3578 }
3579 yang_free_ident_base(module->ident, i + 1, size);
3580 return EXIT_FAILURE;
3581}
3582
3583static int
PavolVican38104a32017-02-08 12:25:23 +01003584yang_check_must(struct lys_module *module, struct lys_restr *must, uint size, struct unres_schema *unres)
3585{
3586 uint i;
3587
3588 for (i = 0; i < size; ++i) {
3589 if (yang_check_ext_instance(module, &must[i].ext, must[i].ext_size, &must[i], unres)) {
3590 return EXIT_FAILURE;
3591 }
3592 }
3593 return EXIT_SUCCESS;
3594}
3595
3596static int
PavolVicane87cb932016-12-30 15:36:18 +01003597yang_check_container(struct lys_module *module, struct lys_node_container *cont, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003598 int options, struct unres_schema *unres)
Pavol Vican05810b62016-11-23 14:07:22 +01003599{
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003600 if (yang_check_typedef(module, (struct lys_node *)cont, unres)) {
Pavol Vican05810b62016-11-23 14:07:22 +01003601 goto error;
3602 }
3603
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003604 if (yang_check_iffeatures(module, NULL, cont, CONTAINER_KEYWORD, unres)) {
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003605 goto error;
3606 }
3607
Radek Krejci7212e0a2017-03-08 15:58:22 +01003608 if (yang_check_nodes(module, (struct lys_node *)cont, *child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003609 *child = NULL;
3610 goto error;
3611 }
3612 *child = NULL;
3613
PavolVican59ba4602017-02-08 11:53:32 +01003614 if (cont->when && yang_check_ext_instance(module, &cont->when->ext, cont->when->ext_size, cont->when, unres)) {
3615 goto error;
3616 }
PavolVican38104a32017-02-08 12:25:23 +01003617 if (yang_check_must(module, cont->must, cont->must_size, unres)) {
3618 goto error;
3619 }
3620
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003621 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01003622 if (cont->when || cont->must_size) {
3623 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003624 if (lyxp_node_check_syntax((struct lys_node *)cont)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003625 goto error;
3626 }
3627 } else {
3628 if (unres_schema_add_node(module, unres, cont, UNRES_XPATH, NULL) == -1) {
3629 goto error;
3630 }
3631 }
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003632 }
3633
3634 return EXIT_SUCCESS;
3635error:
3636 return EXIT_FAILURE;
3637}
3638
3639static int
Radek Krejci7212e0a2017-03-08 15:58:22 +01003640yang_check_leaf(struct lys_module *module, struct lys_node_leaf *leaf, int options, struct unres_schema *unres)
Pavol Vicana69aff22016-11-24 18:23:50 +01003641{
PavolVican056fcd12017-02-07 15:36:53 +01003642 if (yang_fill_type(module, &leaf->type, (struct yang_type *)leaf->type.der, leaf, unres)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003643 yang_type_free(module->ctx, &leaf->type);
3644 goto error;
Pavol Vicana69aff22016-11-24 18:23:50 +01003645 }
PavolVicana08d3652016-12-29 21:07:47 +01003646 if (yang_check_iffeatures(module, NULL, leaf, LEAF_KEYWORD, unres)) {
3647 yang_type_free(module->ctx, &leaf->type);
3648 goto error;
3649 }
3650
Pavol Vicanfda8c802016-12-03 02:00:42 +01003651 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, (struct lys_node *)leaf) == -1) {
Pavol Vicana69aff22016-11-24 18:23:50 +01003652 yang_type_free(module->ctx, &leaf->type);
3653 goto error;
3654 }
3655
Radek Krejciab08f0f2017-03-09 16:37:15 +01003656 if (!(options & LYS_PARSE_OPT_INGRP) &&
3657 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)&leaf->dflt) == -1)) {
Pavol Vicana69aff22016-11-24 18:23:50 +01003658 goto error;
3659 }
3660
PavolVican59ba4602017-02-08 11:53:32 +01003661 if (leaf->when && yang_check_ext_instance(module, &leaf->when->ext, leaf->when->ext_size, leaf->when, unres)) {
3662 goto error;
3663 }
PavolVican38104a32017-02-08 12:25:23 +01003664 if (yang_check_must(module, leaf->must, leaf->must_size, unres)) {
3665 goto error;
3666 }
Michal Vasko89afc112017-03-16 13:57:28 +01003667
Pavol Vicana69aff22016-11-24 18:23:50 +01003668 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01003669 if (leaf->when || leaf->must_size) {
3670 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003671 if (lyxp_node_check_syntax((struct lys_node *)leaf)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003672 goto error;
3673 }
3674 } else {
3675 if (unres_schema_add_node(module, unres, leaf, UNRES_XPATH, NULL) == -1) {
3676 goto error;
3677 }
3678 }
Pavol Vicana69aff22016-11-24 18:23:50 +01003679 }
3680
3681 return EXIT_SUCCESS;
3682error:
3683 return EXIT_FAILURE;
3684}
3685
3686static int
Radek Krejci7212e0a2017-03-08 15:58:22 +01003687yang_check_leaflist(struct lys_module *module, struct lys_node_leaflist *leaflist, int options,
3688 struct unres_schema *unres)
Pavol Vican36aff862016-11-26 17:07:05 +01003689{
Pavol Vicanfda8c802016-12-03 02:00:42 +01003690 int i, j;
Pavol Vican36aff862016-11-26 17:07:05 +01003691
PavolVican056fcd12017-02-07 15:36:53 +01003692 if (yang_fill_type(module, &leaflist->type, (struct yang_type *)leaflist->type.der, leaflist, unres)) {
PavolVican6a2148f2017-02-07 23:09:55 +01003693 yang_type_free(module->ctx, &leaflist->type);
3694 goto error;
Pavol Vican36aff862016-11-26 17:07:05 +01003695 }
PavolVicana08d3652016-12-29 21:07:47 +01003696 if (yang_check_iffeatures(module, NULL, leaflist, LEAF_LIST_KEYWORD, unres)) {
3697 yang_type_free(module->ctx, &leaflist->type);
3698 goto error;
3699 }
3700
Pavol Vicanfda8c802016-12-03 02:00:42 +01003701 if (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DER, (struct lys_node *)leaflist) == -1) {
Pavol Vican36aff862016-11-26 17:07:05 +01003702 yang_type_free(module->ctx, &leaflist->type);
3703 goto error;
3704 }
3705
Pavol Vican36aff862016-11-26 17:07:05 +01003706 for (i = 0; i < leaflist->dflt_size; ++i) {
Pavol Vicanfda8c802016-12-03 02:00:42 +01003707 /* check for duplicity in case of configuration data,
3708 * in case of status data duplicities are allowed */
3709 if (leaflist->flags & LYS_CONFIG_W) {
3710 for (j = i +1; j < leaflist->dflt_size; ++j) {
3711 if (ly_strequal(leaflist->dflt[i], leaflist->dflt[j], 1)) {
PavolVican196694c2017-01-27 10:33:09 +01003712 LOGVAL(LYE_INARG, LY_VLOG_LYS, leaflist, leaflist->dflt[i], "default");
3713 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leaflist, "Duplicated default value \"%s\".", leaflist->dflt[i]);
Pavol Vicanfda8c802016-12-03 02:00:42 +01003714 goto error;
3715 }
3716 }
3717 }
3718 /* check default value (if not defined, there still could be some restrictions
3719 * that need to be checked against a default value from a derived type) */
Radek Krejciab08f0f2017-03-09 16:37:15 +01003720 if (!(options & LYS_PARSE_OPT_INGRP) &&
3721 (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DFLT,
3722 (struct lys_node *)(&leaflist->dflt[i])) == -1)) {
Pavol Vican36aff862016-11-26 17:07:05 +01003723 goto error;
3724 }
3725 }
3726
PavolVican59ba4602017-02-08 11:53:32 +01003727 if (leaflist->when && yang_check_ext_instance(module, &leaflist->when->ext, leaflist->when->ext_size, leaflist->when, unres)) {
3728 goto error;
3729 }
PavolVican38104a32017-02-08 12:25:23 +01003730 if (yang_check_must(module, leaflist->must, leaflist->must_size, unres)) {
3731 goto error;
3732 }
PavolVican59ba4602017-02-08 11:53:32 +01003733
Pavol Vican36aff862016-11-26 17:07:05 +01003734 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01003735 if (leaflist->when || leaflist->must_size) {
3736 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003737 if (lyxp_node_check_syntax((struct lys_node *)leaflist)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003738 goto error;
3739 }
3740 } else {
3741 if (unres_schema_add_node(module, unres, leaflist, UNRES_XPATH, NULL) == -1) {
3742 goto error;
3743 }
3744 }
Pavol Vican36aff862016-11-26 17:07:05 +01003745 }
3746
3747 return EXIT_SUCCESS;
3748error:
3749 return EXIT_FAILURE;
3750}
3751
3752static int
PavolVicane87cb932016-12-30 15:36:18 +01003753yang_check_list(struct lys_module *module, struct lys_node_list *list, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003754 int options, struct unres_schema *unres)
Pavol Vicand8136a42016-11-27 13:28:04 +01003755{
Pavol Vicanfda8c802016-12-03 02:00:42 +01003756 struct lys_node *node;
3757
Pavol Vicand8136a42016-11-27 13:28:04 +01003758 if (yang_check_typedef(module, (struct lys_node *)list, unres)) {
3759 goto error;
3760 }
3761
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003762 if (yang_check_iffeatures(module, NULL, list, LIST_KEYWORD, unres)) {
3763 goto error;
Pavol Vicand8136a42016-11-27 13:28:04 +01003764 }
3765
Pavol Vicanfda8c802016-12-03 02:00:42 +01003766 if (list->flags & LYS_CONFIG_R) {
3767 /* RFC 6020, 7.7.5 - ignore ordering when the list represents state data
3768 * ignore oredering MASK - 0x7F
3769 */
3770 list->flags &= 0x7F;
3771 }
3772 /* check - if list is configuration, key statement is mandatory
3773 * (but only if we are not in a grouping or augment, then the check is deferred) */
PavolVicanc68dfea2017-02-21 15:40:43 +01003774 for (node = (struct lys_node *)list; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Pavol Vicanfda8c802016-12-03 02:00:42 +01003775 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys) {
3776 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, list, "key", "list");
3777 goto error;
3778 }
3779
Radek Krejci7212e0a2017-03-08 15:58:22 +01003780 if (yang_check_nodes(module, (struct lys_node *)list, *child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003781 *child = NULL;
3782 goto error;
3783 }
3784 *child = NULL;
3785
Pavol Vicand8136a42016-11-27 13:28:04 +01003786 if (list->keys && yang_read_key(module, list, unres)) {
3787 goto error;
3788 }
3789
3790 if (yang_read_unique(module, list, unres)) {
3791 goto error;
3792 }
3793
PavolVican59ba4602017-02-08 11:53:32 +01003794 if (list->when && yang_check_ext_instance(module, &list->when->ext, list->when->ext_size, list->when, unres)) {
3795 goto error;
3796 }
PavolVican38104a32017-02-08 12:25:23 +01003797 if (yang_check_must(module, list->must, list->must_size, unres)) {
3798 goto error;
3799 }
Michal Vasko89afc112017-03-16 13:57:28 +01003800
Pavol Vicand8136a42016-11-27 13:28:04 +01003801 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01003802 if (list->when || list->must_size) {
3803 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003804 if (lyxp_node_check_syntax((struct lys_node *)list)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003805 goto error;
3806 }
3807 } else {
3808 if (unres_schema_add_node(module, unres, list, UNRES_XPATH, NULL) == -1) {
3809 goto error;
3810 }
3811 }
Pavol Vicand8136a42016-11-27 13:28:04 +01003812 }
3813
3814 return EXIT_SUCCESS;
3815error:
3816 return EXIT_FAILURE;
3817}
3818
3819static int
PavolVicane87cb932016-12-30 15:36:18 +01003820yang_check_choice(struct lys_module *module, struct lys_node_choice *choice, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003821 int options, struct unres_schema *unres)
Pavol Vican36ace102016-11-28 11:46:59 +01003822{
3823 char *value;
Pavol Vican36ace102016-11-28 11:46:59 +01003824
PavolVicana08d3652016-12-29 21:07:47 +01003825 if (yang_check_iffeatures(module, NULL, choice, CHOICE_KEYWORD, unres)) {
3826 free(choice->dflt);
3827 choice->dflt = NULL;
3828 goto error;
3829 }
3830
Radek Krejci7212e0a2017-03-08 15:58:22 +01003831 if (yang_check_nodes(module, (struct lys_node *)choice, *child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003832 *child = NULL;
3833 free(choice->dflt);
3834 choice->dflt = NULL;
3835 goto error;
3836 }
3837 *child = NULL;
3838
Pavol Vican36ace102016-11-28 11:46:59 +01003839 if (choice->dflt) {
3840 value = (char *)choice->dflt;
3841 choice->dflt = NULL;
3842 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
3843 free(value);
3844 goto error;
3845 }
3846 free(value);
3847 }
3848
PavolVican59ba4602017-02-08 11:53:32 +01003849 if (choice->when && yang_check_ext_instance(module, &choice->when->ext, choice->when->ext_size, choice->when, unres)) {
3850 goto error;
3851 }
3852
Pavol Vican36ace102016-11-28 11:46:59 +01003853 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01003854 if (choice->when) {
3855 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003856 if (lyxp_node_check_syntax((struct lys_node *)choice)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003857 goto error;
3858 }
3859 } else {
3860 if (unres_schema_add_node(module, unres, choice, UNRES_XPATH, NULL) == -1) {
3861 goto error;
3862 }
3863 }
Pavol Vican36ace102016-11-28 11:46:59 +01003864 }
3865
3866 return EXIT_SUCCESS;
3867error:
3868 return EXIT_FAILURE;
3869}
3870
3871static int
PavolVicane87cb932016-12-30 15:36:18 +01003872yang_check_rpc_action(struct lys_module *module, struct lys_node_rpc_action *rpc, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003873 int options, struct unres_schema *unres)
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003874{
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003875 struct lys_node *node;
3876
3877 if (rpc->nodetype == LYS_ACTION) {
3878 for (node = rpc->parent; node; node = lys_parent(node)) {
3879 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Pavol Vican73ff8032016-12-04 15:03:51 +01003880 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys)) {
PavolVican196694c2017-01-27 10:33:09 +01003881 LOGVAL(LYE_INPAR, LY_VLOG_LYS, rpc->parent, strnodetype(node->nodetype), "action");
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003882 goto error;
3883 }
3884 }
3885 }
3886 if (yang_check_typedef(module, (struct lys_node *)rpc, unres)) {
3887 goto error;
3888 }
3889
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003890 if (yang_check_iffeatures(module, NULL, rpc, RPC_KEYWORD, unres)) {
3891 goto error;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003892 }
3893
Radek Krejci7212e0a2017-03-08 15:58:22 +01003894 if (yang_check_nodes(module, (struct lys_node *)rpc, *child, options | LYS_PARSE_OPT_CFG_IGNORE, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003895 *child = NULL;
3896 goto error;
3897 }
3898 *child = NULL;
3899
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003900 return EXIT_SUCCESS;
3901error:
3902 return EXIT_FAILURE;
3903}
3904
3905static int
PavolVicane87cb932016-12-30 15:36:18 +01003906yang_check_notif(struct lys_module *module, struct lys_node_notif *notif, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003907 int options, struct unres_schema *unres)
Pavol Vican29bf8802016-11-28 20:44:57 +01003908{
Pavol Vican29bf8802016-11-28 20:44:57 +01003909 if (yang_check_typedef(module, (struct lys_node *)notif, unres)) {
3910 goto error;
3911 }
3912
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003913 if (yang_check_iffeatures(module, NULL, notif, NOTIFICATION_KEYWORD, unres)) {
3914 goto error;
Pavol Vican29bf8802016-11-28 20:44:57 +01003915 }
3916
Radek Krejci7212e0a2017-03-08 15:58:22 +01003917 if (yang_check_nodes(module, (struct lys_node *)notif, *child, options | LYS_PARSE_OPT_CFG_IGNORE, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003918 *child = NULL;
3919 goto error;
3920 }
3921 *child = NULL;
3922
Michal Vasko89afc112017-03-16 13:57:28 +01003923 if (yang_check_must(module, notif->must, notif->must_size, unres)) {
3924 goto error;
3925 }
3926
3927 /* check XPath dependencies */
PavolVican38104a32017-02-08 12:25:23 +01003928 if (notif->must_size) {
Michal Vasko89afc112017-03-16 13:57:28 +01003929 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003930 if (lyxp_node_check_syntax((struct lys_node *)notif)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003931 goto error;
3932 }
3933 } else {
3934 if (unres_schema_add_node(module, unres, notif, UNRES_XPATH, NULL) == -1) {
3935 goto error;
3936 }
PavolVican38104a32017-02-08 12:25:23 +01003937 }
Pavol Vican29bf8802016-11-28 20:44:57 +01003938 }
3939
3940 return EXIT_SUCCESS;
3941error:
3942 return EXIT_FAILURE;
3943}
3944
3945static int
Radek Krejci7212e0a2017-03-08 15:58:22 +01003946yang_check_augment(struct lys_module *module, struct lys_node_augment *augment, int options, struct unres_schema *unres)
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003947{
Pavol Vican3ad50f82016-12-04 15:00:36 +01003948 struct lys_node *child;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003949
Pavol Vican3ad50f82016-12-04 15:00:36 +01003950 child = augment->child;
3951 augment->child = NULL;
3952
PavolVicana08d3652016-12-29 21:07:47 +01003953 if (yang_check_iffeatures(module, NULL, augment, AUGMENT_KEYWORD, unres)) {
3954 yang_free_nodes(module->ctx, child);
Pavol Vican3ad50f82016-12-04 15:00:36 +01003955 goto error;
3956 }
3957
Radek Krejci7212e0a2017-03-08 15:58:22 +01003958 if (yang_check_nodes(module, (struct lys_node *)augment, child, options, unres)) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01003959 goto error;
3960 }
3961
PavolVicanfa9510e2017-02-08 17:20:46 +01003962 if (yang_check_ext_instance(module, &augment->ext, augment->ext_size, augment, unres)) {
3963 goto error;
3964 }
3965
PavolVican59ba4602017-02-08 11:53:32 +01003966 if (augment->when && yang_check_ext_instance(module, &augment->when->ext, augment->when->ext_size, augment->when, unres)) {
3967 goto error;
3968 }
3969
Pavol Vican3ad50f82016-12-04 15:00:36 +01003970 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01003971 if (augment->when) {
3972 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003973 if (lyxp_node_check_syntax((struct lys_node *)augment)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003974 goto error;
3975 }
3976 } else {
3977 if (unres_schema_add_node(module, unres, augment, UNRES_XPATH, NULL) == -1) {
3978 goto error;
3979 }
3980 }
Pavol Vican3ad50f82016-12-04 15:00:36 +01003981 }
3982
3983 return EXIT_SUCCESS;
3984error:
3985 return EXIT_FAILURE;
3986}
3987
3988static int
Radek Krejci7212e0a2017-03-08 15:58:22 +01003989yang_check_uses(struct lys_module *module, struct lys_node_uses *uses, int options, struct unres_schema *unres)
Pavol Vican3ad50f82016-12-04 15:00:36 +01003990{
3991 uint i, size;
3992
3993 size = uses->augment_size;
3994 uses->augment_size = 0;
3995
3996 if (yang_check_iffeatures(module, NULL, uses, USES_KEYWORD, unres)) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003997 goto error;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003998 }
3999
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004000 for (i = 0; i < uses->refine_size; ++i) {
PavolVican77374ee2017-02-08 15:18:45 +01004001 if (yang_check_iffeatures(module, &uses->refine[i], uses, REFINE_KEYWORD, unres)) {
4002 goto error;
4003 }
4004 if (yang_check_must(module, uses->refine[i].must, uses->refine[i].must_size, unres)) {
4005 goto error;
4006 }
4007 if (yang_check_ext_instance(module, &uses->refine[i].ext, uses->refine[i].ext_size, &uses->refine[i], unres)) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004008 goto error;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004009 }
4010 }
4011
Pavol Vican3ad50f82016-12-04 15:00:36 +01004012 for (i = 0; i < size; ++i) {
4013 uses->augment_size++;
Radek Krejci7212e0a2017-03-08 15:58:22 +01004014 if (yang_check_augment(module, &uses->augment[i], options, unres)) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01004015 goto error;
4016 }
4017 }
4018
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004019 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
4020 goto error;
4021 }
4022
PavolVican59ba4602017-02-08 11:53:32 +01004023 if (uses->when && yang_check_ext_instance(module, &uses->when->ext, uses->when->ext_size, uses->when, unres)) {
4024 goto error;
4025 }
4026
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004027 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004028 if (uses->when) {
4029 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004030 if (lyxp_node_check_syntax((struct lys_node *)uses)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004031 goto error;
4032 }
4033 } else {
4034 if (unres_schema_add_node(module, unres, uses, UNRES_XPATH, NULL) == -1) {
4035 goto error;
4036 }
4037 }
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004038 }
4039
4040 return EXIT_SUCCESS;
4041error:
Pavol Vican3ad50f82016-12-04 15:00:36 +01004042 for (i = uses->augment_size; i < size; ++i) {
4043 yang_free_augment(module->ctx, &uses->augment[i]);
4044 }
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004045 return EXIT_FAILURE;
4046}
4047
4048static int
PavolVican59ba4602017-02-08 11:53:32 +01004049yang_check_anydata(struct lys_module *module, struct lys_node_anydata *anydata, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004050 int options, struct unres_schema *unres)
PavolVican59ba4602017-02-08 11:53:32 +01004051{
4052 if (yang_check_iffeatures(module, NULL, anydata, ANYDATA_KEYWORD, unres)) {
4053 goto error;
4054 }
4055
Radek Krejci7212e0a2017-03-08 15:58:22 +01004056 if (yang_check_nodes(module, (struct lys_node *)anydata, *child, options, unres)) {
PavolVican59ba4602017-02-08 11:53:32 +01004057 *child = NULL;
4058 goto error;
4059 }
4060 *child = NULL;
4061
4062 if (anydata->when && yang_check_ext_instance(module, &anydata->when->ext, anydata->when->ext_size, anydata->when, unres)) {
4063 goto error;
4064 }
PavolVican38104a32017-02-08 12:25:23 +01004065 if (yang_check_must(module, anydata->must, anydata->must_size, unres)) {
4066 goto error;
4067 }
PavolVican59ba4602017-02-08 11:53:32 +01004068
4069 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004070 if (anydata->when || anydata->must_size) {
4071 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004072 if (lyxp_node_check_syntax((struct lys_node *)anydata)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004073 goto error;
4074 }
4075 } else {
4076 if (unres_schema_add_node(module, unres, anydata, UNRES_XPATH, NULL) == -1) {
4077 goto error;
4078 }
4079 }
PavolVican59ba4602017-02-08 11:53:32 +01004080 }
Michal Vasko89afc112017-03-16 13:57:28 +01004081
PavolVican59ba4602017-02-08 11:53:32 +01004082 return EXIT_SUCCESS;
4083error:
4084 return EXIT_FAILURE;
4085}
4086
4087static int
Pavol Vican3ad50f82016-12-04 15:00:36 +01004088yang_check_nodes(struct lys_module *module, struct lys_node *parent, struct lys_node *nodes,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004089 int options, struct unres_schema *unres)
Pavol Vican05810b62016-11-23 14:07:22 +01004090{
Pavol Vican3ad50f82016-12-04 15:00:36 +01004091 struct lys_node *node = nodes, *sibling, *child;
Pavol Vican05810b62016-11-23 14:07:22 +01004092
4093 while (node) {
4094 sibling = node->next;
4095 child = node->child;
4096 node->next = NULL;
4097 node->child = NULL;
4098 node->prev = node;
4099
Pavol Vican24ba7f62016-11-28 12:15:20 +01004100 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
4101 lys_node_unlink(node);
PavolVican4b80d042017-02-23 14:30:27 +01004102 yang_free_nodes(module->ctx, node);
Pavol Vican05810b62016-11-23 14:07:22 +01004103 goto error;
4104 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004105 store_config_flag(node, options);
PavolVican70ce7452017-02-01 15:39:39 +01004106 if (yang_check_ext_instance(module, &node->ext, node->ext_size, node, unres)) {
4107 goto error;
4108 }
Pavol Vicanfda8c802016-12-03 02:00:42 +01004109
Pavol Vican05810b62016-11-23 14:07:22 +01004110 switch (node->nodetype) {
4111 case LYS_GROUPING:
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004112 if (yang_check_typedef(module, node, unres)) {
4113 goto error;
4114 }
4115 if (yang_check_iffeatures(module, NULL, node, GROUPING_KEYWORD, unres)) {
Pavol Vican05810b62016-11-23 14:07:22 +01004116 goto error;
4117 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004118 if (yang_check_nodes(module, node, child, options | LYS_PARSE_OPT_INGRP, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004119 child = NULL;
4120 goto error;
4121 }
Pavol Vican05810b62016-11-23 14:07:22 +01004122 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01004123 case LYS_CONTAINER:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004124 if (yang_check_container(module, (struct lys_node_container *)node, &child, options, unres)) {
Pavol Vicanc54a8f72016-11-23 16:45:55 +01004125 goto error;
4126 }
4127 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01004128 case LYS_LEAF:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004129 if (yang_check_leaf(module, (struct lys_node_leaf *)node, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004130 child = NULL;
Pavol Vicana69aff22016-11-24 18:23:50 +01004131 goto error;
4132 }
4133 break;
Pavol Vican36aff862016-11-26 17:07:05 +01004134 case LYS_LEAFLIST:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004135 if (yang_check_leaflist(module, (struct lys_node_leaflist *)node, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004136 child = NULL;
Pavol Vican36aff862016-11-26 17:07:05 +01004137 goto error;
4138 }
4139 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01004140 case LYS_LIST:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004141 if (yang_check_list(module, (struct lys_node_list *)node, &child, options, unres)) {
Pavol Vicand8136a42016-11-27 13:28:04 +01004142 goto error;
4143 }
4144 break;
Pavol Vican36ace102016-11-28 11:46:59 +01004145 case LYS_CHOICE:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004146 if (yang_check_choice(module, (struct lys_node_choice *)node, &child, options, unres)) {
Pavol Vican36ace102016-11-28 11:46:59 +01004147 goto error;
4148 }
4149 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01004150 case LYS_CASE:
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004151 if (yang_check_iffeatures(module, NULL, node, CASE_KEYWORD, unres)) {
Pavol Vicana420bac2016-11-28 14:51:54 +01004152 goto error;
4153 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004154 if (yang_check_nodes(module, node, child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004155 child = NULL;
4156 goto error;
4157 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004158 if (((struct lys_node_case *)node)->when) {
4159 if (yang_check_ext_instance(module, &((struct lys_node_case *)node)->when->ext,
4160 ((struct lys_node_case *)node)->when->ext_size, ((struct lys_node_case *)node)->when, unres)) {
4161 goto error;
4162 }
4163 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004164 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004165 if (lyxp_node_check_syntax(node)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004166 goto error;
4167 }
4168 } else {
4169 if (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1) {
4170 goto error;
4171 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004172 }
4173 }
Pavol Vicana420bac2016-11-28 14:51:54 +01004174 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01004175 case LYS_ANYDATA:
4176 case LYS_ANYXML:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004177 if (yang_check_anydata(module, (struct lys_node_anydata *)node, &child, options, unres)) {
Pavol Vicanbfa1a582016-11-28 15:35:59 +01004178 goto error;
4179 }
4180 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01004181 case LYS_RPC:
4182 case LYS_ACTION:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004183 if (yang_check_rpc_action(module, (struct lys_node_rpc_action *)node, &child, options, unres)){
Pavol Vicanebc9ef82016-11-28 16:46:49 +01004184 goto error;
4185 }
4186 break;
Pavol Vican78729392016-11-28 17:18:22 +01004187 case LYS_INPUT:
4188 case LYS_OUTPUT:
PavolVicane87cb932016-12-30 15:36:18 +01004189 if (yang_check_typedef(module, node, unres)) {
4190 goto error;
4191 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004192 if (yang_check_nodes(module, node, child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004193 child = NULL;
4194 goto error;
4195 }
PavolVican38104a32017-02-08 12:25:23 +01004196 if (((struct lys_node_inout *)node)->must_size) {
4197 if (yang_check_must(module, ((struct lys_node_inout *)node)->must, ((struct lys_node_inout *)node)->must_size, unres)) {
4198 goto error;
4199 }
4200 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004201 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004202 if (lyxp_node_check_syntax(node)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004203 goto error;
4204 }
4205 } else {
4206 if (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1) {
4207 goto error;
4208 }
PavolVican38104a32017-02-08 12:25:23 +01004209 }
Pavol Vican78729392016-11-28 17:18:22 +01004210 }
Pavol Vican78729392016-11-28 17:18:22 +01004211 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01004212 case LYS_NOTIF:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004213 if (yang_check_notif(module, (struct lys_node_notif *)node, &child, options, unres)) {
Pavol Vican29bf8802016-11-28 20:44:57 +01004214 goto error;
4215 }
4216 break;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004217 case LYS_USES:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004218 if (yang_check_uses(module, (struct lys_node_uses *)node, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004219 child = NULL;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004220 goto error;
4221 }
4222 break;
Pavol Vican05810b62016-11-23 14:07:22 +01004223 default:
4224 LOGINT;
Pavol Vican05810b62016-11-23 14:07:22 +01004225 goto error;
4226 }
Pavol Vican05810b62016-11-23 14:07:22 +01004227 node = sibling;
4228 }
4229
4230 return EXIT_SUCCESS;
4231error:
4232 yang_free_nodes(module->ctx, sibling);
4233 yang_free_nodes(module->ctx, child);
4234 return EXIT_FAILURE;
4235}
4236
4237static int
PavolVican75af21d2016-12-29 20:04:07 +01004238yang_check_deviate(struct lys_module *module, struct unres_schema *unres, struct lys_deviate *deviate,
4239 struct lys_node *dev_target, struct ly_set *dflt_check)
4240{
4241 struct lys_node_leaflist *llist;
4242 struct lys_type *type;
4243 struct lys_tpdf *tmp_parent;
4244 int i, j;
4245
PavolVican6f000922017-02-10 12:56:59 +01004246 if (yang_check_ext_instance(module, &deviate->ext, deviate->ext_size, deviate, unres)) {
4247 goto error;
4248 }
PavolVican75af21d2016-12-29 20:04:07 +01004249 if (deviate->must_size && yang_check_deviate_must(module, unres, deviate, dev_target)) {
4250 goto error;
4251 }
4252 if (deviate->unique && yang_check_deviate_unique(module, deviate, dev_target)) {
4253 goto error;
4254 }
4255 if (deviate->dflt_size) {
4256 if (yang_read_deviate_default(module, deviate, dev_target, dflt_check)) {
4257 goto error;
4258 }
4259 if (dev_target->nodetype == LYS_LEAFLIST && deviate->mod == LY_DEVIATE_DEL) {
4260 /* consolidate the final list in the target after removing items from it */
4261 llist = (struct lys_node_leaflist *)dev_target;
4262 for (i = j = 0; j < llist->dflt_size; j++) {
4263 llist->dflt[i] = llist->dflt[j];
4264 if (llist->dflt[i]) {
4265 i++;
4266 }
4267 }
4268 llist->dflt_size = i + 1;
4269 }
4270 }
4271
4272 if (deviate->max_set && yang_read_deviate_minmax(deviate, dev_target, deviate->max, 1)) {
4273 goto error;
4274 }
4275
4276 if (deviate->min_set && yang_read_deviate_minmax(deviate, dev_target, deviate->min, 0)) {
4277 goto error;
4278 }
4279
4280 if (deviate->units && yang_read_deviate_units(module->ctx, deviate, dev_target)) {
4281 goto error;
4282 }
4283
4284 if ((deviate->flags & LYS_CONFIG_MASK)) {
4285 /* add and replace are the same in this case */
4286 /* remove current config value of the target ... */
4287 dev_target->flags &= ~LYS_CONFIG_MASK;
4288
4289 /* ... and replace it with the value specified in deviation */
4290 dev_target->flags |= deviate->flags & LYS_CONFIG_MASK;
4291 }
4292
4293 if ((deviate->flags & LYS_MAND_MASK) && yang_check_deviate_mandatory(deviate, dev_target)) {
4294 goto error;
4295 }
4296
4297 if (deviate->type) {
4298 /* check target node type */
4299 if (dev_target->nodetype == LYS_LEAF) {
4300 type = &((struct lys_node_leaf *)dev_target)->type;
4301 } else if (dev_target->nodetype == LYS_LEAFLIST) {
4302 type = &((struct lys_node_leaflist *)dev_target)->type;
4303 } else {
4304 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
4305 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
4306 goto error;
4307 }
4308 /* remove type and initialize it */
4309 tmp_parent = type->parent;
Radek Krejci5138e9f2017-04-12 13:10:46 +02004310 lys_type_free(module->ctx, type, NULL);
PavolVican75af21d2016-12-29 20:04:07 +01004311 memcpy(type, deviate->type, sizeof *deviate->type);
4312 free(deviate->type);
4313 deviate->type = type;
4314 deviate->type->parent = tmp_parent;
PavolVican6f000922017-02-10 12:56:59 +01004315 if (yang_fill_type(module, type, (struct yang_type *)type->der, tmp_parent, unres)) {
4316 goto error;
4317 }
4318
PavolVican75af21d2016-12-29 20:04:07 +01004319 if (unres_schema_add_node(module, unres, deviate->type, UNRES_TYPE_DER, dev_target) == -1) {
4320 goto error;
4321 }
4322 }
4323
4324 return EXIT_SUCCESS;
4325error:
4326 if (deviate->type) {
4327 yang_type_free(module->ctx, deviate->type);
4328 deviate->type = NULL;
4329 }
4330 return EXIT_FAILURE;
4331}
4332
4333static int
4334yang_check_deviation(struct lys_module *module, struct unres_schema *unres, struct lys_deviation *dev)
4335{
4336 int rc;
4337 uint i;
4338 struct lys_node *dev_target = NULL, *parent;
Michal Vasko50576712017-07-28 12:28:33 +02004339 struct ly_set *dflt_check = ly_set_new(), *set;
PavolVican75af21d2016-12-29 20:04:07 +01004340 unsigned int u;
4341 const char *value, *target_name;
4342 struct lys_node_leaflist *llist;
4343 struct lys_node_leaf *leaf;
4344 struct unres_schema tmp_unres;
4345 struct lys_module *mod;
4346
4347 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02004348 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4349 if (rc == -1) {
PavolVican75af21d2016-12-29 20:04:07 +01004350 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Michal Vasko50576712017-07-28 12:28:33 +02004351 ly_set_free(set);
PavolVican75af21d2016-12-29 20:04:07 +01004352 goto error;
4353 }
Michal Vasko50576712017-07-28 12:28:33 +02004354 dev_target = set->set.s[0];
4355 ly_set_free(set);
4356
PavolVican75af21d2016-12-29 20:04:07 +01004357 if (dev_target->module == lys_main_module(module)) {
4358 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
4359 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
4360 goto error;
4361 }
4362
4363 if (!dflt_check) {
4364 LOGMEM;
4365 goto error;
4366 }
4367
4368 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
4369 /* you cannot remove a key leaf */
4370 if ((dev_target->nodetype == LYS_LEAF) && dev_target->parent && (dev_target->parent->nodetype == LYS_LIST)) {
4371 for (i = 0; i < ((struct lys_node_list *)dev_target->parent)->keys_size; ++i) {
4372 if (((struct lys_node_list *)dev_target->parent)->keys[i] == (struct lys_node_leaf *)dev_target) {
4373 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
4374 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
PavolVican4b80d042017-02-23 14:30:27 +01004375 goto error;
PavolVican75af21d2016-12-29 20:04:07 +01004376 }
4377 }
4378 }
4379 /* unlink and store the original node */
4380 lys_node_unlink(dev_target);
4381 dev->orig_node = dev_target;
4382 } else {
4383 /* store a shallow copy of the original node */
4384 memset(&tmp_unres, 0, sizeof tmp_unres);
PavolVican8c33b152017-01-27 12:45:34 +01004385 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
PavolVican75af21d2016-12-29 20:04:07 +01004386 /* just to be safe */
4387 if (tmp_unres.count) {
4388 LOGINT;
4389 goto error;
4390 }
4391 }
4392
PavolVican6f000922017-02-10 12:56:59 +01004393 if (yang_check_ext_instance(module, &dev->ext, dev->ext_size, dev, unres)) {
4394 goto error;
4395 }
4396
PavolVican75af21d2016-12-29 20:04:07 +01004397 for (i = 0; i < dev->deviate_size; ++i) {
4398 if (yang_check_deviate(module, unres, &dev->deviate[i], dev_target, dflt_check)) {
4399 yang_free_deviate(module->ctx, dev, i + 1);
4400 dev->deviate_size = i+1;
4401 goto error; // missing free unresolve type in deviate
4402 }
4403 }
4404 /* now check whether default value, if any, matches the type */
4405 for (u = 0; u < dflt_check->number; ++u) {
4406 value = NULL;
4407 rc = EXIT_SUCCESS;
4408 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
4409 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
4410 target_name = leaf->name;
4411 value = leaf->dflt;
4412 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
4413 } else { /* LYS_LEAFLIST */
4414 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
4415 target_name = llist->name;
4416 for (i = 0; i < llist->dflt_size; i++) {
4417 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4418 (struct lys_node *)(&llist->dflt[i]));
4419 if (rc == -1) {
4420 value = llist->dflt[i];
4421 break;
4422 }
4423 }
4424 }
4425 if (rc == -1) {
4426 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
4427 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
4428 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
4429 target_name);
4430 goto error;
4431 }
4432 }
4433 ly_set_free(dflt_check);
4434
Radek Krejci29eac3d2017-06-01 16:50:02 +02004435 /* mark all the affected modules as deviated and implemented */
4436 for (parent = dev_target; parent; parent = lys_parent(parent)) {
PavolVican75af21d2016-12-29 20:04:07 +01004437 mod = lys_node_module(parent);
4438 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02004439 mod->deviated = 1; /* main module */
4440 parent->module->deviated = 1; /* possible submodule */
4441 if (lys_set_implemented(mod)) {
4442 LOGERR(ly_errno, "Setting the deviated module \"%s\" implemented failed.", mod->name);
4443 goto error;
4444 }
4445 }
PavolVican75af21d2016-12-29 20:04:07 +01004446 }
PavolVican75af21d2016-12-29 20:04:07 +01004447
4448 return EXIT_SUCCESS;
4449error:
4450 ly_set_free(dflt_check);
4451 return EXIT_FAILURE;
4452}
4453
4454static int
Pavol Vican7313fc02016-11-14 01:10:31 +01004455yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node)
4456{
PavolVican75af21d2016-12-29 20:04:07 +01004457 uint i, erase_identities = 1, erase_nodes = 1, aug_size, dev_size = 0;
Pavol Vican3ad50f82016-12-04 15:00:36 +01004458
4459 aug_size = module->augment_size;
4460 module->augment_size = 0;
PavolVican75af21d2016-12-29 20:04:07 +01004461 dev_size = module->deviation_size;
4462 module->deviation_size = 0;
Pavol Vican7a7916f2016-11-21 23:38:30 +01004463
PavolVican6f87bf92017-02-15 19:38:55 +01004464 if (yang_check_typedef(module, NULL, unres)) {
4465 goto error;
4466 }
4467
PavolVicanc1807262017-01-31 18:00:27 +01004468 if (yang_check_ext_instance(module, &module->ext, module->ext_size, module, unres)) {
4469 goto error;
4470 }
4471
PavolVican171717d2017-02-01 14:49:55 +01004472 /* check extension in revision */
4473 for (i = 0; i < module->rev_size; ++i) {
4474 if (yang_check_ext_instance(module, &module->rev[i].ext, module->rev[i].ext_size, &module->rev[i], unres)) {
4475 goto error;
4476 }
4477 }
4478
PavolVican19dc6152017-02-06 12:04:15 +01004479 /* check extension in definition of extension */
PavolVican5393d3f2017-02-06 23:30:55 +01004480 for (i = 0; i < module->extensions_size; ++i) {
PavolVican19dc6152017-02-06 12:04:15 +01004481 if (yang_check_ext_instance(module, &module->extensions[i].ext, module->extensions[i].ext_size, &module->extensions[i], unres)) {
4482 goto error;
4483 }
4484 }
4485
Pavol Vican7a7916f2016-11-21 23:38:30 +01004486 /* check features */
4487 for (i = 0; i < module->features_size; ++i) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004488 if (yang_check_iffeatures(module, NULL, &module->features[i], FEATURE_KEYWORD, unres)) {
4489 goto error;
4490 }
PavolVican5393d3f2017-02-06 23:30:55 +01004491 if (yang_check_ext_instance(module, &module->features[i].ext, module->features[i].ext_size, &module->features[i], unres)) {
4492 goto error;
4493 }
4494
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004495 /* check for circular dependencies */
4496 if (module->features[i].iffeature_size && (unres_schema_add_node(module, unres, &module->features[i], UNRES_FEATURE, NULL) == -1)) {
4497 goto error;
Pavol Vican7a7916f2016-11-21 23:38:30 +01004498 }
4499 }
Pavol Vican36e27272016-11-22 15:47:28 +01004500 erase_identities = 0;
4501 if (yang_check_identities(module, unres)) {
4502 goto error;
4503 }
Pavol Vican05810b62016-11-23 14:07:22 +01004504 erase_nodes = 0;
Radek Krejci7212e0a2017-03-08 15:58:22 +01004505 if (yang_check_nodes(module, NULL, node, 0, unres)) {
Pavol Vican05810b62016-11-23 14:07:22 +01004506 goto error;
4507 }
Pavol Vican7a7916f2016-11-21 23:38:30 +01004508
PavolVican75af21d2016-12-29 20:04:07 +01004509 /* check deviation */
4510 for (i = 0; i < dev_size; ++i) {
4511 module->deviation_size++;
4512 if (yang_check_deviation(module, unres, &module->deviation[i])) {
4513 goto error;
4514 }
4515 }
4516
Pavol Vican3ad50f82016-12-04 15:00:36 +01004517 /* check augments */
4518 for (i = 0; i < aug_size; ++i) {
4519 module->augment_size++;
Radek Krejci7212e0a2017-03-08 15:58:22 +01004520 if (yang_check_augment(module, &module->augment[i], 0, unres)) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01004521 goto error;
4522 }
4523 if (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1) {
4524 goto error;
4525 }
4526 }
4527
Pavol Vican7313fc02016-11-14 01:10:31 +01004528 return EXIT_SUCCESS;
4529error:
Pavol Vican36e27272016-11-22 15:47:28 +01004530 if (erase_identities) {
4531 yang_free_ident_base(module->ident, 0, module->ident_size);
4532 }
Pavol Vican05810b62016-11-23 14:07:22 +01004533 if (erase_nodes) {
4534 yang_free_nodes(module->ctx, node);
4535 }
Pavol Vican3ad50f82016-12-04 15:00:36 +01004536 for (i = module->augment_size; i < aug_size; ++i) {
4537 yang_free_augment(module->ctx, &module->augment[i]);
4538 }
PavolVican75af21d2016-12-29 20:04:07 +01004539 for (i = module->deviation_size; i < dev_size; ++i) {
4540 yang_free_deviate(module->ctx, &module->deviation[i], 0);
4541 free(module->deviation[i].deviate);
4542 }
Pavol Vican7313fc02016-11-14 01:10:31 +01004543 return EXIT_FAILURE;
4544}
PavolVican22e88682017-02-14 22:38:18 +01004545
4546int
Michal Vasko3e3228d2017-02-24 14:55:32 +01004547yang_read_extcomplex_str(struct lys_module *module, struct lys_ext_instance_complex *ext, const char *arg_name,
PavolVican22e88682017-02-14 22:38:18 +01004548 const char *parent_name, char *value, int parent_stmt, LY_STMT stmt)
4549{
4550 int c;
4551 const char **str, ***p = NULL;
4552 void *reallocated;
4553 struct lyext_substmt *info;
4554
4555 c = 0;
4556 if (stmt == LY_STMT_PREFIX && parent_stmt == LY_STMT_BELONGSTO) {
PavolVican4b80d042017-02-23 14:30:27 +01004557 /* str contains no NULL value */
PavolVican22e88682017-02-14 22:38:18 +01004558 str = lys_ext_complex_get_substmt(LY_STMT_BELONGSTO, ext, &info);
4559 if (info->cardinality < LY_STMT_CARD_SOME) {
4560 str++;
4561 } else {
4562 /* get the index in the array to add new item */
4563 p = (const char ***)str;
4564 for (c = 0; p[0][c + 1]; c++);
4565 str = p[1];
4566 }
4567 str[c] = lydict_insert_zc(module->ctx, value);
4568 } else {
4569 str = lys_ext_complex_get_substmt(stmt, ext, &info);
4570 if (!str) {
4571 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, arg_name, parent_name);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004572 goto error;
PavolVican22e88682017-02-14 22:38:18 +01004573 }
4574 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
4575 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, arg_name, parent_name);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004576 goto error;
PavolVican22e88682017-02-14 22:38:18 +01004577 }
4578
4579 if (info->cardinality >= LY_STMT_CARD_SOME) {
4580 /* there can be multiple instances, str is actually const char *** */
4581 p = (const char ***)str;
4582 if (!p[0]) {
4583 /* allocate initial array */
PavolVican50809742017-02-18 21:22:54 +01004584 p[0] = calloc(2, sizeof(const char *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004585 LY_CHECK_ERR_GOTO(!p[0], LOGMEM, error);
PavolVican22e88682017-02-14 22:38:18 +01004586 if (stmt == LY_STMT_BELONGSTO) {
4587 /* allocate another array for the belongs-to's prefixes */
4588 p[1] = calloc(2, sizeof(const char *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004589 LY_CHECK_ERR_GOTO(!p[1], LOGMEM, error);
PavolVican50809742017-02-18 21:22:54 +01004590 } else if (stmt == LY_STMT_ARGUMENT) {
4591 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01004592 ((uint8_t **)p)[1] = calloc(2, sizeof(uint8_t));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004593 LY_CHECK_ERR_GOTO(!p[1], LOGMEM, error);
PavolVican50809742017-02-18 21:22:54 +01004594 /* default value of yin element */
4595 ((uint8_t *)p[1])[0] = 2;
PavolVican22e88682017-02-14 22:38:18 +01004596 }
4597 } else {
4598 /* get the index in the array to add new item */
4599 for (c = 0; p[0][c]; c++);
4600 }
4601 str = p[0];
4602 }
4603
4604 str[c] = lydict_insert_zc(module->ctx, value);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004605 value = NULL;
PavolVican22e88682017-02-14 22:38:18 +01004606
PavolVican50809742017-02-18 21:22:54 +01004607 if (c) {
PavolVican22e88682017-02-14 22:38:18 +01004608 /* enlarge the array(s) */
4609 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
4610 if (!reallocated) {
4611 LOGMEM;
4612 lydict_remove(module->ctx, p[0][c]);
4613 p[0][c] = NULL;
4614 return EXIT_FAILURE;
4615 }
4616 p[0] = reallocated;
4617 p[0][c + 1] = NULL;
4618
4619 if (stmt == LY_STMT_BELONGSTO) {
4620 /* enlarge the second belongs-to's array with prefixes */
4621 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
4622 if (!reallocated) {
4623 LOGMEM;
4624 lydict_remove(module->ctx, p[1][c]);
4625 p[1][c] = NULL;
4626 return EXIT_FAILURE;
4627 }
4628 p[1] = reallocated;
4629 p[1][c + 1] = NULL;
PavolVican50809742017-02-18 21:22:54 +01004630 } else if (stmt == LY_STMT_ARGUMENT) {
4631 /* enlarge the second argument's array with yin element */
4632 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
4633 if (!reallocated) {
4634 LOGMEM;
4635 ((uint8_t *)p[1])[c] = 0;
4636 return EXIT_FAILURE;
4637 }
4638 p[1] = reallocated;
4639 ((uint8_t *)p[1])[c + 1] = 0;
PavolVican22e88682017-02-14 22:38:18 +01004640 }
4641 }
4642 }
4643
4644 return EXIT_SUCCESS;
Radek Krejcia8d111f2017-05-31 13:57:37 +02004645
4646error:
4647 free(value);
4648 return EXIT_FAILURE;
PavolVican22e88682017-02-14 22:38:18 +01004649}
PavolVican5334c892017-02-15 16:29:09 +01004650
4651static int
4652yang_fill_ext_substm_index(struct lys_ext_instance_complex *ext, LY_STMT stmt, enum yytokentype keyword)
4653{
4654 int c = 0, decrement = 0;
4655 const char **str, ***p = NULL;
4656 struct lyext_substmt *info;
4657
4658
4659 if (keyword == BELONGS_TO_KEYWORD || stmt == LY_STMT_BELONGSTO) {
4660 stmt = LY_STMT_BELONGSTO;
4661 decrement = -1;
PavolVican50809742017-02-18 21:22:54 +01004662 } else if (keyword == ARGUMENT_KEYWORD || stmt == LY_STMT_ARGUMENT) {
4663 stmt = LY_STMT_ARGUMENT;
4664 decrement = -1;
PavolVican5334c892017-02-15 16:29:09 +01004665 }
4666
4667 str = lys_ext_complex_get_substmt(stmt, ext, &info);
4668 if (!str || info->cardinality < LY_STMT_CARD_SOME || !((const char ***)str)[0]) {
4669 return 0;
4670 } else {
4671 p = (const char ***)str;
4672 /* get the index in the array */
4673 for (c = 0; p[0][c]; c++);
4674 return c + decrement;
4675 }
4676}
PavolVicana0fdbf32017-02-15 17:59:02 +01004677
4678void **
PavolVicanfe83b152017-02-19 03:19:29 +01004679yang_getplace_for_extcomplex_struct(struct lys_ext_instance_complex *ext, int *index,
4680 char *parent_name, char *node_name, LY_STMT stmt)
PavolVicana0fdbf32017-02-15 17:59:02 +01004681{
4682 int c;
4683 void **data, ***p = NULL;
4684 void *reallocated;
4685 struct lyext_substmt *info;
4686
4687 data = lys_ext_complex_get_substmt(stmt, ext, &info);
4688 if (!data) {
4689 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node_name, parent_name);
4690 return NULL;
4691 }
4692 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
4693 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4694 return NULL;
4695 }
4696
4697 c = 0;
4698 if (info->cardinality >= LY_STMT_CARD_SOME) {
4699 /* there can be multiple instances, so instead of pointer to array,
4700 * we have in data pointer to pointer to array */
4701 p = (void ***)data;
4702 data = *p;
4703 if (!data) {
4704 /* allocate initial array */
PavolVicaneef1d912017-02-19 00:19:15 +01004705 *p = data = calloc(2, sizeof(void *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004706 LY_CHECK_ERR_RETURN(!data, LOGMEM, NULL);
PavolVicana0fdbf32017-02-15 17:59:02 +01004707 } else {
4708 for (c = 0; *data; data++, c++);
4709 }
4710 }
4711
PavolVicaneef1d912017-02-19 00:19:15 +01004712 if (c) {
PavolVicana0fdbf32017-02-15 17:59:02 +01004713 /* enlarge the array */
4714 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004715 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM, NULL);
PavolVicana0fdbf32017-02-15 17:59:02 +01004716 *p = reallocated;
4717 data = *p;
4718 data[c + 1] = NULL;
4719 }
4720
PavolVicanfe83b152017-02-19 03:19:29 +01004721 if (index) {
4722 *index = c;
4723 return data;
4724 } else {
4725 return &data[c];
4726 }
PavolVicana0fdbf32017-02-15 17:59:02 +01004727}
PavolVicanff0f7f42017-02-16 11:35:42 +01004728
4729int
4730yang_fill_extcomplex_flags(struct lys_ext_instance_complex *ext, char *parent_name, char *node_name,
4731 LY_STMT stmt, uint16_t value, uint16_t mask)
4732{
4733 uint16_t *data;
4734 struct lyext_substmt *info;
4735
4736 data = lys_ext_complex_get_substmt(stmt, ext, &info);
4737 if (!data) {
4738 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node_name, parent_name);
4739 return EXIT_FAILURE;
4740 }
4741 if (info->cardinality < LY_STMT_CARD_SOME && (*data & mask)) {
4742 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4743 return EXIT_FAILURE;
4744 }
4745
4746 *data |= value;
4747 return EXIT_SUCCESS;
4748}
PavolVican8e8dfd12017-02-16 13:51:41 +01004749
4750int
PavolVican6a852a62017-02-16 15:36:01 +01004751yang_fill_extcomplex_uint8(struct lys_ext_instance_complex *ext, char *parent_name, char *node_name,
4752 LY_STMT stmt, uint8_t value)
PavolVican8e8dfd12017-02-16 13:51:41 +01004753{
PavolVican6a852a62017-02-16 15:36:01 +01004754 uint8_t *val, **pp = NULL, *reallocated;
PavolVican8e8dfd12017-02-16 13:51:41 +01004755 struct lyext_substmt *info;
PavolVican6a852a62017-02-16 15:36:01 +01004756 int i = 0;
PavolVican8e8dfd12017-02-16 13:51:41 +01004757
4758 val = lys_ext_complex_get_substmt(stmt, ext, &info);
4759 if (!val) {
4760 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node_name, parent_name);
4761 return EXIT_FAILURE;
4762 }
PavolVican6a852a62017-02-16 15:36:01 +01004763 if (stmt == LY_STMT_DIGITS) {
4764 if (info->cardinality < LY_STMT_CARD_SOME && *val) {
4765 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4766 return EXIT_FAILURE;
4767 }
PavolVican8e8dfd12017-02-16 13:51:41 +01004768
PavolVican6a852a62017-02-16 15:36:01 +01004769 if (info->cardinality >= LY_STMT_CARD_SOME) {
4770 /* there can be multiple instances */
4771 pp = (uint8_t**)val;
4772 if (!(*pp)) {
4773 *pp = calloc(2, sizeof(uint8_t)); /* allocate initial array */
Radek Krejcia8d111f2017-05-31 13:57:37 +02004774 LY_CHECK_ERR_RETURN(!*pp, LOGMEM, EXIT_FAILURE);
PavolVican6a852a62017-02-16 15:36:01 +01004775 } else {
4776 for (i = 0; (*pp)[i]; i++);
4777 }
4778 val = &(*pp)[i];
4779 }
4780
4781 /* stored value */
4782 *val = value;
4783
4784 if (i) {
4785 /* enlarge the array */
4786 reallocated = realloc(*pp, (i + 2) * sizeof *val);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004787 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM, EXIT_FAILURE);
PavolVican6a852a62017-02-16 15:36:01 +01004788 *pp = reallocated;
4789 (*pp)[i + 1] = 0;
4790 }
PavolVican8e8dfd12017-02-16 13:51:41 +01004791 } else {
PavolVican6a852a62017-02-16 15:36:01 +01004792 if (*val) {
4793 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4794 return EXIT_FAILURE;
4795 }
4796
4797 if (stmt == LY_STMT_REQINSTANCE) {
4798 *val = (value == 1) ? 1 : 2;
4799 } else if (stmt == LY_STMT_MODIFIER) {
4800 *val = 1;
4801 } else {
4802 LOGINT;
4803 return EXIT_FAILURE;
4804 }
PavolVican8e8dfd12017-02-16 13:51:41 +01004805 }
4806
4807 return EXIT_SUCCESS;
4808}
PavolVican3f47b292017-02-16 20:38:16 +01004809
PavolVicanf3091bf2017-02-19 18:27:01 +01004810int
4811yang_extcomplex_node(struct lys_ext_instance_complex *ext, char *parent_name, char *node_name,
4812 struct lys_node *node, LY_STMT stmt)
4813{
4814 struct lyext_substmt *info;
4815 struct lys_node **snode, *siter;
4816
4817 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
4818 if (!snode) {
4819 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node_name, parent_name);
4820 return EXIT_FAILURE;
4821 }
4822 if (info->cardinality < LY_STMT_CARD_SOME) {
4823 LY_TREE_FOR(node, siter) {
4824 if (stmt == lys_snode2stmt(siter->nodetype)) {
4825 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4826 return EXIT_FAILURE;
4827 }
4828 }
4829 }
4830
4831 return EXIT_SUCCESS;
4832}
PavolVicandb0e8172017-02-20 00:46:09 +01004833
4834int
4835yang_fill_extcomplex_module(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext,
4836 char *parent_name, char **values, int implemented)
4837{
4838 int c, i;
4839 struct lys_module **modules, ***p, *reallocated, **pp;
4840 struct lyext_substmt *info;
4841
4842 if (!values) {
4843 return EXIT_SUCCESS;
4844 }
4845 pp = modules = lys_ext_complex_get_substmt(LY_STMT_MODULE, ext, &info);
4846 if (!modules) {
4847 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "module", parent_name);
4848 return EXIT_FAILURE;
4849 }
4850
4851 for (i = 0; values[i]; ++i) {
4852 c = 0;
4853 if (info->cardinality < LY_STMT_CARD_SOME && *modules) {
4854 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "module", parent_name);
4855 return EXIT_FAILURE;
4856 }
4857 if (info->cardinality >= LY_STMT_CARD_SOME) {
4858 /* there can be multiple instances, so instead of pointer to array,
4859 * we have in modules pointer to pointer to array */
4860 p = (struct lys_module ***)pp;
4861 modules = *p;
4862 if (!modules) {
4863 /* allocate initial array */
4864 *p = modules = calloc(2, sizeof(struct lys_module *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004865 LY_CHECK_ERR_RETURN(!*p, LOGMEM, EXIT_FAILURE);
PavolVicandb0e8172017-02-20 00:46:09 +01004866 } else {
4867 for (c = 0; *modules; modules++, c++);
4868 }
4869 }
4870
4871 if (c) {
4872 /* enlarge the array */
4873 reallocated = realloc(*p, (c + 2) * sizeof(struct lys_module *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004874 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM, EXIT_FAILURE);
PavolVicandb0e8172017-02-20 00:46:09 +01004875 *p = (struct lys_module **)reallocated;
4876 modules = *p;
4877 modules[c + 1] = NULL;
4878 }
4879
4880 modules[c] = yang_read_module(ctx, values[i], 0, NULL, implemented);
4881 if (!modules[c]) {
4882 return EXIT_FAILURE;
4883 }
4884 }
4885
4886 return EXIT_SUCCESS;
4887}