blob: ce38aeb96fd2cfb5330ce3c4ccc5750bc54b8d4d [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 Vican021488a2016-01-25 23:56:12 +010016#include "parser_yang.h"
Pavol Vican8e7110b2016-03-22 17:00:26 +010017#include "parser_yang_lex.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010018#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010019#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010020
Michal Vaskofe7e5a72016-05-02 14:49:23 +020021static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010022yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010023{
Pavol Vicanbf805472016-01-26 14:24:56 +010024 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010025 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010026 free(value);
27 return 1;
28 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010029 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010030 return 0;
31 }
32}
33
Pavol Vican810892e2016-07-12 16:55:34 +020034static int
35yang_check_typedef_identif(struct lys_node *root, struct lys_node *node, char *id)
36{
37 struct lys_node *child, *next;
38 int size;
39 struct lys_tpdf *tpdf;
40
Pavol Vican810892e2016-07-12 16:55:34 +020041 if (root) {
42 node = root;
43 }
44
45 do {
46 LY_TREE_DFS_BEGIN(node, next, child) {
47 if (child->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_GROUPING | LYS_RPC | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF)) {
48 switch (child->nodetype) {
49 case LYS_CONTAINER:
50 tpdf = ((struct lys_node_container *)child)->tpdf;
51 size = ((struct lys_node_container *)child)->tpdf_size;
52 break;
53 case LYS_LIST:
54 tpdf = ((struct lys_node_list *)child)->tpdf;
55 size = ((struct lys_node_list *)child)->tpdf_size;
56 break;
57 case LYS_GROUPING:
58 tpdf = ((struct lys_node_grp *)child)->tpdf;
59 size = ((struct lys_node_grp *)child)->tpdf_size;
60 break;
61 case LYS_RPC:
Radek Krejci71d51832016-07-14 15:59:06 +020062 tpdf = ((struct lys_node_rpc_action *)child)->tpdf;
63 size = ((struct lys_node_rpc_action *)child)->tpdf_size;
Pavol Vican810892e2016-07-12 16:55:34 +020064 break;
65 case LYS_INPUT:
66 case LYS_OUTPUT:
Radek Krejci71d51832016-07-14 15:59:06 +020067 tpdf = ((struct lys_node_inout *)child)->tpdf;
68 size = ((struct lys_node_inout *)child)->tpdf_size;
Pavol Vican810892e2016-07-12 16:55:34 +020069 break;
70 case LYS_NOTIF:
71 tpdf = ((struct lys_node_notif *)child)->tpdf;
72 size = ((struct lys_node_notif *)child)->tpdf_size;
73 break;
74 default:
75 size = 0;
76 break;
77 }
Radek Krejcifc824a42016-07-14 15:48:38 +020078 if (size && dup_typedef_check(id, tpdf, size)) {
Pavol Vican810892e2016-07-12 16:55:34 +020079 LOGVAL(LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
80 return EXIT_FAILURE;
81 }
Michal Vasko3767fb22016-07-21 12:10:57 +020082 }
Pavol Vican810892e2016-07-12 16:55:34 +020083 LY_TREE_DFS_END(node, next, child)}
84 } while (root && (node = node->next));
85 return EXIT_SUCCESS;
86}
87
Michal Vaskofe7e5a72016-05-02 14:49:23 +020088int
Pavol Vican5f0316a2016-04-05 21:21:11 +020089yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010090{
Pavol Vican6eb14e82016-02-03 12:27:13 +010091 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010092
93 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010094 case MODULE_KEYWORD:
95 module->name = lydict_insert_zc(module->ctx, value);
96 break;
97 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010098 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010099 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +0100100 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100101 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100102 break;
103 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100104 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100105 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200106 default:
107 free(value);
108 LOGINT;
109 ret = EXIT_FAILURE;
110 break;
Pavol Vican2a064652016-02-02 22:54:34 +0100111 }
112
Pavol Vican021488a2016-01-25 23:56:12 +0100113 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +0100114}
115
Michal Vaskofe7e5a72016-05-02 14:49:23 +0200116int
Pavol Vicand0b64c12016-07-15 09:56:19 +0200117yang_check_version(struct lys_module *module, struct lys_submodule *submodule, char *value, int repeat)
118{
119 int ret = EXIT_SUCCESS;
120
121 if (repeat) {
Michal Vasko3767fb22016-07-21 12:10:57 +0200122 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module");
123 ret = EXIT_FAILURE;
Pavol Vicand0b64c12016-07-15 09:56:19 +0200124 } else {
125 if (!strcmp(value, "1")) {
126 if (submodule) {
127 if (module->version > 1) {
128 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
129 ret = EXIT_FAILURE;
130 }
131 } else {
132 module->version = 1;
133 }
134 } else if (!strcmp(value, "1.1")) {
135 if (submodule) {
136 if (module->version != 2) {
137 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
138 ret = EXIT_FAILURE;
139 }
140 } else {
141 module->version = 2;
142 }
143 } else {
144 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
145 ret = EXIT_FAILURE;
Michal Vasko3767fb22016-07-21 12:10:57 +0200146 }
Pavol Vicand0b64c12016-07-15 09:56:19 +0200147 }
148 free(value);
149 return ret;
150}
151
152int
Pavol Vicane024ab72016-07-27 14:27:43 +0200153yang_read_prefix(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +0100154{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100155 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100156
Pavol Vican0adf01d2016-03-22 12:29:33 +0100157 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100158 free(value);
159 return EXIT_FAILURE;
160 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200161
162 if (imp) {
163 ret = yang_check_string(module, &imp->prefix, "prefix", "import", value);
164 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100165 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100166 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100167
Pavol Vicanbf805472016-01-26 14:24:56 +0100168 return ret;
169}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100170
Pavol Vican6eb14e82016-02-03 12:27:13 +0100171int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100172yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican6eb14e82016-02-03 12:27:13 +0100173{
Pavol Vican0da132e2016-03-21 12:03:03 +0100174 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200175 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100176
Pavol Vicane024ab72016-07-27 14:27:43 +0200177 if (!imp->prefix) {
178 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "import");
179 return EXIT_FAILURE;
180 }
Pavol Vican0da132e2016-03-21 12:03:03 +0100181 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican0adf01d2016-03-22 12:29:33 +0100182 rc = lyp_check_import(module, exp, imp);
Pavol Vican0da132e2016-03-21 12:03:03 +0100183 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200184 module->imp_size++;
Pavol Vican0da132e2016-03-21 12:03:03 +0100185 if (rc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200186 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100187 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100188
Pavol Vican6eb14e82016-02-03 12:27:13 +0100189 return EXIT_SUCCESS;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100190}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100191
192int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100193yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100194{
195 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100196 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100197
198 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100199 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100200 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100201 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100202 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200203 } else if (!strcmp("import", where)){
204 ret = yang_check_string(module, &((struct lys_import *)node)->dsc, dsc, where, value);
205 } else if (!strcmp("include", where)){
206 ret = yang_check_string(module, &((struct lys_include *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100207 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100208 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100209 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100210 }
211 return ret;
212}
213
214int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100215yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100216{
217 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100218 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100219
220 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100221 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100222 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100223 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100224 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200225 } else if (!strcmp("import", where)){
226 ret = yang_check_string(module, &((struct lys_import *)node)->ref, ref, where, value);
227 } else if (!strcmp("include", where)){
228 ret = yang_check_string(module, &((struct lys_include *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100229 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100230 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100231 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100232 }
233 return ret;
234}
Pavol Vicanbedff692016-02-03 14:29:17 +0100235
236void *
237yang_read_revision(struct lys_module *module, char *value)
238{
239 struct lys_revision *retval;
240
Pavol Vican1eeb1992016-02-09 11:10:45 +0100241 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100242
243 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100244 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100245 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
246 memcpy(module->rev[0].date, value, LY_REV_SIZE);
247 retval->dsc = module->rev[0].dsc;
248 retval->ref = module->rev[0].ref;
249 retval = module->rev;
250 retval->dsc = NULL;
251 retval->ref = NULL;
252 } else {
253 memcpy(retval->date, value, LY_REV_SIZE);
254 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100255 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100256 free(value);
257 return retval;
258}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100259
260int
Pavol Vicana1827962016-02-29 15:39:42 +0100261yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100262{
Pavol Vican45ccc592016-03-09 18:53:48 +0100263 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100264 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
265 LOGMEM;
266 return EXIT_FAILURE;
267 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100268 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100269 }
270 }
271 (*size)++;
272 return EXIT_SUCCESS;
273}
Pavol Vicane1354e92016-02-09 14:02:09 +0100274
275void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100276yang_read_feature(struct lys_module *module, char *value)
Pavol Vicane1354e92016-02-09 14:02:09 +0100277{
278 struct lys_feature *retval;
279
280 /* check uniqueness of feature's names */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100281 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100282 goto error;
283 }
284 retval = &module->features[module->features_size];
285 retval->name = lydict_insert_zc(module->ctx, value);
286 retval->module = module;
287 module->features_size++;
288 return retval;
289
290error:
291 free(value);
292 return NULL;
293}
294
295int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200296yang_read_if_feature(struct lys_module *module, void *ptr, char *value, struct unres_schema *unres, enum yytokentype type)
Pavol Vicane1354e92016-02-09 14:02:09 +0100297{
298 const char *exp;
299 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100300 struct lys_feature *f;
Pavol Vican4df80542016-08-08 09:37:55 +0200301 struct lys_ident *i;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100302 struct lys_node *n;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200303 struct lys_type_enum *e;
304 struct lys_type_bit *b;
Pavol Vicane1354e92016-02-09 14:02:09 +0100305
Michal Vasko97b32be2016-07-25 10:59:53 +0200306 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
307 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
308 free(value);
309 return EXIT_FAILURE;
310 }
311
Pavol Vican0adf01d2016-03-22 12:29:33 +0100312 if (!(exp = transform_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100313 free(value);
314 return EXIT_FAILURE;
315 }
316 free(value);
317
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200318 switch (type) {
319 case FEATURE_KEYWORD:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100320 f = (struct lys_feature *) ptr;
Radek Krejci9ff0a922016-07-14 13:08:05 +0200321 ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200322 f->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200323 break;
324 case IDENTITY_KEYWORD:
Pavol Vican4df80542016-08-08 09:37:55 +0200325 i = (struct lys_ident *) ptr;
326 ret = resolve_iffeature_compile(&i->iffeature[i->iffeature_size], exp, (struct lys_node *)i, unres);
327 i->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200328 break;
329 case ENUM_KEYWORD:
330 e = &((struct yang_type *)ptr)->type->info.enums.enm[((struct yang_type *)ptr)->type->info.enums.count - 1];
331 ret = resolve_iffeature_compile(&e->iffeature[e->iffeature_size], exp, (struct lys_node *)((struct yang_type *)ptr)->type->parent, unres);
332 e->iffeature_size++;
333 break;
334 case BIT_KEYWORD:
335 b = &((struct yang_type *)ptr)->type->info.bits.bit[((struct yang_type *)ptr)->type->info.bits.count - 1];
336 ret = resolve_iffeature_compile(&b->iffeature[b->iffeature_size], exp, (struct lys_node *)((struct yang_type *)ptr)->type->parent, unres);
337 b->iffeature_size++;
338 break;
339 default:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100340 n = (struct lys_node *) ptr;
Radek Krejci9ff0a922016-07-14 13:08:05 +0200341 ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200342 n->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200343 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100344 }
Radek Krejci9ff0a922016-07-14 13:08:05 +0200345 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100346
Radek Krejci9ff0a922016-07-14 13:08:05 +0200347 if (ret) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100348 return EXIT_FAILURE;
349 }
350 return EXIT_SUCCESS;
351}
352
Pavol Vican4fb66c92016-03-17 10:32:27 +0100353int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200354yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100355{
356 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100357 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100358 return EXIT_FAILURE;
359 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200360 if (shortint) {
361 *((uint8_t *)flags) |= (uint8_t)value;
362 } else {
363 *flags |= value;
364 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100365 return EXIT_SUCCESS;
366 }
367}
368
Pavol Vicanbbdef532016-02-09 14:52:12 +0100369void *
370yang_read_identity(struct lys_module *module, char *value)
371{
372 struct lys_ident *ret;
373
374 ret = &module->ident[module->ident_size];
375 ret->name = lydict_insert_zc(module->ctx, value);
376 ret->module = module;
Pavol Vicand6cda452016-07-13 15:08:29 +0200377 if (dup_identities_check(ret->name, module)) {
378 lydict_remove(module->ctx, ret->name);
379 return NULL;
380 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100381 module->ident_size++;
382 return ret;
383}
384
385int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100386yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100387{
388 const char *exp;
389
Pavol Vican0adf01d2016-03-22 12:29:33 +0100390 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100391 free(value);
392 if (!exp) {
393 return EXIT_FAILURE;
394 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100395 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100396 lydict_remove(module->ctx, exp);
397 return EXIT_FAILURE;
398 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100399
Pavol Vicanbbdef532016-02-09 14:52:12 +0100400 lydict_remove(module->ctx, exp);
401 return EXIT_SUCCESS;
402}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100403
404void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200405yang_read_must(struct lys_module *module, struct lys_node *node, char *value, enum yytokentype type)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100406{
407 struct lys_restr *retval;
408
409 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100410 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100411 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100412 break;
413 case ANYXML_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100414 retval = &((struct lys_node_anyxml *)node)->must[((struct lys_node_anyxml *)node)->must_size++];
415 break;
416 case LEAF_KEYWORD:
417 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100418 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100419 case LEAF_LIST_KEYWORD:
420 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
421 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100422 case LIST_KEYWORD:
423 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
424 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100425 case REFINE_KEYWORD:
426 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
427 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100428 case ADD_KEYWORD:
429 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
430 memset(retval, 0, sizeof *retval);
431 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100432 case DELETE_KEYWORD:
433 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
434 break;
Pavol Vican9b14b492016-08-09 14:55:10 +0200435 case NOTIFICATION_KEYWORD:
436 retval = &((struct lys_node_notif *)node)->must[((struct lys_node_notif *)node)->must_size++];
437 break;
438 case INPUT_KEYWORD:
439 retval = &((struct lys_node_inout *)node)->must[((struct lys_node_inout *)node)->must_size++];
440 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200441 default:
442 goto error;
443 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100444 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100445 retval->expr = transform_schema2json(module, value);
446 if (!retval->expr || lyxp_syntax_check(retval->expr)) {
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100447 goto error;
448 }
449 free(value);
450 return retval;
451
452error:
453 free(value);
454 return NULL;
455}
456
457int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100458yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100459{
460 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100461
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100462 if (message==ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100463 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100464 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100465 ret = yang_check_string(module, &save->emsg, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100466 }
467 return ret;
468}
Pavol Vicanb5687112016-02-09 22:35:59 +0100469
470int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100471yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100472{
473 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100474 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100475 free(value);
476 return EXIT_FAILURE;
477 } else {
478 cont->presence = lydict_insert_zc(module->ctx, value);
479 return EXIT_SUCCESS;
480 }
481}
482
Pavol Vican235dbd42016-02-10 10:34:19 +0100483void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200484yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100485{
486 struct lys_when *retval;
487
488 retval = calloc(1, sizeof *retval);
489 if (!retval) {
490 LOGMEM;
491 free(value);
492 return NULL;
493 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100494 retval->cond = transform_schema2json(module, value);
495 if (!retval->cond || lyxp_syntax_check(retval->cond)) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100496 goto error;
497 }
498 switch (type) {
499 case CONTAINER_KEYWORD:
500 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100501 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100502 goto error;
503 }
504 ((struct lys_node_container *)node)->when = retval;
505 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100506 case ANYXML_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100507 if (((struct lys_node_anyxml *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100508 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "anyxml");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100509 goto error;
510 }
511 ((struct lys_node_anyxml *)node)->when = retval;
512 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100513 case CHOICE_KEYWORD:
514 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100515 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100516 goto error;
517 }
518 ((struct lys_node_choice *)node)->when = retval;
519 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100520 case CASE_KEYWORD:
521 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100522 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100523 goto error;
524 }
525 ((struct lys_node_case *)node)->when = retval;
526 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100527 case LEAF_KEYWORD:
528 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100529 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100530 goto error;
531 }
532 ((struct lys_node_leaf *)node)->when = retval;
533 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100534 case LEAF_LIST_KEYWORD:
535 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100536 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100537 goto error;
538 }
539 ((struct lys_node_leaflist *)node)->when = retval;
540 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100541 case LIST_KEYWORD:
542 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100543 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100544 goto error;
545 }
546 ((struct lys_node_list *)node)->when = retval;
547 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100548 case USES_KEYWORD:
549 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100550 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100551 goto error;
552 }
553 ((struct lys_node_uses *)node)->when = retval;
554 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100555 case AUGMENT_KEYWORD:
556 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100557 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100558 goto error;
559 }
560 ((struct lys_node_augment *)node)->when = retval;
561 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200562 default:
563 goto error;
564 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100565 }
566 free(value);
567 return retval;
568
569error:
570 free(value);
571 lys_when_free(module->ctx, retval);
572 return NULL;
573}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100574
575void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100576yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100577{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100578 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100579
Pavol Vican7cadfe72016-02-11 12:33:34 +0100580 node = calloc(1, sizeof_struct);
581 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100582 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100583 LOGMEM;
584 return NULL;
585 }
Pavol Vican531a9132016-03-03 10:10:09 +0100586 if (value) {
587 node->name = lydict_insert_zc(module->ctx, value);
588 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100589 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100590 node->nodetype = nodetype;
591 node->prev = node;
592
593 /* insert the node into the schema tree */
594 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100595 if (value) {
596 lydict_remove(module->ctx, node->name);
597 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100598 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100599 return NULL;
600 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100601 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100602}
603
Pavol Vican8c793992016-07-15 10:44:57 +0200604void *
605yang_read_action(struct lys_module *module, struct lys_node *parent, char *value)
606{
607 struct lys_node *node;
608
Michal Vaskobb174852016-07-25 11:00:21 +0200609 if (module->version != 2) {
610 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
611 return NULL;
612 }
613
Pavol Vican8c793992016-07-15 10:44:57 +0200614 for (node = parent; node; node = lys_parent(node)) {
615 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
Pavol Vicanbbe77822016-07-15 12:53:07 +0200616 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Pavol Vican8c793992016-07-15 10:44:57 +0200617 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
618 return NULL;
619 }
620 }
621 return yang_read_node(module, parent, value, LYS_ACTION, sizeof(struct lys_node_rpc_action));
622}
623
Pavol Vican8c82fa82016-02-10 13:13:24 +0100624int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200625yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100626{
627 int ret;
628
629 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100630 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100631 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100632 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100633 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100634 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100635 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200636 default:
637 free(value);
638 LOGINT;
639 ret = EXIT_FAILURE;
640 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100641 }
642 return ret;
643}
644
645int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200646yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100647{
648 int ret;
649
650 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100651 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100652 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100653 break;
654 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100655 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100656 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100657 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100658 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100659 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200660 default:
661 free(value);
662 LOGINT;
663 ret = EXIT_FAILURE;
664 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100665 }
666 return ret;
667}
Pavol Vican5de33492016-02-22 14:03:24 +0100668
669int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100670yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100671{
672 char *exp, *value;
673
674 exp = value = (char *) list->keys;
Pavol Vicanbbe77822016-07-15 12:53:07 +0200675 list->keys_size = 0;
Pavol Vican5de33492016-02-22 14:03:24 +0100676 while ((value = strpbrk(value, " \t\n"))) {
677 list->keys_size++;
678 while (isspace(*value)) {
679 value++;
680 }
681 }
682 list->keys_size++;
683 list->keys = calloc(list->keys_size, sizeof *list->keys);
684 if (!list->keys) {
685 LOGMEM;
686 goto error;
687 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100688 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp) == -1) {
Pavol Vican5de33492016-02-22 14:03:24 +0100689 goto error;
690 }
691 free(exp);
692 return EXIT_SUCCESS;
693
694error:
695 free(exp);
696 return EXIT_FAILURE;
697}
698
699int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100700yang_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 +0100701{
702 int i, j;
703 char *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200704 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100705
706 /* count the number of unique leafs in the value */
707 vaux = value;
708 while ((vaux = strpbrk(vaux, " \t\n"))) {
709 unique->expr_size++;
710 while (isspace(*vaux)) {
711 vaux++;
712 }
713 }
714 unique->expr_size++;
715 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
716 if (!unique->expr) {
717 LOGMEM;
718 goto error;
719 }
720
721 for (i = 0; i < unique->expr_size; i++) {
722 vaux = strpbrk(value, " \t\n");
723 if (!vaux) {
724 /* the last token, lydict_insert() will count its size on its own */
725 vaux = value;
726 }
727
728 /* store token into unique structure */
729 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
730
731 /* check that the expression does not repeat */
732 for (j = 0; j < i; j++) {
733 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100734 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
735 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100736 goto error;
737 }
738 }
739 /* try to resolve leaf */
740 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200741 unique_info = malloc(sizeof *unique_info);
742 unique_info->list = (struct lys_node *)list;
743 unique_info->expr = unique->expr[i];
744 unique_info->trg_type = &unique->trg_type;
745 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200746 goto error;
747 }
Pavol Vican85f12022016-03-05 16:30:35 +0100748 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200749 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100750 goto error;
751 }
752 }
753
754 /* move to next token */
755 value = vaux;
756 while(isspace(*value)) {
757 value++;
758 }
759 }
760
761 return EXIT_SUCCESS;
762
763error:
764 return EXIT_FAILURE;
765}
766
767int
Pavol Vican5de33492016-02-22 14:03:24 +0100768yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
769{
770 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100771 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100772
773 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100774 str = (char *)list->unique[k].expr;
775 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100776 goto error;
777 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100778 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100779 }
780 return EXIT_SUCCESS;
781
782error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100783 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100784 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100785}
786
Pavol Vican1ff0e222016-02-26 12:27:01 +0100787static int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100788yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100789{
790 const char *value, *tmp;
791 int rc, ret = EXIT_FAILURE;
792
793 value = tmp = type->info.lref.path;
794 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100795 value = transform_schema2json(module, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100796 if (!value) {
797 goto end;
798 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100799 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100800 lydict_remove(module->ctx, value);
801
802 if (rc == -1) {
803 goto end;
804 }
805
806 ret = EXIT_SUCCESS;
807
808end:
809 lydict_remove(module->ctx, tmp);
810 return ret;
811}
812
Pavol Vican73e7c992016-02-24 12:18:05 +0100813int
Radek Krejci3a5501d2016-07-18 22:03:34 +0200814yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, int tpdftype, struct unres_schema *unres)
Pavol Vican73e7c992016-02-24 12:18:05 +0100815{
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200816 int i, j, rc;
Pavol Vican73e7c992016-02-24 12:18:05 +0100817 int ret = -1;
818 const char *name, *value;
819 LY_DATA_TYPE base;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200820 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200821 struct lys_type *dertype;
822 struct lys_type_enum *enms_sc = NULL;
823 struct lys_type_bit *bits_sc = NULL;
824 struct lys_type_bit bit_tmp;
825
Pavol Vican73e7c992016-02-24 12:18:05 +0100826
Pavol Vican6b072512016-04-04 10:50:21 +0200827 base = typ->base;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100828 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100829 if (!value) {
830 goto error;
831 }
832
833 i = parse_identifier(value);
834 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100835 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100836 lydict_remove(module->ctx, value);
837 goto error;
838 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200839 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100840 name = value;
841 if (value[i]) {
842 typ->type->module_name = lydict_insert(module->ctx, value, i);
843 name += i;
844 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100845 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100846 lydict_remove(module->ctx, value);
847 goto error;
848 }
849 ++name;
850 }
851
852 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100853 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100854 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, typ->type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200855 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100856 goto error;
857
Michal Vasko01c6fd22016-05-20 11:43:05 +0200858 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100859 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200860 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200861 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100862 ret = EXIT_FAILURE;
863 goto error;
864 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200865 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200866
867 if (typ->type->base == LY_TYPE_INGRP) {
868 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
869 * unresolved item left inside the grouping */
870 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
871 if (siter) {
872 if (!((struct lys_node_grp *)siter)->nacm) {
873 LOGINT;
874 goto error;
875 }
876 ((struct lys_node_grp *)siter)->nacm--;
877 } else {
878 LOGINT;
879 goto error;
880 }
881 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100882 typ->type->base = typ->type->der->type.base;
883 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100884 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100885 }
886 switch (base) {
887 case LY_TYPE_STRING:
888 if (typ->type->base == LY_TYPE_BINARY) {
889 if (typ->type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100890 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100891 goto error;
892 }
893 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100894 if (typ->type->info.binary.length && lyp_check_length_range(typ->type->info.binary.length->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100895 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100896 goto error;
897 }
898 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100899 if (typ->type->info.str.length && lyp_check_length_range(typ->type->info.str.length->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100900 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100901 goto error;
902 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100903 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200904 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100905 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100906 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100907 break;
908 case LY_TYPE_DEC64:
909 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100910 if (typ->type->info.dec64.range && lyp_check_length_range(typ->type->info.dec64.range->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100911 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100912 goto error;
913 }
Pavol Vican07ea68d2016-02-25 12:01:37 +0100914 /* mandatory sub-statement(s) check */
915 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
916 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100917 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100918 goto error;
919 }
920 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
921 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100922 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100923 goto error;
924 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100925 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
926 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100927 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100928 goto error;
929 }
930 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100931 if (typ->type->info.num.range && lyp_check_length_range(typ->type->info.num.range->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100932 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100933 goto error;
934 }
935 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200936 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100937 goto error;
938 }
939 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100940 case LY_TYPE_ENUM:
941 if (typ->type->base != LY_TYPE_ENUM) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200942 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100943 goto error;
944 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200945 dertype = &typ->type->der->type;
946
947 if (!dertype->der) {
948 if (!typ->type->info.enums.count) {
949 /* type is derived directly from buit-in enumeartion type and enum statement is required */
950 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
951 goto error;
952 }
953 } else {
954 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
955 if (module->version < 2 && typ->type->info.enums.count) {
956 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
957 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
958 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
959 goto error;
960 }
961
962 /* restricted enumeration type - the name MUST be used in the base type */
963 enms_sc = dertype->info.enums.enm;
964 for(i = 0; i < typ->type->info.enums.count; i++) {
965 for (j = 0; j < dertype->info.enums.count; j++) {
966 if (ly_strequal(enms_sc[j].name, typ->type->info.enums.enm[i].name, 1)) {
967 break;
968 }
969 }
970 if (j == dertype->info.enums.count) {
971 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
972 goto error;
973 }
974
975 if (typ->type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
976 /* automatically assign value from base type */
977 typ->type->info.enums.enm[i].value = enms_sc[j].value;
978 } else {
979 /* check that the assigned value corresponds to the original
980 * value of the enum in the base type */
981 if (typ->type->info.enums.enm[i].value != enms_sc[j].value) {
982 /* typ->type->info.enums.enm[i].value - assigned value in restricted enum
983 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
984 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].value,
985 typ->type->info.enums.enm[i].name, enms_sc[j].value);
986 goto error;
987 }
988 }
989 }
Pavol Vican79a763d2016-02-25 15:41:27 +0100990 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100991 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100992 case LY_TYPE_BITS:
993 if (typ->type->base != LY_TYPE_BITS) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200994 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100995 goto error;
996 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200997 dertype = &typ->type->der->type;
998
999 if (!dertype->der) {
1000 if (!typ->type->info.bits.count) {
1001 /* type is derived directly from buit-in bits type and bit statement is required */
1002 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
1003 goto error;
1004 }
1005 } else {
1006 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
1007 if (module->version < 2 && typ->type->info.bits.count) {
1008 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
1009 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
1010 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
1011 goto error;
1012 }
1013
1014 bits_sc = dertype->info.bits.bit;
1015 for (i = 0; i < typ->type->info.bits.count; i++) {
1016 for (j = 0; j < dertype->info.bits.count; j++) {
1017 if (ly_strequal(bits_sc[j].name, typ->type->info.bits.bit[i].name, 1)) {
1018 break;
1019 }
1020 }
1021 if (j == dertype->info.bits.count) {
1022 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].name);
1023 goto error;
1024 }
1025
1026 /* restricted bits type */
1027 if (typ->type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
1028 /* automatically assign position from base type */
1029 typ->type->info.bits.bit[i].pos = bits_sc[j].pos;
1030 } else {
1031 /* check that the assigned position corresponds to the original
1032 * position of the bit in the base type */
1033 if (typ->type->info.bits.bit[i].pos != bits_sc[j].pos) {
1034 /* typ->type->info.bits.bit[i].pos - assigned position in restricted bits
1035 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
1036 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].pos,
1037 typ->type->info.bits.bit[i].name, bits_sc[j].pos);
1038 goto error;
1039 }
1040 }
1041 }
Pavol Vican03a59442016-03-21 15:23:45 +01001042 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001043
1044 for (i = typ->type->info.bits.count - 1; i > 0; i--) {
1045 j = i;
1046
1047 /* keep them ordered by position */
1048 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1049 /* switch them */
1050 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1051 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1052 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
1053 j--;
1054 }
Pavol Vican03a59442016-03-21 15:23:45 +01001055 }
1056 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +01001057 case LY_TYPE_LEAFREF:
Pavol Vican6b072512016-04-04 10:50:21 +02001058 if (typ->type->base == LY_TYPE_IDENT && (typ->flags & LYS_TYPE_BASE)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001059 if (yang_read_identyref(module, typ->type, unres)) {
Pavol Vican1ff0e222016-02-26 12:27:01 +01001060 goto error;
1061 }
Pavol Vican191613a2016-02-26 16:21:32 +01001062 } else if (typ->type->base == LY_TYPE_LEAFREF) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001063 /* flag resolving for later use */
1064 if (!tpdftype) {
1065 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1066 if (siter) {
1067 /* just a flag - do not resolve */
1068 tpdftype = 1;
1069 }
1070 }
1071
Pavol Vican6b072512016-04-04 10:50:21 +02001072 if (typ->type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +01001073 value = typ->type->info.lref.path;
1074 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001075 typ->type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +01001076 lydict_remove(module->ctx, value);
1077 if (!typ->type->info.lref.path) {
1078 goto error;
1079 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001080 /* try to resolve leafref path only when this is instantiated
1081 * leaf, so it is not:
1082 * - typedef's type,
1083 * - in grouping definition,
1084 * - just instantiated in a grouping definition,
1085 * because in those cases the nodes referenced in path might not be present
1086 * and it is not a bug. */
1087 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +01001088 goto error;
1089 }
Pavol Vican6b072512016-04-04 10:50:21 +02001090 } else if (!typ->type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001091 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +01001092 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +02001093 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001094 /* copy leafref definition into the derived type */
1095 typ->type->info.lref.path = lydict_insert(module->ctx, typ->type->der->type.info.lref.path, 0);
1096 /* and resolve the path at the place we are (if not in grouping/typedef) */
1097 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001098 goto error;
1099 }
Radek Krejci742be352016-07-17 12:18:54 +02001100
Michal Vasko01c6fd22016-05-20 11:43:05 +02001101 /* add pointer to leafref target, only on leaves (not in typedefs) */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001102 if (typ->type->info.lref.target && lys_leaf_add_leafref_target(typ->type->info.lref.target, (struct lys_node *)typ->type->parent)) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001103 goto error;
1104 }
Pavol Vican191613a2016-02-26 16:21:32 +01001105 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001106 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001107 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001108 goto error;
1109 }
1110 break;
1111 case LY_TYPE_IDENT:
1112 if (typ->type->der->type.der) {
1113 /* this is just a derived type with no base specified/required */
1114 break;
1115 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001116 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Pavol Vican1ff0e222016-02-26 12:27:01 +01001117 goto error;
1118 }
1119 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001120 case LY_TYPE_UNION:
1121 if (typ->type->base != LY_TYPE_UNION) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001122 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001123 goto error;
1124 }
1125 if (!typ->type->info.uni.types) {
1126 if (typ->type->der->type.der) {
1127 /* this is just a derived type with no additional type specified/required */
1128 break;
1129 }
Pavol Vican0adf01d2016-03-22 12:29:33 +01001130 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +01001131 goto error;
1132 }
1133 for (i = 0; i < typ->type->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001134 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i],
Michal Vasko5d631402016-07-21 13:15:15 +02001135 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001136 goto error;
1137 }
1138 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001139 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001140 goto error;
1141 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001142 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001143 goto error;
1144 }
1145 }
1146 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001147
1148 default:
1149 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
1150 if (typ->type->base != base) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001151 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001152 goto error;
1153 }
1154 } else {
1155 LOGINT;
1156 goto error;
1157 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001158 }
1159 return EXIT_SUCCESS;
1160
1161error:
1162 if (typ->type->module_name) {
1163 lydict_remove(module->ctx, typ->type->module_name);
1164 typ->type->module_name = NULL;
1165 }
1166 return ret;
1167}
1168
1169void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001170yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001171{
1172 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001173 struct type_deviation *dev;
1174 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001175
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001176 typ = calloc(1, sizeof *typ);
1177 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001178 LOGMEM;
1179 return NULL;
1180 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001181
1182 typ->flags = LY_YANG_STRUCTURE_FLAG;
1183 switch (type) {
1184 case LEAF_KEYWORD:
1185 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1186 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1187 typ->type = &((struct lys_node_leaf *)parent)->type;
1188 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001189 case LEAF_LIST_KEYWORD:
1190 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1191 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1192 typ->type = &((struct lys_node_leaflist *)parent)->type;
1193 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001194 case UNION_KEYWORD:
1195 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1196 typ->type = (struct lys_type *)parent;
1197 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001198 case TYPEDEF_KEYWORD:
1199 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1200 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001201 break;
1202 case REPLACE_KEYWORD:
1203 /* deviation replace type*/
1204 dev = (struct type_deviation *)parent;
1205 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001206 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001207 goto error;
1208 }
1209 /* check target node type */
1210 if (dev->target->nodetype == LYS_LEAF) {
1211 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1212 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1213 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1214 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001215 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1216 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001217 goto error;
1218 }
1219
1220 /* remove type and initialize it */
1221 lys_type_free(module->ctx, typ->type);
1222 tmp_parent = typ->type->parent;
1223 memset(typ->type, 0, sizeof *typ->type);
1224 typ->type->parent = tmp_parent;
1225
1226 /* replace it with the value specified in deviation */
1227 /* HACK for unres */
1228 typ->type->der = (struct lys_tpdf *)typ;
1229 dev->deviate->type = typ->type;
1230 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001231 default:
1232 goto error;
1233 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001234 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001235 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001236 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001237
1238error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001239 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001240 free(typ);
1241 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001242}
1243
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001244void
1245yang_delete_type(struct lys_module *module, struct yang_type *stype)
1246{
1247 int i;
1248
1249 stype->type->base = stype->base;
1250 stype->type->der = NULL;
1251 lydict_remove(module->ctx, stype->name);
1252 if (stype->base == LY_TYPE_UNION) {
1253 for (i = 0; i < stype->type->info.uni.count; i++) {
1254 if (stype->type->info.uni.types[i].der) {
1255 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1256 }
1257 }
1258 }
1259 free(stype);
1260}
1261
Pavol Vican73e7c992016-02-24 12:18:05 +01001262void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001263yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001264{
1265 struct lys_restr **length;
1266
Pavol Vican6b072512016-04-04 10:50:21 +02001267 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001268 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001269 typ->base = LY_TYPE_STRING;
1270 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001271 length = &typ->type->info.binary.length;
1272 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001273 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001274 goto error;
1275 }
1276
1277 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001278 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001279 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001280 }
1281 *length = calloc(1, sizeof **length);
1282 if (!*length) {
1283 LOGMEM;
1284 goto error;
1285 }
1286 (*length)->expr = lydict_insert_zc(module->ctx, value);
1287 return *length;
1288
1289error:
1290 free(value);
1291 return NULL;
1292
1293}
Pavol Vican1c203db2016-02-24 14:05:23 +01001294
Pavol Vican6eecf302016-08-10 11:09:05 +02001295int
1296yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001297{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001298 char *buf;
1299 size_t len;
1300
Michal Vasko0aee5c12016-06-17 14:27:26 +02001301 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001302 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001303 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001304 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001305
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001306 len = strlen(value);
1307 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001308
1309 if (!buf) {
1310 LOGMEM;
1311 free(value);
1312 return EXIT_FAILURE;
1313 }
1314
1315 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001316 strcpy(&buf[1], value);
1317 free(value);
1318
Pavol Vican6eecf302016-08-10 11:09:05 +02001319 pattern->expr = lydict_insert_zc(module->ctx, buf);
1320 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001321}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001322
1323void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001324yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001325{
Pavol Vican6b072512016-04-04 10:50:21 +02001326 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001327 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001328 goto error;
1329 }
Pavol Vican6b072512016-04-04 10:50:21 +02001330 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001331 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001332 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001333 goto error;
1334 }
1335 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1336 if (!typ->type->info.dec64.range) {
1337 LOGMEM;
1338 goto error;
1339 }
1340 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1341 return typ->type->info.dec64.range;
1342
1343error:
1344 free(value);
1345 return NULL;
1346}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001347
1348int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001349yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001350{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001351 unsigned int i;
1352
Pavol Vican6b072512016-04-04 10:50:21 +02001353 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1354 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001355 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001356 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001357 goto error;
1358 }
1359 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001360 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001361 goto error;
1362 }
1363 /* range check */
1364 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001365 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001366 goto error;
1367 }
1368 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001369 typ->type->info.dec64.div = 10;
1370 for (i = 1; i < value; i++) {
1371 typ->type->info.dec64.div *= 10;
1372 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001373 return EXIT_SUCCESS;
1374
1375error:
1376 return EXIT_FAILURE;
1377}
Pavol Vican79a763d2016-02-25 15:41:27 +01001378
1379void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001380yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001381{
1382 struct lys_type_enum *enm;
1383 int i;
1384
1385 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1386 enm->name = lydict_insert_zc(module->ctx, value);
1387
1388 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1389 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001390 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001391 goto error;
1392 }
1393
1394 /* check the name uniqueness */
1395 for (i = 0; i < typ->type->info.enums.count; i++) {
1396 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[typ->type->info.enums.count].name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001397 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001398 goto error;
1399 }
1400 }
1401
1402 typ->type->info.enums.count++;
1403 return enm;
1404
1405error:
1406 typ->type->info.enums.count++;
1407 return NULL;
1408}
1409
1410int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001411yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001412{
1413 int i, j;
1414
1415 if (!assign) {
1416 /* assign value automatically */
1417 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001418 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001419 goto error;
1420 }
1421 enm->value = *value;
1422 enm->flags |= LYS_AUTOASSIGNED;
1423 (*value)++;
1424 }
1425
1426 /* check that the value is unique */
1427 j = typ->type->info.enums.count-1;
1428 for (i = 0; i < j; i++) {
1429 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001430 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001431 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1432 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001433 goto error;
1434 }
1435 }
1436
1437 return EXIT_SUCCESS;
1438
1439error:
1440 return EXIT_FAILURE;
1441}
Pavol Vican9887c682016-02-29 11:32:01 +01001442
1443void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001444yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001445{
1446 int i;
1447 struct lys_type_bit *bit;
1448
1449 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001450 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001451 free(value);
1452 goto error;
1453 }
1454 bit->name = lydict_insert_zc(module->ctx, value);
1455
1456 /* check the name uniqueness */
1457 for (i = 0; i < typ->type->info.bits.count; i++) {
1458 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001459 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001460 typ->type->info.bits.count++;
1461 goto error;
1462 }
1463 }
1464 typ->type->info.bits.count++;
1465 return bit;
1466
1467error:
1468 return NULL;
1469}
1470
1471int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001472yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001473{
1474 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001475
1476 if (!assign) {
1477 /* assign value automatically */
1478 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001479 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001480 goto error;
1481 }
1482 bit->pos = (uint32_t)*value;
1483 bit->flags |= LYS_AUTOASSIGNED;
1484 (*value)++;
1485 }
1486
1487 j = typ->type->info.bits.count - 1;
1488 /* check that the value is unique */
1489 for (i = 0; i < j; i++) {
1490 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001491 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 +01001492 goto error;
1493 }
1494 }
1495
Pavol Vican9887c682016-02-29 11:32:01 +01001496 return EXIT_SUCCESS;
1497
1498error:
1499 return EXIT_FAILURE;
1500}
Pavol Vican0df02b02016-03-01 10:28:50 +01001501
1502void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001503yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001504{
1505 struct lys_tpdf *ret;
Pavol Vican810892e2016-07-12 16:55:34 +02001506 struct lys_node *root;
Pavol Vican0df02b02016-03-01 10:28:50 +01001507
Pavol Vican810892e2016-07-12 16:55:34 +02001508 root = (parent) ? NULL : lys_main_module(module)->data;
1509 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent) || yang_check_typedef_identif(root, parent, value)) {
Pavol Vican0df02b02016-03-01 10:28:50 +01001510 free(value);
1511 return NULL;
1512 }
Pavol Vican810892e2016-07-12 16:55:34 +02001513
Pavol Vican0df02b02016-03-01 10:28:50 +01001514 if (!parent) {
1515 ret = &module->tpdf[module->tpdf_size];
Pavol Vican0df02b02016-03-01 10:28:50 +01001516 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001517 } else {
1518 switch (parent->nodetype) {
1519 case LYS_GROUPING:
1520 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001521 ((struct lys_node_grp *)parent)->tpdf_size++;
1522 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001523 case LYS_CONTAINER:
1524 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1525 ((struct lys_node_container *)parent)->tpdf_size++;
1526 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001527 case LYS_LIST:
1528 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1529 ((struct lys_node_list *)parent)->tpdf_size++;
1530 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001531 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001532 case LYS_ACTION:
1533 ret = &((struct lys_node_rpc_action *)parent)->tpdf[((struct lys_node_rpc_action *)parent)->tpdf_size];
1534 ((struct lys_node_rpc_action *)parent)->tpdf_size++;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001535 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001536 case LYS_INPUT:
1537 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001538 ret = &((struct lys_node_inout *)parent)->tpdf[((struct lys_node_inout *)parent)->tpdf_size];
1539 ((struct lys_node_inout *)parent)->tpdf_size++;
Pavol Vican531a9132016-03-03 10:10:09 +01001540 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001541 case LYS_NOTIF:
1542 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1543 ((struct lys_node_notif *)parent)->tpdf_size++;
1544 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001545 default:
1546 /* another type of nodetype is error*/
1547 LOGINT;
1548 free(value);
1549 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001550 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001551 }
1552
Pavol Vican79436472016-04-04 11:22:02 +02001553 ret->type.parent = ret;
Pavol Vican0df02b02016-03-01 10:28:50 +01001554 ret->name = lydict_insert_zc(module->ctx, value);
1555 ret->module = module;
1556 return ret;
1557}
Pavol Vican1003ead2016-03-02 12:24:52 +01001558
1559void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001560yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001561{
1562 struct lys_refine *rfn;
1563
1564 rfn = &uses->refine[uses->refine_size];
1565 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001566 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001567 free(value);
1568 if (!rfn->target_name) {
1569 return NULL;
1570 }
1571 return rfn;
1572}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001573
1574void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001575yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001576{
1577 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001578
1579 if (parent) {
1580 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1581 } else {
1582 aug = &module->augment[module->augment_size];
1583 }
1584 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001585 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001586 free(value);
1587 if (!aug->target_name) {
1588 return NULL;
1589 }
1590 aug->parent = parent;
1591 aug->module = module;
1592 if (parent) {
1593 ((struct lys_node_uses *)parent)->augment_size++;
1594 } else {
1595 module->augment_size++;
1596 }
1597 return aug;
1598}
Pavol Vican220e5a12016-03-03 14:19:43 +01001599
1600void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001601yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001602{
1603 struct lys_node *dev_target = NULL;
1604 struct lys_deviation *dev;
1605 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001606 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001607
Pavol Vican220e5a12016-03-03 14:19:43 +01001608 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001609 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001610 free(value);
1611 if (!dev->target_name) {
1612 goto error;
1613 }
1614
Pavol Vican974377b2016-03-23 00:38:53 +01001615 deviation = calloc(1, sizeof *deviation);
1616 if (!deviation) {
1617 LOGMEM;
1618 goto error;
1619 }
1620
Pavol Vican220e5a12016-03-03 14:19:43 +01001621 /* resolve target node */
1622 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1623 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001624 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001625 goto error;
1626 }
Radek Krejcic4283442016-04-22 09:19:27 +02001627 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001628 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1629 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001630 goto error;
1631 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001632
Michal Vasko89563fc2016-07-28 16:19:35 +02001633 lys_node_module(dev_target)->deviated = 1;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001634
Pavol Vican220e5a12016-03-03 14:19:43 +01001635 /*save pointer to the deviation and deviated target*/
1636 deviation->deviation = dev;
1637 deviation->target = dev_target;
1638
Pavol Vican220e5a12016-03-03 14:19:43 +01001639 return deviation;
1640
1641error:
1642 free(deviation);
1643 lydict_remove(module->ctx, dev->target_name);
1644 return NULL;
1645}
Pavol Vican4c90c642016-03-03 15:06:47 +01001646
1647int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001648yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001649{
1650 int i;
1651
1652 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001653 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001654 return EXIT_FAILURE;
1655 }
1656 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1657
1658 /* you cannot remove a key leaf */
1659 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1660 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1661 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001662 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1663 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001664 return EXIT_FAILURE;
1665 }
1666 }
1667 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001668
Pavol Vican4c90c642016-03-03 15:06:47 +01001669 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001670 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001671 dev->deviation->orig_node = dev->target;
1672
1673 dev->deviation->deviate_size = 1;
1674 return EXIT_SUCCESS;
1675}
Pavol Vican85f12022016-03-05 16:30:35 +01001676
1677int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001678yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001679{
1680 struct unres_schema tmp_unres;
1681
1682 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1683 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1684 dev->deviation->deviate_size++;
1685 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001686 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1687 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001688 return EXIT_FAILURE;
1689 }
1690
1691 /* store a shallow copy of the original node */
1692 if (!dev->deviation->orig_node) {
1693 memset(&tmp_unres, 0, sizeof tmp_unres);
1694 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1695 /* just to be safe */
1696 if (tmp_unres.count) {
1697 LOGINT;
1698 return EXIT_FAILURE;
1699 }
1700 }
1701
1702 return EXIT_SUCCESS;
1703}
1704
1705int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001706yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001707{
1708 const char **stritem;
1709
1710 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001711 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001712 free(value);
1713 goto error;
1714 }
1715
1716 /* check target node type */
1717 if (dev->target->nodetype == LYS_LEAFLIST) {
1718 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1719 } else if (dev->target->nodetype == LYS_LEAF) {
1720 stritem = &((struct lys_node_leaf *)dev->target)->units;
1721 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001722 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1723 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001724 free(value);
1725 goto error;
1726 }
1727
1728 dev->deviate->units = lydict_insert_zc(ctx, value);
1729
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001730 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1731 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001732 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001733 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1734 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001735 goto error;
1736 }
1737 /* remove current units value of the target */
1738 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001739 } else {
1740 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1741 /* check that there is no current value */
1742 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001743 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1744 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001745 goto error;
1746 }
1747 } else { /* replace */
1748 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001749 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1750 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001751 goto error;
1752 }
1753 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001754 /* remove current units value of the target ... */
1755 lydict_remove(ctx, *stritem);
1756
1757 /* ... and replace it with the value specified in deviation */
1758 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1759 }
1760
Pavol Vican85f12022016-03-05 16:30:35 +01001761 return EXIT_SUCCESS;
1762
1763error:
1764 return EXIT_FAILURE;
1765}
1766
1767int
Pavol Vican974377b2016-03-23 00:38:53 +01001768yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001769{
Pavol Vican85f12022016-03-05 16:30:35 +01001770 /* check target node type */
1771 switch (dev->target->nodetype) {
1772 case LYS_LEAF:
1773 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1774 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1775 break;
1776 case LYS_CONTAINER:
1777 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1778 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1779 break;
1780 case LYS_LEAFLIST:
1781 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1782 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1783 break;
1784 case LYS_LIST:
1785 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1786 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1787 break;
1788 case LYS_ANYXML:
1789 dev->trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1790 dev->trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
1791 break;
1792 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001793 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1794 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001795 goto error;
1796 }
1797
1798 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1799 /* reallocate the must array of the target */
1800 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1801 if (!dev->deviate->must) {
1802 LOGMEM;
1803 goto error;
1804 }
1805 *dev->trg_must = dev->deviate->must;
1806 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1807 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001808 } else {
1809 /* LY_DEVIATE_DEL */
1810 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1811 if (!dev->deviate->must) {
1812 LOGMEM;
1813 goto error;
1814 }
Pavol Vican85f12022016-03-05 16:30:35 +01001815 }
1816
1817 return EXIT_SUCCESS;
1818
1819error:
1820 return EXIT_FAILURE;
1821}
1822
1823int
Pavol Vican974377b2016-03-23 00:38:53 +01001824yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001825{
Pavol Vican85f12022016-03-05 16:30:35 +01001826 struct lys_node_list *list;
1827
1828 /* check target node type */
1829 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001830 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1831 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001832 goto error;
1833 }
1834
1835 list = (struct lys_node_list *)dev->target;
1836 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1837 /* reallocate the unique array of the target */
1838 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1839 if (!dev->deviate->unique) {
1840 LOGMEM;
1841 goto error;
1842 }
1843 list->unique = dev->deviate->unique;
1844 dev->deviate->unique = &list->unique[list->unique_size];
1845 dev->deviate->unique_size = c_uniq;
1846 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001847 } else {
1848 /* LY_DEVIATE_DEL */
1849 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1850 if (!dev->deviate->unique) {
1851 LOGMEM;
1852 goto error;
1853 }
Pavol Vican85f12022016-03-05 16:30:35 +01001854 }
1855
1856 return EXIT_SUCCESS;
1857
1858error:
1859 return EXIT_FAILURE;
1860}
1861
1862int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001863yang_read_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001864{
1865 int rc;
1866 struct lys_node_choice *choice;
1867 struct lys_node_leaf *leaf;
1868 struct lys_node *node;
1869
1870 if (dev->deviate->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001871 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "default", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001872 free(value);
1873 goto error;
1874 }
1875
1876 dev->deviate->dflt = lydict_insert_zc(ctx, value);
1877
1878 if (dev->target->nodetype == LYS_CHOICE) {
1879 choice = (struct lys_node_choice *)dev->target;
1880
Pavol Vican85f12022016-03-05 16:30:35 +01001881 rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
1882 if (rc || !node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001883 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vican85f12022016-03-05 16:30:35 +01001884 goto error;
1885 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001886 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1887 if (!choice->dflt || (choice->dflt != node)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001888 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1889 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001890 goto error;
1891 }
1892 choice->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001893 } else {
1894 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1895 /* check that there is no current value */
1896 if (choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001897 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1898 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001899 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001900 } else if (choice->flags & LYS_MAND_TRUE) {
1901 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
1902 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
1903 goto error;
Pavol Vican4766aca2016-03-07 12:42:36 +01001904 }
1905 } else { /* replace*/
1906 if (!choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001907 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1908 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001909 goto error;
1910 }
1911 }
1912
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001913 choice->dflt = node;
1914 if (!choice->dflt) {
1915 /* default branch not found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001916 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001917 goto error;
1918 }
Pavol Vican85f12022016-03-05 16:30:35 +01001919 }
1920 } else if (dev->target->nodetype == LYS_LEAF) {
1921 leaf = (struct lys_node_leaf *)dev->target;
1922
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001923 if (dev->deviate->mod == LY_DEVIATE_DEL) {
Michal Vaskob42b6972016-06-06 14:21:30 +02001924 if (!leaf->dflt || !ly_strequal(leaf->dflt, dev->deviate->dflt, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001925 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1926 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001927 goto error;
1928 }
1929 /* remove value */
1930 lydict_remove(ctx, leaf->dflt);
1931 leaf->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001932 } else {
1933 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1934 /* check that there is no current value */
1935 if (leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001936 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1937 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001938 goto error;
Pavol Vicanfdf81c42016-04-05 15:55:31 +02001939 } else if (leaf->flags & LYS_MAND_TRUE) {
1940 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1941 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "leaf");
1942 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on leaf with \"mandatory\".");
1943 goto error;
Pavol Vican4766aca2016-03-07 12:42:36 +01001944 }
1945 } else { /* replace*/
1946 if (!leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001947 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1948 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001949 goto error;
1950 }
1951 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001952 /* remove value */
1953 lydict_remove(ctx, leaf->dflt);
Pavol Vican85f12022016-03-05 16:30:35 +01001954
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001955 /* set new value */
1956 leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
1957 }
Pavol Vican85f12022016-03-05 16:30:35 +01001958 } else {
1959 /* invalid target for default value */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001960 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1961 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001962 goto error;
1963 }
1964
1965 return EXIT_SUCCESS;
1966
1967error:
1968 return EXIT_FAILURE;
1969}
1970
1971int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001972yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001973{
1974 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001975 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001976 goto error;
1977 }
1978
1979 /* for we deviate from RFC 6020 and allow config property even it is/is not
1980 * specified in the target explicitly since config property inherits. So we expect
1981 * that config is specified in every node. But for delete, we check that the value
1982 * is the same as here in deviation
1983 */
1984 dev->deviate->flags |= value;
1985
1986 /* add and replace are the same in this case */
1987 /* remove current config value of the target ... */
1988 dev->target->flags &= ~LYS_CONFIG_MASK;
1989
1990 /* ... and replace it with the value specified in deviation */
1991 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1992
1993 return EXIT_SUCCESS;
1994
1995error:
1996 return EXIT_FAILURE;
1997}
1998
1999int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002000yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002001{
Radek Krejcie00d2312016-08-12 15:27:49 +02002002 struct lys_node *parent;
2003
Pavol Vican85f12022016-03-05 16:30:35 +01002004 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002005 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002006 goto error;
2007 }
2008
2009 /* check target node type */
2010 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002011 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2012 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002013 goto error;
2014 }
2015
2016 dev->deviate->flags |= value;
2017
2018 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2019 /* check that there is no current value */
2020 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002021 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2022 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002023 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02002024 } else {
2025 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
2026 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2027 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
2028 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2029 goto error;
2030 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
2031 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
2032 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
2033 goto error;
2034 }
Pavol Vican85f12022016-03-05 16:30:35 +01002035 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002036 } else { /* replace */
2037 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002038 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2039 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002040 goto error;
2041 }
Pavol Vican85f12022016-03-05 16:30:35 +01002042 }
2043
Pavol Vican85f12022016-03-05 16:30:35 +01002044 /* remove current mandatory value of the target ... */
2045 dev->target->flags &= ~LYS_MAND_MASK;
2046
2047 /* ... and replace it with the value specified in deviation */
2048 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2049
Radek Krejcie00d2312016-08-12 15:27:49 +02002050 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2051 for (parent = dev->target->parent;
2052 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2053 parent = parent->parent) {
2054 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2055 /* stop also on presence containers */
2056 break;
2057 }
2058 }
2059 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2060 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2061 if (lyp_check_mandatory_choice(parent)) {
2062 goto error;
2063 }
2064 }
2065
Pavol Vican85f12022016-03-05 16:30:35 +01002066 return EXIT_SUCCESS;
2067
2068error:
2069 return EXIT_FAILURE;
2070}
2071
2072int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002073yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002074{
2075 uint32_t *ui32val;
2076
2077 /* check target node type */
2078 if (dev->target->nodetype == LYS_LEAFLIST) {
2079 if (type) {
2080 ui32val = &((struct lys_node_leaflist *)dev->target)->max;
2081 } else {
2082 ui32val = &((struct lys_node_leaflist *)dev->target)->min;
2083 }
2084 } else if (dev->target->nodetype == LYS_LIST) {
2085 if (type) {
2086 ui32val = &((struct lys_node_list *)dev->target)->max;
2087 } else {
2088 ui32val = &((struct lys_node_list *)dev->target)->min;
2089 }
2090 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002091 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2092 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 +01002093 goto error;
2094 }
2095
2096 if (type) {
2097 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002098 dev->deviate->max_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01002099 } else {
2100 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002101 dev->deviate->min_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01002102 }
2103
2104 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2105 /* check that there is no current value */
2106 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002107 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2108 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002109 goto error;
2110 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002111 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2112 /* unfortunately, there is no way to check reliably that there
2113 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002114 }
2115
2116 /* add (already checked) and replace */
2117 /* set new value specified in deviation */
2118 *ui32val = value;
2119
2120 return EXIT_SUCCESS;
2121
2122error:
2123 return EXIT_FAILURE;
2124}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002125
2126int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002127yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002128{
2129 int i;
2130
2131 /* find must to delete, we are ok with just matching conditions */
2132 for (i = 0; i < *dev->trg_must_size; i++) {
2133 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2134 /* we have a match, free the must structure ... */
2135 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2136 /* ... and maintain the array */
2137 (*dev->trg_must_size)--;
2138 if (i != *dev->trg_must_size) {
2139 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2140 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2141 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2142 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2143 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2144 }
2145 if (!(*dev->trg_must_size)) {
2146 free(*dev->trg_must);
2147 *dev->trg_must = NULL;
2148 } else {
2149 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2150 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2151 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2152 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2153 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2154 }
2155
2156 i = -1; /* set match flag */
2157 break;
2158 }
2159 }
2160 if (i != -1) {
2161 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002162 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2163 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002164 return EXIT_FAILURE;
2165 }
2166
2167 return EXIT_SUCCESS;
2168}
2169
2170int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002171yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002172{
2173 struct lys_node_list *list;
2174 int i, j;
2175
2176 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002177 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002178 dev->deviate->unique_size++;
2179 goto error;
2180 }
2181
2182 /* find unique structures to delete */
2183 for (i = 0; i < list->unique_size; i++) {
2184 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2185 continue;
2186 }
2187
2188 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2189 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2190 break;
2191 }
2192 }
2193
2194 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2195 /* we have a match, free the unique structure ... */
2196 for (j = 0; j < list->unique[i].expr_size; j++) {
2197 lydict_remove(module->ctx, list->unique[i].expr[j]);
2198 }
2199 free(list->unique[i].expr);
2200 /* ... and maintain the array */
2201 list->unique_size--;
2202 if (i != list->unique_size) {
2203 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2204 list->unique[i].expr = list->unique[list->unique_size].expr;
2205 }
2206
2207 if (!list->unique_size) {
2208 free(list->unique);
2209 list->unique = NULL;
2210 } else {
2211 list->unique[list->unique_size].expr_size = 0;
2212 list->unique[list->unique_size].expr = NULL;
2213 }
2214
2215 i = -1; /* set match flag */
2216 break;
2217 }
2218 }
2219 dev->deviate->unique_size++;
2220
2221 if (i != -1) {
2222 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002223 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2224 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002225 goto error;
2226 }
2227
2228 free(value);
2229 return EXIT_SUCCESS;
2230
2231error:
2232 free(value);
2233 return EXIT_FAILURE;
2234}
Pavol Vicane92421d2016-03-08 10:12:33 +01002235
2236int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002237yang_check_deviation(struct lys_module *module, struct type_deviation *dev, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002238{
2239 int i, rc;
2240
2241 if (dev->target->nodetype == LYS_LEAF) {
2242 for(i = 0; i < dev->deviation->deviate_size; ++i) {
2243 if (dev->deviation->deviate[i].mod != LY_DEVIATE_DEL) {
2244 if (dev->deviation->deviate[i].dflt || dev->deviation->deviate[i].type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002245 rc = unres_schema_add_str(module, unres, &((struct lys_node_leaf *)dev->target)->type, UNRES_TYPE_DFLT, ((struct lys_node_leaf *)dev->target)->dflt);
Pavol Vicane92421d2016-03-08 10:12:33 +01002246 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002247 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->deviation->target_name);
Pavol Vicane92421d2016-03-08 10:12:33 +01002248 return EXIT_FAILURE;
2249 }
2250 break;
2251 }
2252 }
2253 }
2254 }
2255 return EXIT_SUCCESS;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002256}
2257
2258int
2259yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
Pavol Vicane024ab72016-07-27 14:27:43 +02002260 struct lys_include *inc, struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002261{
Pavol Vican9b89dda2016-03-09 15:36:55 +01002262 struct lys_module *trg;
Pavol Vican55870412016-03-10 12:36:21 +01002263 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002264 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002265 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002266
Pavol Vican55870412016-03-10 12:36:21 +01002267 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002268 trg = (submodule) ? (struct lys_module *)submodule : module;
Pavol Vicane024ab72016-07-27 14:27:43 +02002269 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002270 if (!rc) {
2271 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002272 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002273 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002274 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002275 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002276 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002277
Pavol Vican55870412016-03-10 12:36:21 +01002278 lydict_remove(module->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002279 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002280}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002281
2282int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002283yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002284{
2285 char *prefix;
2286 char *identif;
2287 const char *ns = NULL;
2288 int i;
2289
Pavol Vicanf4717e62016-03-16 11:30:01 +01002290 /* check to the same pointer */
2291 if (data_node != actual) {
2292 return EXIT_SUCCESS;
2293 }
2294
Pavol Vicana302aa62016-03-17 10:45:35 +01002295 prefix = strdup(value);
2296 if (!prefix) {
2297 LOGMEM;
2298 goto error;
2299 }
2300 /* find prefix anf identificator*/
2301 identif = strchr(prefix, ':');
2302 *identif = '\0';
2303 identif++;
2304
Pavol Vicanf4717e62016-03-16 11:30:01 +01002305 for(i = 0; i < module->imp_size; ++i) {
2306 if (!strcmp(module->imp[i].prefix, prefix)) {
2307 ns = module->imp[i].module->ns;
2308 break;
2309 }
2310 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002311 if (!ns && !strcmp(module->prefix, prefix)) {
2312 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2313 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002314 if (ns && !strcmp(ns, LY_NSNACM)) {
2315 if (!strcmp(identif, "default-deny-write")) {
2316 data_node->nacm |= LYS_NACM_DENYW;
2317 } else if (!strcmp(identif, "default-deny-all")) {
2318 data_node->nacm |= LYS_NACM_DENYA;
2319 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002320 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002321 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002322 }
2323 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002324 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002325 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002326
2327error:
2328 free(prefix);
2329 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002330}
2331
2332void
2333nacm_inherit(struct lys_module *module)
2334{
Pavol Vican10ffba52016-04-04 12:21:22 +02002335 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002336
2337 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002338 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002339 if (elem->parent) {
2340 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002341 case LYS_GROUPING:
2342 /* extension nacm not inherited*/
2343 break;
2344 case LYS_CHOICE:
2345 case LYS_ANYXML:
2346 case LYS_USES:
2347 if (elem->parent->nodetype != LYS_GROUPING) {
2348 elem->nacm |= elem->parent->nacm;
2349 }
2350 break;
2351 case LYS_CONTAINER:
2352 case LYS_LIST:
2353 case LYS_CASE:
2354 case LYS_NOTIF:
2355 case LYS_RPC:
2356 case LYS_INPUT:
2357 case LYS_OUTPUT:
2358 case LYS_AUGMENT:
2359 elem->nacm |= elem->parent->nacm;
2360 break;
2361 case LYS_LEAF:
2362 case LYS_LEAFLIST:
2363 tmp_node = elem;
2364 tmp_child = elem->child;
2365 elem->child = NULL;
2366 default:
2367 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002368 }
2369 }
2370 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002371 if (tmp_node) {
2372 tmp_node->child = tmp_child;
2373 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002374 }
2375}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002376
2377void
2378store_flags(struct lys_node *node, uint8_t flags, int config_inherit)
2379{
2380 node->flags |= flags;
2381 if (!(node->flags & LYS_CONFIG_MASK) && config_inherit) {
2382 /* get config flag from parent */
2383 if (node->parent) {
2384 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2385 } else {
2386 /* default config is true */
2387 node->flags |= LYS_CONFIG_W;
2388 }
2389 }
2390}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002391
Pavol Vican1938d882016-04-10 13:36:31 +02002392static int
2393yang_parse(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data,
2394 unsigned int size, struct lys_array_size *size_arrays, int type_read)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002395{
2396 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002397 yyscan_t scanner = NULL;
Pavol Vican1938d882016-04-10 13:36:31 +02002398 int ret = EXIT_SUCCESS;
2399
2400 yylex_init(&scanner);
2401 bp = yy_scan_buffer((char *)data, size, scanner);
2402 yy_switch_to_buffer(bp, scanner);
2403 if (yyparse(scanner, module, submodule, unres, size_arrays, type_read)) {
2404 ret = EXIT_FAILURE;
2405 }
2406 yy_delete_buffer(bp, scanner);
2407 yylex_destroy(scanner);
2408 return ret;
2409}
2410
2411int
2412yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data, unsigned int size_data)
2413{
Pavol Vican8e7110b2016-03-22 17:00:26 +01002414 struct lys_array_size *size_arrays=NULL;
Pavol Vican974377b2016-03-23 00:38:53 +01002415 unsigned int size;
Pavol Vican1938d882016-04-10 13:36:31 +02002416 int ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002417
2418 size_arrays = calloc(1, sizeof *size_arrays);
2419 if (!size_arrays) {
2420 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002421 return EXIT_FAILURE;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002422 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002423 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002424 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ONLY_SIZE);
2425 if (!ret) {
2426 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ALL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002427 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002428 free(size_arrays->node);
2429 free(size_arrays);
Pavol Vican1938d882016-04-10 13:36:31 +02002430 return ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002431}
2432
2433struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002434yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002435{
2436
Pavol Vican10ffba52016-04-04 12:21:22 +02002437 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002438 struct unres_schema *unres = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002439 int i;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002440
2441 unres = calloc(1, sizeof *unres);
2442 if (!unres) {
2443 LOGMEM;
2444 goto error;
2445 }
2446
2447 module = calloc(1, sizeof *module);
2448 if (!module) {
2449 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002450 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002451 }
2452
2453 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002454 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002455 module->type = 0;
2456 module->implemented = (implement ? 1 : 0);
2457
2458 if (yang_parse_mem(module, NULL, unres, data, size)) {
2459 goto error;
2460 }
2461
2462 if (module && unres->count && resolve_unres_schema(module, unres)) {
2463 goto error;
2464 }
2465
2466 if (revision) {
2467 /* check revision of the parsed model */
2468 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2469 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2470 module->name, module->rev[0].date, revision);
2471 goto error;
2472 }
2473 }
2474
Pavol Vican10ffba52016-04-04 12:21:22 +02002475 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002476 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002477 goto error;
2478 }
2479
Pavol Vican10ffba52016-04-04 12:21:22 +02002480 if (module == tmp_module) {
2481 nacm_inherit(module);
2482 }
2483
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002484 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02002485 if (!module->implemented) {
2486 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
2487 }
Michal Vasko26055752016-05-03 11:36:31 +02002488 if (lys_module_set_implement(module)) {
2489 goto error;
2490 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002491
Michal Vasko26055752016-05-03 11:36:31 +02002492 if (lys_sub_module_set_dev_aug_target_implement(module)) {
2493 goto error;
2494 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002495 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02002496 if (!module->inc[i].submodule) {
2497 continue;
2498 }
Michal Vasko26055752016-05-03 11:36:31 +02002499 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
2500 goto error;
2501 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002502 }
2503 }
2504
Pavol Vican8e7110b2016-03-22 17:00:26 +01002505 unres_schema_free(NULL, &unres);
2506 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2507 return module;
2508
2509error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002510 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002511 unres_schema_free(module, &unres);
2512 if (!module || !module->name) {
2513 free(module);
2514 LOGERR(ly_errno, "Module parsing failed.");
2515 return NULL;
2516 }
2517
2518 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002519
2520 lys_sub_module_remove_devs_augs(module);
2521 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002522 return NULL;
2523}
2524
2525struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002526yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002527{
2528 struct lys_submodule *submodule;
2529
2530 submodule = calloc(1, sizeof *submodule);
2531 if (!submodule) {
2532 LOGMEM;
2533 goto error;
2534 }
2535
2536 submodule->ctx = module->ctx;
2537 submodule->type = 1;
2538 submodule->belongsto = module;
2539
2540 if (yang_parse_mem(module, submodule, unres, data, size)) {
2541 goto error;
2542 }
2543
Pavol Vican8e7110b2016-03-22 17:00:26 +01002544 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002545 return submodule;
2546
2547error:
2548 /* cleanup */
2549 unres_schema_free((struct lys_module *)submodule, &unres);
2550
2551 if (!submodule || !submodule->name) {
2552 free(submodule);
2553 LOGERR(ly_errno, "Submodule parsing failed.");
2554 return NULL;
2555 }
2556
2557 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2558
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002559 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2560 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002561 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002562 return NULL;
2563}
Pavol Vican8760bb72016-04-07 09:44:01 +02002564
2565static int
2566count_substring(const char *str, char c)
2567{
2568 const char *tmp = str;
2569 int count = 0;
2570
2571 while ((tmp = strchr(tmp, c))) {
2572 tmp++;
2573 count++;
2574 }
2575 return count;
2576}
2577
2578static int
2579read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2580{
2581 int k = 0, j;
2582
2583 while (in_index < size) {
2584 if (input[in_index] == ' ') {
2585 k++;
2586 } else if (input[in_index] == '\t') {
2587 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2588 k += 8;
2589 } else {
2590 break;
2591 }
2592 ++in_index;
2593 if (k >= indent) {
2594 for (j = k - indent; j > 0; --j) {
2595 output[*out_index] = ' ';
2596 ++(*out_index);
2597 }
2598 break;
2599 }
2600 }
2601 return in_index;
2602}
2603
2604char *
Pavol Vican677b0132016-08-09 15:44:58 +02002605yang_read_string(const char *input, int size, int indent, int version)
Pavol Vican8760bb72016-04-07 09:44:01 +02002606{
2607 int space, count;
2608 int in_index, out_index;
2609 char *value;
2610 char *retval = NULL;
2611
2612 value = malloc(size + 1);
2613 if (!value) {
2614 LOGMEM;
2615 return NULL;
2616 }
2617 /* replace special character in escape sequence */
2618 in_index = out_index = 0;
2619 while (in_index < size) {
2620 if (input[in_index] == '\\') {
2621 if (input[in_index + 1] == 'n') {
2622 value[out_index] = '\n';
2623 ++in_index;
2624 } else if (input[in_index + 1] == 't') {
2625 value[out_index] = '\t';
2626 ++in_index;
2627 } else if (input[in_index + 1] == '\\') {
2628 value[out_index] = '\\';
2629 ++in_index;
2630 } else if ((in_index + 1) != size && input[in_index + 1] == '"') {
2631 value[out_index] = '"';
2632 ++in_index;
2633 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002634 if (version < 2) {
2635 value[out_index] = input[in_index];
2636 } else {
2637 /* YANG 1.1 backslash must not be followed by any other character */
2638 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
2639 goto error;
2640 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002641 }
2642 } else {
2643 value[out_index] = input[in_index];
2644 }
2645 ++in_index;
2646 ++out_index;
2647 }
2648 value[out_index] = '\0';
2649 size = out_index;
2650 count = count_substring(value, '\t');
2651
2652 /* extend size of string due to replacing character '\t' with 8 spaces */
2653 retval = malloc(size + 1 + 7 * count);
2654 if (!retval) {
2655 LOGMEM;
2656 goto error;
2657 }
2658 in_index = out_index = space = 0;
2659 while (in_index < size) {
2660 if (value[in_index] == '\n') {
2661 out_index -= space;
2662 space = 0;
2663 retval[out_index] = '\n';
2664 ++out_index;
2665 ++in_index;
2666 in_index = read_indent(value, indent, size, in_index, &out_index, retval);
2667 continue;
2668 } else {
2669 space = (value[in_index] == ' ' || value[in_index] == '\t') ? space + 1 : 0;
2670 retval[out_index] = value[in_index];
2671 ++out_index;
2672 }
2673 ++in_index;
2674 }
2675 retval[out_index] = '\0';
2676 if (out_index != size) {
2677 retval = ly_realloc(retval, out_index + 1);
2678 }
2679 free(value);
2680 return retval;
2681error:
2682 free(value);
2683 return NULL;
2684}