blob: 8a27bb3a148434d984d2bca9d9d1982d805bd6cb [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);
Frank Rimplerc4db1c72017-09-12 12:56:39 +000031void lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size, int shallow,
Radek Krejci5138e9f2017-04-12 13:10:46 +020032 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;
PavolVicanbd1d1ae2017-07-20 00:06:00 +0200402 node->parent = parent;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100403
404 /* insert the node into the schema tree */
Pavol Vican05810b62016-11-23 14:07:22 +0100405 child = (parent) ? &parent->child : root;
406 if (*child) {
407 (*child)->prev->next = node;
408 (*child)->prev = node;
409 } else {
410 *child = node;
411 node->prev = node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100412 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100413 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100414}
415
416int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200417yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100418{
419 int ret;
420
421 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100422 case LEAF_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100423 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value, node);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100424 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100425 case TYPEDEF_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100426 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value, NULL);
Pavol Vican0df02b02016-03-01 10:28:50 +0100427 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200428 default:
429 free(value);
430 LOGINT;
431 ret = EXIT_FAILURE;
432 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100433 }
434 return ret;
435}
436
437int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200438yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100439{
440 int ret;
441
442 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100443 case LEAF_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100444 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value, node);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100445 break;
446 case LEAF_LIST_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100447 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value, node);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100448 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100449 case TYPEDEF_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100450 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value, NULL);
Pavol Vican0df02b02016-03-01 10:28:50 +0100451 break;
PavolVican75af21d2016-12-29 20:04:07 +0100452 case ADD_KEYWORD:
453 case REPLACE_KEYWORD:
PavolVican6f000922017-02-10 12:56:59 +0100454 case DELETE_KEYWORD:
PavolVican196694c2017-01-27 10:33:09 +0100455 ret = yang_check_string(module, &((struct lys_deviate *) node)->units, "units", "deviate", value, NULL);
Pavol Vican021488a2016-01-25 23:56:12 +0100456 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200457 default:
458 free(value);
459 LOGINT;
460 ret = EXIT_FAILURE;
461 break;
Pavol Vican021488a2016-01-25 23:56:12 +0100462 }
463 return ret;
464}
Pavol Vican5de33492016-02-22 14:03:24 +0100465
466int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100467yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100468{
469 char *exp, *value;
Radek Krejci5c08a992016-11-02 13:30:04 +0100470 struct lys_node *node;
Pavol Vican5de33492016-02-22 14:03:24 +0100471
472 exp = value = (char *) list->keys;
473 while ((value = strpbrk(value, " \t\n"))) {
474 list->keys_size++;
475 while (isspace(*value)) {
476 value++;
477 }
478 }
479 list->keys_size++;
Radek Krejci5c08a992016-11-02 13:30:04 +0100480
481 list->keys_str = lydict_insert_zc(module->ctx, exp);
Pavol Vican5de33492016-02-22 14:03:24 +0100482 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200483 LY_CHECK_ERR_RETURN(!list->keys, LOGMEM, EXIT_FAILURE);
484
Radek Krejci5c08a992016-11-02 13:30:04 +0100485 for (node = list->parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
486 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
487 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100488 }
Pavol Vican5de33492016-02-22 14:03:24 +0100489 return EXIT_SUCCESS;
Pavol Vican5de33492016-02-22 14:03:24 +0100490}
491
492int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100493yang_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 +0100494{
495 int i, j;
Radek Krejci1a9c3612017-04-24 14:49:43 +0200496 char *vaux, c;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200497 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100498
499 /* count the number of unique leafs in the value */
500 vaux = value;
501 while ((vaux = strpbrk(vaux, " \t\n"))) {
502 unique->expr_size++;
503 while (isspace(*vaux)) {
504 vaux++;
505 }
506 }
507 unique->expr_size++;
508 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200509 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM, error);
Pavol Vican85f12022016-03-05 16:30:35 +0100510
511 for (i = 0; i < unique->expr_size; i++) {
512 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +0200513 if (vaux) {
514 c = *vaux;
515 *vaux = '\0';
Pavol Vican85f12022016-03-05 16:30:35 +0100516 }
517
Radek Krejci1a9c3612017-04-24 14:49:43 +0200518 /* store token into unique structure (includes converting prefix to the module name) */
519 unique->expr[i] = transform_schema2json(module, value);
520 if (vaux) {
521 *vaux = c;
522 }
Pavol Vican85f12022016-03-05 16:30:35 +0100523
524 /* check that the expression does not repeat */
525 for (j = 0; j < i; j++) {
526 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100527 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
PavolVican196694c2017-01-27 10:33:09 +0100528 LOGVAL(LYE_SPEC, LY_VLOG_LYS, list, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100529 goto error;
530 }
531 }
532 /* try to resolve leaf */
533 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200534 unique_info = malloc(sizeof *unique_info);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200535 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM, error);
Radek Krejcid09d1a52016-08-11 14:05:45 +0200536 unique_info->list = (struct lys_node *)list;
537 unique_info->expr = unique->expr[i];
538 unique_info->trg_type = &unique->trg_type;
539 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200540 goto error;
541 }
Pavol Vican85f12022016-03-05 16:30:35 +0100542 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200543 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100544 goto error;
545 }
546 }
547
548 /* move to next token */
549 value = vaux;
Radek Krejci1a9c3612017-04-24 14:49:43 +0200550 while(value && isspace(*value)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100551 value++;
552 }
553 }
554
555 return EXIT_SUCCESS;
556
557error:
558 return EXIT_FAILURE;
559}
560
561int
Pavol Vican5de33492016-02-22 14:03:24 +0100562yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
563{
564 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100565 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100566
567 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100568 str = (char *)list->unique[k].expr;
569 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100570 goto error;
571 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100572 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100573 }
574 return EXIT_SUCCESS;
575
576error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100577 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100578 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100579}
580
Pavol Vican07f220f2016-09-02 13:04:37 +0200581int
Pavol Vican81344ac2016-09-02 14:23:06 +0200582yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100583{
Pavol Vican81344ac2016-09-02 14:23:06 +0200584 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
585 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
586 goto error;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100587 }
Pavol Vican81344ac2016-09-02 14:23:06 +0200588 if (stype->type->info.lref.path) {
589 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
590 goto error;
591 }
592 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
593 stype->base = LY_TYPE_LEAFREF;
594 return EXIT_SUCCESS;
595
596error:
597 free(value);
598 return EXIT_FAILURE;
599}
600
601int
602yang_read_require_instance(struct yang_type *stype, int req)
603{
604 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
605 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
606 return EXIT_FAILURE;
607 }
608 if (stype->type->info.lref.req) {
609 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
610 return EXIT_FAILURE;
611 }
612 stype->type->info.lref.req = req;
613 stype->base = LY_TYPE_LEAFREF;
614 return EXIT_SUCCESS;
615}
616
617int
Pavol Vican7313fc02016-11-14 01:10:31 +0100618yang_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 +0100619{
Radek Krejcidce5f972017-09-12 15:47:49 +0200620 int rc, ret = -1;
621 unsigned int i, j;
Pavol Vican81344ac2016-09-02 14:23:06 +0200622 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100623 const char *name, *value;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100624 LY_DATA_TYPE base = 0, base_tmp;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200625 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200626 struct lys_type *dertype;
627 struct lys_type_enum *enms_sc = NULL;
628 struct lys_type_bit *bits_sc = NULL;
629 struct lys_type_bit bit_tmp;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100630 struct yang_type *yang;
Pavol Vican73e7c992016-02-24 12:18:05 +0100631
Pavol Vican0adf01d2016-03-22 12:29:33 +0100632 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100633 if (!value) {
634 goto error;
635 }
636
637 i = parse_identifier(value);
638 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100639 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100640 lydict_remove(module->ctx, value);
641 goto error;
642 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200643 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100644 name = value;
645 if (value[i]) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100646 type->module_name = lydict_insert(module->ctx, value, i);
Pavol Vican73e7c992016-02-24 12:18:05 +0100647 name += i;
648 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100649 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100650 lydict_remove(module->ctx, value);
651 goto error;
652 }
653 ++name;
654 }
655
Pavol Vican7313fc02016-11-14 01:10:31 +0100656 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100657 if (rc == -1) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100658 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200659 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100660 goto error;
661
Michal Vasko01c6fd22016-05-20 11:43:05 +0200662 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100663 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200664 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200665 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100666 ret = EXIT_FAILURE;
667 goto error;
668 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200669 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200670
Pavol Vican7313fc02016-11-14 01:10:31 +0100671 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200672 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200673 * 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 +0200674 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
675 if (siter) {
Radek Krejci93def382017-05-24 15:33:48 +0200676 assert(((struct lys_node_grp *)siter)->unres_count);
677 ((struct lys_node_grp *)siter)->unres_count--;
Radek Krejcic13db382016-08-16 10:52:42 +0200678 } else {
679 LOGINT;
680 goto error;
681 }
682 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200683
684 /* check status */
Pavol Vican7313fc02016-11-14 01:10:31 +0100685 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
686 type->der->flags, type->der->module, type->der->name, parent)) {
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200687 goto error;
688 }
689
Pavol Vican8bd72e42016-08-29 09:53:05 +0200690 base = typ->base;
PavolVicane87cb932016-12-30 15:36:18 +0100691 base_tmp = type->base;
Pavol Vican7313fc02016-11-14 01:10:31 +0100692 type->base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100693 if (base == 0) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100694 base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100695 }
696 switch (base) {
697 case LY_TYPE_STRING:
Pavol Vican7313fc02016-11-14 01:10:31 +0100698 if (type->base == LY_TYPE_BINARY) {
699 if (type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100700 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100701 goto error;
702 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100703 type->info.binary.length = type->info.str.length;
704 if (type->info.binary.length && lyp_check_length_range(type->info.binary.length->expr, type)) {
705 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100706 goto error;
707 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100708 } else if (type->base == LY_TYPE_STRING) {
709 if (type->info.str.length && lyp_check_length_range(type->info.str.length->expr, type)) {
710 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100711 goto error;
712 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100713 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100714 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100715 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100716 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100717 break;
718 case LY_TYPE_DEC64:
Pavol Vican7313fc02016-11-14 01:10:31 +0100719 if (type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100720 /* mandatory sub-statement(s) check */
Pavol Vican7313fc02016-11-14 01:10:31 +0100721 if (!type->info.dec64.dig && !type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100722 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100723 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100724 goto error;
725 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100726 if (type->info.dec64.dig && type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100727 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100728 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100729 goto error;
730 }
Radek Krejci4800f652016-09-08 14:02:52 +0200731
732 /* copy fraction-digits specification from parent type for easier internal use */
Pavol Vican7313fc02016-11-14 01:10:31 +0100733 if (type->der->type.der) {
734 type->info.dec64.dig = type->der->type.info.dec64.dig;
735 type->info.dec64.div = type->der->type.info.dec64.div;
Radek Krejci4800f652016-09-08 14:02:52 +0200736 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100737 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
738 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.dec64.range->expr, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200739 goto error;
740 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100741 } else if (type->base >= LY_TYPE_INT8 && type->base <=LY_TYPE_UINT64) {
742 if (type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100743 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100744 goto error;
745 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100746 type->info.num.range = type->info.dec64.range;
747 if (type->info.num.range && lyp_check_length_range(type->info.num.range->expr, type)) {
748 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100749 goto error;
750 }
751 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100752 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100753 goto error;
754 }
755 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100756 case LY_TYPE_ENUM:
Pavol Vican7313fc02016-11-14 01:10:31 +0100757 if (type->base != LY_TYPE_ENUM) {
758 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100759 goto error;
760 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100761 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200762
763 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100764 if (!type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200765 /* type is derived directly from buit-in enumeartion type and enum statement is required */
766 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
767 goto error;
768 }
769 } else {
770 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100771 if (module->version < 2 && type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200772 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
773 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
774 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
775 goto error;
776 }
777
778 /* restricted enumeration type - the name MUST be used in the base type */
779 enms_sc = dertype->info.enums.enm;
Pavol Vican7313fc02016-11-14 01:10:31 +0100780 for(i = 0; i < type->info.enums.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200781 for (j = 0; j < dertype->info.enums.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100782 if (ly_strequal(enms_sc[j].name, type->info.enums.enm[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200783 break;
784 }
785 }
786 if (j == dertype->info.enums.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100787 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200788 goto error;
789 }
790
Pavol Vican7313fc02016-11-14 01:10:31 +0100791 if (type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200792 /* automatically assign value from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100793 type->info.enums.enm[i].value = enms_sc[j].value;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200794 } else {
795 /* check that the assigned value corresponds to the original
796 * value of the enum in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100797 if (type->info.enums.enm[i].value != enms_sc[j].value) {
798 /* type->info.enums.enm[i].value - assigned value in restricted enum
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200799 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100800 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, type->info.enums.enm[i].value,
801 type->info.enums.enm[i].name, enms_sc[j].value);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200802 goto error;
803 }
804 }
805 }
Pavol Vican79a763d2016-02-25 15:41:27 +0100806 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100807 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100808 case LY_TYPE_BITS:
Pavol Vican7313fc02016-11-14 01:10:31 +0100809 if (type->base != LY_TYPE_BITS) {
810 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100811 goto error;
812 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100813 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200814
815 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100816 if (!type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200817 /* type is derived directly from buit-in bits type and bit statement is required */
818 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
819 goto error;
820 }
821 } else {
822 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100823 if (module->version < 2 && type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200824 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
825 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
826 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
827 goto error;
828 }
829
830 bits_sc = dertype->info.bits.bit;
Pavol Vican7313fc02016-11-14 01:10:31 +0100831 for (i = 0; i < type->info.bits.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200832 for (j = 0; j < dertype->info.bits.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100833 if (ly_strequal(bits_sc[j].name, type->info.bits.bit[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200834 break;
835 }
836 }
837 if (j == dertype->info.bits.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100838 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200839 goto error;
840 }
841
842 /* restricted bits type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100843 if (type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200844 /* automatically assign position from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100845 type->info.bits.bit[i].pos = bits_sc[j].pos;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200846 } else {
847 /* check that the assigned position corresponds to the original
848 * position of the bit in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100849 if (type->info.bits.bit[i].pos != bits_sc[j].pos) {
850 /* type->info.bits.bit[i].pos - assigned position in restricted bits
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200851 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100852 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
853 type->info.bits.bit[i].name, bits_sc[j].pos);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200854 goto error;
855 }
856 }
857 }
Pavol Vican03a59442016-03-21 15:23:45 +0100858 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200859
Radek Krejcidce5f972017-09-12 15:47:49 +0200860 for (i = type->info.bits.count; i > 0; i--) {
861 j = i - 1;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200862
863 /* keep them ordered by position */
Pavol Vican7313fc02016-11-14 01:10:31 +0100864 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200865 /* switch them */
Pavol Vican7313fc02016-11-14 01:10:31 +0100866 memcpy(&bit_tmp, &type->info.bits.bit[j], sizeof bit_tmp);
867 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit_tmp);
868 memcpy(&type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200869 j--;
870 }
Pavol Vican03a59442016-03-21 15:23:45 +0100871 }
872 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100873 case LY_TYPE_LEAFREF:
Pavol Vican7313fc02016-11-14 01:10:31 +0100874 if (type->base == LY_TYPE_INST) {
875 if (type->info.lref.path) {
Pavol Vican81344ac2016-09-02 14:23:06 +0200876 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
Pavol Vican1ff0e222016-02-26 12:27:01 +0100877 goto error;
878 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100879 if ((req = type->info.lref.req)) {
880 type->info.inst.req = req;
Pavol Vican81344ac2016-09-02 14:23:06 +0200881 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100882 } else if (type->base == LY_TYPE_LEAFREF) {
Pavol Vican92626d72016-09-21 09:36:09 +0200883 /* require-instance only YANG 1.1 */
Pavol Vican7313fc02016-11-14 01:10:31 +0100884 if (type->info.lref.req && (module->version < 2)) {
Pavol Vican92626d72016-09-21 09:36:09 +0200885 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
886 goto error;
887 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200888 /* flag resolving for later use */
889 if (!tpdftype) {
890 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
891 if (siter) {
892 /* just a flag - do not resolve */
893 tpdftype = 1;
894 }
895 }
896
Pavol Vican7313fc02016-11-14 01:10:31 +0100897 if (type->info.lref.path) {
898 if (type->der->type.der) {
Pavol Vican894ee0f2016-08-30 15:29:46 +0200899 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
900 goto error;
901 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100902 value = type->info.lref.path;
Pavol Vican191613a2016-02-26 16:21:32 +0100903 /* store in the JSON format */
Pavol Vican7313fc02016-11-14 01:10:31 +0100904 type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +0100905 lydict_remove(module->ctx, value);
Pavol Vican7313fc02016-11-14 01:10:31 +0100906 if (!type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +0100907 goto error;
908 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200909 /* try to resolve leafref path only when this is instantiated
910 * leaf, so it is not:
911 * - typedef's type,
912 * - in grouping definition,
913 * - just instantiated in a grouping definition,
914 * because in those cases the nodes referenced in path might not be present
915 * and it is not a bug. */
Pavol Vican7313fc02016-11-14 01:10:31 +0100916 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +0100917 goto error;
918 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100919 } else if (!type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100920 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +0100921 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200922 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +0200923 /* copy leafref definition into the derived type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100924 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +0200925 /* and resolve the path at the place we are (if not in grouping/typedef) */
Pavol Vican7313fc02016-11-14 01:10:31 +0100926 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200927 goto error;
928 }
Pavol Vican191613a2016-02-26 16:21:32 +0100929 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100930 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100931 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100932 goto error;
933 }
934 break;
935 case LY_TYPE_IDENT:
Pavol Vican7313fc02016-11-14 01:10:31 +0100936 if (type->base != LY_TYPE_IDENT) {
937 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100938 goto error;
939 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100940 if (type->der->type.der) {
941 if (type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200942 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
943 goto error;
944 }
945 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100946 if (!type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200947 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
948 goto error;
949 }
950 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100951 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100952 case LY_TYPE_UNION:
Pavol Vican7313fc02016-11-14 01:10:31 +0100953 if (type->base != LY_TYPE_UNION) {
954 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100955 goto error;
956 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100957 if (!type->info.uni.types) {
958 if (type->der->type.der) {
Pavol Vicana4f045a2016-02-29 15:01:20 +0100959 /* this is just a derived type with no additional type specified/required */
960 break;
961 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100962 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +0100963 goto error;
964 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100965 for (i = 0; i < type->info.uni.count; i++) {
PavolVican811f03b2016-12-29 23:03:20 +0100966 dertype = &type->info.uni.types[i];
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100967 if (dertype->base == LY_TYPE_DER || dertype->base == LY_TYPE_ERR) {
968 yang = (struct yang_type *)dertype->der;
969 dertype->der = NULL;
PavolVicane87cb932016-12-30 15:36:18 +0100970 dertype->parent = type->parent;
971 if (yang_check_type(module, parent, yang, dertype, tpdftype, unres)) {
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100972 dertype->der = (struct lys_tpdf *)yang;
973 ret = EXIT_FAILURE;
PavolVican811f03b2016-12-29 23:03:20 +0100974 type->base = base_tmp;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100975 base = 0;
976 goto error;
977 } else {
978 lydict_remove(module->ctx, yang->name);
979 free(yang);
980 }
Pavol Vicana4f045a2016-02-29 15:01:20 +0100981 }
Pavol Vican8e00e7a2016-09-20 11:07:48 +0200982 if (module->version < 2) {
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100983 if (dertype->base == LY_TYPE_EMPTY) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +0200984 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
985 goto error;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100986 } else if (dertype->base == LY_TYPE_LEAFREF) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +0200987 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
988 goto error;
989 }
Pavol Vicana4f045a2016-02-29 15:01:20 +0100990 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100991 if ((dertype->base == LY_TYPE_INST) || (dertype->base == LY_TYPE_LEAFREF)
992 || ((dertype->base == LY_TYPE_UNION) && dertype->info.uni.has_ptr_type)) {
Radek Krejcia726f9b2017-02-28 09:56:44 +0100993 type->info.uni.has_ptr_type = 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100994 }
Pavol Vicana4f045a2016-02-29 15:01:20 +0100995 }
996 break;
Pavol Vicana1827962016-02-29 15:39:42 +0100997
998 default:
999 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001000 if (type->base != base) {
1001 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001002 goto error;
1003 }
1004 } else {
1005 LOGINT;
1006 goto error;
1007 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001008 }
1009 return EXIT_SUCCESS;
1010
1011error:
Pavol Vican7313fc02016-11-14 01:10:31 +01001012 if (type->module_name) {
1013 lydict_remove(module->ctx, type->module_name);
1014 type->module_name = NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001015 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001016 if (base) {
PavolVicane87cb932016-12-30 15:36:18 +01001017 type->base = base_tmp;
Pavol Vican8bd72e42016-08-29 09:53:05 +02001018 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001019 return ret;
1020}
1021
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001022void
1023yang_free_type_union(struct ly_ctx *ctx, struct lys_type *type)
1024{
1025 struct lys_type *stype;
1026 struct yang_type *yang;
Radek Krejcidce5f972017-09-12 15:47:49 +02001027 unsigned int i;
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001028
1029 for (i = 0; i < type->info.uni.count; ++i) {
1030 stype = &type->info.uni.types[i];
1031 if (stype->base == LY_TYPE_DER || stype->base == LY_TYPE_ERR) {
1032 yang = (struct yang_type *)stype->der;
1033 stype->base = yang->base;
1034 lydict_remove(ctx, yang->name);
1035 free(yang);
1036 } else if (stype->base == LY_TYPE_UNION) {
1037 yang_free_type_union(ctx, stype);
1038 }
1039 }
1040}
1041
Pavol Vican73e7c992016-02-24 12:18:05 +01001042void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001043yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001044{
1045 struct yang_type *typ;
PavolVican75af21d2016-12-29 20:04:07 +01001046 struct lys_deviate *dev;
Pavol Vican73e7c992016-02-24 12:18:05 +01001047
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001048 typ = calloc(1, sizeof *typ);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001049 LY_CHECK_ERR_RETURN(!typ, LOGMEM, NULL);
Pavol Vican73e7c992016-02-24 12:18:05 +01001050
1051 typ->flags = LY_YANG_STRUCTURE_FLAG;
1052 switch (type) {
1053 case LEAF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001054 if (((struct lys_node_leaf *)parent)->type.der) {
1055 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf");
1056 goto error;
1057 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001058 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1059 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1060 typ->type = &((struct lys_node_leaf *)parent)->type;
1061 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001062 case LEAF_LIST_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001063 if (((struct lys_node_leaflist *)parent)->type.der) {
1064 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf-list");
1065 goto error;
1066 }
Pavol Vicana55992a2016-03-01 13:37:17 +01001067 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1068 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1069 typ->type = &((struct lys_node_leaflist *)parent)->type;
1070 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001071 case UNION_KEYWORD:
1072 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1073 typ->type = (struct lys_type *)parent;
1074 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001075 case TYPEDEF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001076 if (((struct lys_tpdf *)parent)->type.der) {
1077 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "typedef");
1078 goto error;
1079 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001080 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1081 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001082 break;
1083 case REPLACE_KEYWORD:
1084 /* deviation replace type*/
PavolVican75af21d2016-12-29 20:04:07 +01001085 dev = (struct lys_deviate *)parent;
1086 if (dev->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001087 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001088 goto error;
1089 }
PavolVican75af21d2016-12-29 20:04:07 +01001090 dev->type = calloc(1, sizeof *dev->type);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001091 LY_CHECK_ERR_GOTO(!dev->type, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001092 dev->type->der = (struct lys_tpdf *)typ;
1093 typ->type = dev->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001094 break;
PavolVicana0fdbf32017-02-15 17:59:02 +01001095 case EXTENSION_INSTANCE:
1096 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1097 typ->type = parent;
1098 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001099 default:
1100 goto error;
1101 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001102 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001103 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001104 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001105
1106error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001107 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001108 free(typ);
1109 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001110}
1111
1112void *
PavolVicaneef1d912017-02-19 00:19:15 +01001113yang_read_length(struct lys_module *module, struct yang_type *stype, char *value, int is_ext_instance)
Pavol Vican73e7c992016-02-24 12:18:05 +01001114{
PavolVicaneef1d912017-02-19 00:19:15 +01001115 struct lys_restr *length;
Pavol Vican73e7c992016-02-24 12:18:05 +01001116
PavolVicaneef1d912017-02-19 00:19:15 +01001117 if (is_ext_instance) {
1118 length = (struct lys_restr *)stype;
Pavol Vican73e7c992016-02-24 12:18:05 +01001119 } else {
PavolVicaneef1d912017-02-19 00:19:15 +01001120 if (stype->base == 0 || stype->base == LY_TYPE_STRING) {
1121 stype->base = LY_TYPE_STRING;
1122 } else {
1123 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
1124 goto error;
1125 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001126
PavolVicaneef1d912017-02-19 00:19:15 +01001127 if (stype->type->info.str.length) {
1128 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
1129 goto error;
1130 }
1131 length = calloc(1, sizeof *length);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001132 LY_CHECK_ERR_GOTO(!length, LOGMEM, error);
PavolVicaneef1d912017-02-19 00:19:15 +01001133 stype->type->info.str.length = length;
Pavol Vican73e7c992016-02-24 12:18:05 +01001134 }
PavolVicaneef1d912017-02-19 00:19:15 +01001135 length->expr = lydict_insert_zc(module->ctx, value);
1136 return length;
Pavol Vican73e7c992016-02-24 12:18:05 +01001137
1138error:
1139 free(value);
1140 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001141}
Pavol Vican1c203db2016-02-24 14:05:23 +01001142
Pavol Vican6eecf302016-08-10 11:09:05 +02001143int
Radek Krejcib53154b2017-07-19 09:14:13 +02001144yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, void **precomp, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001145{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001146 char *buf;
1147 size_t len;
1148
PavolVicanbd1d1ae2017-07-20 00:06:00 +02001149 if (precomp && lyp_precompile_pattern(value, (pcre**)&precomp[0], (pcre_extra**)&precomp[1])) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001150 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001151 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001152 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001153
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001154 len = strlen(value);
1155 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Radek Krejcia8d111f2017-05-31 13:57:37 +02001156 LY_CHECK_ERR_RETURN(!buf, LOGMEM; free(value), EXIT_FAILURE);
Pavol Vican6eecf302016-08-10 11:09:05 +02001157
1158 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001159 strcpy(&buf[1], value);
1160 free(value);
1161
Pavol Vican6eecf302016-08-10 11:09:05 +02001162 pattern->expr = lydict_insert_zc(module->ctx, buf);
1163 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001164}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001165
1166void *
PavolVicaneef1d912017-02-19 00:19:15 +01001167yang_read_range(struct lys_module *module, struct yang_type *stype, char *value, int is_ext_instance)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001168{
PavolVicaneef1d912017-02-19 00:19:15 +01001169 struct lys_restr * range;
1170
1171 if (is_ext_instance) {
1172 range = (struct lys_restr *)stype;
1173 } else {
1174 if (stype->base != 0 && stype->base != LY_TYPE_DEC64) {
1175 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
1176 goto error;
1177 }
1178 stype->base = LY_TYPE_DEC64;
1179 if (stype->type->info.dec64.range) {
1180 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
1181 goto error;
1182 }
1183 range = calloc(1, sizeof *range);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001184 LY_CHECK_ERR_GOTO(!range, LOGMEM, error);
PavolVicaneef1d912017-02-19 00:19:15 +01001185 stype->type->info.dec64.range = range;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001186 }
PavolVicaneef1d912017-02-19 00:19:15 +01001187 range->expr = lydict_insert_zc(module->ctx, value);
1188 return range;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001189
1190error:
1191 free(value);
1192 return NULL;
1193}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001194
1195int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001196yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001197{
Pavol Vican6b072512016-04-04 10:50:21 +02001198 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1199 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001200 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001201 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001202 goto error;
1203 }
1204 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001205 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001206 goto error;
1207 }
1208 /* range check */
1209 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001210 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001211 goto error;
1212 }
1213 typ->type->info.dec64.dig = value;
1214 return EXIT_SUCCESS;
1215
1216error:
1217 return EXIT_FAILURE;
1218}
Pavol Vican79a763d2016-02-25 15:41:27 +01001219
Pavol Vican874715f2016-10-25 14:52:08 +02001220int
1221yang_read_enum(struct lys_module *module, struct yang_type *typ, struct lys_type_enum *enm, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001222{
Pavol Vican874715f2016-10-25 14:52:08 +02001223 int i, j;
Pavol Vican79a763d2016-02-25 15:41:27 +01001224
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01001225 typ->base = LY_TYPE_ENUM;
Pavol Vicanc6662412016-08-30 08:06:28 +02001226 if (!value[0]) {
1227 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1228 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1229 free(value);
1230 goto error;
1231 }
1232
Pavol Vican79a763d2016-02-25 15:41:27 +01001233 enm->name = lydict_insert_zc(module->ctx, value);
1234
1235 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1236 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001237 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001238 goto error;
1239 }
1240
Pavol Vican874715f2016-10-25 14:52:08 +02001241 j = typ->type->info.enums.count - 1;
Pavol Vican79a763d2016-02-25 15:41:27 +01001242 /* check the name uniqueness */
Pavol Vican874715f2016-10-25 14:52:08 +02001243 for (i = 0; i < j; i++) {
PavolVican4b80d042017-02-23 14:30:27 +01001244 if (ly_strequal(typ->type->info.enums.enm[i].name, enm->name, 1)) {
1245 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001246 goto error;
1247 }
1248 }
1249
Pavol Vican874715f2016-10-25 14:52:08 +02001250 return EXIT_SUCCESS;
Pavol Vican79a763d2016-02-25 15:41:27 +01001251
1252error:
Pavol Vican874715f2016-10-25 14:52:08 +02001253 return EXIT_FAILURE;
Pavol Vican79a763d2016-02-25 15:41:27 +01001254}
1255
1256int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001257yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001258{
1259 int i, j;
1260
1261 if (!assign) {
1262 /* assign value automatically */
1263 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001264 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001265 goto error;
1266 }
1267 enm->value = *value;
1268 enm->flags |= LYS_AUTOASSIGNED;
1269 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001270 } else if (typ->type->info.enums.enm == enm) {
1271 /* change value, which is assigned automatically, if first enum has value. */
1272 *value = typ->type->info.enums.enm[0].value;
1273 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001274 }
1275
1276 /* check that the value is unique */
1277 j = typ->type->info.enums.count-1;
1278 for (i = 0; i < j; i++) {
1279 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001280 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001281 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1282 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001283 goto error;
1284 }
1285 }
1286
1287 return EXIT_SUCCESS;
1288
1289error:
1290 return EXIT_FAILURE;
1291}
Pavol Vican9887c682016-02-29 11:32:01 +01001292
Pavol Vican59e8dee2016-10-25 15:29:38 +02001293int
1294yang_read_bit(struct lys_module *module, struct yang_type *typ, struct lys_type_bit *bit, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001295{
Pavol Vican59e8dee2016-10-25 15:29:38 +02001296 int i, j;
Pavol Vican9887c682016-02-29 11:32:01 +01001297
PavolVicane87cb932016-12-30 15:36:18 +01001298 typ->base = LY_TYPE_BITS;
Pavol Vican59e8dee2016-10-25 15:29:38 +02001299 bit->name = lydict_insert_zc(module->ctx, value);
1300 if (lyp_check_identifier(bit->name, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001301 goto error;
1302 }
Pavol Vican9887c682016-02-29 11:32:01 +01001303
Pavol Vican59e8dee2016-10-25 15:29:38 +02001304 j = typ->type->info.bits.count - 1;
Pavol Vican9887c682016-02-29 11:32:01 +01001305 /* check the name uniqueness */
Pavol Vican59e8dee2016-10-25 15:29:38 +02001306 for (i = 0; i < j; i++) {
PavolVican4b80d042017-02-23 14:30:27 +01001307 if (ly_strequal(typ->type->info.bits.bit[i].name, bit->name, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001308 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001309 goto error;
1310 }
1311 }
Pavol Vican59e8dee2016-10-25 15:29:38 +02001312 return EXIT_SUCCESS;
Pavol Vican9887c682016-02-29 11:32:01 +01001313
1314error:
Pavol Vican59e8dee2016-10-25 15:29:38 +02001315 return EXIT_FAILURE;
Pavol Vican9887c682016-02-29 11:32:01 +01001316}
1317
1318int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001319yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001320{
1321 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001322
1323 if (!assign) {
1324 /* assign value automatically */
1325 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001326 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001327 goto error;
1328 }
1329 bit->pos = (uint32_t)*value;
1330 bit->flags |= LYS_AUTOASSIGNED;
1331 (*value)++;
1332 }
1333
1334 j = typ->type->info.bits.count - 1;
1335 /* check that the value is unique */
1336 for (i = 0; i < j; i++) {
1337 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001338 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 +01001339 goto error;
1340 }
1341 }
1342
Pavol Vican9887c682016-02-29 11:32:01 +01001343 return EXIT_SUCCESS;
1344
1345error:
1346 return EXIT_FAILURE;
1347}
Pavol Vican0df02b02016-03-01 10:28:50 +01001348
Pavol Vican3ad50f82016-12-04 15:00:36 +01001349int
1350yang_read_augment(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *aug, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001351{
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001352 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001353 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001354 free(value);
1355 if (!aug->target_name) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01001356 return EXIT_FAILURE;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001357 }
1358 aug->parent = parent;
1359 aug->module = module;
Pavol Vican3ad50f82016-12-04 15:00:36 +01001360 return EXIT_SUCCESS;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001361}
Pavol Vican220e5a12016-03-03 14:19:43 +01001362
PavolVican6f000922017-02-10 12:56:59 +01001363void *
PavolVican75af21d2016-12-29 20:04:07 +01001364yang_read_deviate_unsupported(struct lys_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001365{
PavolVican75af21d2016-12-29 20:04:07 +01001366 if (dev->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001367 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
PavolVican6f000922017-02-10 12:56:59 +01001368 return NULL;
Pavol Vican220e5a12016-03-03 14:19:43 +01001369 }
PavolVican75af21d2016-12-29 20:04:07 +01001370 dev->deviate = calloc(1, sizeof *dev->deviate);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001371 LY_CHECK_ERR_RETURN(!dev->deviate, LOGMEM, NULL);
PavolVican75af21d2016-12-29 20:04:07 +01001372 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1373 dev->deviate_size = 1;
PavolVican6f000922017-02-10 12:56:59 +01001374 return dev->deviate;
Pavol Vican220e5a12016-03-03 14:19:43 +01001375}
1376
1377void *
PavolVican75af21d2016-12-29 20:04:07 +01001378yang_read_deviate(struct lys_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican220e5a12016-03-03 14:19:43 +01001379{
PavolVican75af21d2016-12-29 20:04:07 +01001380 struct lys_deviate *deviate;
Pavol Vican220e5a12016-03-03 14:19:43 +01001381
PavolVican4b80d042017-02-23 14:30:27 +01001382 if (dev->deviate_size && dev->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001383 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1384 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
PavolVican75af21d2016-12-29 20:04:07 +01001385 return NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001386 }
PavolVican75af21d2016-12-29 20:04:07 +01001387 if (!(dev->deviate_size % LY_YANG_ARRAY_SIZE)) {
1388 deviate = realloc(dev->deviate, (LY_YANG_ARRAY_SIZE + dev->deviate_size) * sizeof *deviate);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001389 LY_CHECK_ERR_RETURN(!deviate, LOGMEM, NULL);
PavolVican75af21d2016-12-29 20:04:07 +01001390 memset(deviate + dev->deviate_size, 0, LY_YANG_ARRAY_SIZE * sizeof *deviate);
1391 dev->deviate = deviate;
Pavol Vican85f12022016-03-05 16:30:35 +01001392 }
PavolVican75af21d2016-12-29 20:04:07 +01001393 dev->deviate[dev->deviate_size].mod = mod;
1394 return &dev->deviate[dev->deviate_size++];
Pavol Vican85f12022016-03-05 16:30:35 +01001395}
1396
1397int
PavolVican75af21d2016-12-29 20:04:07 +01001398yang_read_deviate_units(struct ly_ctx *ctx, struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vican85f12022016-03-05 16:30:35 +01001399{
1400 const char **stritem;
PavolVican6f000922017-02-10 12:56:59 +01001401 int j;
Pavol Vican85f12022016-03-05 16:30:35 +01001402
Pavol Vican85f12022016-03-05 16:30:35 +01001403 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001404 if (dev_target->nodetype == LYS_LEAFLIST) {
1405 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1406 } else if (dev_target->nodetype == LYS_LEAF) {
1407 stritem = &((struct lys_node_leaf *)dev_target)->units;
Pavol Vican85f12022016-03-05 16:30:35 +01001408 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001409 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1410 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001411 goto error;
1412 }
1413
PavolVican75af21d2016-12-29 20:04:07 +01001414 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001415 /* check values */
PavolVican75af21d2016-12-29 20:04:07 +01001416 if (!ly_strequal(*stritem, deviate->units, 1)) {
1417 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, deviate->units, "units");
Pavol Vican0adf01d2016-03-22 12:29:33 +01001418 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001419 goto error;
1420 }
1421 /* remove current units value of the target */
1422 lydict_remove(ctx, *stritem);
PavolVican6f000922017-02-10 12:56:59 +01001423 *stritem = NULL;
1424 /* remove its extensions */
1425 j = -1;
1426 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
1427 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
1428 --j;
1429 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001430 } else {
PavolVican75af21d2016-12-29 20:04:07 +01001431 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican4766aca2016-03-07 12:42:36 +01001432 /* check that there is no current value */
1433 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001434 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1435 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001436 goto error;
1437 }
1438 } else { /* replace */
1439 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001440 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1441 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001442 goto error;
1443 }
1444 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001445 /* remove current units value of the target ... */
1446 lydict_remove(ctx, *stritem);
1447
1448 /* ... and replace it with the value specified in deviation */
PavolVican75af21d2016-12-29 20:04:07 +01001449 *stritem = lydict_insert(ctx, deviate->units, 0);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001450 }
1451
Pavol Vican85f12022016-03-05 16:30:35 +01001452 return EXIT_SUCCESS;
1453
1454error:
1455 return EXIT_FAILURE;
1456}
1457
1458int
PavolVican75af21d2016-12-29 20:04:07 +01001459yang_read_deviate_unique(struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vican85f12022016-03-05 16:30:35 +01001460{
Pavol Vican85f12022016-03-05 16:30:35 +01001461 struct lys_node_list *list;
PavolVican75af21d2016-12-29 20:04:07 +01001462 struct lys_unique *unique;
Pavol Vican85f12022016-03-05 16:30:35 +01001463
1464 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001465 if (dev_target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001466 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1467 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001468 goto error;
1469 }
1470
PavolVican75af21d2016-12-29 20:04:07 +01001471 list = (struct lys_node_list *)dev_target;
1472 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican85f12022016-03-05 16:30:35 +01001473 /* reallocate the unique array of the target */
PavolVican75af21d2016-12-29 20:04:07 +01001474 unique = ly_realloc(list->unique, (deviate->unique_size + list->unique_size) * sizeof *unique);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001475 LY_CHECK_ERR_GOTO(!unique, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001476 list->unique = unique;
1477 memset(unique + list->unique_size, 0, deviate->unique_size * sizeof *unique);
Pavol Vican85f12022016-03-05 16:30:35 +01001478 }
1479
1480 return EXIT_SUCCESS;
1481
1482error:
1483 return EXIT_FAILURE;
1484}
1485
1486int
PavolVican75af21d2016-12-29 20:04:07 +01001487yang_fill_deviate_default(struct ly_ctx *ctx, struct lys_deviate *deviate, struct lys_node *dev_target,
1488 struct ly_set *dflt_check, const char *value)
Pavol Vican38321d02016-08-16 14:56:02 +02001489{
1490 struct lys_node *node;
1491 struct lys_node_choice *choice;
1492 struct lys_node_leaf *leaf;
1493 struct lys_node_leaflist *llist;
PavolVican6f000922017-02-10 12:56:59 +01001494 int rc, i, j;
Pavol Vican38321d02016-08-16 14:56:02 +02001495 unsigned int u;
Pavol Vican38321d02016-08-16 14:56:02 +02001496
Pavol Vican38321d02016-08-16 14:56:02 +02001497 u = strlen(value);
PavolVican75af21d2016-12-29 20:04:07 +01001498 if (dev_target->nodetype == LYS_CHOICE) {
1499 choice = (struct lys_node_choice *)dev_target;
Pavol Vican38321d02016-08-16 14:56:02 +02001500 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
1501 if (rc || !node) {
1502 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1503 goto error;
1504 }
PavolVican75af21d2016-12-29 20:04:07 +01001505 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vican38321d02016-08-16 14:56:02 +02001506 if (!choice->dflt || (choice->dflt != node)) {
1507 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1508 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1509 goto error;
1510 }
PavolVican6f000922017-02-10 12:56:59 +01001511 choice->dflt = NULL;
1512 /* remove extensions of this default instance from the target node */
1513 j = -1;
1514 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
1515 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
1516 --j;
1517 }
Pavol Vican38321d02016-08-16 14:56:02 +02001518 } else { /* add or replace */
1519 choice->dflt = node;
1520 if (!choice->dflt) {
1521 /* default branch not found */
1522 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1523 goto error;
1524 }
1525 }
PavolVican75af21d2016-12-29 20:04:07 +01001526 } else if (dev_target->nodetype == LYS_LEAF) {
1527 leaf = (struct lys_node_leaf *)dev_target;
1528 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vican38321d02016-08-16 14:56:02 +02001529 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
1530 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1531 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1532 goto error;
1533 }
1534 /* remove value */
1535 lydict_remove(ctx, leaf->dflt);
1536 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01001537 leaf->flags &= ~LYS_DFLTJSON;
PavolVican6f000922017-02-10 12:56:59 +01001538 /* remove extensions of this default instance from the target node */
1539 j = -1;
1540 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
1541 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
1542 --j;
1543 }
Pavol Vican38321d02016-08-16 14:56:02 +02001544 } else { /* add (already checked) and replace */
1545 /* remove value */
1546 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01001547 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001548
1549 /* set new value */
1550 leaf->dflt = lydict_insert(ctx, value, u);
1551
1552 /* remember to check it later (it may not fit now, but the type can be deviated too) */
PavolVican75af21d2016-12-29 20:04:07 +01001553 ly_set_add(dflt_check, dev_target, 0);
Pavol Vican38321d02016-08-16 14:56:02 +02001554 }
1555 } else { /* LYS_LEAFLIST */
PavolVican75af21d2016-12-29 20:04:07 +01001556 llist = (struct lys_node_leaflist *)dev_target;
1557 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vican38321d02016-08-16 14:56:02 +02001558 /* find and remove the value in target list */
1559 for (i = 0; i < llist->dflt_size; i++) {
1560 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
1561 /* match, remove the value */
1562 lydict_remove(llist->module->ctx, llist->dflt[i]);
1563 llist->dflt[i] = NULL;
PavolVican6f000922017-02-10 12:56:59 +01001564 /* remove extensions of this default instance from the target node */
1565 j = -1;
1566 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
1567 if (dev_target->ext[j]->insubstmt_index == i) {
1568 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
1569 --j;
1570 } else if (dev_target->ext[j]->insubstmt_index > i) {
1571 /* decrease the substatement index of the extension because of the changed array of defaults */
1572 dev_target->ext[j]->insubstmt_index--;
1573 }
1574 }
Pavol Vican38321d02016-08-16 14:56:02 +02001575 break;
1576 }
1577 }
1578 if (i == llist->dflt_size) {
1579 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1580 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
1581 goto error;
1582 }
1583 } else {
1584 /* add or replace, anyway we place items into the deviate's list
1585 which propagates to the target */
1586 /* we just want to check that the value isn't already in the list */
1587 for (i = 0; i < llist->dflt_size; i++) {
1588 if (ly_strequal(llist->dflt[i], value, 1)) {
1589 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1590 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
1591 goto error;
1592 }
1593 }
1594 /* store it in target node */
1595 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
1596
1597 /* remember to check it later (it may not fit now, but the type can be deviated too) */
PavolVican75af21d2016-12-29 20:04:07 +01001598 ly_set_add(dflt_check, dev_target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01001599 llist->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001600 }
1601 }
1602
1603 return EXIT_SUCCESS;
1604error:
1605 return EXIT_FAILURE;
1606}
1607
Pavol Vican38321d02016-08-16 14:56:02 +02001608int
PavolVican75af21d2016-12-29 20:04:07 +01001609yang_read_deviate_default(struct lys_module *module, struct lys_deviate *deviate,
1610 struct lys_node *dev_target, struct ly_set * dflt_check)
Pavol Vican85f12022016-03-05 16:30:35 +01001611{
PavolVican75af21d2016-12-29 20:04:07 +01001612 int i;
1613 struct lys_node_leaflist *llist;
1614 const char **dflt;
1615
1616 /* check target node type */
1617 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
1618 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1619 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1620 goto error;
1621 } else if (deviate->dflt_size > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1622 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1623 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1624 goto error;
1625 } else if (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
1626 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1627 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001628 goto error;
1629 }
1630
PavolVican75af21d2016-12-29 20:04:07 +01001631 if (deviate->mod == LY_DEVIATE_ADD) {
1632 /* check that there is no current value */
1633 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
1634 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
1635 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1636 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
1637 goto error;
1638 }
Pavol Vican85f12022016-03-05 16:30:35 +01001639
PavolVican75af21d2016-12-29 20:04:07 +01001640 /* check collision with mandatory/min-elements */
1641 if ((dev_target->flags & LYS_MAND_TRUE) ||
1642 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
1643 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
1644 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1645 "Adding the \"default\" statement is forbidden on %s statement.",
1646 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
1647 goto error;
1648 }
1649 } else if (deviate->mod == LY_DEVIATE_RPL) {
1650 /* check that there was a value before */
1651 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
1652 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
1653 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1654 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
1655 goto error;
1656 }
1657 }
Pavol Vican85f12022016-03-05 16:30:35 +01001658
PavolVican75af21d2016-12-29 20:04:07 +01001659 if (dev_target->nodetype == LYS_LEAFLIST) {
1660 /* reallocate default list in the target */
1661 llist = (struct lys_node_leaflist *)dev_target;
1662 if (deviate->mod == LY_DEVIATE_ADD) {
1663 /* reallocate (enlarge) the unique array of the target */
1664 dflt = realloc(llist->dflt, (deviate->dflt_size + llist->dflt_size) * sizeof *dflt);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001665 LY_CHECK_ERR_GOTO(!dflt, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001666 llist->dflt = dflt;
1667 } else if (deviate->mod == LY_DEVIATE_RPL) {
1668 /* reallocate (replace) the unique array of the target */
1669 for (i = 0; i < llist->dflt_size; i++) {
1670 lydict_remove(llist->module->ctx, llist->dflt[i]);
1671 }
1672 dflt = realloc(llist->dflt, deviate->dflt_size * sizeof *dflt);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001673 LY_CHECK_ERR_GOTO(!dflt, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001674 llist->dflt = dflt;
1675 llist->dflt_size = 0;
1676 }
1677 }
1678
1679 for (i = 0; i < deviate->dflt_size; ++i) {
1680 if (yang_fill_deviate_default(module->ctx, deviate, dev_target, dflt_check, deviate->dflt[i])) {
1681 goto error;
1682 }
1683 }
Pavol Vican85f12022016-03-05 16:30:35 +01001684
1685 return EXIT_SUCCESS;
1686
1687error:
1688 return EXIT_FAILURE;
1689}
1690
1691int
PavolVican75af21d2016-12-29 20:04:07 +01001692yang_check_deviate_mandatory(struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vican85f12022016-03-05 16:30:35 +01001693{
Radek Krejcie00d2312016-08-12 15:27:49 +02001694 struct lys_node *parent;
1695
Pavol Vican85f12022016-03-05 16:30:35 +01001696 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001697 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001698 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1699 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001700 goto error;
1701 }
1702
PavolVican75af21d2016-12-29 20:04:07 +01001703 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican85f12022016-03-05 16:30:35 +01001704 /* check that there is no current value */
PavolVican75af21d2016-12-29 20:04:07 +01001705 if (dev_target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001706 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1707 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001708 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001709 } else {
PavolVican75af21d2016-12-29 20:04:07 +01001710 if (dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) {
Pavol Vican321a02e2016-04-05 16:11:59 +02001711 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1712 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
1713 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
1714 goto error;
PavolVican75af21d2016-12-29 20:04:07 +01001715 } else if (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt) {
Pavol Vican321a02e2016-04-05 16:11:59 +02001716 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
1717 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
1718 goto error;
1719 }
Pavol Vican85f12022016-03-05 16:30:35 +01001720 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001721 } else { /* replace */
PavolVican75af21d2016-12-29 20:04:07 +01001722 if (!(dev_target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001723 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1724 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001725 goto error;
1726 }
Pavol Vican85f12022016-03-05 16:30:35 +01001727 }
1728
Pavol Vican85f12022016-03-05 16:30:35 +01001729 /* remove current mandatory value of the target ... */
PavolVican75af21d2016-12-29 20:04:07 +01001730 dev_target->flags &= ~LYS_MAND_MASK;
Pavol Vican85f12022016-03-05 16:30:35 +01001731
1732 /* ... and replace it with the value specified in deviation */
PavolVican75af21d2016-12-29 20:04:07 +01001733 dev_target->flags |= deviate->flags & LYS_MAND_MASK;
Pavol Vican85f12022016-03-05 16:30:35 +01001734
Radek Krejcie00d2312016-08-12 15:27:49 +02001735 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
PavolVican75af21d2016-12-29 20:04:07 +01001736 for (parent = dev_target->parent;
Radek Krejcie00d2312016-08-12 15:27:49 +02001737 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
1738 parent = parent->parent) {
1739 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
1740 /* stop also on presence containers */
1741 break;
1742 }
1743 }
1744 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
1745 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
1746 if (lyp_check_mandatory_choice(parent)) {
1747 goto error;
1748 }
1749 }
1750
Pavol Vican85f12022016-03-05 16:30:35 +01001751 return EXIT_SUCCESS;
1752
1753error:
1754 return EXIT_FAILURE;
1755}
1756
1757int
PavolVican75af21d2016-12-29 20:04:07 +01001758yang_read_deviate_minmax(struct lys_deviate *deviate, struct lys_node *dev_target, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01001759{
Pavol Vican09adcc32016-08-25 10:51:36 +02001760 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01001761
1762 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001763 if (dev_target->nodetype == LYS_LEAFLIST) {
1764 max = &((struct lys_node_leaflist *)dev_target)->max;
1765 min = &((struct lys_node_leaflist *)dev_target)->min;
1766 } else if (dev_target->nodetype == LYS_LIST) {
1767 max = &((struct lys_node_list *)dev_target)->max;
1768 min = &((struct lys_node_list *)dev_target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01001769 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001770 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1771 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 +01001772 goto error;
1773 }
1774
PavolVican75af21d2016-12-29 20:04:07 +01001775 ui32val = (type) ? max : min;
1776 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican85f12022016-03-05 16:30:35 +01001777 /* check that there is no current value */
1778 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001779 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1780 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001781 goto error;
1782 }
PavolVican75af21d2016-12-29 20:04:07 +01001783 } else if (deviate->mod == LY_DEVIATE_RPL) {
Pavol Vican4766aca2016-03-07 12:42:36 +01001784 /* unfortunately, there is no way to check reliably that there
1785 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01001786 }
1787
1788 /* add (already checked) and replace */
1789 /* set new value specified in deviation */
1790 *ui32val = value;
1791
Pavol Vican09adcc32016-08-25 10:51:36 +02001792 /* check min-elements is smaller than max-elements */
1793 if (*max && *min > *max) {
1794 if (type) {
1795 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
1796 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1797 } else {
1798 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
1799 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1800 }
1801 goto error;
1802 }
1803
Pavol Vican85f12022016-03-05 16:30:35 +01001804 return EXIT_SUCCESS;
1805
1806error:
1807 return EXIT_FAILURE;
1808}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001809
1810int
PavolVican75af21d2016-12-29 20:04:07 +01001811yang_check_deviate_must(struct lys_module *module, struct unres_schema *unres,
1812 struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001813{
PavolVican75af21d2016-12-29 20:04:07 +01001814 int i, j, erase_must = 1;
1815 struct lys_restr **trg_must, *must;
PavolVican214408f2017-02-03 11:54:05 +01001816 uint8_t *trg_must_size;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001817
PavolVican75af21d2016-12-29 20:04:07 +01001818 /* check target node type */
1819 switch (dev_target->nodetype) {
1820 case LYS_LEAF:
1821 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1822 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001823 break;
PavolVican75af21d2016-12-29 20:04:07 +01001824 case LYS_CONTAINER:
1825 trg_must = &((struct lys_node_container *)dev_target)->must;
1826 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
1827 break;
1828 case LYS_LEAFLIST:
1829 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1830 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
1831 break;
1832 case LYS_LIST:
1833 trg_must = &((struct lys_node_list *)dev_target)->must;
1834 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
1835 break;
1836 case LYS_ANYXML:
1837 case LYS_ANYDATA:
1838 trg_must = &((struct lys_node_anydata *)dev_target)->must;
1839 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
1840 break;
1841 default:
1842 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1843 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
1844 goto error;
1845 }
1846
1847 /* flag will be checked again, clear it for now */
PavolVicancec18782017-01-26 21:48:46 +01001848 dev_target->flags &= ~LYS_XPATH_DEP;
PavolVican75af21d2016-12-29 20:04:07 +01001849
1850 if (deviate->mod == LY_DEVIATE_ADD) {
1851 /* reallocate the must array of the target */
1852 must = ly_realloc(*trg_must, (deviate->must_size + *trg_must_size) * sizeof *must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001853 LY_CHECK_ERR_GOTO(!must, LOGMEM, error);
PavolVican75af21d2016-12-29 20:04:07 +01001854 *trg_must = must;
PavolVican214408f2017-02-03 11:54:05 +01001855 memcpy(&(*trg_must)[*trg_must_size], deviate->must, deviate->must_size * sizeof *must);
PavolVican75af21d2016-12-29 20:04:07 +01001856 free(deviate->must);
1857 deviate->must = &must[*trg_must_size];
PavolVican214408f2017-02-03 11:54:05 +01001858 *trg_must_size = *trg_must_size + deviate->must_size;
PavolVican75af21d2016-12-29 20:04:07 +01001859 erase_must = 0;
1860 } else if (deviate->mod == LY_DEVIATE_DEL) {
1861 /* find must to delete, we are ok with just matching conditions */
1862 for (j = 0; j < deviate->must_size; ++j) {
1863 for (i = 0; i < *trg_must_size; i++) {
1864 if (ly_strequal(deviate->must[j].expr, (*trg_must)[i].expr, 1)) {
1865 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02001866 lys_restr_free(module->ctx, &((*trg_must)[i]), NULL);
PavolVican75af21d2016-12-29 20:04:07 +01001867 /* ... and maintain the array */
1868 (*trg_must_size)--;
1869 if (i != *trg_must_size) {
PavolVican214408f2017-02-03 11:54:05 +01001870 memcpy(&(*trg_must)[i], &(*trg_must)[*trg_must_size], sizeof *must);
PavolVican75af21d2016-12-29 20:04:07 +01001871 }
1872 if (!(*trg_must_size)) {
1873 free(*trg_must);
1874 *trg_must = NULL;
1875 } else {
PavolVican214408f2017-02-03 11:54:05 +01001876 memset(&(*trg_must)[*trg_must_size], 0, sizeof *must);
PavolVican75af21d2016-12-29 20:04:07 +01001877 }
1878
1879 i = -1; /* set match flag */
1880 break;
1881 }
1882 }
1883 if (i != -1) {
1884 /* no match found */
1885 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, deviate->must[j].expr, "must");
1886 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
1887 goto error;
1888 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001889 }
1890 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001891
PavolVican6f000922017-02-10 12:56:59 +01001892 if (yang_check_must(module, deviate->must, deviate->must_size, unres)) {
1893 goto error;
1894 }
PavolVican75af21d2016-12-29 20:04:07 +01001895 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02001896 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && *trg_must_size
1897 && (unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL) == -1)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001898 goto error;
1899 }
1900
PavolVican75af21d2016-12-29 20:04:07 +01001901 return EXIT_SUCCESS;
1902error:
1903 if (deviate->mod == LY_DEVIATE_ADD && erase_must) {
1904 for (i = 0; i < deviate->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001905 lys_restr_free(module->ctx, &deviate->must[i], NULL);
PavolVican75af21d2016-12-29 20:04:07 +01001906 }
1907 free(deviate->must);
1908 }
1909 return EXIT_FAILURE;
1910}
1911
1912int
1913yang_deviate_delete_unique(struct lys_module *module, struct lys_deviate *deviate,
1914 struct lys_node_list *list, int index, char * value)
1915{
PavolVican6f000922017-02-10 12:56:59 +01001916 int i, j, k;
PavolVican75af21d2016-12-29 20:04:07 +01001917
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001918 /* find unique structures to delete */
1919 for (i = 0; i < list->unique_size; i++) {
PavolVican75af21d2016-12-29 20:04:07 +01001920 if (list->unique[i].expr_size != deviate->unique[index].expr_size) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001921 continue;
1922 }
1923
PavolVican75af21d2016-12-29 20:04:07 +01001924 for (j = 0; j < deviate->unique[index].expr_size; j++) {
1925 if (!ly_strequal(list->unique[i].expr[j], deviate->unique[index].expr[j], 1)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001926 break;
1927 }
1928 }
1929
PavolVican75af21d2016-12-29 20:04:07 +01001930 if (j == deviate->unique[index].expr_size) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001931 /* we have a match, free the unique structure ... */
1932 for (j = 0; j < list->unique[i].expr_size; j++) {
1933 lydict_remove(module->ctx, list->unique[i].expr[j]);
1934 }
1935 free(list->unique[i].expr);
1936 /* ... and maintain the array */
1937 list->unique_size--;
1938 if (i != list->unique_size) {
1939 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1940 list->unique[i].expr = list->unique[list->unique_size].expr;
1941 }
1942
1943 if (!list->unique_size) {
1944 free(list->unique);
1945 list->unique = NULL;
1946 } else {
1947 list->unique[list->unique_size].expr_size = 0;
1948 list->unique[list->unique_size].expr = NULL;
1949 }
1950
PavolVican6f000922017-02-10 12:56:59 +01001951 k = i; /* remember index for removing extensions */
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001952 i = -1; /* set match flag */
1953 break;
1954 }
1955 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001956
1957 if (i != -1) {
1958 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001959 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
1960 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
PavolVican75af21d2016-12-29 20:04:07 +01001961 return EXIT_FAILURE;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001962 }
1963
PavolVican6f000922017-02-10 12:56:59 +01001964 /* remove extensions of this unique instance from the target node */
1965 j = -1;
1966 while ((j = lys_ext_iter(list->ext, list->ext_size, j + 1, LYEXT_SUBSTMT_UNIQUE)) != -1) {
1967 if (list->ext[j]->insubstmt_index == k) {
1968 lyp_ext_instance_rm(module->ctx, &list->ext, &list->ext_size, j);
1969 --j;
1970 } else if (list->ext[j]->insubstmt_index > k) {
1971 /* decrease the substatement index of the extension because of the changed array of uniques */
1972 list->ext[j]->insubstmt_index--;
1973 }
1974 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001975 return EXIT_SUCCESS;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001976}
Pavol Vican021488a2016-01-25 23:56:12 +01001977
PavolVican75af21d2016-12-29 20:04:07 +01001978int yang_check_deviate_unique(struct lys_module *module, struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vicane92421d2016-03-08 10:12:33 +01001979{
PavolVican75af21d2016-12-29 20:04:07 +01001980 struct lys_node_list *list;
1981 char *str;
PavolVican4b80d042017-02-23 14:30:27 +01001982 uint i = 0;
1983 struct lys_unique *last_unique = NULL;
Pavol Vicane92421d2016-03-08 10:12:33 +01001984
PavolVican75af21d2016-12-29 20:04:07 +01001985 if (yang_read_deviate_unique(deviate, dev_target)) {
1986 goto error;
1987 }
1988 list = (struct lys_node_list *)dev_target;
1989 last_unique = &list->unique[list->unique_size];
1990 for (i = 0; i < deviate->unique_size; ++i) {
1991 str = (char *) deviate->unique[i].expr;
1992 if (deviate->mod == LY_DEVIATE_ADD) {
1993 if (yang_fill_unique(module, list, &list->unique[list->unique_size], str, NULL)) {
1994 free(str);
1995 goto error;
1996 }
1997 list->unique_size++;
1998 } else if (deviate->mod == LY_DEVIATE_DEL) {
1999 if (yang_fill_unique(module, list, &deviate->unique[i], str, NULL)) {
2000 free(str);
2001 goto error;
2002 }
2003 if (yang_deviate_delete_unique(module, deviate, list, i, str)) {
2004 free(str);
2005 goto error;
Pavol Vicane92421d2016-03-08 10:12:33 +01002006 }
2007 }
PavolVican75af21d2016-12-29 20:04:07 +01002008 free(str);
2009 }
2010 if (deviate->mod == LY_DEVIATE_ADD) {
2011 free(deviate->unique);
2012 deviate->unique = last_unique;
Pavol Vicane92421d2016-03-08 10:12:33 +01002013 }
Pavol Vican38321d02016-08-16 14:56:02 +02002014
Pavol Vican38321d02016-08-16 14:56:02 +02002015
PavolVican75af21d2016-12-29 20:04:07 +01002016 return EXIT_SUCCESS;
Pavol Vican021488a2016-01-25 23:56:12 +01002017error:
PavolVican75af21d2016-12-29 20:04:07 +01002018 if (deviate->mod == LY_DEVIATE_ADD) {
2019 for (i = i + 1; i < deviate->unique_size; ++i) {
2020 free(deviate->unique[i].expr);
2021 }
2022 free(deviate->unique);
2023 deviate->unique = last_unique;
2024
2025 }
Pavol Vican021488a2016-01-25 23:56:12 +01002026 return EXIT_FAILURE;
2027}
2028
Pavol Vicanec423c92016-10-24 21:33:43 +02002029static int
2030yang_fill_include(struct lys_module *trg, char *value, struct lys_include *inc,
2031 struct unres_schema *unres)
Pavol Vican021488a2016-01-25 23:56:12 +01002032{
Pavol Vican55870412016-03-10 12:36:21 +01002033 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002034 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002035 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002036
Pavol Vicanec423c92016-10-24 21:33:43 +02002037 str = lydict_insert_zc(trg->ctx, value);
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01002038 rc = lyp_check_include(trg, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002039 if (!rc) {
2040 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002041 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
PavolVican7d0b5ab2017-02-01 13:06:53 +01002042 if (yang_check_ext_instance(trg, &trg->inc[trg->inc_size].ext, trg->inc[trg->inc_size].ext_size,
2043 &trg->inc[trg->inc_size], unres)) {
2044 ret = -1;
2045 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02002046 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002047 } else if (rc == -1) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002048 lys_extension_instances_free(trg->ctx, inc->ext, inc->ext_size, NULL);
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002049 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002050 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002051
Pavol Vicanec423c92016-10-24 21:33:43 +02002052 lydict_remove(trg->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002053 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002054}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002055
PavolVicanc1807262017-01-31 18:00:27 +01002056struct lys_ext_instance *
PavolVican22e88682017-02-14 22:38:18 +01002057yang_ext_instance(void *node, enum yytokentype type, int is_ext_instance)
PavolVicanc1807262017-01-31 18:00:27 +01002058{
2059 struct lys_ext_instance ***ext, **tmp, *instance = NULL;
2060 LYEXT_PAR parent_type;
2061 uint8_t *size;
2062
2063 switch (type) {
2064 case MODULE_KEYWORD:
PavolVicane6fa67b2017-02-01 11:06:57 +01002065 case SUBMODULE_KEYWORD:
PavolVicanc1807262017-01-31 18:00:27 +01002066 ext = &((struct lys_module *)node)->ext;
2067 size = &((struct lys_module *)node)->ext_size;
2068 parent_type = LYEXT_PAR_MODULE;
2069 break;
PavolVican22e88682017-02-14 22:38:18 +01002070 case BELONGS_TO_KEYWORD:
2071 if (is_ext_instance) {
2072 ext = &((struct lys_ext_instance *)node)->ext;
2073 size = &((struct lys_ext_instance *)node)->ext_size;
2074 parent_type = LYEXT_PAR_EXTINST;
2075 } else {
2076 ext = &((struct lys_module *)node)->ext;
2077 size = &((struct lys_module *)node)->ext_size;
2078 parent_type = LYEXT_PAR_MODULE;
2079 }
2080 break;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002081 case IMPORT_KEYWORD:
2082 ext = &((struct lys_import *)node)->ext;
2083 size = &((struct lys_import *)node)->ext_size;
2084 parent_type = LYEXT_PAR_IMPORT;
2085 break;
2086 case INCLUDE_KEYWORD:
2087 ext = &((struct lys_include *)node)->ext;
2088 size = &((struct lys_include *)node)->ext_size;
2089 parent_type = LYEXT_PAR_INCLUDE;
2090 break;
PavolVican171717d2017-02-01 14:49:55 +01002091 case REVISION_KEYWORD:
2092 ext = &((struct lys_revision *)node)->ext;
2093 size = &((struct lys_revision *)node)->ext_size;
2094 parent_type = LYEXT_PAR_REVISION;
2095 break;
PavolVican70ce7452017-02-01 15:39:39 +01002096 case GROUPING_KEYWORD:
PavolVican59af9be2017-02-01 16:04:37 +01002097 case CONTAINER_KEYWORD:
PavolVicana6c3ac92017-02-03 13:15:13 +01002098 case LEAF_KEYWORD:
2099 case LEAF_LIST_KEYWORD:
2100 case LIST_KEYWORD:
PavolVican91eb04a2017-02-03 13:45:52 +01002101 case CHOICE_KEYWORD:
2102 case CASE_KEYWORD:
2103 case ANYXML_KEYWORD:
2104 case ANYDATA_KEYWORD:
PavolVican07596382017-02-03 14:05:12 +01002105 case USES_KEYWORD:
2106 case AUGMENT_KEYWORD:
PavolVican97d1e6f2017-02-03 14:39:52 +01002107 case ACTION_KEYWORD:
2108 case RPC_KEYWORD:
2109 case INPUT_KEYWORD:
2110 case OUTPUT_KEYWORD:
2111 case NOTIFICATION_KEYWORD:
PavolVican70ce7452017-02-01 15:39:39 +01002112 ext = &((struct lys_node *)node)->ext;
2113 size = &((struct lys_node *)node)->ext_size;
2114 parent_type = LYEXT_PAR_NODE;
2115 break;
PavolVican19dc6152017-02-06 12:04:15 +01002116 case ARGUMENT_KEYWORD:
PavolVican50809742017-02-18 21:22:54 +01002117 if (is_ext_instance) {
2118 ext = &((struct lys_ext_instance *)node)->ext;
2119 size = &((struct lys_ext_instance *)node)->ext_size;
2120 parent_type = LYEXT_PAR_EXTINST;
2121 } else {
2122 ext = &((struct lys_ext *)node)->ext;
2123 size = &((struct lys_ext *)node)->ext_size;
2124 parent_type = LYEXT_PAR_EXT;
2125 }
2126 break;
PavolVican19dc6152017-02-06 12:04:15 +01002127 case EXTENSION_KEYWORD:
2128 ext = &((struct lys_ext *)node)->ext;
2129 size = &((struct lys_ext *)node)->ext_size;
2130 parent_type = LYEXT_PAR_EXT;
2131 break;
PavolVican5393d3f2017-02-06 23:30:55 +01002132 case FEATURE_KEYWORD:
2133 ext = &((struct lys_feature *)node)->ext;
2134 size = &((struct lys_feature *)node)->ext_size;
2135 parent_type = LYEXT_PAR_FEATURE;
2136 break;
PavolVican8fa31242017-02-07 11:04:26 +01002137 case IDENTITY_KEYWORD:
2138 ext = &((struct lys_ident *)node)->ext;
2139 size = &((struct lys_ident *)node)->ext_size;
2140 parent_type = LYEXT_PAR_IDENT;
2141 break;
2142 case IF_FEATURE_KEYWORD:
2143 ext = &((struct lys_iffeature *)node)->ext;
2144 size = &((struct lys_iffeature *)node)->ext_size;
2145 parent_type = LYEXT_PAR_IFFEATURE;
2146 break;
PavolVicandf9e7972017-02-07 11:41:38 +01002147 case TYPEDEF_KEYWORD:
2148 ext = &((struct lys_tpdf *)node)->ext;
2149 size = &((struct lys_tpdf *)node)->ext_size;
2150 parent_type = LYEXT_PAR_TPDF;
2151 break;
PavolVican056fcd12017-02-07 15:36:53 +01002152 case TYPE_KEYWORD:
2153 ext = &((struct yang_type *)node)->type->ext;
2154 size = &((struct yang_type *)node)->type->ext_size;
2155 parent_type = LYEXT_PAR_TYPE;
2156 break;
2157 case LENGTH_KEYWORD:
2158 case PATTERN_KEYWORD:
2159 case RANGE_KEYWORD:
PavolVican38104a32017-02-08 12:25:23 +01002160 case MUST_KEYWORD:
PavolVican056fcd12017-02-07 15:36:53 +01002161 ext = &((struct lys_restr *)node)->ext;
2162 size = &((struct lys_restr *)node)->ext_size;
2163 parent_type = LYEXT_PAR_RESTR;
2164 break;
PavolVican59ba4602017-02-08 11:53:32 +01002165 case WHEN_KEYWORD:
2166 ext = &((struct lys_when *)node)->ext;
2167 size = &((struct lys_when *)node)->ext_size;
2168 parent_type = LYEXT_PAR_RESTR;
2169 break;
PavolVican056fcd12017-02-07 15:36:53 +01002170 case ENUM_KEYWORD:
2171 ext = &((struct lys_type_enum *)node)->ext;
2172 size = &((struct lys_type_enum *)node)->ext_size;
2173 parent_type = LYEXT_PAR_TYPE_ENUM;
2174 break;
2175 case BIT_KEYWORD:
2176 ext = &((struct lys_type_bit *)node)->ext;
2177 size = &((struct lys_type_bit *)node)->ext_size;
2178 parent_type = LYEXT_PAR_TYPE_BIT;
2179 break;
PavolVican77374ee2017-02-08 15:18:45 +01002180 case REFINE_KEYWORD:
2181 ext = &((struct lys_type_bit *)node)->ext;
2182 size = &((struct lys_type_bit *)node)->ext_size;
2183 parent_type = LYEXT_PAR_REFINE;
2184 break;
PavolVican6f000922017-02-10 12:56:59 +01002185 case DEVIATION_KEYWORD:
2186 ext = &((struct lys_deviation *)node)->ext;
2187 size = &((struct lys_deviation *)node)->ext_size;
2188 parent_type = LYEXT_PAR_DEVIATION;
2189 break;
2190 case NOT_SUPPORTED_KEYWORD:
2191 case ADD_KEYWORD:
2192 case DELETE_KEYWORD:
2193 case REPLACE_KEYWORD:
2194 ext = &((struct lys_deviate *)node)->ext;
2195 size = &((struct lys_deviate *)node)->ext_size;
2196 parent_type = LYEXT_PAR_DEVIATE;
2197 break;
PavolVicandefa4852017-02-10 13:13:23 +01002198 case EXTENSION_INSTANCE:
2199 ext = &((struct lys_ext_instance *)node)->ext;
2200 size = &((struct lys_ext_instance *)node)->ext_size;
2201 parent_type = LYEXT_PAR_EXTINST;
2202 break;
PavolVicanc1807262017-01-31 18:00:27 +01002203 default:
2204 LOGINT;
2205 return NULL;
2206 }
2207
2208 instance = calloc(1, sizeof *instance);
2209 if (!instance) {
2210 goto error;
2211 }
2212 instance->parent_type = parent_type;
2213 tmp = realloc(*ext, (*size + 1) * sizeof *tmp);
2214 if (!tmp) {
2215 goto error;
2216 }
2217 tmp[*size] = instance;
2218 *ext = tmp;
2219 (*size)++;
2220 return instance;
2221
2222error:
2223 LOGMEM;
2224 free(instance);
2225 return NULL;
2226}
2227
2228void *
2229yang_read_ext(struct lys_module *module, void *actual, char *ext_name, char *ext_arg,
PavolVican22e88682017-02-14 22:38:18 +01002230 enum yytokentype actual_type, enum yytokentype backup_type, int is_ext_instance)
PavolVicanc1807262017-01-31 18:00:27 +01002231{
2232 struct lys_ext_instance *instance;
PavolVican5334c892017-02-15 16:29:09 +01002233 LY_STMT stmt = LY_STMT_UNKNOWN;
PavolVicanc1807262017-01-31 18:00:27 +01002234
2235 if (backup_type != NODE) {
PavolVican4b80d042017-02-23 14:30:27 +01002236 instance = yang_ext_instance(actual, backup_type, is_ext_instance);
PavolVicane6fa67b2017-02-01 11:06:57 +01002237 if (!instance) {
2238 return NULL;
2239 }
PavolVicanc1807262017-01-31 18:00:27 +01002240 switch (actual_type) {
PavolVicana4b79bc2017-02-08 13:47:00 +01002241 case YANG_VERSION_KEYWORD:
2242 instance->insubstmt = LYEXT_SUBSTMT_VERSION;
PavolVican5334c892017-02-15 16:29:09 +01002243 stmt = LY_STMT_VERSION;
PavolVicana4b79bc2017-02-08 13:47:00 +01002244 break;
PavolVicanc1807262017-01-31 18:00:27 +01002245 case NAMESPACE_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002246 instance->insubstmt = LYEXT_SUBSTMT_NAMESPACE;
PavolVican5334c892017-02-15 16:29:09 +01002247 stmt = LY_STMT_NAMESPACE;
PavolVicanc1807262017-01-31 18:00:27 +01002248 break;
PavolVicane6fa67b2017-02-01 11:06:57 +01002249 case PREFIX_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002250 instance->insubstmt = LYEXT_SUBSTMT_PREFIX;
PavolVican5334c892017-02-15 16:29:09 +01002251 stmt = LY_STMT_PREFIX;
PavolVicane6fa67b2017-02-01 11:06:57 +01002252 break;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002253 case REVISION_DATE_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002254 instance->insubstmt = LYEXT_SUBSTMT_REVISIONDATE;
PavolVican5334c892017-02-15 16:29:09 +01002255 stmt = LY_STMT_REVISIONDATE;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002256 break;
2257 case DESCRIPTION_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002258 instance->insubstmt = LYEXT_SUBSTMT_DESCRIPTION;
PavolVican5334c892017-02-15 16:29:09 +01002259 stmt = LY_STMT_DESCRIPTION;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002260 break;
2261 case REFERENCE_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002262 instance->insubstmt = LYEXT_SUBSTMT_REFERENCE;
PavolVican5334c892017-02-15 16:29:09 +01002263 stmt = LY_STMT_REFERENCE;
PavolVican7d0b5ab2017-02-01 13:06:53 +01002264 break;
PavolVican171717d2017-02-01 14:49:55 +01002265 case CONTACT_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002266 instance->insubstmt = LYEXT_SUBSTMT_CONTACT;
PavolVican5334c892017-02-15 16:29:09 +01002267 stmt = LY_STMT_CONTACT;
PavolVican171717d2017-02-01 14:49:55 +01002268 break;
2269 case ORGANIZATION_KEYWORD:
Radek Krejcifebdad72017-02-06 11:35:51 +01002270 instance->insubstmt = LYEXT_SUBSTMT_ORGANIZATION;
PavolVican5334c892017-02-15 16:29:09 +01002271 stmt = LY_STMT_ORGANIZATION;
PavolVican171717d2017-02-01 14:49:55 +01002272 break;
PavolVican19dc6152017-02-06 12:04:15 +01002273 case YIN_ELEMENT_KEYWORD:
2274 instance->insubstmt = LYEXT_SUBSTMT_YINELEM;
PavolVican5334c892017-02-15 16:29:09 +01002275 stmt = LY_STMT_YINELEM;
PavolVican19dc6152017-02-06 12:04:15 +01002276 break;
2277 case STATUS_KEYWORD:
2278 instance->insubstmt = LYEXT_SUBSTMT_STATUS;
PavolVican5334c892017-02-15 16:29:09 +01002279 stmt = LY_STMT_STATUS;
PavolVican19dc6152017-02-06 12:04:15 +01002280 break;
PavolVican8fa31242017-02-07 11:04:26 +01002281 case BASE_KEYWORD:
2282 instance->insubstmt = LYEXT_SUBSTMT_BASE;
PavolVican5334c892017-02-15 16:29:09 +01002283 stmt = LY_STMT_BASE;
PavolVican056fcd12017-02-07 15:36:53 +01002284 if (backup_type == IDENTITY_KEYWORD) {
2285 instance->insubstmt_index = ((struct lys_ident *)actual)->base_size;
PavolVican5334c892017-02-15 16:29:09 +01002286 } else if (backup_type == TYPE_KEYWORD) {
PavolVican056fcd12017-02-07 15:36:53 +01002287 instance->insubstmt_index = ((struct yang_type *)actual)->type->info.ident.count;
2288 }
PavolVican8fa31242017-02-07 11:04:26 +01002289 break;
PavolVicandf9e7972017-02-07 11:41:38 +01002290 case DEFAULT_KEYWORD:
2291 instance->insubstmt = LYEXT_SUBSTMT_DEFAULT;
PavolVican5334c892017-02-15 16:29:09 +01002292 stmt = LY_STMT_DEFAULT;
PavolVican6f000922017-02-10 12:56:59 +01002293 switch (backup_type) {
2294 case LEAF_LIST_KEYWORD:
PavolVican3feb2f92017-02-08 13:44:39 +01002295 instance->insubstmt_index = ((struct lys_node_leaflist *)actual)->dflt_size;
PavolVican6f000922017-02-10 12:56:59 +01002296 break;
2297 case REFINE_KEYWORD:
PavolVican77374ee2017-02-08 15:18:45 +01002298 instance->insubstmt_index = ((struct lys_refine *)actual)->dflt_size;
PavolVican6f000922017-02-10 12:56:59 +01002299 break;
2300 case ADD_KEYWORD:
2301 instance->insubstmt_index = ((struct lys_deviate *)actual)->dflt_size;
2302 break;
2303 default:
2304 /* nothing changes */
2305 break;
PavolVican3feb2f92017-02-08 13:44:39 +01002306 }
PavolVicandf9e7972017-02-07 11:41:38 +01002307 break;
2308 case UNITS_KEYWORD:
2309 instance->insubstmt = LYEXT_SUBSTMT_UNITS;
PavolVican5334c892017-02-15 16:29:09 +01002310 stmt = LY_STMT_UNITS;
PavolVicandf9e7972017-02-07 11:41:38 +01002311 break;
PavolVican056fcd12017-02-07 15:36:53 +01002312 case REQUIRE_INSTANCE_KEYWORD:
2313 instance->insubstmt = LYEXT_SUBSTMT_REQINSTANCE;
PavolVican5334c892017-02-15 16:29:09 +01002314 stmt = LY_STMT_REQINSTANCE;
PavolVican056fcd12017-02-07 15:36:53 +01002315 break;
2316 case PATH_KEYWORD:
2317 instance->insubstmt = LYEXT_SUBSTMT_PATH;
PavolVican5334c892017-02-15 16:29:09 +01002318 stmt = LY_STMT_PATH;
PavolVican056fcd12017-02-07 15:36:53 +01002319 break;
2320 case ERROR_MESSAGE_KEYWORD:
2321 instance->insubstmt = LYEXT_SUBSTMT_ERRMSG;
PavolVican5334c892017-02-15 16:29:09 +01002322 stmt = LY_STMT_ERRMSG;
PavolVican056fcd12017-02-07 15:36:53 +01002323 break;
2324 case ERROR_APP_TAG_KEYWORD:
2325 instance->insubstmt = LYEXT_SUBSTMT_ERRTAG;
PavolVican5334c892017-02-15 16:29:09 +01002326 stmt = LY_STMT_ERRTAG;
PavolVican056fcd12017-02-07 15:36:53 +01002327 break;
2328 case MODIFIER_KEYWORD:
2329 instance->insubstmt = LYEXT_SUBSTMT_MODIFIER;
PavolVican5334c892017-02-15 16:29:09 +01002330 stmt = LY_STMT_MODIFIER;
PavolVican056fcd12017-02-07 15:36:53 +01002331 break;
2332 case FRACTION_DIGITS_KEYWORD:
2333 instance->insubstmt = LYEXT_SUBSTMT_DIGITS;
PavolVican5334c892017-02-15 16:29:09 +01002334 stmt = LY_STMT_DIGITS;
PavolVican056fcd12017-02-07 15:36:53 +01002335 break;
2336 case VALUE_KEYWORD:
2337 instance->insubstmt = LYEXT_SUBSTMT_VALUE;
PavolVican5334c892017-02-15 16:29:09 +01002338 stmt = LY_STMT_VALUE;
PavolVican056fcd12017-02-07 15:36:53 +01002339 break;
2340 case POSITION_KEYWORD:
2341 instance->insubstmt = LYEXT_SUBSTMT_POSITION;
PavolVican5334c892017-02-15 16:29:09 +01002342 stmt = LY_STMT_POSITION;
PavolVican056fcd12017-02-07 15:36:53 +01002343 break;
PavolVican5b910842017-02-08 13:08:47 +01002344 case PRESENCE_KEYWORD:
2345 instance->insubstmt = LYEXT_SUBSTMT_PRESENCE;
PavolVican5334c892017-02-15 16:29:09 +01002346 stmt = LY_STMT_PRESENCE;
PavolVican5b910842017-02-08 13:08:47 +01002347 break;
2348 case CONFIG_KEYWORD:
2349 instance->insubstmt = LYEXT_SUBSTMT_CONFIG;
PavolVican5334c892017-02-15 16:29:09 +01002350 stmt = LY_STMT_CONFIG;
PavolVican5b910842017-02-08 13:08:47 +01002351 break;
PavolVican3feb2f92017-02-08 13:44:39 +01002352 case MANDATORY_KEYWORD:
2353 instance->insubstmt = LYEXT_SUBSTMT_MANDATORY;
PavolVican5334c892017-02-15 16:29:09 +01002354 stmt = LY_STMT_MANDATORY;
PavolVican3feb2f92017-02-08 13:44:39 +01002355 break;
2356 case MIN_ELEMENTS_KEYWORD:
2357 instance->insubstmt = LYEXT_SUBSTMT_MIN;
PavolVican5334c892017-02-15 16:29:09 +01002358 stmt = LY_STMT_MIN;
PavolVican3feb2f92017-02-08 13:44:39 +01002359 break;
2360 case MAX_ELEMENTS_KEYWORD:
2361 instance->insubstmt = LYEXT_SUBSTMT_MAX;
PavolVican5334c892017-02-15 16:29:09 +01002362 stmt = LY_STMT_MAX;
PavolVican3feb2f92017-02-08 13:44:39 +01002363 break;
2364 case ORDERED_BY_KEYWORD:
2365 instance->insubstmt = LYEXT_SUBSTMT_ORDEREDBY;
PavolVican5334c892017-02-15 16:29:09 +01002366 stmt = LY_STMT_ORDEREDBY;
PavolVican3feb2f92017-02-08 13:44:39 +01002367 break;
2368 case KEY_KEYWORD:
2369 instance->insubstmt = LYEXT_SUBSTMT_KEY;
PavolVican5334c892017-02-15 16:29:09 +01002370 stmt = LY_STMT_KEY;
PavolVican3feb2f92017-02-08 13:44:39 +01002371 break;
2372 case UNIQUE_KEYWORD:
2373 instance->insubstmt = LYEXT_SUBSTMT_UNIQUE;
PavolVican5334c892017-02-15 16:29:09 +01002374 stmt = LY_STMT_UNIQUE;
2375 switch (backup_type) {
2376 case LIST_KEYWORD:
PavolVican6f000922017-02-10 12:56:59 +01002377 instance->insubstmt_index = ((struct lys_node_list *)actual)->unique_size;
PavolVican5334c892017-02-15 16:29:09 +01002378 break;
2379 case ADD_KEYWORD:
2380 case DELETE_KEYWORD:
2381 case REPLACE_KEYWORD:
PavolVican6f000922017-02-10 12:56:59 +01002382 instance->insubstmt_index = ((struct lys_deviate *)actual)->unique_size;
PavolVican5334c892017-02-15 16:29:09 +01002383 break;
2384 default:
2385 /* nothing changes */
2386 break;
PavolVican6f000922017-02-10 12:56:59 +01002387 }
PavolVican3feb2f92017-02-08 13:44:39 +01002388 break;
PavolVicanc1807262017-01-31 18:00:27 +01002389 default:
2390 LOGINT;
2391 return NULL;
2392 }
2393 } else {
PavolVican4b80d042017-02-23 14:30:27 +01002394 instance = yang_ext_instance(actual, actual_type, is_ext_instance);
PavolVicane6fa67b2017-02-01 11:06:57 +01002395 if (!instance) {
2396 return NULL;
2397 }
Radek Krejcifebdad72017-02-06 11:35:51 +01002398 instance->insubstmt = LYEXT_SUBSTMT_SELF;
PavolVican19dc6152017-02-06 12:04:15 +01002399 switch (actual_type) {
2400 case ARGUMENT_KEYWORD:
2401 instance->insubstmt = LYEXT_SUBSTMT_ARGUMENT;
PavolVican5334c892017-02-15 16:29:09 +01002402 stmt = LY_STMT_ARGUMENT;
PavolVican19dc6152017-02-06 12:04:15 +01002403 break;
PavolVicanfaa49702017-02-06 12:10:59 +01002404 case BELONGS_TO_KEYWORD:
2405 instance->insubstmt = LYEXT_SUBSTMT_BELONGSTO;
PavolVican5334c892017-02-15 16:29:09 +01002406 stmt = LY_STMT_BELONGSTO;
PavolVicanfaa49702017-02-06 12:10:59 +01002407 break;
PavolVican19dc6152017-02-06 12:04:15 +01002408 default:
2409 instance->insubstmt = LYEXT_SUBSTMT_SELF;
2410 break;
2411 }
PavolVicanc1807262017-01-31 18:00:27 +01002412 }
2413 instance->flags |= LYEXT_OPT_YANG;
2414 instance->def = (struct lys_ext *)ext_name; /* hack for UNRES */
2415 instance->arg_value = lydict_insert_zc(module->ctx, ext_arg);
PavolVican5334c892017-02-15 16:29:09 +01002416 if (is_ext_instance && stmt != LY_STMT_UNKNOWN && instance->parent_type == LYEXT_PAR_EXTINST) {
2417 instance->insubstmt_index = yang_fill_ext_substm_index(actual, stmt, backup_type);
2418 }
PavolVicanc1807262017-01-31 18:00:27 +01002419 return instance;
2420}
2421
PavolVican05c4f9b2017-09-07 13:33:54 +02002422static int
2423check_status_flag(struct lys_node *node, struct lys_node *parent)
2424{
2425 char *str;
2426
Radek Krejcie4dce292017-10-30 11:16:47 +01002427 if (node->nodetype & (LYS_OUTPUT | LYS_INPUT)) {
2428 return EXIT_SUCCESS;
2429 }
2430
PavolVican05c4f9b2017-09-07 13:33:54 +02002431 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
2432 /* status is not inherited by specification, but it not make sense to have
2433 * current in deprecated or deprecated in obsolete, so we print warning
2434 * and fix the schema by inheriting */
2435 if (!(node->flags & (LYS_STATUS_MASK))) {
2436 /* status not explicitely specified on the current node -> inherit */
Radek Krejcie4dce292017-10-30 11:16:47 +01002437 str = lys_path(node);
PavolVican05c4f9b2017-09-07 13:33:54 +02002438 LOGWRN("Missing status in %s subtree (%s), inheriting.",
2439 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", str);
2440 free(str);
2441 node->flags |= parent->flags & LYS_STATUS_MASK;
2442 } else if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
2443 /* invalid combination of statuses */
2444 switch (node->flags & LYS_STATUS_MASK) {
2445 case 0:
2446 case LYS_STATUS_CURR:
2447 LOGVAL(LYE_INSTATUS, LY_VLOG_LYS, parent, "current", strnodetype(node->nodetype), "is child of",
2448 parent->flags & LYS_STATUS_DEPRC ? "deprecated" : "obsolete", parent->name);
2449 break;
2450 case LYS_STATUS_DEPRC:
2451 LOGVAL(LYE_INSTATUS, LY_VLOG_LYS, parent, "deprecated", strnodetype(node->nodetype), "is child of",
2452 "obsolete", parent->name);
2453 break;
2454 }
2455 return EXIT_FAILURE;
2456 }
2457 }
2458
2459 return EXIT_SUCCESS;
2460}
2461
Pavol Vicanf4717e62016-03-16 11:30:01 +01002462int
Radek Krejci7212e0a2017-03-08 15:58:22 +01002463store_config_flag(struct lys_node *node, int options)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002464{
Pavol Vicanec598812016-11-30 14:13:38 +01002465 switch (node->nodetype) {
2466 case LYS_CONTAINER:
2467 case LYS_LEAF:
2468 case LYS_LEAFLIST:
2469 case LYS_LIST:
2470 case LYS_CHOICE:
2471 case LYS_ANYDATA:
2472 case LYS_ANYXML:
Radek Krejci7212e0a2017-03-08 15:58:22 +01002473 if (options & LYS_PARSE_OPT_CFG_IGNORE) {
Pavol Vicanec598812016-11-30 14:13:38 +01002474 node->flags |= node->flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET));
Radek Krejci7212e0a2017-03-08 15:58:22 +01002475 } else if (!(options & LYS_PARSE_OPT_CFG_NOINHERIT)) {
Pavol Vicanec598812016-11-30 14:13:38 +01002476 if (!(node->flags & LYS_CONFIG_MASK)) {
2477 /* get config flag from parent */
2478 if (node->parent) {
2479 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2480 } else {
2481 /* default config is true */
2482 node->flags |= LYS_CONFIG_W;
2483 }
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002484 }
2485 }
Pavol Vicanec598812016-11-30 14:13:38 +01002486 break;
2487 case LYS_CASE:
Radek Krejci7212e0a2017-03-08 15:58:22 +01002488 if (!(options & (LYS_PARSE_OPT_CFG_IGNORE | LYS_PARSE_OPT_CFG_NOINHERIT))) {
Pavol Vicanec598812016-11-30 14:13:38 +01002489 if (!(node->flags & LYS_CONFIG_MASK)) {
2490 /* get config flag from parent */
2491 if (node->parent) {
2492 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2493 } else {
2494 /* default config is true */
2495 node->flags |= LYS_CONFIG_W;
2496 }
2497 }
2498 }
2499 break;
Pavol Vicanec598812016-11-30 14:13:38 +01002500 default:
2501 break;
Pavol Vican1938d882016-04-10 13:36:31 +02002502 }
Pavol Vicanec598812016-11-30 14:13:38 +01002503
Radek Krejci7212e0a2017-03-08 15:58:22 +01002504 return EXIT_SUCCESS;
Pavol Vican1938d882016-04-10 13:36:31 +02002505}
2506
2507int
Pavol Vican9d50a772016-10-14 22:23:36 +02002508yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres,
2509 const char *data, unsigned int size_data, struct lys_node **node)
Pavol Vican1938d882016-04-10 13:36:31 +02002510{
Pavol Vican974377b2016-03-23 00:38:53 +01002511 unsigned int size;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002512 YY_BUFFER_STATE bp;
2513 yyscan_t scanner = NULL;
PavolVican9e81c6a2017-02-09 13:09:07 +01002514 int ret = 0;
Pavol Vican082afd02016-10-25 12:39:15 +02002515 struct lys_module *trg;
PavolVican196694c2017-01-27 10:33:09 +01002516 struct yang_parameter param;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002517
Pavol Vican8e7110b2016-03-22 17:00:26 +01002518 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002519 yylex_init(&scanner);
2520 bp = yy_scan_buffer((char *)data, size, scanner);
2521 yy_switch_to_buffer(bp, scanner);
PavolVican22e88682017-02-14 22:38:18 +01002522 memset(&param, 0, sizeof param);
PavolVican196694c2017-01-27 10:33:09 +01002523 param.module = module;
2524 param.submodule = submodule;
2525 param.unres = unres;
2526 param.node = node;
PavolVican22e88682017-02-14 22:38:18 +01002527 param.flags |= YANG_REMOVE_IMPORT;
PavolVican196694c2017-01-27 10:33:09 +01002528 if (yyparse(scanner, &param)) {
PavolVican22e88682017-02-14 22:38:18 +01002529 if (param.flags & YANG_REMOVE_IMPORT) {
Pavol Vican082afd02016-10-25 12:39:15 +02002530 trg = (submodule) ? (struct lys_module *)submodule : module;
2531 yang_free_import(trg->ctx, trg->imp, 0, trg->imp_size);
2532 yang_free_include(trg->ctx, trg->inc, 0, trg->inc_size);
2533 trg->inc_size = 0;
2534 trg->imp_size = 0;
2535 }
PavolVican22e88682017-02-14 22:38:18 +01002536 ret = (param.flags & YANG_EXIST_MODULE) ? 1 : -1;
2537 }
2538 yy_delete_buffer(bp, scanner);
2539 yylex_destroy(scanner);
2540 return ret;
2541}
2542
2543int
2544yang_parse_ext_substatement(struct lys_module *module, struct unres_schema *unres, const char *data,
2545 char *ext_name, struct lys_ext_instance_complex *ext)
2546{
2547 unsigned int size;
2548 YY_BUFFER_STATE bp;
2549 yyscan_t scanner = NULL;
2550 int ret = 0;
2551 struct yang_parameter param;
PavolVicanf3091bf2017-02-19 18:27:01 +01002552 struct lys_node *node = NULL;
PavolVican22e88682017-02-14 22:38:18 +01002553
PavolVicandb0e8172017-02-20 00:46:09 +01002554 if (!data) {
2555 return EXIT_SUCCESS;
2556 }
PavolVican22e88682017-02-14 22:38:18 +01002557 size = strlen(data) + 2;
2558 yylex_init(&scanner);
2559 bp = yy_scan_buffer((char *)data, size, scanner);
2560 yy_switch_to_buffer(bp, scanner);
2561 memset(&param, 0, sizeof param);
2562 param.module = module;
2563 param.unres = unres;
PavolVicanf3091bf2017-02-19 18:27:01 +01002564 param.node = &node;
PavolVican22e88682017-02-14 22:38:18 +01002565 param.actual_node = (void **)ext;
2566 param.data_node = (void **)ext_name;
2567 param.flags |= EXT_INSTANCE_SUBSTMT;
2568 if (yyparse(scanner, &param)) {
PavolVicanf3091bf2017-02-19 18:27:01 +01002569 yang_free_nodes(module->ctx, node);
PavolVican22e88682017-02-14 22:38:18 +01002570 ret = -1;
PavolVicanf3091bf2017-02-19 18:27:01 +01002571 } else {
2572 /* success parse, but it needs some sematic controls */
Radek Krejci7212e0a2017-03-08 15:58:22 +01002573 if (node && yang_check_nodes(module, (struct lys_node *)ext, node, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) {
PavolVicanf3091bf2017-02-19 18:27:01 +01002574 ret = -1;
2575 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002576 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002577 yy_delete_buffer(bp, scanner);
2578 yylex_destroy(scanner);
Pavol Vican1938d882016-04-10 13:36:31 +02002579 return ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002580}
2581
2582struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002583yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002584{
2585
PavolVican9e81c6a2017-02-09 13:09:07 +01002586 struct lys_module *module = NULL, *tmp_mod;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002587 struct unres_schema *unres = NULL;
Pavol Vican9d50a772016-10-14 22:23:36 +02002588 struct lys_node *node = NULL;
PavolVican9e81c6a2017-02-09 13:09:07 +01002589 int ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002590
2591 unres = calloc(1, sizeof *unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002592 LY_CHECK_ERR_GOTO(!unres, LOGMEM, error);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002593
2594 module = calloc(1, sizeof *module);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002595 LY_CHECK_ERR_GOTO(!module, LOGMEM, error);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002596
2597 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002598 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002599 module->type = 0;
2600 module->implemented = (implement ? 1 : 0);
2601
Radek Krejci9e757e02017-03-08 17:18:09 +01002602 /* add into the list of processed modules */
2603 if (lyp_check_circmod_add(module)) {
2604 goto error;
2605 }
2606
PavolVican9e81c6a2017-02-09 13:09:07 +01002607 ret = yang_parse_mem(module, NULL, unres, data, size, &node);
2608 if (ret == -1) {
Pavol Vican05810b62016-11-23 14:07:22 +01002609 free_yang_common(module, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002610 goto error;
Michal Vasko7b460e52017-02-10 14:50:26 +01002611 } else if (ret == 1) {
PavolVican9e81c6a2017-02-09 13:09:07 +01002612 assert(!unres->count);
2613 } else {
2614 if (yang_check_sub_module(module, unres, node)) {
2615 goto error;
2616 }
Pavol Vican7313fc02016-11-14 01:10:31 +01002617
Michal Vasko7b460e52017-02-10 14:50:26 +01002618 if (unres->count && resolve_unres_schema(module, unres)) {
PavolVican9e81c6a2017-02-09 13:09:07 +01002619 goto error;
2620 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002621 }
2622
PavolVicanfe83b152017-02-19 03:19:29 +01002623 lyp_sort_revisions(module);
2624
Pavol Vican8e7110b2016-03-22 17:00:26 +01002625 if (revision) {
2626 /* check revision of the parsed model */
2627 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2628 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2629 module->name, module->rev[0].date, revision);
2630 goto error;
2631 }
2632 }
2633
PavolVican9e81c6a2017-02-09 13:09:07 +01002634 /* add into context if not already there */
2635 if (!ret) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01002636 /* check correctness of includes */
2637 if (lyp_check_include_missing(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002638 goto error;
2639 }
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01002640
PavolVicanfd6f6952017-02-14 00:09:42 +01002641 /* remove our submodules from the parsed submodules list */
2642 lyp_del_includedup(module);
2643
2644
PavolVican6f000922017-02-10 12:56:59 +01002645 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01002646 goto error;
2647 }
2648
PavolVican9e81c6a2017-02-09 13:09:07 +01002649 if (lyp_ctx_add_module(module)) {
Michal Vasko7da5b0b2016-05-02 16:36:59 +02002650 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002651 }
PavolVican9e81c6a2017-02-09 13:09:07 +01002652
2653 if (module->deviation_size && !module->implemented) {
2654 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2655 /* deviations always causes target to be made implemented,
2656 * but augents and leafrefs not, so we have to apply them now */
2657 if (lys_set_implemented(module)) {
2658 goto error;
2659 }
2660 }
2661 } else {
2662 tmp_mod = module;
2663
2664 /* get the model from the context */
Radek Krejcidfb00d62017-09-06 09:39:35 +02002665 module = (struct lys_module *)ly_ctx_get_module(ctx, module->name, revision, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01002666 assert(module);
2667
2668 /* free what was parsed */
2669 lys_free(tmp_mod, NULL, 0);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002670 }
2671
Michal Vasko44ab1462017-05-18 13:18:36 +02002672 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01002673 lyp_check_circmod_pop(ctx);
Michal Vaskobe136f62017-09-21 12:08:39 +02002674 LOGVRB("Module \"%s%s%s\" successfully parsed as %s.", module->name, (module->rev_size ? "@" : ""),
2675 (module->rev_size ? module->rev[0].date : ""), (module->implemented ? "implemented" : "imported"));
Pavol Vican8e7110b2016-03-22 17:00:26 +01002676 return module;
2677
2678error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002679 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02002680 unres_schema_free(module, &unres, 1);
Radek Krejcif505cd12017-06-13 10:32:48 +02002681 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01002682 if (ly_vecode != LYVE_SUBMODULE) {
2683 LOGERR(ly_errno, "Module parsing failed.");
2684 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002685 return NULL;
2686 }
2687
Radek Krejcif505cd12017-06-13 10:32:48 +02002688 if (module->name) {
2689 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
2690 } else {
2691 LOGERR(ly_errno, "Module parsing failed.");
2692 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002693
Radek Krejci9e757e02017-03-08 17:18:09 +01002694 lyp_check_circmod_pop(ctx);
Michal Vaskocf0489e2017-02-13 11:57:45 +01002695 lyp_del_includedup(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002696 lys_sub_module_remove_devs_augs(module);
2697 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002698 return NULL;
2699}
2700
2701struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002702yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002703{
2704 struct lys_submodule *submodule;
Pavol Vican9d50a772016-10-14 22:23:36 +02002705 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002706
2707 submodule = calloc(1, sizeof *submodule);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002708 LY_CHECK_ERR_GOTO(!submodule, LOGMEM, error);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002709
2710 submodule->ctx = module->ctx;
2711 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02002712 submodule->implemented = module->implemented;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002713 submodule->belongsto = module;
2714
Radek Krejci9e757e02017-03-08 17:18:09 +01002715 /* add into the list of processed modules */
2716 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
2717 goto error;
2718 }
2719
PavolVican9e81c6a2017-02-09 13:09:07 +01002720 /* module cannot be changed in this case and 1 cannot be returned */
Pavol Vican9d50a772016-10-14 22:23:36 +02002721 if (yang_parse_mem(module, submodule, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002722 free_yang_common((struct lys_module *)submodule, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002723 goto error;
2724 }
2725
PavolVicanfe83b152017-02-19 03:19:29 +01002726 lyp_sort_revisions((struct lys_module *)submodule);
2727
Pavol Vican7313fc02016-11-14 01:10:31 +01002728 if (yang_check_sub_module((struct lys_module *)submodule, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002729 goto error;
2730 }
2731
Radek Krejci9e757e02017-03-08 17:18:09 +01002732 lyp_check_circmod_pop(module->ctx);
2733
Pavol Vican8e7110b2016-03-22 17:00:26 +01002734 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002735 return submodule;
2736
2737error:
2738 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02002739 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002740
2741 if (!submodule || !submodule->name) {
2742 free(submodule);
2743 LOGERR(ly_errno, "Submodule parsing failed.");
2744 return NULL;
2745 }
2746
2747 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2748
Radek Krejci9e757e02017-03-08 17:18:09 +01002749 lyp_check_circmod_pop(module->ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002750 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2751 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002752 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002753 return NULL;
2754}
Pavol Vican8760bb72016-04-07 09:44:01 +02002755
2756static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002757read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2758{
2759 int k = 0, j;
2760
2761 while (in_index < size) {
2762 if (input[in_index] == ' ') {
2763 k++;
2764 } else if (input[in_index] == '\t') {
2765 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2766 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002767 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2768 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2769 k += 8;
2770 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002771 } else {
2772 break;
2773 }
2774 ++in_index;
2775 if (k >= indent) {
2776 for (j = k - indent; j > 0; --j) {
2777 output[*out_index] = ' ';
Pavol Vicana7bf3372016-12-01 15:58:18 +01002778 if (j > 1) {
2779 ++(*out_index);
2780 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002781 }
2782 break;
2783 }
2784 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002785 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002786}
2787
2788char *
PavolVican1bc22062017-01-19 15:09:04 +01002789yang_read_string(const char *input, char *output, int size, int offset, int indent) {
Pavol Vican3f598892016-09-28 15:41:07 +02002790 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002791
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002792 while (i < size) {
2793 switch (input[i]) {
2794 case '\n':
2795 out_index -= space;
2796 output[out_index] = '\n';
2797 space = 0;
2798 i = read_indent(input, indent, size, i + 1, &out_index, output);
2799 break;
2800 case ' ':
2801 case '\t':
2802 output[out_index] = input[i];
2803 ++space;
2804 break;
2805 case '\\':
2806 if (input[i + 1] == 'n') {
2807 out_index -= space;
2808 output[out_index] = '\n';
2809 space = 0;
2810 i = read_indent(input, indent, size, i + 2, &out_index, output);
2811 } else if (input[i + 1] == 't') {
2812 output[out_index] = '\t';
2813 ++i;
2814 ++space;
2815 } else if (input[i + 1] == '\\') {
2816 output[out_index] = '\\';
2817 ++i;
2818 } else if ((i + 1) != size && input[i + 1] == '"') {
2819 output[out_index] = '"';
2820 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002821 } else {
PavolVican1bc22062017-01-19 15:09:04 +01002822 /* backslash must not be followed by any other character */
2823 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
2824 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002825 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002826 break;
2827 default:
2828 output[out_index] = input[i];
2829 space = 0;
2830 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002831 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002832 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002833 ++out_index;
2834 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002835 output[out_index] = '\0';
2836 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002837 output = realloc(output, out_index + 1);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002838 LY_CHECK_ERR_RETURN(!output, LOGMEM, NULL);
Pavol Vican8760bb72016-04-07 09:44:01 +02002839 }
Pavol Vican3f598892016-09-28 15:41:07 +02002840 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002841}
Pavol Vican1cc4e192016-10-24 16:38:31 +02002842
2843/* free function */
2844
PavolVicana0fdbf32017-02-15 17:59:02 +01002845void
2846yang_type_free(struct ly_ctx *ctx, struct lys_type *type)
Pavol Vican7313fc02016-11-14 01:10:31 +01002847{
2848 struct yang_type *stype = (struct yang_type *)type->der;
Radek Krejcidce5f972017-09-12 15:47:49 +02002849 unsigned int i;
Pavol Vican7313fc02016-11-14 01:10:31 +01002850
2851 if (!stype) {
2852 return ;
2853 }
PavolVicane87cb932016-12-30 15:36:18 +01002854 if (type->base == LY_TYPE_DER || type->base == LY_TYPE_ERR || type->base == LY_TYPE_UNION) {
2855 lydict_remove(ctx, stype->name);
2856 if (stype->base == LY_TYPE_IDENT && (!(stype->flags & LYS_NO_ERASE_IDENTITY))) {
2857 for (i = 0; i < type->info.ident.count; ++i) {
2858 free(type->info.ident.ref[i]);
2859 }
Pavol Vican7313fc02016-11-14 01:10:31 +01002860 }
PavolVicane87cb932016-12-30 15:36:18 +01002861 if (stype->base == LY_TYPE_UNION) {
2862 for (i = 0; i < type->info.uni.count; ++i) {
2863 yang_type_free(ctx, &type->info.uni.types[i]);
2864 }
2865 free(type->info.uni.types);
2866 type->base = LY_TYPE_DER;
2867 } else {
2868 type->base = stype->base;
2869 }
2870 free(stype);
2871 type->der = NULL;
Pavol Vican7313fc02016-11-14 01:10:31 +01002872 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02002873 lys_type_free(ctx, type, NULL);
Pavol Vican36aff862016-11-26 17:07:05 +01002874 type->base = LY_TYPE_DER;
PavolVican575a9342017-02-15 18:14:39 +01002875 type->ext_size = 0;
2876 type->ext = NULL;
Pavol Vican7313fc02016-11-14 01:10:31 +01002877}
2878
2879static void
Radek Krejcia2ac9262017-09-12 16:39:04 +02002880yang_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf, uint16_t start, uint16_t size)
Pavol Vican7313fc02016-11-14 01:10:31 +01002881{
2882 uint8_t i;
2883
2884 assert(ctx);
2885 if (!tpdf) {
2886 return;
2887 }
2888
2889 for (i = start; i < size; ++i) {
Pavol Vicancee10802016-11-22 15:48:35 +01002890 lydict_remove(ctx, tpdf[i].name);
2891 lydict_remove(ctx, tpdf[i].dsc);
2892 lydict_remove(ctx, tpdf[i].ref);
Pavol Vican7313fc02016-11-14 01:10:31 +01002893
Pavol Vicancee10802016-11-22 15:48:35 +01002894 yang_type_free(ctx, &tpdf[i].type);
Pavol Vican7313fc02016-11-14 01:10:31 +01002895
Pavol Vicancee10802016-11-22 15:48:35 +01002896 lydict_remove(ctx, tpdf[i].units);
2897 lydict_remove(ctx, tpdf[i].dflt);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002898 lys_extension_instances_free(ctx, tpdf[i].ext, tpdf[i].ext_size, NULL);
Pavol Vican7313fc02016-11-14 01:10:31 +01002899 }
2900}
2901
Pavol Vican1cc4e192016-10-24 16:38:31 +02002902static void
2903yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size)
2904{
2905 uint8_t i;
2906
2907 for (i = start; i < size; ++i){
2908 free((char *)imp[i].module);
2909 lydict_remove(ctx, imp[i].prefix);
2910 lydict_remove(ctx, imp[i].dsc);
2911 lydict_remove(ctx, imp[i].ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002912 lys_extension_instances_free(ctx, imp[i].ext, imp[i].ext_size, NULL);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002913 }
2914}
2915
Pavol Vicanec423c92016-10-24 21:33:43 +02002916static void
2917yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size)
2918{
2919 uint8_t i;
2920
2921 for (i = start; i < size; ++i){
2922 free((char *)inc[i].submodule);
2923 lydict_remove(ctx, inc[i].dsc);
2924 lydict_remove(ctx, inc[i].ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002925 lys_extension_instances_free(ctx, inc[i].ext, inc[i].ext_size, NULL);
Pavol Vicanec423c92016-10-24 21:33:43 +02002926 }
2927}
2928
Pavol Vican36e27272016-11-22 15:47:28 +01002929static void
2930yang_free_ident_base(struct lys_ident *ident, uint32_t start, uint32_t size)
2931{
2932 uint32_t i;
2933 uint8_t j;
2934
2935 /* free base name */
2936 for (i = start; i < size; ++i) {
2937 for (j = 0; j < ident[i].base_size; ++j) {
2938 free(ident[i].base[j]);
2939 }
2940 }
2941}
2942
Pavol Vican05810b62016-11-23 14:07:22 +01002943static void
2944yang_free_grouping(struct ly_ctx *ctx, struct lys_node_grp * grp)
2945{
2946 yang_tpdf_free(ctx, grp->tpdf, 0, grp->tpdf_size);
2947 free(grp->tpdf);
2948}
2949
2950static void
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002951yang_free_container(struct ly_ctx *ctx, struct lys_node_container * cont)
2952{
2953 uint8_t i;
2954
2955 yang_tpdf_free(ctx, cont->tpdf, 0, cont->tpdf_size);
2956 free(cont->tpdf);
2957 lydict_remove(ctx, cont->presence);
2958
Pavol Vicanfda8c802016-12-03 02:00:42 +01002959 for (i = 0; i < cont->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002960 lys_restr_free(ctx, &cont->must[i], NULL);
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002961 }
2962 free(cont->must);
2963
Radek Krejci5138e9f2017-04-12 13:10:46 +02002964 lys_when_free(ctx, cont->when, NULL);
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002965}
2966
2967static void
Pavol Vicana69aff22016-11-24 18:23:50 +01002968yang_free_leaf(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
2969{
2970 uint8_t i;
2971
2972 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002973 lys_restr_free(ctx, &leaf->must[i], NULL);
Pavol Vicana69aff22016-11-24 18:23:50 +01002974 }
2975 free(leaf->must);
2976
Radek Krejci5138e9f2017-04-12 13:10:46 +02002977 lys_when_free(ctx, leaf->when, NULL);
Pavol Vicana69aff22016-11-24 18:23:50 +01002978
2979 yang_type_free(ctx, &leaf->type);
2980 lydict_remove(ctx, leaf->units);
2981 lydict_remove(ctx, leaf->dflt);
2982}
2983
2984static void
Pavol Vican36aff862016-11-26 17:07:05 +01002985yang_free_leaflist(struct ly_ctx *ctx, struct lys_node_leaflist *leaflist)
2986{
2987 uint8_t i;
2988
2989 for (i = 0; i < leaflist->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002990 lys_restr_free(ctx, &leaflist->must[i], NULL);
Pavol Vican36aff862016-11-26 17:07:05 +01002991 }
2992 free(leaflist->must);
2993
2994 for (i = 0; i < leaflist->dflt_size; i++) {
2995 lydict_remove(ctx, leaflist->dflt[i]);
2996 }
2997 free(leaflist->dflt);
2998
Radek Krejci5138e9f2017-04-12 13:10:46 +02002999 lys_when_free(ctx, leaflist->when, NULL);
Pavol Vican36aff862016-11-26 17:07:05 +01003000
3001 yang_type_free(ctx, &leaflist->type);
3002 lydict_remove(ctx, leaflist->units);
3003}
3004
3005static void
Pavol Vicand8136a42016-11-27 13:28:04 +01003006yang_free_list(struct ly_ctx *ctx, struct lys_node_list *list)
3007{
3008 uint8_t i;
3009
3010 yang_tpdf_free(ctx, list->tpdf, 0, list->tpdf_size);
3011 free(list->tpdf);
3012
3013 for (i = 0; i < list->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003014 lys_restr_free(ctx, &list->must[i], NULL);
Pavol Vicand8136a42016-11-27 13:28:04 +01003015 }
3016 free(list->must);
3017
Radek Krejci5138e9f2017-04-12 13:10:46 +02003018 lys_when_free(ctx, list->when, NULL);
Pavol Vicand8136a42016-11-27 13:28:04 +01003019
3020 for (i = 0; i < list->unique_size; ++i) {
3021 free(list->unique[i].expr);
3022 }
3023 free(list->unique);
3024
3025 free(list->keys);
3026}
3027
3028static void
Pavol Vican36ace102016-11-28 11:46:59 +01003029yang_free_choice(struct ly_ctx *ctx, struct lys_node_choice *choice)
3030{
3031 free(choice->dflt);
Radek Krejci5138e9f2017-04-12 13:10:46 +02003032 lys_when_free(ctx, choice->when, NULL);
Pavol Vican36ace102016-11-28 11:46:59 +01003033}
3034
3035static void
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003036yang_free_anydata(struct ly_ctx *ctx, struct lys_node_anydata *anydata)
3037{
3038 uint8_t i;
3039
3040 for (i = 0; i < anydata->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003041 lys_restr_free(ctx, &anydata->must[i], NULL);
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003042 }
3043 free(anydata->must);
3044
Radek Krejci5138e9f2017-04-12 13:10:46 +02003045 lys_when_free(ctx, anydata->when, NULL);
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003046}
3047
3048static void
Pavol Vican78729392016-11-28 17:18:22 +01003049yang_free_inout(struct ly_ctx *ctx, struct lys_node_inout *inout)
3050{
3051 uint8_t i;
3052
3053 yang_tpdf_free(ctx, inout->tpdf, 0, inout->tpdf_size);
3054 free(inout->tpdf);
3055
3056 for (i = 0; i < inout->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003057 lys_restr_free(ctx, &inout->must[i], NULL);
Pavol Vican78729392016-11-28 17:18:22 +01003058 }
3059 free(inout->must);
3060}
3061
3062static void
Pavol Vican29bf8802016-11-28 20:44:57 +01003063yang_free_notif(struct ly_ctx *ctx, struct lys_node_notif *notif)
3064{
3065 uint8_t i;
3066
3067 yang_tpdf_free(ctx, notif->tpdf, 0, notif->tpdf_size);
3068 free(notif->tpdf);
3069
3070 for (i = 0; i < notif->must_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003071 lys_restr_free(ctx, &notif->must[i], NULL);
Pavol Vican29bf8802016-11-28 20:44:57 +01003072 }
3073 free(notif->must);
3074}
3075
3076static void
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003077yang_free_uses(struct ly_ctx *ctx, struct lys_node_uses *uses)
3078{
3079 int i, j;
3080
3081 for (i = 0; i < uses->refine_size; i++) {
3082 lydict_remove(ctx, uses->refine[i].target_name);
3083 lydict_remove(ctx, uses->refine[i].dsc);
3084 lydict_remove(ctx, uses->refine[i].ref);
3085
3086 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003087 lys_restr_free(ctx, &uses->refine[i].must[j], NULL);
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003088 }
3089 free(uses->refine[i].must);
3090
3091 for (j = 0; j < uses->refine[i].dflt_size; j++) {
3092 lydict_remove(ctx, uses->refine[i].dflt[j]);
3093 }
3094 free(uses->refine[i].dflt);
3095
3096 if (uses->refine[i].target_type & LYS_CONTAINER) {
3097 lydict_remove(ctx, uses->refine[i].mod.presence);
3098 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02003099 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size, NULL);
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003100 }
3101 free(uses->refine);
3102
Radek Krejci5138e9f2017-04-12 13:10:46 +02003103 lys_when_free(ctx, uses->when, NULL);
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003104}
3105
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003106static void
Pavol Vican05810b62016-11-23 14:07:22 +01003107yang_free_nodes(struct ly_ctx *ctx, struct lys_node *node)
3108{
3109 struct lys_node *tmp, *child, *sibling;
3110
3111 if (!node) {
3112 return;
3113 }
3114 tmp = node;
Pavol Vican05810b62016-11-23 14:07:22 +01003115
3116 while (tmp) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01003117 child = tmp->child;
Pavol Vican05810b62016-11-23 14:07:22 +01003118 sibling = tmp->next;
3119 /* common part */
3120 lydict_remove(ctx, tmp->name);
3121 if (!(tmp->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Frank Rimplerc4db1c72017-09-12 12:56:39 +00003122 lys_iffeature_free(ctx, tmp->iffeature, tmp->iffeature_size, 0, NULL);
Pavol Vicane87ff8d2016-11-24 18:25:01 +01003123 lydict_remove(ctx, tmp->dsc);
3124 lydict_remove(ctx, tmp->ref);
Pavol Vican05810b62016-11-23 14:07:22 +01003125 }
3126
3127 switch (tmp->nodetype) {
3128 case LYS_GROUPING:
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003129 case LYS_RPC:
3130 case LYS_ACTION:
Pavol Vican05810b62016-11-23 14:07:22 +01003131 yang_free_grouping(ctx, (struct lys_node_grp *)tmp);
3132 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003133 case LYS_CONTAINER:
3134 yang_free_container(ctx, (struct lys_node_container *)tmp);
3135 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01003136 case LYS_LEAF:
3137 yang_free_leaf(ctx, (struct lys_node_leaf *)tmp);
3138 break;
Pavol Vican36aff862016-11-26 17:07:05 +01003139 case LYS_LEAFLIST:
3140 yang_free_leaflist(ctx, (struct lys_node_leaflist *)tmp);
3141 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003142 case LYS_LIST:
3143 yang_free_list(ctx, (struct lys_node_list *)tmp);
3144 break;
Pavol Vican36ace102016-11-28 11:46:59 +01003145 case LYS_CHOICE:
3146 yang_free_choice(ctx, (struct lys_node_choice *)tmp);
3147 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01003148 case LYS_CASE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02003149 lys_when_free(ctx, ((struct lys_node_case *)tmp)->when, NULL);
Pavol Vicana420bac2016-11-28 14:51:54 +01003150 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003151 case LYS_ANYXML:
3152 case LYS_ANYDATA:
3153 yang_free_anydata(ctx, (struct lys_node_anydata *)tmp);
3154 break;
Pavol Vican78729392016-11-28 17:18:22 +01003155 case LYS_INPUT:
3156 case LYS_OUTPUT:
3157 yang_free_inout(ctx, (struct lys_node_inout *)tmp);
3158 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01003159 case LYS_NOTIF:
3160 yang_free_notif(ctx, (struct lys_node_notif *)tmp);
3161 break;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003162 case LYS_USES:
3163 yang_free_uses(ctx, (struct lys_node_uses *)tmp);
3164 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003165 default:
3166 break;
3167 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02003168 lys_extension_instances_free(ctx, tmp->ext, tmp->ext_size, NULL);
Pavol Vican05810b62016-11-23 14:07:22 +01003169 yang_free_nodes(ctx, child);
3170 free(tmp);
3171 tmp = sibling;
3172 }
3173}
3174
Pavol Vican3ad50f82016-12-04 15:00:36 +01003175static void
3176yang_free_augment(struct ly_ctx *ctx, struct lys_node_augment *aug)
3177{
3178 lydict_remove(ctx, aug->target_name);
3179 lydict_remove(ctx, aug->dsc);
3180 lydict_remove(ctx, aug->ref);
3181
Frank Rimplerc4db1c72017-09-12 12:56:39 +00003182 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size, 0, NULL);
Radek Krejci5138e9f2017-04-12 13:10:46 +02003183 lys_when_free(ctx, aug->when, NULL);
Pavol Vican3ad50f82016-12-04 15:00:36 +01003184 yang_free_nodes(ctx, aug->child);
Radek Krejci5138e9f2017-04-12 13:10:46 +02003185 lys_extension_instances_free(ctx, aug->ext, aug->ext_size, NULL);
Pavol Vican3ad50f82016-12-04 15:00:36 +01003186}
3187
PavolVican75af21d2016-12-29 20:04:07 +01003188static void
3189yang_free_deviate(struct ly_ctx *ctx, struct lys_deviation *dev, uint index)
3190{
3191 uint i, j;
3192
3193 for (i = index; i < dev->deviate_size; ++i) {
3194 lydict_remove(ctx, dev->deviate[i].units);
3195
3196 if (dev->deviate[i].type) {
3197 yang_type_free(ctx, dev->deviate[i].type);
3198 }
3199
3200 for (j = 0; j < dev->deviate[i].dflt_size; ++j) {
3201 lydict_remove(ctx, dev->deviate[i].dflt[j]);
3202 }
3203 free(dev->deviate[i].dflt);
3204
3205 for (j = 0; j < dev->deviate[i].must_size; ++j) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003206 lys_restr_free(ctx, &dev->deviate[i].must[j], NULL);
PavolVican75af21d2016-12-29 20:04:07 +01003207 }
3208 free(dev->deviate[i].must);
3209
3210 for (j = 0; j < dev->deviate[i].unique_size; ++j) {
3211 free(dev->deviate[i].unique[j].expr);
3212 }
3213 free(dev->deviate[i].unique);
Radek Krejci5138e9f2017-04-12 13:10:46 +02003214 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size, NULL);
PavolVican75af21d2016-12-29 20:04:07 +01003215 }
3216}
3217
PavolVicandb0e8172017-02-20 00:46:09 +01003218void
3219yang_free_ext_data(struct yang_ext_substmt *substmt)
3220{
3221 int i;
3222
3223 if (!substmt) {
3224 return;
3225 }
3226
3227 free(substmt->ext_substmt);
3228 if (substmt->ext_modules) {
3229 for (i = 0; substmt->ext_modules[i]; ++i) {
3230 free(substmt->ext_modules[i]);
3231 }
3232 free(substmt->ext_modules);
3233 }
3234 free(substmt);
3235}
3236
Pavol Vican7313fc02016-11-14 01:10:31 +01003237/* free common item from module and submodule */
3238static void
Pavol Vican05810b62016-11-23 14:07:22 +01003239free_yang_common(struct lys_module *module, struct lys_node *node)
Pavol Vican7313fc02016-11-14 01:10:31 +01003240{
PavolVican75af21d2016-12-29 20:04:07 +01003241 uint i;
Pavol Vican7313fc02016-11-14 01:10:31 +01003242 yang_tpdf_free(module->ctx, module->tpdf, 0, module->tpdf_size);
3243 module->tpdf_size = 0;
Pavol Vican36e27272016-11-22 15:47:28 +01003244 yang_free_ident_base(module->ident, 0, module->ident_size);
Pavol Vican05810b62016-11-23 14:07:22 +01003245 yang_free_nodes(module->ctx, node);
PavolVican75af21d2016-12-29 20:04:07 +01003246 for (i = 0; i < module->augment_size; ++i) {
3247 yang_free_augment(module->ctx, &module->augment[i]);
3248 }
3249 module->augment_size = 0;
3250 for (i = 0; i < module->deviation_size; ++i) {
3251 yang_free_deviate(module->ctx, &module->deviation[i], 0);
3252 free(module->deviation[i].deviate);
3253 }
3254 module->deviation_size = 0;
Pavol Vican7313fc02016-11-14 01:10:31 +01003255}
3256
Pavol Vican1cc4e192016-10-24 16:38:31 +02003257/* check function*/
3258
3259int
PavolVicanc1807262017-01-31 18:00:27 +01003260yang_check_ext_instance(struct lys_module *module, struct lys_ext_instance ***ext, uint size,
3261 void *parent, struct unres_schema *unres)
3262{
3263 struct unres_ext *info;
3264 uint i;
3265
3266 for (i = 0; i < size; ++i) {
3267 info = malloc(sizeof *info);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003268 LY_CHECK_ERR_RETURN(!info, LOGMEM, EXIT_FAILURE);
PavolVicanc1807262017-01-31 18:00:27 +01003269 info->data.yang = (*ext)[i]->parent;
3270 info->datatype = LYS_IN_YANG;
3271 info->parent = parent;
3272 info->mod = module;
3273 info->parent_type = (*ext)[i]->parent_type;
Radek Krejcifebdad72017-02-06 11:35:51 +01003274 info->substmt = (*ext)[i]->insubstmt;
3275 info->substmt_index = (*ext)[i]->insubstmt_index;
PavolVicanc1807262017-01-31 18:00:27 +01003276 info->ext_index = i;
3277 if (unres_schema_add_node(module, unres, ext, UNRES_EXT, (struct lys_node *)info) == -1) {
3278 return EXIT_FAILURE;
3279 }
3280 }
3281
3282 return EXIT_SUCCESS;
3283}
3284
3285int
Pavol Vicanec423c92016-10-24 21:33:43 +02003286yang_check_imports(struct lys_module *module, struct unres_schema *unres)
Pavol Vican1cc4e192016-10-24 16:38:31 +02003287{
3288 struct lys_import *imp;
Pavol Vicanec423c92016-10-24 21:33:43 +02003289 struct lys_include *inc;
3290 uint8_t imp_size, inc_size, j = 0, i = 0;
Pavol Vican1cc4e192016-10-24 16:38:31 +02003291 char *s;
3292
3293 imp = module->imp;
3294 imp_size = module->imp_size;
Pavol Vicanec423c92016-10-24 21:33:43 +02003295 inc = module->inc;
3296 inc_size = module->inc_size;
Pavol Vican1cc4e192016-10-24 16:38:31 +02003297
3298 if (imp_size) {
PavolVican5144fd82017-03-07 19:45:06 +01003299 module->imp = calloc(imp_size, sizeof *module->imp);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003300 module->imp_size = 0;
Radek Krejcia8d111f2017-05-31 13:57:37 +02003301 LY_CHECK_ERR_GOTO(!module->imp, LOGMEM, error);
Pavol Vicanec423c92016-10-24 21:33:43 +02003302 }
Pavol Vican1cc4e192016-10-24 16:38:31 +02003303
Pavol Vicanec423c92016-10-24 21:33:43 +02003304 if (inc_size) {
PavolVican5144fd82017-03-07 19:45:06 +01003305 module->inc = calloc(inc_size, sizeof *module->inc);
Pavol Vicanec423c92016-10-24 21:33:43 +02003306 module->inc_size = 0;
Radek Krejcia8d111f2017-05-31 13:57:37 +02003307 LY_CHECK_ERR_GOTO(!module->inc, LOGMEM, error);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003308 }
3309
3310 for (i = 0; i < imp_size; ++i) {
3311 s = (char *) imp[i].module;
3312 imp[i].module = NULL;
PavolVican7d0b5ab2017-02-01 13:06:53 +01003313 if (yang_fill_import(module, &imp[i], &module->imp[module->imp_size], s, unres)) {
Pavol Vican1cc4e192016-10-24 16:38:31 +02003314 ++i;
3315 goto error;
3316 }
3317 }
Pavol Vicanec423c92016-10-24 21:33:43 +02003318 for (j = 0; j < inc_size; ++j) {
Pavol Vicanfda8c802016-12-03 02:00:42 +01003319 s = (char *) inc[j].submodule;
3320 inc[j].submodule = NULL;
3321 if (yang_fill_include(module, s, &inc[j], unres)) {
3322 ++j;
Pavol Vicanec423c92016-10-24 21:33:43 +02003323 goto error;
3324 }
3325 }
3326 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003327 free(imp);
3328
3329 return EXIT_SUCCESS;
3330
3331error:
3332 yang_free_import(module->ctx, imp, i, imp_size);
Pavol Vicanec423c92016-10-24 21:33:43 +02003333 yang_free_include(module->ctx, inc, j, inc_size);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003334 free(imp);
Pavol Vicanec423c92016-10-24 21:33:43 +02003335 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003336 return EXIT_FAILURE;
3337}
Pavol Vican7313fc02016-11-14 01:10:31 +01003338
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003339static int
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003340yang_check_iffeatures(struct lys_module *module, void *ptr, void *parent, enum yytokentype type, struct unres_schema *unres)
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003341{
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003342 struct lys_iffeature *iffeature;
3343 uint8_t *ptr_size, size, i;
3344 char *s;
3345 int parent_is_feature = 0;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003346
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003347 switch (type) {
3348 case FEATURE_KEYWORD:
3349 iffeature = ((struct lys_feature *)parent)->iffeature;
3350 size = ((struct lys_feature *)parent)->iffeature_size;
3351 ptr_size = &((struct lys_feature *)parent)->iffeature_size;
3352 parent_is_feature = 1;
3353 break;
3354 case IDENTITY_KEYWORD:
3355 iffeature = ((struct lys_ident *)parent)->iffeature;
3356 size = ((struct lys_ident *)parent)->iffeature_size;
3357 ptr_size = &((struct lys_ident *)parent)->iffeature_size;
3358 break;
3359 case ENUM_KEYWORD:
3360 iffeature = ((struct lys_type_enum *)ptr)->iffeature;
3361 size = ((struct lys_type_enum *)ptr)->iffeature_size;
3362 ptr_size = &((struct lys_type_enum *)ptr)->iffeature_size;
3363 break;
3364 case BIT_KEYWORD:
3365 iffeature = ((struct lys_type_bit *)ptr)->iffeature;
3366 size = ((struct lys_type_bit *)ptr)->iffeature_size;
3367 ptr_size = &((struct lys_type_bit *)ptr)->iffeature_size;
3368 break;
3369 case REFINE_KEYWORD:
3370 iffeature = ((struct lys_refine *)ptr)->iffeature;
3371 size = ((struct lys_refine *)ptr)->iffeature_size;
3372 ptr_size = &((struct lys_refine *)ptr)->iffeature_size;
3373 break;
3374 default:
3375 iffeature = ((struct lys_node *)parent)->iffeature;
3376 size = ((struct lys_node *)parent)->iffeature_size;
3377 ptr_size = &((struct lys_node *)parent)->iffeature_size;
3378 break;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003379 }
3380
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003381 *ptr_size = 0;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003382 for (i = 0; i < size; ++i) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003383 s = (char *)iffeature[i].features;
3384 iffeature[i].features = NULL;
3385 if (yang_fill_iffeature(module, &iffeature[i], parent, s, unres, parent_is_feature)) {
3386 *ptr_size = size;
3387 return EXIT_FAILURE;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003388 }
PavolVican8fa31242017-02-07 11:04:26 +01003389 if (yang_check_ext_instance(module, &iffeature[i].ext, iffeature[i].ext_size, &iffeature[i], unres)) {
3390 *ptr_size = size;
3391 return EXIT_FAILURE;
3392 }
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003393 (*ptr_size)++;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003394 }
3395
3396 return EXIT_SUCCESS;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003397}
3398
Pavol Vicanb60a1d12016-12-03 01:56:55 +01003399static int
3400yang_check_identityref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres)
3401{
3402 uint size, i;
3403 int rc;
3404 struct lys_ident **ref;
3405 const char *value;
3406 char *expr;
3407
3408 ref = type->info.ident.ref;
3409 size = type->info.ident.count;
3410 type->info.ident.count = 0;
3411 type->info.ident.ref = NULL;
3412 ((struct yang_type *)type->der)->flags |= LYS_NO_ERASE_IDENTITY;
3413
3414 for (i = 0; i < size; ++i) {
3415 expr = (char *)ref[i];
3416 /* store in the JSON format */
3417 value = transform_schema2json(module, expr);
3418 free(expr);
3419
3420 if (!value) {
3421 goto error;
3422 }
3423 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
3424 lydict_remove(module->ctx, value);
3425
3426 if (rc == -1) {
3427 goto error;
3428 }
3429 }
3430 free(ref);
3431
3432 return EXIT_SUCCESS;
3433error:
3434 for (i = i+1; i < size; ++i) {
3435 free(ref[i]);
3436 }
3437 free(ref);
3438 return EXIT_FAILURE;
3439}
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003440
Pavol Vican7313fc02016-11-14 01:10:31 +01003441int
PavolVican056fcd12017-02-07 15:36:53 +01003442yang_fill_type(struct lys_module *module, struct lys_type *type, struct yang_type *stype,
3443 void *parent, struct unres_schema *unres)
3444{
Radek Krejcidce5f972017-09-12 15:47:49 +02003445 unsigned int i;
PavolVican056fcd12017-02-07 15:36:53 +01003446
3447 type->parent = parent;
3448 if (yang_check_ext_instance(module, &type->ext, type->ext_size, type, unres)) {
3449 return EXIT_FAILURE;
3450 }
3451 switch (stype->base) {
3452 case LY_TYPE_ENUM:
3453 for (i = 0; i < type->info.enums.count; ++i) {
3454 if (yang_check_iffeatures(module, &type->info.enums.enm[i], parent, ENUM_KEYWORD, unres)) {
3455 return EXIT_FAILURE;
3456 }
3457 if (yang_check_ext_instance(module, &type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size,
3458 &type->info.enums.enm[i], unres)) {
3459 return EXIT_FAILURE;
3460 }
3461 }
3462 break;
3463 case LY_TYPE_BITS:
3464 for (i = 0; i < type->info.bits.count; ++i) {
3465 if (yang_check_iffeatures(module, &type->info.bits.bit[i], parent, BIT_KEYWORD, unres)) {
3466 return EXIT_FAILURE;
3467 }
3468 if (yang_check_ext_instance(module, &type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size,
3469 &type->info.bits.bit[i], unres)) {
3470 return EXIT_FAILURE;
3471 }
3472 }
3473 break;
3474 case LY_TYPE_IDENT:
3475 if (yang_check_identityref(module, type, unres)) {
3476 return EXIT_FAILURE;
3477 }
3478 break;
3479 case LY_TYPE_STRING:
3480 if (type->info.str.length && yang_check_ext_instance(module, &type->info.str.length->ext,
3481 type->info.str.length->ext_size, type->info.str.length, unres)) {
3482 return EXIT_FAILURE;
3483 }
3484 for (i = 0; i < type->info.str.pat_count; ++i) {
3485 if (yang_check_ext_instance(module, &type->info.str.patterns[i].ext, type->info.str.patterns[i].ext_size,
3486 &type->info.str.patterns[i], unres)) {
3487 return EXIT_FAILURE;
3488 }
3489 }
3490 break;
3491 case LY_TYPE_DEC64:
3492 if (type->info.dec64.range && yang_check_ext_instance(module, &type->info.dec64.range->ext,
3493 type->info.dec64.range->ext_size, type->info.dec64.range, unres)) {
3494 return EXIT_FAILURE;
3495 }
3496 break;
3497 case LY_TYPE_UNION:
3498 for (i = 0; i < type->info.uni.count; ++i) {
3499 if (yang_fill_type(module, &type->info.uni.types[i], (struct yang_type *)type->info.uni.types[i].der,
3500 parent, unres)) {
3501 return EXIT_FAILURE;
3502 }
3503 }
Radek Krejci57b41682017-03-07 12:33:24 +01003504 break;
PavolVican056fcd12017-02-07 15:36:53 +01003505 default:
3506 /* nothing checks */
3507 break;
3508 }
3509 return EXIT_SUCCESS;
3510}
3511
3512int
Pavol Vican7313fc02016-11-14 01:10:31 +01003513yang_check_typedef(struct lys_module *module, struct lys_node *parent, struct unres_schema *unres)
3514{
3515 struct lys_tpdf *tpdf;
Radek Krejcidaa547a2017-09-22 15:56:27 +02003516 uint8_t *ptr_tpdf_size = NULL;
Radek Krejcia2ac9262017-09-12 16:39:04 +02003517 uint16_t i, tpdf_size, *ptr_tpdf_size16 = NULL;
Pavol Vican7313fc02016-11-14 01:10:31 +01003518
3519 if (!parent) {
3520 tpdf = module->tpdf;
Radek Krejcia2ac9262017-09-12 16:39:04 +02003521 //ptr_tpdf_size = &module->tpdf_size;
3522 ptr_tpdf_size16 = &module->tpdf_size;
Pavol Vican05810b62016-11-23 14:07:22 +01003523 } else {
3524 switch (parent->nodetype) {
3525 case LYS_GROUPING:
3526 tpdf = ((struct lys_node_grp *)parent)->tpdf;
Radek Krejcia2ac9262017-09-12 16:39:04 +02003527 ptr_tpdf_size16 = &((struct lys_node_grp *)parent)->tpdf_size;
Pavol Vican05810b62016-11-23 14:07:22 +01003528 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003529 case LYS_CONTAINER:
3530 tpdf = ((struct lys_node_container *)parent)->tpdf;
Radek Krejcia2ac9262017-09-12 16:39:04 +02003531 ptr_tpdf_size16 = &((struct lys_node_container *)parent)->tpdf_size;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003532 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003533 case LYS_LIST:
3534 tpdf = ((struct lys_node_list *)parent)->tpdf;
3535 ptr_tpdf_size = &((struct lys_node_list *)parent)->tpdf_size;
3536 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003537 case LYS_RPC:
3538 case LYS_ACTION:
3539 tpdf = ((struct lys_node_rpc_action *)parent)->tpdf;
Radek Krejcia2ac9262017-09-12 16:39:04 +02003540 ptr_tpdf_size16 = &((struct lys_node_rpc_action *)parent)->tpdf_size;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003541 break;
Pavol Vican78729392016-11-28 17:18:22 +01003542 case LYS_INPUT:
3543 case LYS_OUTPUT:
3544 tpdf = ((struct lys_node_inout *)parent)->tpdf;
Radek Krejcia2ac9262017-09-12 16:39:04 +02003545 ptr_tpdf_size16 = &((struct lys_node_inout *)parent)->tpdf_size;
Pavol Vican78729392016-11-28 17:18:22 +01003546 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01003547 case LYS_NOTIF:
3548 tpdf = ((struct lys_node_notif *)parent)->tpdf;
Radek Krejcia2ac9262017-09-12 16:39:04 +02003549 ptr_tpdf_size16 = &((struct lys_node_notif *)parent)->tpdf_size;
Pavol Vican29bf8802016-11-28 20:44:57 +01003550 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003551 default:
3552 LOGINT;
3553 return EXIT_FAILURE;
3554 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003555 }
3556
Radek Krejcia2ac9262017-09-12 16:39:04 +02003557 if (ptr_tpdf_size16) {
3558 tpdf_size = *ptr_tpdf_size16;
3559 *ptr_tpdf_size16 = 0;
3560 } else {
3561 tpdf_size = *ptr_tpdf_size;
3562 *ptr_tpdf_size = 0;
3563 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003564
3565 for (i = 0; i < tpdf_size; ++i) {
Pavol Vicanfda8c802016-12-03 02:00:42 +01003566 if (lyp_check_identifier(tpdf[i].name, LY_IDENT_TYPE, module, parent)) {
3567 goto error;
3568 }
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003569
PavolVican056fcd12017-02-07 15:36:53 +01003570 if (yang_fill_type(module, &tpdf[i].type, (struct yang_type *)tpdf[i].type.der, &tpdf[i], unres)) {
3571 goto error;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003572 }
PavolVicandf9e7972017-02-07 11:41:38 +01003573 if (yang_check_ext_instance(module, &tpdf[i].ext, tpdf[i].ext_size, &tpdf[i], unres)) {
3574 goto error;
3575 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003576 if (unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003577 goto error;
Pavol Vican7313fc02016-11-14 01:10:31 +01003578 }
3579
Radek Krejcia2ac9262017-09-12 16:39:04 +02003580 if (ptr_tpdf_size16) {
3581 (*ptr_tpdf_size16)++;
3582 } else {
3583 (*ptr_tpdf_size)++;
3584 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003585 /* check default value*/
Michal Vasko15a43372017-09-25 14:12:42 +02003586 if (!(module->ctx->models.flags & LY_CTX_TRUSTED)
3587 && unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf[i].dflt)) == -1) {
Pavol Vican7313fc02016-11-14 01:10:31 +01003588 ++i;
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003589 goto error;
Pavol Vican7313fc02016-11-14 01:10:31 +01003590 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003591 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003592
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003593 return EXIT_SUCCESS;
3594
3595error:
3596 yang_tpdf_free(module->ctx, tpdf, i, tpdf_size);
3597 return EXIT_FAILURE;
Pavol Vican7313fc02016-11-14 01:10:31 +01003598}
3599
3600static int
Pavol Vican36e27272016-11-22 15:47:28 +01003601yang_check_identities(struct lys_module *module, struct unres_schema *unres)
3602{
3603 uint32_t i, size, base_size;
3604 uint8_t j;
3605
3606 size = module->ident_size;
3607 module->ident_size = 0;
3608 for (i = 0; i < size; ++i) {
3609 base_size = module->ident[i].base_size;
3610 module->ident[i].base_size = 0;
3611 for (j = 0; j < base_size; ++j) {
3612 if (yang_read_base(module, &module->ident[i], (char *)module->ident[i].base[j], unres)) {
3613 ++j;
3614 module->ident_size = size;
3615 goto error;
3616 }
3617 }
3618 module->ident_size++;
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003619 if (yang_check_iffeatures(module, NULL, &module->ident[i], IDENTITY_KEYWORD, unres)) {
3620 goto error;
3621 }
PavolVican8fa31242017-02-07 11:04:26 +01003622 if (yang_check_ext_instance(module, &module->ident[i].ext, module->ident[i].ext_size, &module->ident[i], unres)) {
3623 goto error;
3624 }
Pavol Vican36e27272016-11-22 15:47:28 +01003625 }
3626
PavolVican8fa31242017-02-07 11:04:26 +01003627
Pavol Vican36e27272016-11-22 15:47:28 +01003628 return EXIT_SUCCESS;
3629
3630error:
3631 for (; j< module->ident[i].base_size; ++j) {
3632 free(module->ident[i].base[j]);
3633 }
3634 yang_free_ident_base(module->ident, i + 1, size);
3635 return EXIT_FAILURE;
3636}
3637
3638static int
PavolVican38104a32017-02-08 12:25:23 +01003639yang_check_must(struct lys_module *module, struct lys_restr *must, uint size, struct unres_schema *unres)
3640{
3641 uint i;
3642
3643 for (i = 0; i < size; ++i) {
3644 if (yang_check_ext_instance(module, &must[i].ext, must[i].ext_size, &must[i], unres)) {
3645 return EXIT_FAILURE;
3646 }
3647 }
3648 return EXIT_SUCCESS;
3649}
3650
3651static int
PavolVicane87cb932016-12-30 15:36:18 +01003652yang_check_container(struct lys_module *module, struct lys_node_container *cont, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003653 int options, struct unres_schema *unres)
Pavol Vican05810b62016-11-23 14:07:22 +01003654{
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003655 if (yang_check_typedef(module, (struct lys_node *)cont, unres)) {
Pavol Vican05810b62016-11-23 14:07:22 +01003656 goto error;
3657 }
3658
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003659 if (yang_check_iffeatures(module, NULL, cont, CONTAINER_KEYWORD, unres)) {
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003660 goto error;
3661 }
3662
Radek Krejci7212e0a2017-03-08 15:58:22 +01003663 if (yang_check_nodes(module, (struct lys_node *)cont, *child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003664 *child = NULL;
3665 goto error;
3666 }
3667 *child = NULL;
3668
PavolVican59ba4602017-02-08 11:53:32 +01003669 if (cont->when && yang_check_ext_instance(module, &cont->when->ext, cont->when->ext_size, cont->when, unres)) {
3670 goto error;
3671 }
PavolVican38104a32017-02-08 12:25:23 +01003672 if (yang_check_must(module, cont->must, cont->must_size, unres)) {
3673 goto error;
3674 }
3675
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003676 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02003677 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && (cont->when || cont->must_size)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003678 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003679 if (lyxp_node_check_syntax((struct lys_node *)cont)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003680 goto error;
3681 }
3682 } else {
3683 if (unres_schema_add_node(module, unres, cont, UNRES_XPATH, NULL) == -1) {
3684 goto error;
3685 }
3686 }
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003687 }
3688
3689 return EXIT_SUCCESS;
3690error:
3691 return EXIT_FAILURE;
3692}
3693
3694static int
Radek Krejci7212e0a2017-03-08 15:58:22 +01003695yang_check_leaf(struct lys_module *module, struct lys_node_leaf *leaf, int options, struct unres_schema *unres)
Pavol Vicana69aff22016-11-24 18:23:50 +01003696{
PavolVican056fcd12017-02-07 15:36:53 +01003697 if (yang_fill_type(module, &leaf->type, (struct yang_type *)leaf->type.der, leaf, unres)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003698 yang_type_free(module->ctx, &leaf->type);
3699 goto error;
Pavol Vicana69aff22016-11-24 18:23:50 +01003700 }
PavolVicana08d3652016-12-29 21:07:47 +01003701 if (yang_check_iffeatures(module, NULL, leaf, LEAF_KEYWORD, unres)) {
3702 yang_type_free(module->ctx, &leaf->type);
3703 goto error;
3704 }
3705
Pavol Vicanfda8c802016-12-03 02:00:42 +01003706 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, (struct lys_node *)leaf) == -1) {
Pavol Vicana69aff22016-11-24 18:23:50 +01003707 yang_type_free(module->ctx, &leaf->type);
3708 goto error;
3709 }
3710
Michal Vasko15a43372017-09-25 14:12:42 +02003711 if (!(options & LYS_PARSE_OPT_INGRP) && !(module->ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01003712 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)&leaf->dflt) == -1)) {
Pavol Vicana69aff22016-11-24 18:23:50 +01003713 goto error;
3714 }
3715
PavolVican59ba4602017-02-08 11:53:32 +01003716 if (leaf->when && yang_check_ext_instance(module, &leaf->when->ext, leaf->when->ext_size, leaf->when, unres)) {
3717 goto error;
3718 }
PavolVican38104a32017-02-08 12:25:23 +01003719 if (yang_check_must(module, leaf->must, leaf->must_size, unres)) {
3720 goto error;
3721 }
Michal Vasko89afc112017-03-16 13:57:28 +01003722
Pavol Vicana69aff22016-11-24 18:23:50 +01003723 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02003724 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && (leaf->when || leaf->must_size)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003725 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003726 if (lyxp_node_check_syntax((struct lys_node *)leaf)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003727 goto error;
3728 }
3729 } else {
3730 if (unres_schema_add_node(module, unres, leaf, UNRES_XPATH, NULL) == -1) {
3731 goto error;
3732 }
3733 }
Pavol Vicana69aff22016-11-24 18:23:50 +01003734 }
3735
3736 return EXIT_SUCCESS;
3737error:
3738 return EXIT_FAILURE;
3739}
3740
3741static int
Radek Krejci7212e0a2017-03-08 15:58:22 +01003742yang_check_leaflist(struct lys_module *module, struct lys_node_leaflist *leaflist, int options,
3743 struct unres_schema *unres)
Pavol Vican36aff862016-11-26 17:07:05 +01003744{
Pavol Vicanfda8c802016-12-03 02:00:42 +01003745 int i, j;
Pavol Vican36aff862016-11-26 17:07:05 +01003746
PavolVican056fcd12017-02-07 15:36:53 +01003747 if (yang_fill_type(module, &leaflist->type, (struct yang_type *)leaflist->type.der, leaflist, unres)) {
PavolVican6a2148f2017-02-07 23:09:55 +01003748 yang_type_free(module->ctx, &leaflist->type);
3749 goto error;
Pavol Vican36aff862016-11-26 17:07:05 +01003750 }
PavolVicana08d3652016-12-29 21:07:47 +01003751 if (yang_check_iffeatures(module, NULL, leaflist, LEAF_LIST_KEYWORD, unres)) {
3752 yang_type_free(module->ctx, &leaflist->type);
3753 goto error;
3754 }
3755
Pavol Vicanfda8c802016-12-03 02:00:42 +01003756 if (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DER, (struct lys_node *)leaflist) == -1) {
Pavol Vican36aff862016-11-26 17:07:05 +01003757 yang_type_free(module->ctx, &leaflist->type);
3758 goto error;
3759 }
3760
Pavol Vican36aff862016-11-26 17:07:05 +01003761 for (i = 0; i < leaflist->dflt_size; ++i) {
Pavol Vicanfda8c802016-12-03 02:00:42 +01003762 /* check for duplicity in case of configuration data,
3763 * in case of status data duplicities are allowed */
3764 if (leaflist->flags & LYS_CONFIG_W) {
3765 for (j = i +1; j < leaflist->dflt_size; ++j) {
3766 if (ly_strequal(leaflist->dflt[i], leaflist->dflt[j], 1)) {
PavolVican196694c2017-01-27 10:33:09 +01003767 LOGVAL(LYE_INARG, LY_VLOG_LYS, leaflist, leaflist->dflt[i], "default");
3768 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leaflist, "Duplicated default value \"%s\".", leaflist->dflt[i]);
Pavol Vicanfda8c802016-12-03 02:00:42 +01003769 goto error;
3770 }
3771 }
3772 }
3773 /* check default value (if not defined, there still could be some restrictions
3774 * that need to be checked against a default value from a derived type) */
Michal Vasko15a43372017-09-25 14:12:42 +02003775 if (!(options & LYS_PARSE_OPT_INGRP) && !(module->ctx->models.flags & LY_CTX_TRUSTED) &&
Radek Krejciab08f0f2017-03-09 16:37:15 +01003776 (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DFLT,
3777 (struct lys_node *)(&leaflist->dflt[i])) == -1)) {
Pavol Vican36aff862016-11-26 17:07:05 +01003778 goto error;
3779 }
3780 }
3781
PavolVican59ba4602017-02-08 11:53:32 +01003782 if (leaflist->when && yang_check_ext_instance(module, &leaflist->when->ext, leaflist->when->ext_size, leaflist->when, unres)) {
3783 goto error;
3784 }
PavolVican38104a32017-02-08 12:25:23 +01003785 if (yang_check_must(module, leaflist->must, leaflist->must_size, unres)) {
3786 goto error;
3787 }
PavolVican59ba4602017-02-08 11:53:32 +01003788
Pavol Vican36aff862016-11-26 17:07:05 +01003789 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02003790 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && (leaflist->when || leaflist->must_size)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003791 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003792 if (lyxp_node_check_syntax((struct lys_node *)leaflist)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003793 goto error;
3794 }
3795 } else {
3796 if (unres_schema_add_node(module, unres, leaflist, UNRES_XPATH, NULL) == -1) {
3797 goto error;
3798 }
3799 }
Pavol Vican36aff862016-11-26 17:07:05 +01003800 }
3801
3802 return EXIT_SUCCESS;
3803error:
3804 return EXIT_FAILURE;
3805}
3806
3807static int
PavolVicane87cb932016-12-30 15:36:18 +01003808yang_check_list(struct lys_module *module, struct lys_node_list *list, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003809 int options, struct unres_schema *unres)
Pavol Vicand8136a42016-11-27 13:28:04 +01003810{
Pavol Vicanfda8c802016-12-03 02:00:42 +01003811 struct lys_node *node;
3812
Pavol Vicand8136a42016-11-27 13:28:04 +01003813 if (yang_check_typedef(module, (struct lys_node *)list, unres)) {
3814 goto error;
3815 }
3816
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003817 if (yang_check_iffeatures(module, NULL, list, LIST_KEYWORD, unres)) {
3818 goto error;
Pavol Vicand8136a42016-11-27 13:28:04 +01003819 }
3820
Pavol Vicanfda8c802016-12-03 02:00:42 +01003821 if (list->flags & LYS_CONFIG_R) {
3822 /* RFC 6020, 7.7.5 - ignore ordering when the list represents state data
3823 * ignore oredering MASK - 0x7F
3824 */
3825 list->flags &= 0x7F;
3826 }
3827 /* check - if list is configuration, key statement is mandatory
3828 * (but only if we are not in a grouping or augment, then the check is deferred) */
PavolVicanc68dfea2017-02-21 15:40:43 +01003829 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 +01003830 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys) {
3831 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, list, "key", "list");
3832 goto error;
3833 }
3834
Radek Krejci7212e0a2017-03-08 15:58:22 +01003835 if (yang_check_nodes(module, (struct lys_node *)list, *child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003836 *child = NULL;
3837 goto error;
3838 }
3839 *child = NULL;
3840
Pavol Vicand8136a42016-11-27 13:28:04 +01003841 if (list->keys && yang_read_key(module, list, unres)) {
3842 goto error;
3843 }
3844
3845 if (yang_read_unique(module, list, unres)) {
3846 goto error;
3847 }
3848
PavolVican59ba4602017-02-08 11:53:32 +01003849 if (list->when && yang_check_ext_instance(module, &list->when->ext, list->when->ext_size, list->when, unres)) {
3850 goto error;
3851 }
PavolVican38104a32017-02-08 12:25:23 +01003852 if (yang_check_must(module, list->must, list->must_size, unres)) {
3853 goto error;
3854 }
Michal Vasko89afc112017-03-16 13:57:28 +01003855
Pavol Vicand8136a42016-11-27 13:28:04 +01003856 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02003857 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && (list->when || list->must_size)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003858 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003859 if (lyxp_node_check_syntax((struct lys_node *)list)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003860 goto error;
3861 }
3862 } else {
3863 if (unres_schema_add_node(module, unres, list, UNRES_XPATH, NULL) == -1) {
3864 goto error;
3865 }
3866 }
Pavol Vicand8136a42016-11-27 13:28:04 +01003867 }
3868
3869 return EXIT_SUCCESS;
3870error:
3871 return EXIT_FAILURE;
3872}
3873
3874static int
PavolVicane87cb932016-12-30 15:36:18 +01003875yang_check_choice(struct lys_module *module, struct lys_node_choice *choice, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003876 int options, struct unres_schema *unres)
Pavol Vican36ace102016-11-28 11:46:59 +01003877{
3878 char *value;
Pavol Vican36ace102016-11-28 11:46:59 +01003879
PavolVicana08d3652016-12-29 21:07:47 +01003880 if (yang_check_iffeatures(module, NULL, choice, CHOICE_KEYWORD, unres)) {
3881 free(choice->dflt);
3882 choice->dflt = NULL;
3883 goto error;
3884 }
3885
Radek Krejci7212e0a2017-03-08 15:58:22 +01003886 if (yang_check_nodes(module, (struct lys_node *)choice, *child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003887 *child = NULL;
3888 free(choice->dflt);
3889 choice->dflt = NULL;
3890 goto error;
3891 }
3892 *child = NULL;
3893
Pavol Vican36ace102016-11-28 11:46:59 +01003894 if (choice->dflt) {
3895 value = (char *)choice->dflt;
3896 choice->dflt = NULL;
3897 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
3898 free(value);
3899 goto error;
3900 }
3901 free(value);
3902 }
3903
PavolVican59ba4602017-02-08 11:53:32 +01003904 if (choice->when && yang_check_ext_instance(module, &choice->when->ext, choice->when->ext_size, choice->when, unres)) {
3905 goto error;
3906 }
3907
Pavol Vican36ace102016-11-28 11:46:59 +01003908 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02003909 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && choice->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01003910 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003911 if (lyxp_node_check_syntax((struct lys_node *)choice)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003912 goto error;
3913 }
3914 } else {
3915 if (unres_schema_add_node(module, unres, choice, UNRES_XPATH, NULL) == -1) {
3916 goto error;
3917 }
3918 }
Pavol Vican36ace102016-11-28 11:46:59 +01003919 }
3920
3921 return EXIT_SUCCESS;
3922error:
3923 return EXIT_FAILURE;
3924}
3925
3926static int
PavolVicane87cb932016-12-30 15:36:18 +01003927yang_check_rpc_action(struct lys_module *module, struct lys_node_rpc_action *rpc, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003928 int options, struct unres_schema *unres)
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003929{
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003930 struct lys_node *node;
3931
3932 if (rpc->nodetype == LYS_ACTION) {
3933 for (node = rpc->parent; node; node = lys_parent(node)) {
3934 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Pavol Vican73ff8032016-12-04 15:03:51 +01003935 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys)) {
PavolVican196694c2017-01-27 10:33:09 +01003936 LOGVAL(LYE_INPAR, LY_VLOG_LYS, rpc->parent, strnodetype(node->nodetype), "action");
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003937 goto error;
3938 }
3939 }
3940 }
3941 if (yang_check_typedef(module, (struct lys_node *)rpc, unres)) {
3942 goto error;
3943 }
3944
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003945 if (yang_check_iffeatures(module, NULL, rpc, RPC_KEYWORD, unres)) {
3946 goto error;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003947 }
3948
Radek Krejci7212e0a2017-03-08 15:58:22 +01003949 if (yang_check_nodes(module, (struct lys_node *)rpc, *child, options | LYS_PARSE_OPT_CFG_IGNORE, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003950 *child = NULL;
3951 goto error;
3952 }
3953 *child = NULL;
3954
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003955 return EXIT_SUCCESS;
3956error:
3957 return EXIT_FAILURE;
3958}
3959
3960static int
PavolVicane87cb932016-12-30 15:36:18 +01003961yang_check_notif(struct lys_module *module, struct lys_node_notif *notif, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003962 int options, struct unres_schema *unres)
Pavol Vican29bf8802016-11-28 20:44:57 +01003963{
Pavol Vican29bf8802016-11-28 20:44:57 +01003964 if (yang_check_typedef(module, (struct lys_node *)notif, unres)) {
3965 goto error;
3966 }
3967
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003968 if (yang_check_iffeatures(module, NULL, notif, NOTIFICATION_KEYWORD, unres)) {
3969 goto error;
Pavol Vican29bf8802016-11-28 20:44:57 +01003970 }
3971
Radek Krejci7212e0a2017-03-08 15:58:22 +01003972 if (yang_check_nodes(module, (struct lys_node *)notif, *child, options | LYS_PARSE_OPT_CFG_IGNORE, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003973 *child = NULL;
3974 goto error;
3975 }
3976 *child = NULL;
3977
Michal Vasko89afc112017-03-16 13:57:28 +01003978 if (yang_check_must(module, notif->must, notif->must_size, unres)) {
3979 goto error;
3980 }
3981
3982 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02003983 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && notif->must_size) {
Michal Vasko89afc112017-03-16 13:57:28 +01003984 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003985 if (lyxp_node_check_syntax((struct lys_node *)notif)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003986 goto error;
3987 }
3988 } else {
3989 if (unres_schema_add_node(module, unres, notif, UNRES_XPATH, NULL) == -1) {
3990 goto error;
3991 }
PavolVican38104a32017-02-08 12:25:23 +01003992 }
Pavol Vican29bf8802016-11-28 20:44:57 +01003993 }
3994
3995 return EXIT_SUCCESS;
3996error:
3997 return EXIT_FAILURE;
3998}
3999
4000static int
Radek Krejci7212e0a2017-03-08 15:58:22 +01004001yang_check_augment(struct lys_module *module, struct lys_node_augment *augment, int options, struct unres_schema *unres)
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004002{
Pavol Vican3ad50f82016-12-04 15:00:36 +01004003 struct lys_node *child;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004004
Pavol Vican3ad50f82016-12-04 15:00:36 +01004005 child = augment->child;
4006 augment->child = NULL;
4007
PavolVicana08d3652016-12-29 21:07:47 +01004008 if (yang_check_iffeatures(module, NULL, augment, AUGMENT_KEYWORD, unres)) {
4009 yang_free_nodes(module->ctx, child);
Pavol Vican3ad50f82016-12-04 15:00:36 +01004010 goto error;
4011 }
4012
Radek Krejci7212e0a2017-03-08 15:58:22 +01004013 if (yang_check_nodes(module, (struct lys_node *)augment, child, options, unres)) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01004014 goto error;
4015 }
4016
PavolVicanfa9510e2017-02-08 17:20:46 +01004017 if (yang_check_ext_instance(module, &augment->ext, augment->ext_size, augment, unres)) {
4018 goto error;
4019 }
4020
PavolVican59ba4602017-02-08 11:53:32 +01004021 if (augment->when && yang_check_ext_instance(module, &augment->when->ext, augment->when->ext_size, augment->when, unres)) {
4022 goto error;
4023 }
4024
Pavol Vican3ad50f82016-12-04 15:00:36 +01004025 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02004026 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && augment->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004027 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004028 if (lyxp_node_check_syntax((struct lys_node *)augment)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004029 goto error;
4030 }
4031 } else {
4032 if (unres_schema_add_node(module, unres, augment, UNRES_XPATH, NULL) == -1) {
4033 goto error;
4034 }
4035 }
Pavol Vican3ad50f82016-12-04 15:00:36 +01004036 }
4037
4038 return EXIT_SUCCESS;
4039error:
4040 return EXIT_FAILURE;
4041}
4042
4043static int
Radek Krejci7212e0a2017-03-08 15:58:22 +01004044yang_check_uses(struct lys_module *module, struct lys_node_uses *uses, int options, struct unres_schema *unres)
Pavol Vican3ad50f82016-12-04 15:00:36 +01004045{
4046 uint i, size;
4047
4048 size = uses->augment_size;
4049 uses->augment_size = 0;
4050
4051 if (yang_check_iffeatures(module, NULL, uses, USES_KEYWORD, unres)) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004052 goto error;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004053 }
4054
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004055 for (i = 0; i < uses->refine_size; ++i) {
PavolVican77374ee2017-02-08 15:18:45 +01004056 if (yang_check_iffeatures(module, &uses->refine[i], uses, REFINE_KEYWORD, unres)) {
4057 goto error;
4058 }
4059 if (yang_check_must(module, uses->refine[i].must, uses->refine[i].must_size, unres)) {
4060 goto error;
4061 }
4062 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 +01004063 goto error;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004064 }
4065 }
4066
Pavol Vican3ad50f82016-12-04 15:00:36 +01004067 for (i = 0; i < size; ++i) {
4068 uses->augment_size++;
Radek Krejci7212e0a2017-03-08 15:58:22 +01004069 if (yang_check_augment(module, &uses->augment[i], options, unres)) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01004070 goto error;
4071 }
4072 }
4073
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004074 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
4075 goto error;
4076 }
4077
PavolVican59ba4602017-02-08 11:53:32 +01004078 if (uses->when && yang_check_ext_instance(module, &uses->when->ext, uses->when->ext_size, uses->when, unres)) {
4079 goto error;
4080 }
4081
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004082 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02004083 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && uses->when) {
Michal Vasko89afc112017-03-16 13:57:28 +01004084 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004085 if (lyxp_node_check_syntax((struct lys_node *)uses)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004086 goto error;
4087 }
4088 } else {
4089 if (unres_schema_add_node(module, unres, uses, UNRES_XPATH, NULL) == -1) {
4090 goto error;
4091 }
4092 }
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004093 }
4094
4095 return EXIT_SUCCESS;
4096error:
Pavol Vican3ad50f82016-12-04 15:00:36 +01004097 for (i = uses->augment_size; i < size; ++i) {
4098 yang_free_augment(module->ctx, &uses->augment[i]);
4099 }
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004100 return EXIT_FAILURE;
4101}
4102
4103static int
PavolVican59ba4602017-02-08 11:53:32 +01004104yang_check_anydata(struct lys_module *module, struct lys_node_anydata *anydata, struct lys_node **child,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004105 int options, struct unres_schema *unres)
PavolVican59ba4602017-02-08 11:53:32 +01004106{
4107 if (yang_check_iffeatures(module, NULL, anydata, ANYDATA_KEYWORD, unres)) {
4108 goto error;
4109 }
4110
Radek Krejci7212e0a2017-03-08 15:58:22 +01004111 if (yang_check_nodes(module, (struct lys_node *)anydata, *child, options, unres)) {
PavolVican59ba4602017-02-08 11:53:32 +01004112 *child = NULL;
4113 goto error;
4114 }
4115 *child = NULL;
4116
4117 if (anydata->when && yang_check_ext_instance(module, &anydata->when->ext, anydata->when->ext_size, anydata->when, unres)) {
4118 goto error;
4119 }
PavolVican38104a32017-02-08 12:25:23 +01004120 if (yang_check_must(module, anydata->must, anydata->must_size, unres)) {
4121 goto error;
4122 }
PavolVican59ba4602017-02-08 11:53:32 +01004123
4124 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02004125 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && (anydata->when || anydata->must_size)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004126 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004127 if (lyxp_node_check_syntax((struct lys_node *)anydata)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004128 goto error;
4129 }
4130 } else {
4131 if (unres_schema_add_node(module, unres, anydata, UNRES_XPATH, NULL) == -1) {
4132 goto error;
4133 }
4134 }
PavolVican59ba4602017-02-08 11:53:32 +01004135 }
Michal Vasko89afc112017-03-16 13:57:28 +01004136
PavolVican59ba4602017-02-08 11:53:32 +01004137 return EXIT_SUCCESS;
4138error:
4139 return EXIT_FAILURE;
4140}
4141
4142static int
Pavol Vican3ad50f82016-12-04 15:00:36 +01004143yang_check_nodes(struct lys_module *module, struct lys_node *parent, struct lys_node *nodes,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004144 int options, struct unres_schema *unres)
Pavol Vican05810b62016-11-23 14:07:22 +01004145{
Pavol Vican3ad50f82016-12-04 15:00:36 +01004146 struct lys_node *node = nodes, *sibling, *child;
Pavol Vican05810b62016-11-23 14:07:22 +01004147
4148 while (node) {
4149 sibling = node->next;
4150 child = node->child;
4151 node->next = NULL;
4152 node->child = NULL;
PavolVicanbd1d1ae2017-07-20 00:06:00 +02004153 node->parent = NULL;
Pavol Vican05810b62016-11-23 14:07:22 +01004154 node->prev = node;
4155
PavolVican05c4f9b2017-09-07 13:33:54 +02004156 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node) ||
4157 check_status_flag(node, parent)) {
Pavol Vican24ba7f62016-11-28 12:15:20 +01004158 lys_node_unlink(node);
PavolVican4b80d042017-02-23 14:30:27 +01004159 yang_free_nodes(module->ctx, node);
Pavol Vican05810b62016-11-23 14:07:22 +01004160 goto error;
4161 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004162 store_config_flag(node, options);
PavolVican70ce7452017-02-01 15:39:39 +01004163 if (yang_check_ext_instance(module, &node->ext, node->ext_size, node, unres)) {
4164 goto error;
4165 }
Pavol Vicanfda8c802016-12-03 02:00:42 +01004166
Pavol Vican05810b62016-11-23 14:07:22 +01004167 switch (node->nodetype) {
4168 case LYS_GROUPING:
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004169 if (yang_check_typedef(module, node, unres)) {
4170 goto error;
4171 }
4172 if (yang_check_iffeatures(module, NULL, node, GROUPING_KEYWORD, unres)) {
Pavol Vican05810b62016-11-23 14:07:22 +01004173 goto error;
4174 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004175 if (yang_check_nodes(module, node, child, options | LYS_PARSE_OPT_INGRP, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004176 child = NULL;
4177 goto error;
4178 }
Pavol Vican05810b62016-11-23 14:07:22 +01004179 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01004180 case LYS_CONTAINER:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004181 if (yang_check_container(module, (struct lys_node_container *)node, &child, options, unres)) {
Pavol Vicanc54a8f72016-11-23 16:45:55 +01004182 goto error;
4183 }
4184 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01004185 case LYS_LEAF:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004186 if (yang_check_leaf(module, (struct lys_node_leaf *)node, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004187 child = NULL;
Pavol Vicana69aff22016-11-24 18:23:50 +01004188 goto error;
4189 }
4190 break;
Pavol Vican36aff862016-11-26 17:07:05 +01004191 case LYS_LEAFLIST:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004192 if (yang_check_leaflist(module, (struct lys_node_leaflist *)node, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004193 child = NULL;
Pavol Vican36aff862016-11-26 17:07:05 +01004194 goto error;
4195 }
4196 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01004197 case LYS_LIST:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004198 if (yang_check_list(module, (struct lys_node_list *)node, &child, options, unres)) {
Pavol Vicand8136a42016-11-27 13:28:04 +01004199 goto error;
4200 }
4201 break;
Pavol Vican36ace102016-11-28 11:46:59 +01004202 case LYS_CHOICE:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004203 if (yang_check_choice(module, (struct lys_node_choice *)node, &child, options, unres)) {
Pavol Vican36ace102016-11-28 11:46:59 +01004204 goto error;
4205 }
4206 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01004207 case LYS_CASE:
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004208 if (yang_check_iffeatures(module, NULL, node, CASE_KEYWORD, unres)) {
Pavol Vicana420bac2016-11-28 14:51:54 +01004209 goto error;
4210 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004211 if (yang_check_nodes(module, node, child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004212 child = NULL;
4213 goto error;
4214 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004215 if (((struct lys_node_case *)node)->when) {
4216 if (yang_check_ext_instance(module, &((struct lys_node_case *)node)->when->ext,
4217 ((struct lys_node_case *)node)->when->ext_size, ((struct lys_node_case *)node)->when, unres)) {
4218 goto error;
4219 }
4220 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02004221 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && (options & LYS_PARSE_OPT_INGRP)) {
Michal Vasko364918a2017-03-17 13:23:46 +01004222 if (lyxp_node_check_syntax(node)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004223 goto error;
4224 }
4225 } else {
4226 if (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1) {
4227 goto error;
4228 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004229 }
4230 }
Pavol Vicana420bac2016-11-28 14:51:54 +01004231 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01004232 case LYS_ANYDATA:
4233 case LYS_ANYXML:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004234 if (yang_check_anydata(module, (struct lys_node_anydata *)node, &child, options, unres)) {
Pavol Vicanbfa1a582016-11-28 15:35:59 +01004235 goto error;
4236 }
4237 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01004238 case LYS_RPC:
4239 case LYS_ACTION:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004240 if (yang_check_rpc_action(module, (struct lys_node_rpc_action *)node, &child, options, unres)){
Pavol Vicanebc9ef82016-11-28 16:46:49 +01004241 goto error;
4242 }
4243 break;
Pavol Vican78729392016-11-28 17:18:22 +01004244 case LYS_INPUT:
4245 case LYS_OUTPUT:
PavolVicane87cb932016-12-30 15:36:18 +01004246 if (yang_check_typedef(module, node, unres)) {
4247 goto error;
4248 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01004249 if (yang_check_nodes(module, node, child, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004250 child = NULL;
4251 goto error;
4252 }
PavolVican38104a32017-02-08 12:25:23 +01004253 if (((struct lys_node_inout *)node)->must_size) {
4254 if (yang_check_must(module, ((struct lys_node_inout *)node)->must, ((struct lys_node_inout *)node)->must_size, unres)) {
4255 goto error;
4256 }
4257 /* check XPath dependencies */
Michal Vasko15a43372017-09-25 14:12:42 +02004258 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && (options & LYS_PARSE_OPT_INGRP)) {
Michal Vasko364918a2017-03-17 13:23:46 +01004259 if (lyxp_node_check_syntax(node)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004260 goto error;
4261 }
4262 } else {
4263 if (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1) {
4264 goto error;
4265 }
PavolVican38104a32017-02-08 12:25:23 +01004266 }
Pavol Vican78729392016-11-28 17:18:22 +01004267 }
Pavol Vican78729392016-11-28 17:18:22 +01004268 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01004269 case LYS_NOTIF:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004270 if (yang_check_notif(module, (struct lys_node_notif *)node, &child, options, unres)) {
Pavol Vican29bf8802016-11-28 20:44:57 +01004271 goto error;
4272 }
4273 break;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004274 case LYS_USES:
Radek Krejci7212e0a2017-03-08 15:58:22 +01004275 if (yang_check_uses(module, (struct lys_node_uses *)node, options, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01004276 child = NULL;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01004277 goto error;
4278 }
4279 break;
Pavol Vican05810b62016-11-23 14:07:22 +01004280 default:
4281 LOGINT;
Pavol Vican05810b62016-11-23 14:07:22 +01004282 goto error;
4283 }
Pavol Vican05810b62016-11-23 14:07:22 +01004284 node = sibling;
4285 }
4286
4287 return EXIT_SUCCESS;
4288error:
4289 yang_free_nodes(module->ctx, sibling);
4290 yang_free_nodes(module->ctx, child);
4291 return EXIT_FAILURE;
4292}
4293
4294static int
PavolVican75af21d2016-12-29 20:04:07 +01004295yang_check_deviate(struct lys_module *module, struct unres_schema *unres, struct lys_deviate *deviate,
4296 struct lys_node *dev_target, struct ly_set *dflt_check)
4297{
4298 struct lys_node_leaflist *llist;
4299 struct lys_type *type;
4300 struct lys_tpdf *tmp_parent;
4301 int i, j;
4302
PavolVican6f000922017-02-10 12:56:59 +01004303 if (yang_check_ext_instance(module, &deviate->ext, deviate->ext_size, deviate, unres)) {
4304 goto error;
4305 }
PavolVican75af21d2016-12-29 20:04:07 +01004306 if (deviate->must_size && yang_check_deviate_must(module, unres, deviate, dev_target)) {
4307 goto error;
4308 }
4309 if (deviate->unique && yang_check_deviate_unique(module, deviate, dev_target)) {
4310 goto error;
4311 }
4312 if (deviate->dflt_size) {
4313 if (yang_read_deviate_default(module, deviate, dev_target, dflt_check)) {
4314 goto error;
4315 }
4316 if (dev_target->nodetype == LYS_LEAFLIST && deviate->mod == LY_DEVIATE_DEL) {
4317 /* consolidate the final list in the target after removing items from it */
4318 llist = (struct lys_node_leaflist *)dev_target;
4319 for (i = j = 0; j < llist->dflt_size; j++) {
4320 llist->dflt[i] = llist->dflt[j];
4321 if (llist->dflt[i]) {
4322 i++;
4323 }
4324 }
4325 llist->dflt_size = i + 1;
4326 }
4327 }
4328
4329 if (deviate->max_set && yang_read_deviate_minmax(deviate, dev_target, deviate->max, 1)) {
4330 goto error;
4331 }
4332
4333 if (deviate->min_set && yang_read_deviate_minmax(deviate, dev_target, deviate->min, 0)) {
4334 goto error;
4335 }
4336
4337 if (deviate->units && yang_read_deviate_units(module->ctx, deviate, dev_target)) {
4338 goto error;
4339 }
4340
4341 if ((deviate->flags & LYS_CONFIG_MASK)) {
4342 /* add and replace are the same in this case */
4343 /* remove current config value of the target ... */
4344 dev_target->flags &= ~LYS_CONFIG_MASK;
4345
4346 /* ... and replace it with the value specified in deviation */
4347 dev_target->flags |= deviate->flags & LYS_CONFIG_MASK;
4348 }
4349
4350 if ((deviate->flags & LYS_MAND_MASK) && yang_check_deviate_mandatory(deviate, dev_target)) {
4351 goto error;
4352 }
4353
4354 if (deviate->type) {
4355 /* check target node type */
4356 if (dev_target->nodetype == LYS_LEAF) {
4357 type = &((struct lys_node_leaf *)dev_target)->type;
4358 } else if (dev_target->nodetype == LYS_LEAFLIST) {
4359 type = &((struct lys_node_leaflist *)dev_target)->type;
4360 } else {
4361 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
4362 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
4363 goto error;
4364 }
4365 /* remove type and initialize it */
4366 tmp_parent = type->parent;
Radek Krejci5138e9f2017-04-12 13:10:46 +02004367 lys_type_free(module->ctx, type, NULL);
PavolVican75af21d2016-12-29 20:04:07 +01004368 memcpy(type, deviate->type, sizeof *deviate->type);
4369 free(deviate->type);
4370 deviate->type = type;
4371 deviate->type->parent = tmp_parent;
PavolVican6f000922017-02-10 12:56:59 +01004372 if (yang_fill_type(module, type, (struct yang_type *)type->der, tmp_parent, unres)) {
4373 goto error;
4374 }
4375
PavolVican75af21d2016-12-29 20:04:07 +01004376 if (unres_schema_add_node(module, unres, deviate->type, UNRES_TYPE_DER, dev_target) == -1) {
4377 goto error;
4378 }
4379 }
4380
4381 return EXIT_SUCCESS;
4382error:
4383 if (deviate->type) {
4384 yang_type_free(module->ctx, deviate->type);
4385 deviate->type = NULL;
4386 }
4387 return EXIT_FAILURE;
4388}
4389
4390static int
4391yang_check_deviation(struct lys_module *module, struct unres_schema *unres, struct lys_deviation *dev)
4392{
4393 int rc;
4394 uint i;
4395 struct lys_node *dev_target = NULL, *parent;
Michal Vasko50576712017-07-28 12:28:33 +02004396 struct ly_set *dflt_check = ly_set_new(), *set;
PavolVican75af21d2016-12-29 20:04:07 +01004397 unsigned int u;
4398 const char *value, *target_name;
4399 struct lys_node_leaflist *llist;
4400 struct lys_node_leaf *leaf;
4401 struct unres_schema tmp_unres;
4402 struct lys_module *mod;
4403
4404 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02004405 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4406 if (rc == -1) {
PavolVican75af21d2016-12-29 20:04:07 +01004407 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Michal Vasko50576712017-07-28 12:28:33 +02004408 ly_set_free(set);
PavolVican75af21d2016-12-29 20:04:07 +01004409 goto error;
4410 }
Michal Vasko50576712017-07-28 12:28:33 +02004411 dev_target = set->set.s[0];
4412 ly_set_free(set);
4413
PavolVican75af21d2016-12-29 20:04:07 +01004414 if (dev_target->module == lys_main_module(module)) {
4415 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
4416 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
4417 goto error;
4418 }
4419
4420 if (!dflt_check) {
4421 LOGMEM;
4422 goto error;
4423 }
4424
4425 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
4426 /* you cannot remove a key leaf */
4427 if ((dev_target->nodetype == LYS_LEAF) && dev_target->parent && (dev_target->parent->nodetype == LYS_LIST)) {
4428 for (i = 0; i < ((struct lys_node_list *)dev_target->parent)->keys_size; ++i) {
4429 if (((struct lys_node_list *)dev_target->parent)->keys[i] == (struct lys_node_leaf *)dev_target) {
4430 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
4431 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
PavolVican4b80d042017-02-23 14:30:27 +01004432 goto error;
PavolVican75af21d2016-12-29 20:04:07 +01004433 }
4434 }
4435 }
4436 /* unlink and store the original node */
Radek Krejci9cf034c2017-08-24 17:10:35 +02004437 parent = dev_target->parent;
PavolVican75af21d2016-12-29 20:04:07 +01004438 lys_node_unlink(dev_target);
Radek Krejci9cf034c2017-08-24 17:10:35 +02004439 if (parent && parent->nodetype == LYS_AUGMENT) {
4440 /* hack for augment, because when the original will be sometime reconnected back, we actually need
4441 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
4442 * path), so we need to remember the augment as an addition */
4443 dev_target->parent = parent;
4444 }
PavolVican75af21d2016-12-29 20:04:07 +01004445 dev->orig_node = dev_target;
4446 } else {
4447 /* store a shallow copy of the original node */
4448 memset(&tmp_unres, 0, sizeof tmp_unres);
PavolVican8c33b152017-01-27 12:45:34 +01004449 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
PavolVican75af21d2016-12-29 20:04:07 +01004450 /* just to be safe */
4451 if (tmp_unres.count) {
4452 LOGINT;
4453 goto error;
4454 }
4455 }
4456
PavolVican6f000922017-02-10 12:56:59 +01004457 if (yang_check_ext_instance(module, &dev->ext, dev->ext_size, dev, unres)) {
4458 goto error;
4459 }
4460
Michal Vasko15a43372017-09-25 14:12:42 +02004461 if (!(module->ctx->models.flags & LY_CTX_TRUSTED)) {
4462 for (i = 0; i < dev->deviate_size; ++i) {
4463 if (yang_check_deviate(module, unres, &dev->deviate[i], dev_target, dflt_check)) {
4464 yang_free_deviate(module->ctx, dev, i + 1);
4465 dev->deviate_size = i+1;
4466 goto error; // missing free unresolve type in deviate
PavolVican75af21d2016-12-29 20:04:07 +01004467 }
4468 }
Michal Vasko15a43372017-09-25 14:12:42 +02004469 /* now check whether default value, if any, matches the type */
4470 for (u = 0; u < dflt_check->number; ++u) {
4471 value = NULL;
4472 rc = EXIT_SUCCESS;
4473 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
4474 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
4475 target_name = leaf->name;
4476 value = leaf->dflt;
4477 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
4478 } else { /* LYS_LEAFLIST */
4479 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
4480 target_name = llist->name;
4481 for (i = 0; i < llist->dflt_size; i++) {
4482 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4483 (struct lys_node *)(&llist->dflt[i]));
4484 if (rc == -1) {
4485 value = llist->dflt[i];
4486 break;
4487 }
4488 }
4489 }
4490 if (rc == -1) {
4491 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
4492 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
4493 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
4494 target_name);
4495 goto error;
4496 }
PavolVican75af21d2016-12-29 20:04:07 +01004497 }
Michal Vasko15a43372017-09-25 14:12:42 +02004498 ly_set_free(dflt_check);
PavolVican75af21d2016-12-29 20:04:07 +01004499 }
PavolVican75af21d2016-12-29 20:04:07 +01004500
Radek Krejci29eac3d2017-06-01 16:50:02 +02004501 /* mark all the affected modules as deviated and implemented */
4502 for (parent = dev_target; parent; parent = lys_parent(parent)) {
PavolVican75af21d2016-12-29 20:04:07 +01004503 mod = lys_node_module(parent);
4504 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02004505 mod->deviated = 1; /* main module */
4506 parent->module->deviated = 1; /* possible submodule */
4507 if (lys_set_implemented(mod)) {
4508 LOGERR(ly_errno, "Setting the deviated module \"%s\" implemented failed.", mod->name);
4509 goto error;
4510 }
4511 }
PavolVican75af21d2016-12-29 20:04:07 +01004512 }
PavolVican75af21d2016-12-29 20:04:07 +01004513
4514 return EXIT_SUCCESS;
4515error:
4516 ly_set_free(dflt_check);
4517 return EXIT_FAILURE;
4518}
4519
4520static int
Pavol Vican7313fc02016-11-14 01:10:31 +01004521yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node)
4522{
PavolVican75af21d2016-12-29 20:04:07 +01004523 uint i, erase_identities = 1, erase_nodes = 1, aug_size, dev_size = 0;
Pavol Vican3ad50f82016-12-04 15:00:36 +01004524
4525 aug_size = module->augment_size;
4526 module->augment_size = 0;
PavolVican75af21d2016-12-29 20:04:07 +01004527 dev_size = module->deviation_size;
4528 module->deviation_size = 0;
Pavol Vican7a7916f2016-11-21 23:38:30 +01004529
PavolVican6f87bf92017-02-15 19:38:55 +01004530 if (yang_check_typedef(module, NULL, unres)) {
4531 goto error;
4532 }
4533
PavolVicanc1807262017-01-31 18:00:27 +01004534 if (yang_check_ext_instance(module, &module->ext, module->ext_size, module, unres)) {
4535 goto error;
4536 }
4537
PavolVican171717d2017-02-01 14:49:55 +01004538 /* check extension in revision */
4539 for (i = 0; i < module->rev_size; ++i) {
4540 if (yang_check_ext_instance(module, &module->rev[i].ext, module->rev[i].ext_size, &module->rev[i], unres)) {
4541 goto error;
4542 }
4543 }
4544
PavolVican19dc6152017-02-06 12:04:15 +01004545 /* check extension in definition of extension */
PavolVican5393d3f2017-02-06 23:30:55 +01004546 for (i = 0; i < module->extensions_size; ++i) {
PavolVican19dc6152017-02-06 12:04:15 +01004547 if (yang_check_ext_instance(module, &module->extensions[i].ext, module->extensions[i].ext_size, &module->extensions[i], unres)) {
4548 goto error;
4549 }
4550 }
4551
Pavol Vican7a7916f2016-11-21 23:38:30 +01004552 /* check features */
4553 for (i = 0; i < module->features_size; ++i) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004554 if (yang_check_iffeatures(module, NULL, &module->features[i], FEATURE_KEYWORD, unres)) {
4555 goto error;
4556 }
PavolVican5393d3f2017-02-06 23:30:55 +01004557 if (yang_check_ext_instance(module, &module->features[i].ext, module->features[i].ext_size, &module->features[i], unres)) {
4558 goto error;
4559 }
4560
Pavol Vicandf9a95c2016-12-02 23:34:51 +01004561 /* check for circular dependencies */
4562 if (module->features[i].iffeature_size && (unres_schema_add_node(module, unres, &module->features[i], UNRES_FEATURE, NULL) == -1)) {
4563 goto error;
Pavol Vican7a7916f2016-11-21 23:38:30 +01004564 }
4565 }
Pavol Vican36e27272016-11-22 15:47:28 +01004566 erase_identities = 0;
4567 if (yang_check_identities(module, unres)) {
4568 goto error;
4569 }
Pavol Vican05810b62016-11-23 14:07:22 +01004570 erase_nodes = 0;
Radek Krejci7212e0a2017-03-08 15:58:22 +01004571 if (yang_check_nodes(module, NULL, node, 0, unres)) {
Pavol Vican05810b62016-11-23 14:07:22 +01004572 goto error;
4573 }
Pavol Vican7a7916f2016-11-21 23:38:30 +01004574
PavolVican75af21d2016-12-29 20:04:07 +01004575 /* check deviation */
4576 for (i = 0; i < dev_size; ++i) {
4577 module->deviation_size++;
4578 if (yang_check_deviation(module, unres, &module->deviation[i])) {
4579 goto error;
4580 }
4581 }
4582
Pavol Vican3ad50f82016-12-04 15:00:36 +01004583 /* check augments */
4584 for (i = 0; i < aug_size; ++i) {
4585 module->augment_size++;
Radek Krejci7212e0a2017-03-08 15:58:22 +01004586 if (yang_check_augment(module, &module->augment[i], 0, unres)) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01004587 goto error;
4588 }
4589 if (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1) {
4590 goto error;
4591 }
4592 }
4593
Pavol Vican7313fc02016-11-14 01:10:31 +01004594 return EXIT_SUCCESS;
4595error:
Pavol Vican36e27272016-11-22 15:47:28 +01004596 if (erase_identities) {
4597 yang_free_ident_base(module->ident, 0, module->ident_size);
4598 }
Pavol Vican05810b62016-11-23 14:07:22 +01004599 if (erase_nodes) {
4600 yang_free_nodes(module->ctx, node);
4601 }
Pavol Vican3ad50f82016-12-04 15:00:36 +01004602 for (i = module->augment_size; i < aug_size; ++i) {
4603 yang_free_augment(module->ctx, &module->augment[i]);
4604 }
PavolVican75af21d2016-12-29 20:04:07 +01004605 for (i = module->deviation_size; i < dev_size; ++i) {
4606 yang_free_deviate(module->ctx, &module->deviation[i], 0);
4607 free(module->deviation[i].deviate);
4608 }
Pavol Vican7313fc02016-11-14 01:10:31 +01004609 return EXIT_FAILURE;
4610}
PavolVican22e88682017-02-14 22:38:18 +01004611
4612int
Michal Vasko3e3228d2017-02-24 14:55:32 +01004613yang_read_extcomplex_str(struct lys_module *module, struct lys_ext_instance_complex *ext, const char *arg_name,
PavolVican22e88682017-02-14 22:38:18 +01004614 const char *parent_name, char *value, int parent_stmt, LY_STMT stmt)
4615{
4616 int c;
4617 const char **str, ***p = NULL;
4618 void *reallocated;
4619 struct lyext_substmt *info;
4620
4621 c = 0;
4622 if (stmt == LY_STMT_PREFIX && parent_stmt == LY_STMT_BELONGSTO) {
PavolVican4b80d042017-02-23 14:30:27 +01004623 /* str contains no NULL value */
PavolVican22e88682017-02-14 22:38:18 +01004624 str = lys_ext_complex_get_substmt(LY_STMT_BELONGSTO, ext, &info);
4625 if (info->cardinality < LY_STMT_CARD_SOME) {
4626 str++;
4627 } else {
4628 /* get the index in the array to add new item */
4629 p = (const char ***)str;
4630 for (c = 0; p[0][c + 1]; c++);
4631 str = p[1];
4632 }
4633 str[c] = lydict_insert_zc(module->ctx, value);
4634 } else {
4635 str = lys_ext_complex_get_substmt(stmt, ext, &info);
4636 if (!str) {
4637 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, arg_name, parent_name);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004638 goto error;
PavolVican22e88682017-02-14 22:38:18 +01004639 }
4640 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
4641 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, arg_name, parent_name);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004642 goto error;
PavolVican22e88682017-02-14 22:38:18 +01004643 }
4644
4645 if (info->cardinality >= LY_STMT_CARD_SOME) {
4646 /* there can be multiple instances, str is actually const char *** */
4647 p = (const char ***)str;
4648 if (!p[0]) {
4649 /* allocate initial array */
PavolVican50809742017-02-18 21:22:54 +01004650 p[0] = calloc(2, sizeof(const char *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004651 LY_CHECK_ERR_GOTO(!p[0], LOGMEM, error);
PavolVican22e88682017-02-14 22:38:18 +01004652 if (stmt == LY_STMT_BELONGSTO) {
4653 /* allocate another array for the belongs-to's prefixes */
4654 p[1] = calloc(2, sizeof(const char *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004655 LY_CHECK_ERR_GOTO(!p[1], LOGMEM, error);
PavolVican50809742017-02-18 21:22:54 +01004656 } else if (stmt == LY_STMT_ARGUMENT) {
4657 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01004658 ((uint8_t **)p)[1] = calloc(2, sizeof(uint8_t));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004659 LY_CHECK_ERR_GOTO(!p[1], LOGMEM, error);
PavolVican50809742017-02-18 21:22:54 +01004660 /* default value of yin element */
4661 ((uint8_t *)p[1])[0] = 2;
PavolVican22e88682017-02-14 22:38:18 +01004662 }
4663 } else {
4664 /* get the index in the array to add new item */
4665 for (c = 0; p[0][c]; c++);
4666 }
4667 str = p[0];
4668 }
4669
4670 str[c] = lydict_insert_zc(module->ctx, value);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004671 value = NULL;
PavolVican22e88682017-02-14 22:38:18 +01004672
PavolVican50809742017-02-18 21:22:54 +01004673 if (c) {
PavolVican22e88682017-02-14 22:38:18 +01004674 /* enlarge the array(s) */
4675 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
4676 if (!reallocated) {
4677 LOGMEM;
4678 lydict_remove(module->ctx, p[0][c]);
4679 p[0][c] = NULL;
4680 return EXIT_FAILURE;
4681 }
4682 p[0] = reallocated;
4683 p[0][c + 1] = NULL;
4684
4685 if (stmt == LY_STMT_BELONGSTO) {
4686 /* enlarge the second belongs-to's array with prefixes */
4687 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
4688 if (!reallocated) {
4689 LOGMEM;
4690 lydict_remove(module->ctx, p[1][c]);
4691 p[1][c] = NULL;
4692 return EXIT_FAILURE;
4693 }
4694 p[1] = reallocated;
4695 p[1][c + 1] = NULL;
PavolVican50809742017-02-18 21:22:54 +01004696 } else if (stmt == LY_STMT_ARGUMENT) {
4697 /* enlarge the second argument's array with yin element */
4698 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
4699 if (!reallocated) {
4700 LOGMEM;
4701 ((uint8_t *)p[1])[c] = 0;
4702 return EXIT_FAILURE;
4703 }
4704 p[1] = reallocated;
4705 ((uint8_t *)p[1])[c + 1] = 0;
PavolVican22e88682017-02-14 22:38:18 +01004706 }
4707 }
4708 }
4709
4710 return EXIT_SUCCESS;
Radek Krejcia8d111f2017-05-31 13:57:37 +02004711
4712error:
4713 free(value);
4714 return EXIT_FAILURE;
PavolVican22e88682017-02-14 22:38:18 +01004715}
PavolVican5334c892017-02-15 16:29:09 +01004716
4717static int
4718yang_fill_ext_substm_index(struct lys_ext_instance_complex *ext, LY_STMT stmt, enum yytokentype keyword)
4719{
4720 int c = 0, decrement = 0;
4721 const char **str, ***p = NULL;
4722 struct lyext_substmt *info;
4723
4724
4725 if (keyword == BELONGS_TO_KEYWORD || stmt == LY_STMT_BELONGSTO) {
4726 stmt = LY_STMT_BELONGSTO;
4727 decrement = -1;
PavolVican50809742017-02-18 21:22:54 +01004728 } else if (keyword == ARGUMENT_KEYWORD || stmt == LY_STMT_ARGUMENT) {
4729 stmt = LY_STMT_ARGUMENT;
4730 decrement = -1;
PavolVican5334c892017-02-15 16:29:09 +01004731 }
4732
4733 str = lys_ext_complex_get_substmt(stmt, ext, &info);
4734 if (!str || info->cardinality < LY_STMT_CARD_SOME || !((const char ***)str)[0]) {
4735 return 0;
4736 } else {
4737 p = (const char ***)str;
4738 /* get the index in the array */
4739 for (c = 0; p[0][c]; c++);
4740 return c + decrement;
4741 }
4742}
PavolVicana0fdbf32017-02-15 17:59:02 +01004743
4744void **
PavolVicanfe83b152017-02-19 03:19:29 +01004745yang_getplace_for_extcomplex_struct(struct lys_ext_instance_complex *ext, int *index,
4746 char *parent_name, char *node_name, LY_STMT stmt)
PavolVicana0fdbf32017-02-15 17:59:02 +01004747{
4748 int c;
4749 void **data, ***p = NULL;
4750 void *reallocated;
4751 struct lyext_substmt *info;
4752
4753 data = lys_ext_complex_get_substmt(stmt, ext, &info);
4754 if (!data) {
4755 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node_name, parent_name);
4756 return NULL;
4757 }
4758 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
4759 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4760 return NULL;
4761 }
4762
4763 c = 0;
4764 if (info->cardinality >= LY_STMT_CARD_SOME) {
4765 /* there can be multiple instances, so instead of pointer to array,
4766 * we have in data pointer to pointer to array */
4767 p = (void ***)data;
4768 data = *p;
4769 if (!data) {
4770 /* allocate initial array */
PavolVicaneef1d912017-02-19 00:19:15 +01004771 *p = data = calloc(2, sizeof(void *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004772 LY_CHECK_ERR_RETURN(!data, LOGMEM, NULL);
PavolVicana0fdbf32017-02-15 17:59:02 +01004773 } else {
4774 for (c = 0; *data; data++, c++);
4775 }
4776 }
4777
PavolVicaneef1d912017-02-19 00:19:15 +01004778 if (c) {
PavolVicana0fdbf32017-02-15 17:59:02 +01004779 /* enlarge the array */
4780 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004781 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM, NULL);
PavolVicana0fdbf32017-02-15 17:59:02 +01004782 *p = reallocated;
4783 data = *p;
4784 data[c + 1] = NULL;
4785 }
4786
PavolVicanfe83b152017-02-19 03:19:29 +01004787 if (index) {
4788 *index = c;
4789 return data;
4790 } else {
4791 return &data[c];
4792 }
PavolVicana0fdbf32017-02-15 17:59:02 +01004793}
PavolVicanff0f7f42017-02-16 11:35:42 +01004794
4795int
4796yang_fill_extcomplex_flags(struct lys_ext_instance_complex *ext, char *parent_name, char *node_name,
4797 LY_STMT stmt, uint16_t value, uint16_t mask)
4798{
4799 uint16_t *data;
4800 struct lyext_substmt *info;
4801
4802 data = lys_ext_complex_get_substmt(stmt, ext, &info);
4803 if (!data) {
4804 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node_name, parent_name);
4805 return EXIT_FAILURE;
4806 }
4807 if (info->cardinality < LY_STMT_CARD_SOME && (*data & mask)) {
4808 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4809 return EXIT_FAILURE;
4810 }
4811
4812 *data |= value;
4813 return EXIT_SUCCESS;
4814}
PavolVican8e8dfd12017-02-16 13:51:41 +01004815
4816int
PavolVican6a852a62017-02-16 15:36:01 +01004817yang_fill_extcomplex_uint8(struct lys_ext_instance_complex *ext, char *parent_name, char *node_name,
4818 LY_STMT stmt, uint8_t value)
PavolVican8e8dfd12017-02-16 13:51:41 +01004819{
PavolVican6a852a62017-02-16 15:36:01 +01004820 uint8_t *val, **pp = NULL, *reallocated;
PavolVican8e8dfd12017-02-16 13:51:41 +01004821 struct lyext_substmt *info;
PavolVican6a852a62017-02-16 15:36:01 +01004822 int i = 0;
PavolVican8e8dfd12017-02-16 13:51:41 +01004823
4824 val = lys_ext_complex_get_substmt(stmt, ext, &info);
4825 if (!val) {
4826 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node_name, parent_name);
4827 return EXIT_FAILURE;
4828 }
PavolVican6a852a62017-02-16 15:36:01 +01004829 if (stmt == LY_STMT_DIGITS) {
4830 if (info->cardinality < LY_STMT_CARD_SOME && *val) {
4831 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4832 return EXIT_FAILURE;
4833 }
PavolVican8e8dfd12017-02-16 13:51:41 +01004834
PavolVican6a852a62017-02-16 15:36:01 +01004835 if (info->cardinality >= LY_STMT_CARD_SOME) {
4836 /* there can be multiple instances */
4837 pp = (uint8_t**)val;
4838 if (!(*pp)) {
4839 *pp = calloc(2, sizeof(uint8_t)); /* allocate initial array */
Radek Krejcia8d111f2017-05-31 13:57:37 +02004840 LY_CHECK_ERR_RETURN(!*pp, LOGMEM, EXIT_FAILURE);
PavolVican6a852a62017-02-16 15:36:01 +01004841 } else {
4842 for (i = 0; (*pp)[i]; i++);
4843 }
4844 val = &(*pp)[i];
4845 }
4846
4847 /* stored value */
4848 *val = value;
4849
4850 if (i) {
4851 /* enlarge the array */
4852 reallocated = realloc(*pp, (i + 2) * sizeof *val);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004853 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM, EXIT_FAILURE);
PavolVican6a852a62017-02-16 15:36:01 +01004854 *pp = reallocated;
4855 (*pp)[i + 1] = 0;
4856 }
PavolVican8e8dfd12017-02-16 13:51:41 +01004857 } else {
PavolVican6a852a62017-02-16 15:36:01 +01004858 if (*val) {
4859 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4860 return EXIT_FAILURE;
4861 }
4862
4863 if (stmt == LY_STMT_REQINSTANCE) {
4864 *val = (value == 1) ? 1 : 2;
4865 } else if (stmt == LY_STMT_MODIFIER) {
4866 *val = 1;
4867 } else {
4868 LOGINT;
4869 return EXIT_FAILURE;
4870 }
PavolVican8e8dfd12017-02-16 13:51:41 +01004871 }
4872
4873 return EXIT_SUCCESS;
4874}
PavolVican3f47b292017-02-16 20:38:16 +01004875
PavolVicanf3091bf2017-02-19 18:27:01 +01004876int
4877yang_extcomplex_node(struct lys_ext_instance_complex *ext, char *parent_name, char *node_name,
4878 struct lys_node *node, LY_STMT stmt)
4879{
4880 struct lyext_substmt *info;
4881 struct lys_node **snode, *siter;
4882
4883 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
4884 if (!snode) {
4885 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node_name, parent_name);
4886 return EXIT_FAILURE;
4887 }
4888 if (info->cardinality < LY_STMT_CARD_SOME) {
4889 LY_TREE_FOR(node, siter) {
4890 if (stmt == lys_snode2stmt(siter->nodetype)) {
4891 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node_name, parent_name);
4892 return EXIT_FAILURE;
4893 }
4894 }
4895 }
4896
4897 return EXIT_SUCCESS;
4898}
PavolVicandb0e8172017-02-20 00:46:09 +01004899
4900int
4901yang_fill_extcomplex_module(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext,
4902 char *parent_name, char **values, int implemented)
4903{
4904 int c, i;
4905 struct lys_module **modules, ***p, *reallocated, **pp;
4906 struct lyext_substmt *info;
4907
4908 if (!values) {
4909 return EXIT_SUCCESS;
4910 }
4911 pp = modules = lys_ext_complex_get_substmt(LY_STMT_MODULE, ext, &info);
4912 if (!modules) {
4913 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "module", parent_name);
4914 return EXIT_FAILURE;
4915 }
4916
4917 for (i = 0; values[i]; ++i) {
4918 c = 0;
4919 if (info->cardinality < LY_STMT_CARD_SOME && *modules) {
4920 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "module", parent_name);
4921 return EXIT_FAILURE;
4922 }
4923 if (info->cardinality >= LY_STMT_CARD_SOME) {
4924 /* there can be multiple instances, so instead of pointer to array,
4925 * we have in modules pointer to pointer to array */
4926 p = (struct lys_module ***)pp;
4927 modules = *p;
4928 if (!modules) {
4929 /* allocate initial array */
4930 *p = modules = calloc(2, sizeof(struct lys_module *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004931 LY_CHECK_ERR_RETURN(!*p, LOGMEM, EXIT_FAILURE);
PavolVicandb0e8172017-02-20 00:46:09 +01004932 } else {
4933 for (c = 0; *modules; modules++, c++);
4934 }
4935 }
4936
4937 if (c) {
4938 /* enlarge the array */
4939 reallocated = realloc(*p, (c + 2) * sizeof(struct lys_module *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02004940 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM, EXIT_FAILURE);
PavolVicandb0e8172017-02-20 00:46:09 +01004941 *p = (struct lys_module **)reallocated;
4942 modules = *p;
4943 modules[c + 1] = NULL;
4944 }
4945
4946 modules[c] = yang_read_module(ctx, values[i], 0, NULL, implemented);
4947 if (!modules[c]) {
4948 return EXIT_FAILURE;
4949 }
4950 }
4951
4952 return EXIT_SUCCESS;
4953}