blob: 24e4351023870f4057d04916857716cc0a2e0b75 [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;
704
705 /* count the number of unique leafs in the value */
706 vaux = value;
707 while ((vaux = strpbrk(vaux, " \t\n"))) {
708 unique->expr_size++;
709 while (isspace(*vaux)) {
710 vaux++;
711 }
712 }
713 unique->expr_size++;
714 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
715 if (!unique->expr) {
716 LOGMEM;
717 goto error;
718 }
719
720 for (i = 0; i < unique->expr_size; i++) {
721 vaux = strpbrk(value, " \t\n");
722 if (!vaux) {
723 /* the last token, lydict_insert() will count its size on its own */
724 vaux = value;
725 }
726
727 /* store token into unique structure */
728 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
729
730 /* check that the expression does not repeat */
731 for (j = 0; j < i; j++) {
732 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100733 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
734 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100735 goto error;
736 }
737 }
738 /* try to resolve leaf */
739 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +0200740 if (unres_schema_add_str(module, unres, (struct lys_node *) list, UNRES_LIST_UNIQ, unique->expr[i]) == -1) {
741 goto error;
742 }
Pavol Vican85f12022016-03-05 16:30:35 +0100743 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100744 if (resolve_unique((struct lys_node *)list, unique->expr[i])) {
Pavol Vican85f12022016-03-05 16:30:35 +0100745 goto error;
746 }
747 }
748
749 /* move to next token */
750 value = vaux;
751 while(isspace(*value)) {
752 value++;
753 }
754 }
755
756 return EXIT_SUCCESS;
757
758error:
759 return EXIT_FAILURE;
760}
761
762int
Pavol Vican5de33492016-02-22 14:03:24 +0100763yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
764{
765 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100766 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100767
768 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100769 str = (char *)list->unique[k].expr;
770 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100771 goto error;
772 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100773 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100774 }
775 return EXIT_SUCCESS;
776
777error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100778 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100779 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100780}
781
Pavol Vican1ff0e222016-02-26 12:27:01 +0100782static int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100783yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100784{
785 const char *value, *tmp;
786 int rc, ret = EXIT_FAILURE;
787
788 value = tmp = type->info.lref.path;
789 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100790 value = transform_schema2json(module, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100791 if (!value) {
792 goto end;
793 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100794 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100795 lydict_remove(module->ctx, value);
796
797 if (rc == -1) {
798 goto end;
799 }
800
801 ret = EXIT_SUCCESS;
802
803end:
804 lydict_remove(module->ctx, tmp);
805 return ret;
806}
807
Pavol Vican73e7c992016-02-24 12:18:05 +0100808int
Radek Krejci3a5501d2016-07-18 22:03:34 +0200809yang_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 +0100810{
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200811 int i, j, rc;
Pavol Vican73e7c992016-02-24 12:18:05 +0100812 int ret = -1;
813 const char *name, *value;
814 LY_DATA_TYPE base;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200815 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200816 struct lys_type *dertype;
817 struct lys_type_enum *enms_sc = NULL;
818 struct lys_type_bit *bits_sc = NULL;
819 struct lys_type_bit bit_tmp;
820
Pavol Vican73e7c992016-02-24 12:18:05 +0100821
Pavol Vican6b072512016-04-04 10:50:21 +0200822 base = typ->base;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100823 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100824 if (!value) {
825 goto error;
826 }
827
828 i = parse_identifier(value);
829 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100830 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100831 lydict_remove(module->ctx, value);
832 goto error;
833 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200834 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100835 name = value;
836 if (value[i]) {
837 typ->type->module_name = lydict_insert(module->ctx, value, i);
838 name += i;
839 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100840 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100841 lydict_remove(module->ctx, value);
842 goto error;
843 }
844 ++name;
845 }
846
847 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100848 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100849 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, typ->type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200850 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100851 goto error;
852
Michal Vasko01c6fd22016-05-20 11:43:05 +0200853 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100854 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200855 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200856 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100857 ret = EXIT_FAILURE;
858 goto error;
859 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200860 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100861 typ->type->base = typ->type->der->type.base;
862 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100863 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100864 }
865 switch (base) {
866 case LY_TYPE_STRING:
867 if (typ->type->base == LY_TYPE_BINARY) {
868 if (typ->type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100869 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100870 goto error;
871 }
872 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100873 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 +0100874 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100875 goto error;
876 }
877 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100878 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 +0100879 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100880 goto error;
881 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100882 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200883 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100884 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100885 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100886 break;
887 case LY_TYPE_DEC64:
888 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100889 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 +0100890 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100891 goto error;
892 }
Pavol Vican07ea68d2016-02-25 12:01:37 +0100893 /* mandatory sub-statement(s) check */
894 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
895 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100896 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100897 goto error;
898 }
899 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
900 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100901 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100902 goto error;
903 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100904 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
905 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100906 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100907 goto error;
908 }
909 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100910 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 +0100911 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100912 goto error;
913 }
914 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200915 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100916 goto error;
917 }
918 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100919 case LY_TYPE_ENUM:
920 if (typ->type->base != LY_TYPE_ENUM) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200921 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100922 goto error;
923 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200924 dertype = &typ->type->der->type;
925
926 if (!dertype->der) {
927 if (!typ->type->info.enums.count) {
928 /* type is derived directly from buit-in enumeartion type and enum statement is required */
929 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
930 goto error;
931 }
932 } else {
933 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
934 if (module->version < 2 && typ->type->info.enums.count) {
935 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
936 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
937 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
938 goto error;
939 }
940
941 /* restricted enumeration type - the name MUST be used in the base type */
942 enms_sc = dertype->info.enums.enm;
943 for(i = 0; i < typ->type->info.enums.count; i++) {
944 for (j = 0; j < dertype->info.enums.count; j++) {
945 if (ly_strequal(enms_sc[j].name, typ->type->info.enums.enm[i].name, 1)) {
946 break;
947 }
948 }
949 if (j == dertype->info.enums.count) {
950 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
951 goto error;
952 }
953
954 if (typ->type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
955 /* automatically assign value from base type */
956 typ->type->info.enums.enm[i].value = enms_sc[j].value;
957 } else {
958 /* check that the assigned value corresponds to the original
959 * value of the enum in the base type */
960 if (typ->type->info.enums.enm[i].value != enms_sc[j].value) {
961 /* typ->type->info.enums.enm[i].value - assigned value in restricted enum
962 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
963 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].value,
964 typ->type->info.enums.enm[i].name, enms_sc[j].value);
965 goto error;
966 }
967 }
968 }
Pavol Vican79a763d2016-02-25 15:41:27 +0100969 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100970 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100971 case LY_TYPE_BITS:
972 if (typ->type->base != LY_TYPE_BITS) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200973 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100974 goto error;
975 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200976 dertype = &typ->type->der->type;
977
978 if (!dertype->der) {
979 if (!typ->type->info.bits.count) {
980 /* type is derived directly from buit-in bits type and bit statement is required */
981 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
982 goto error;
983 }
984 } else {
985 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
986 if (module->version < 2 && typ->type->info.bits.count) {
987 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
988 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
989 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
990 goto error;
991 }
992
993 bits_sc = dertype->info.bits.bit;
994 for (i = 0; i < typ->type->info.bits.count; i++) {
995 for (j = 0; j < dertype->info.bits.count; j++) {
996 if (ly_strequal(bits_sc[j].name, typ->type->info.bits.bit[i].name, 1)) {
997 break;
998 }
999 }
1000 if (j == dertype->info.bits.count) {
1001 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].name);
1002 goto error;
1003 }
1004
1005 /* restricted bits type */
1006 if (typ->type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
1007 /* automatically assign position from base type */
1008 typ->type->info.bits.bit[i].pos = bits_sc[j].pos;
1009 } else {
1010 /* check that the assigned position corresponds to the original
1011 * position of the bit in the base type */
1012 if (typ->type->info.bits.bit[i].pos != bits_sc[j].pos) {
1013 /* typ->type->info.bits.bit[i].pos - assigned position in restricted bits
1014 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
1015 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].pos,
1016 typ->type->info.bits.bit[i].name, bits_sc[j].pos);
1017 goto error;
1018 }
1019 }
1020 }
Pavol Vican03a59442016-03-21 15:23:45 +01001021 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001022
1023 for (i = typ->type->info.bits.count - 1; i > 0; i--) {
1024 j = i;
1025
1026 /* keep them ordered by position */
1027 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1028 /* switch them */
1029 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1030 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1031 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
1032 j--;
1033 }
Pavol Vican03a59442016-03-21 15:23:45 +01001034 }
1035 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +01001036 case LY_TYPE_LEAFREF:
Pavol Vican6b072512016-04-04 10:50:21 +02001037 if (typ->type->base == LY_TYPE_IDENT && (typ->flags & LYS_TYPE_BASE)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001038 if (yang_read_identyref(module, typ->type, unres)) {
Pavol Vican1ff0e222016-02-26 12:27:01 +01001039 goto error;
1040 }
Pavol Vican191613a2016-02-26 16:21:32 +01001041 } else if (typ->type->base == LY_TYPE_LEAFREF) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001042 /* flag resolving for later use */
1043 if (!tpdftype) {
1044 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1045 if (siter) {
1046 /* just a flag - do not resolve */
1047 tpdftype = 1;
1048 }
1049 }
1050
Pavol Vican6b072512016-04-04 10:50:21 +02001051 if (typ->type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +01001052 value = typ->type->info.lref.path;
1053 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001054 typ->type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +01001055 lydict_remove(module->ctx, value);
1056 if (!typ->type->info.lref.path) {
1057 goto error;
1058 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001059 /* try to resolve leafref path only when this is instantiated
1060 * leaf, so it is not:
1061 * - typedef's type,
1062 * - in grouping definition,
1063 * - just instantiated in a grouping definition,
1064 * because in those cases the nodes referenced in path might not be present
1065 * and it is not a bug. */
1066 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +01001067 goto error;
1068 }
Pavol Vican6b072512016-04-04 10:50:21 +02001069 } else if (!typ->type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001070 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +01001071 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +02001072 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001073 /* copy leafref definition into the derived type */
1074 typ->type->info.lref.path = lydict_insert(module->ctx, typ->type->der->type.info.lref.path, 0);
1075 /* and resolve the path at the place we are (if not in grouping/typedef) */
1076 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001077 goto error;
1078 }
Radek Krejci742be352016-07-17 12:18:54 +02001079
Michal Vasko01c6fd22016-05-20 11:43:05 +02001080 /* add pointer to leafref target, only on leaves (not in typedefs) */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001081 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 +02001082 goto error;
1083 }
Pavol Vican191613a2016-02-26 16:21:32 +01001084 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001085 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001086 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001087 goto error;
1088 }
1089 break;
1090 case LY_TYPE_IDENT:
1091 if (typ->type->der->type.der) {
1092 /* this is just a derived type with no base specified/required */
1093 break;
1094 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001095 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Pavol Vican1ff0e222016-02-26 12:27:01 +01001096 goto error;
1097 }
1098 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001099 case LY_TYPE_UNION:
1100 if (typ->type->base != LY_TYPE_UNION) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001101 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001102 goto error;
1103 }
1104 if (!typ->type->info.uni.types) {
1105 if (typ->type->der->type.der) {
1106 /* this is just a derived type with no additional type specified/required */
1107 break;
1108 }
Pavol Vican0adf01d2016-03-22 12:29:33 +01001109 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +01001110 goto error;
1111 }
1112 for (i = 0; i < typ->type->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001113 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i],
Michal Vasko5d631402016-07-21 13:15:15 +02001114 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001115 goto error;
1116 }
1117 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001118 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001119 goto error;
1120 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001121 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001122 goto error;
1123 }
1124 }
1125 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001126
1127 default:
1128 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
1129 if (typ->type->base != base) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001130 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001131 goto error;
1132 }
1133 } else {
1134 LOGINT;
1135 goto error;
1136 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001137 }
1138 return EXIT_SUCCESS;
1139
1140error:
1141 if (typ->type->module_name) {
1142 lydict_remove(module->ctx, typ->type->module_name);
1143 typ->type->module_name = NULL;
1144 }
1145 return ret;
1146}
1147
1148void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001149yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001150{
1151 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001152 struct type_deviation *dev;
1153 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001154
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001155 typ = calloc(1, sizeof *typ);
1156 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001157 LOGMEM;
1158 return NULL;
1159 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001160
1161 typ->flags = LY_YANG_STRUCTURE_FLAG;
1162 switch (type) {
1163 case LEAF_KEYWORD:
1164 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1165 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1166 typ->type = &((struct lys_node_leaf *)parent)->type;
1167 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001168 case LEAF_LIST_KEYWORD:
1169 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1170 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1171 typ->type = &((struct lys_node_leaflist *)parent)->type;
1172 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001173 case UNION_KEYWORD:
1174 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1175 typ->type = (struct lys_type *)parent;
1176 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001177 case TYPEDEF_KEYWORD:
1178 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1179 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001180 break;
1181 case REPLACE_KEYWORD:
1182 /* deviation replace type*/
1183 dev = (struct type_deviation *)parent;
1184 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001185 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001186 goto error;
1187 }
1188 /* check target node type */
1189 if (dev->target->nodetype == LYS_LEAF) {
1190 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1191 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1192 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1193 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001194 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1195 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001196 goto error;
1197 }
1198
1199 /* remove type and initialize it */
1200 lys_type_free(module->ctx, typ->type);
1201 tmp_parent = typ->type->parent;
1202 memset(typ->type, 0, sizeof *typ->type);
1203 typ->type->parent = tmp_parent;
1204
1205 /* replace it with the value specified in deviation */
1206 /* HACK for unres */
1207 typ->type->der = (struct lys_tpdf *)typ;
1208 dev->deviate->type = typ->type;
1209 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001210 default:
1211 goto error;
1212 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001213 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001214 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001215 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001216
1217error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001218 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001219 free(typ);
1220 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001221}
1222
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001223void
1224yang_delete_type(struct lys_module *module, struct yang_type *stype)
1225{
1226 int i;
1227
1228 stype->type->base = stype->base;
1229 stype->type->der = NULL;
1230 lydict_remove(module->ctx, stype->name);
1231 if (stype->base == LY_TYPE_UNION) {
1232 for (i = 0; i < stype->type->info.uni.count; i++) {
1233 if (stype->type->info.uni.types[i].der) {
1234 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1235 }
1236 }
1237 }
1238 free(stype);
1239}
1240
Pavol Vican73e7c992016-02-24 12:18:05 +01001241void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001242yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001243{
1244 struct lys_restr **length;
1245
Pavol Vican6b072512016-04-04 10:50:21 +02001246 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001247 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001248 typ->base = LY_TYPE_STRING;
1249 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001250 length = &typ->type->info.binary.length;
1251 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001252 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001253 goto error;
1254 }
1255
1256 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001257 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001258 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001259 }
1260 *length = calloc(1, sizeof **length);
1261 if (!*length) {
1262 LOGMEM;
1263 goto error;
1264 }
1265 (*length)->expr = lydict_insert_zc(module->ctx, value);
1266 return *length;
1267
1268error:
1269 free(value);
1270 return NULL;
1271
1272}
Pavol Vican1c203db2016-02-24 14:05:23 +01001273
Pavol Vican6eecf302016-08-10 11:09:05 +02001274int
1275yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001276{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001277 char *buf;
1278 size_t len;
1279
Michal Vasko0aee5c12016-06-17 14:27:26 +02001280 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001281 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001282 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001283 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001284
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001285 len = strlen(value);
1286 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001287
1288 if (!buf) {
1289 LOGMEM;
1290 free(value);
1291 return EXIT_FAILURE;
1292 }
1293
1294 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001295 strcpy(&buf[1], value);
1296 free(value);
1297
Pavol Vican6eecf302016-08-10 11:09:05 +02001298 pattern->expr = lydict_insert_zc(module->ctx, buf);
1299 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001300}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001301
1302void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001303yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001304{
Pavol Vican6b072512016-04-04 10:50:21 +02001305 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001306 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001307 goto error;
1308 }
Pavol Vican6b072512016-04-04 10:50:21 +02001309 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001310 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001311 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001312 goto error;
1313 }
1314 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1315 if (!typ->type->info.dec64.range) {
1316 LOGMEM;
1317 goto error;
1318 }
1319 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1320 return typ->type->info.dec64.range;
1321
1322error:
1323 free(value);
1324 return NULL;
1325}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001326
1327int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001328yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001329{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001330 unsigned int i;
1331
Pavol Vican6b072512016-04-04 10:50:21 +02001332 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1333 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001334 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001335 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001336 goto error;
1337 }
1338 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001339 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001340 goto error;
1341 }
1342 /* range check */
1343 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001344 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001345 goto error;
1346 }
1347 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001348 typ->type->info.dec64.div = 10;
1349 for (i = 1; i < value; i++) {
1350 typ->type->info.dec64.div *= 10;
1351 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001352 return EXIT_SUCCESS;
1353
1354error:
1355 return EXIT_FAILURE;
1356}
Pavol Vican79a763d2016-02-25 15:41:27 +01001357
1358void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001359yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001360{
1361 struct lys_type_enum *enm;
1362 int i;
1363
1364 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1365 enm->name = lydict_insert_zc(module->ctx, value);
1366
1367 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1368 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001369 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001370 goto error;
1371 }
1372
1373 /* check the name uniqueness */
1374 for (i = 0; i < typ->type->info.enums.count; i++) {
1375 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 +01001376 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001377 goto error;
1378 }
1379 }
1380
1381 typ->type->info.enums.count++;
1382 return enm;
1383
1384error:
1385 typ->type->info.enums.count++;
1386 return NULL;
1387}
1388
1389int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001390yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001391{
1392 int i, j;
1393
1394 if (!assign) {
1395 /* assign value automatically */
1396 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001397 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001398 goto error;
1399 }
1400 enm->value = *value;
1401 enm->flags |= LYS_AUTOASSIGNED;
1402 (*value)++;
1403 }
1404
1405 /* check that the value is unique */
1406 j = typ->type->info.enums.count-1;
1407 for (i = 0; i < j; i++) {
1408 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001409 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001410 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1411 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001412 goto error;
1413 }
1414 }
1415
1416 return EXIT_SUCCESS;
1417
1418error:
1419 return EXIT_FAILURE;
1420}
Pavol Vican9887c682016-02-29 11:32:01 +01001421
1422void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001423yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001424{
1425 int i;
1426 struct lys_type_bit *bit;
1427
1428 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001429 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001430 free(value);
1431 goto error;
1432 }
1433 bit->name = lydict_insert_zc(module->ctx, value);
1434
1435 /* check the name uniqueness */
1436 for (i = 0; i < typ->type->info.bits.count; i++) {
1437 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001438 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001439 typ->type->info.bits.count++;
1440 goto error;
1441 }
1442 }
1443 typ->type->info.bits.count++;
1444 return bit;
1445
1446error:
1447 return NULL;
1448}
1449
1450int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001451yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001452{
1453 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001454
1455 if (!assign) {
1456 /* assign value automatically */
1457 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001458 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001459 goto error;
1460 }
1461 bit->pos = (uint32_t)*value;
1462 bit->flags |= LYS_AUTOASSIGNED;
1463 (*value)++;
1464 }
1465
1466 j = typ->type->info.bits.count - 1;
1467 /* check that the value is unique */
1468 for (i = 0; i < j; i++) {
1469 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001470 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 +01001471 goto error;
1472 }
1473 }
1474
Pavol Vican9887c682016-02-29 11:32:01 +01001475 return EXIT_SUCCESS;
1476
1477error:
1478 return EXIT_FAILURE;
1479}
Pavol Vican0df02b02016-03-01 10:28:50 +01001480
1481void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001482yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001483{
1484 struct lys_tpdf *ret;
Pavol Vican810892e2016-07-12 16:55:34 +02001485 struct lys_node *root;
Pavol Vican0df02b02016-03-01 10:28:50 +01001486
Pavol Vican810892e2016-07-12 16:55:34 +02001487 root = (parent) ? NULL : lys_main_module(module)->data;
1488 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent) || yang_check_typedef_identif(root, parent, value)) {
Pavol Vican0df02b02016-03-01 10:28:50 +01001489 free(value);
1490 return NULL;
1491 }
Pavol Vican810892e2016-07-12 16:55:34 +02001492
Pavol Vican0df02b02016-03-01 10:28:50 +01001493 if (!parent) {
1494 ret = &module->tpdf[module->tpdf_size];
Pavol Vican0df02b02016-03-01 10:28:50 +01001495 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001496 } else {
1497 switch (parent->nodetype) {
1498 case LYS_GROUPING:
1499 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001500 ((struct lys_node_grp *)parent)->tpdf_size++;
1501 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001502 case LYS_CONTAINER:
1503 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1504 ((struct lys_node_container *)parent)->tpdf_size++;
1505 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001506 case LYS_LIST:
1507 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1508 ((struct lys_node_list *)parent)->tpdf_size++;
1509 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001510 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001511 case LYS_ACTION:
1512 ret = &((struct lys_node_rpc_action *)parent)->tpdf[((struct lys_node_rpc_action *)parent)->tpdf_size];
1513 ((struct lys_node_rpc_action *)parent)->tpdf_size++;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001514 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001515 case LYS_INPUT:
1516 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001517 ret = &((struct lys_node_inout *)parent)->tpdf[((struct lys_node_inout *)parent)->tpdf_size];
1518 ((struct lys_node_inout *)parent)->tpdf_size++;
Pavol Vican531a9132016-03-03 10:10:09 +01001519 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001520 case LYS_NOTIF:
1521 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1522 ((struct lys_node_notif *)parent)->tpdf_size++;
1523 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001524 default:
1525 /* another type of nodetype is error*/
1526 LOGINT;
1527 free(value);
1528 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001529 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001530 }
1531
Pavol Vican79436472016-04-04 11:22:02 +02001532 ret->type.parent = ret;
Pavol Vican0df02b02016-03-01 10:28:50 +01001533 ret->name = lydict_insert_zc(module->ctx, value);
1534 ret->module = module;
1535 return ret;
1536}
Pavol Vican1003ead2016-03-02 12:24:52 +01001537
1538void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001539yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001540{
1541 struct lys_refine *rfn;
1542
1543 rfn = &uses->refine[uses->refine_size];
1544 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001545 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001546 free(value);
1547 if (!rfn->target_name) {
1548 return NULL;
1549 }
1550 return rfn;
1551}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001552
1553void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001554yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001555{
1556 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001557
1558 if (parent) {
1559 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1560 } else {
1561 aug = &module->augment[module->augment_size];
1562 }
1563 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001564 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001565 free(value);
1566 if (!aug->target_name) {
1567 return NULL;
1568 }
1569 aug->parent = parent;
1570 aug->module = module;
1571 if (parent) {
1572 ((struct lys_node_uses *)parent)->augment_size++;
1573 } else {
1574 module->augment_size++;
1575 }
1576 return aug;
1577}
Pavol Vican220e5a12016-03-03 14:19:43 +01001578
1579void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001580yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001581{
1582 struct lys_node *dev_target = NULL;
1583 struct lys_deviation *dev;
1584 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001585 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001586
Pavol Vican220e5a12016-03-03 14:19:43 +01001587 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001588 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001589 free(value);
1590 if (!dev->target_name) {
1591 goto error;
1592 }
1593
Pavol Vican974377b2016-03-23 00:38:53 +01001594 deviation = calloc(1, sizeof *deviation);
1595 if (!deviation) {
1596 LOGMEM;
1597 goto error;
1598 }
1599
Pavol Vican220e5a12016-03-03 14:19:43 +01001600 /* resolve target node */
1601 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1602 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001603 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001604 goto error;
1605 }
Radek Krejcic4283442016-04-22 09:19:27 +02001606 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001607 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1608 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001609 goto error;
1610 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001611
Michal Vasko89563fc2016-07-28 16:19:35 +02001612 lys_node_module(dev_target)->deviated = 1;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001613
Pavol Vican220e5a12016-03-03 14:19:43 +01001614 /*save pointer to the deviation and deviated target*/
1615 deviation->deviation = dev;
1616 deviation->target = dev_target;
1617
Pavol Vican220e5a12016-03-03 14:19:43 +01001618 return deviation;
1619
1620error:
1621 free(deviation);
1622 lydict_remove(module->ctx, dev->target_name);
1623 return NULL;
1624}
Pavol Vican4c90c642016-03-03 15:06:47 +01001625
1626int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001627yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001628{
1629 int i;
1630
1631 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001632 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001633 return EXIT_FAILURE;
1634 }
1635 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1636
1637 /* you cannot remove a key leaf */
1638 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1639 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1640 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001641 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1642 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001643 return EXIT_FAILURE;
1644 }
1645 }
1646 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001647
Pavol Vican4c90c642016-03-03 15:06:47 +01001648 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001649 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001650 dev->deviation->orig_node = dev->target;
1651
1652 dev->deviation->deviate_size = 1;
1653 return EXIT_SUCCESS;
1654}
Pavol Vican85f12022016-03-05 16:30:35 +01001655
1656int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001657yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001658{
1659 struct unres_schema tmp_unres;
1660
1661 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1662 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1663 dev->deviation->deviate_size++;
1664 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001665 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1666 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001667 return EXIT_FAILURE;
1668 }
1669
1670 /* store a shallow copy of the original node */
1671 if (!dev->deviation->orig_node) {
1672 memset(&tmp_unres, 0, sizeof tmp_unres);
1673 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1674 /* just to be safe */
1675 if (tmp_unres.count) {
1676 LOGINT;
1677 return EXIT_FAILURE;
1678 }
1679 }
1680
1681 return EXIT_SUCCESS;
1682}
1683
1684int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001685yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001686{
1687 const char **stritem;
1688
1689 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001690 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001691 free(value);
1692 goto error;
1693 }
1694
1695 /* check target node type */
1696 if (dev->target->nodetype == LYS_LEAFLIST) {
1697 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1698 } else if (dev->target->nodetype == LYS_LEAF) {
1699 stritem = &((struct lys_node_leaf *)dev->target)->units;
1700 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001701 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1702 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001703 free(value);
1704 goto error;
1705 }
1706
1707 dev->deviate->units = lydict_insert_zc(ctx, value);
1708
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001709 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1710 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001711 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001712 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1713 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001714 goto error;
1715 }
1716 /* remove current units value of the target */
1717 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001718 } else {
1719 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1720 /* check that there is no current value */
1721 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001722 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1723 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001724 goto error;
1725 }
1726 } else { /* replace */
1727 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001728 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1729 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001730 goto error;
1731 }
1732 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001733 /* remove current units value of the target ... */
1734 lydict_remove(ctx, *stritem);
1735
1736 /* ... and replace it with the value specified in deviation */
1737 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1738 }
1739
Pavol Vican85f12022016-03-05 16:30:35 +01001740 return EXIT_SUCCESS;
1741
1742error:
1743 return EXIT_FAILURE;
1744}
1745
1746int
Pavol Vican974377b2016-03-23 00:38:53 +01001747yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001748{
Pavol Vican85f12022016-03-05 16:30:35 +01001749 /* check target node type */
1750 switch (dev->target->nodetype) {
1751 case LYS_LEAF:
1752 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1753 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1754 break;
1755 case LYS_CONTAINER:
1756 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1757 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1758 break;
1759 case LYS_LEAFLIST:
1760 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1761 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1762 break;
1763 case LYS_LIST:
1764 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1765 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1766 break;
1767 case LYS_ANYXML:
1768 dev->trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1769 dev->trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
1770 break;
1771 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001772 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1773 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001774 goto error;
1775 }
1776
1777 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1778 /* reallocate the must array of the target */
1779 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1780 if (!dev->deviate->must) {
1781 LOGMEM;
1782 goto error;
1783 }
1784 *dev->trg_must = dev->deviate->must;
1785 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1786 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001787 } else {
1788 /* LY_DEVIATE_DEL */
1789 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1790 if (!dev->deviate->must) {
1791 LOGMEM;
1792 goto error;
1793 }
Pavol Vican85f12022016-03-05 16:30:35 +01001794 }
1795
1796 return EXIT_SUCCESS;
1797
1798error:
1799 return EXIT_FAILURE;
1800}
1801
1802int
Pavol Vican974377b2016-03-23 00:38:53 +01001803yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001804{
Pavol Vican85f12022016-03-05 16:30:35 +01001805 struct lys_node_list *list;
1806
1807 /* check target node type */
1808 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001809 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1810 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001811 goto error;
1812 }
1813
1814 list = (struct lys_node_list *)dev->target;
1815 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1816 /* reallocate the unique array of the target */
1817 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1818 if (!dev->deviate->unique) {
1819 LOGMEM;
1820 goto error;
1821 }
1822 list->unique = dev->deviate->unique;
1823 dev->deviate->unique = &list->unique[list->unique_size];
1824 dev->deviate->unique_size = c_uniq;
1825 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001826 } else {
1827 /* LY_DEVIATE_DEL */
1828 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1829 if (!dev->deviate->unique) {
1830 LOGMEM;
1831 goto error;
1832 }
Pavol Vican85f12022016-03-05 16:30:35 +01001833 }
1834
1835 return EXIT_SUCCESS;
1836
1837error:
1838 return EXIT_FAILURE;
1839}
1840
1841int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001842yang_read_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001843{
1844 int rc;
1845 struct lys_node_choice *choice;
1846 struct lys_node_leaf *leaf;
1847 struct lys_node *node;
1848
1849 if (dev->deviate->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001850 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "default", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001851 free(value);
1852 goto error;
1853 }
1854
1855 dev->deviate->dflt = lydict_insert_zc(ctx, value);
1856
1857 if (dev->target->nodetype == LYS_CHOICE) {
1858 choice = (struct lys_node_choice *)dev->target;
1859
Pavol Vican85f12022016-03-05 16:30:35 +01001860 rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
1861 if (rc || !node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001862 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vican85f12022016-03-05 16:30:35 +01001863 goto error;
1864 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001865 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1866 if (!choice->dflt || (choice->dflt != node)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001867 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1868 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001869 goto error;
1870 }
1871 choice->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001872 } else {
1873 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1874 /* check that there is no current value */
1875 if (choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001876 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1877 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001878 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001879 } else if (choice->flags & LYS_MAND_TRUE) {
1880 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
1881 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
1882 goto error;
Pavol Vican4766aca2016-03-07 12:42:36 +01001883 }
1884 } else { /* replace*/
1885 if (!choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001886 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1887 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001888 goto error;
1889 }
1890 }
1891
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001892 choice->dflt = node;
1893 if (!choice->dflt) {
1894 /* default branch not found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001895 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001896 goto error;
1897 }
Pavol Vican85f12022016-03-05 16:30:35 +01001898 }
1899 } else if (dev->target->nodetype == LYS_LEAF) {
1900 leaf = (struct lys_node_leaf *)dev->target;
1901
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001902 if (dev->deviate->mod == LY_DEVIATE_DEL) {
Michal Vaskob42b6972016-06-06 14:21:30 +02001903 if (!leaf->dflt || !ly_strequal(leaf->dflt, dev->deviate->dflt, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001904 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1905 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001906 goto error;
1907 }
1908 /* remove value */
1909 lydict_remove(ctx, leaf->dflt);
1910 leaf->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001911 } else {
1912 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1913 /* check that there is no current value */
1914 if (leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001915 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1916 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001917 goto error;
Pavol Vicanfdf81c42016-04-05 15:55:31 +02001918 } else if (leaf->flags & LYS_MAND_TRUE) {
1919 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1920 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "leaf");
1921 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on leaf with \"mandatory\".");
1922 goto error;
Pavol Vican4766aca2016-03-07 12:42:36 +01001923 }
1924 } else { /* replace*/
1925 if (!leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001926 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1927 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001928 goto error;
1929 }
1930 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001931 /* remove value */
1932 lydict_remove(ctx, leaf->dflt);
Pavol Vican85f12022016-03-05 16:30:35 +01001933
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001934 /* set new value */
1935 leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
1936 }
Pavol Vican85f12022016-03-05 16:30:35 +01001937 } else {
1938 /* invalid target for default value */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001939 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1940 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001941 goto error;
1942 }
1943
1944 return EXIT_SUCCESS;
1945
1946error:
1947 return EXIT_FAILURE;
1948}
1949
1950int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001951yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001952{
1953 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001954 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001955 goto error;
1956 }
1957
1958 /* for we deviate from RFC 6020 and allow config property even it is/is not
1959 * specified in the target explicitly since config property inherits. So we expect
1960 * that config is specified in every node. But for delete, we check that the value
1961 * is the same as here in deviation
1962 */
1963 dev->deviate->flags |= value;
1964
1965 /* add and replace are the same in this case */
1966 /* remove current config value of the target ... */
1967 dev->target->flags &= ~LYS_CONFIG_MASK;
1968
1969 /* ... and replace it with the value specified in deviation */
1970 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1971
1972 return EXIT_SUCCESS;
1973
1974error:
1975 return EXIT_FAILURE;
1976}
1977
1978int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001979yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001980{
1981 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001982 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001983 goto error;
1984 }
1985
1986 /* check target node type */
1987 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001988 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1989 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001990 goto error;
1991 }
1992
1993 dev->deviate->flags |= value;
1994
1995 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1996 /* check that there is no current value */
1997 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001998 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1999 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002000 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02002001 } else {
2002 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
2003 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2004 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
2005 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2006 goto error;
2007 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
2008 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
2009 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
2010 goto error;
2011 }
Pavol Vican85f12022016-03-05 16:30:35 +01002012 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002013 } else { /* replace */
2014 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002015 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2016 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002017 goto error;
2018 }
Pavol Vican85f12022016-03-05 16:30:35 +01002019 }
2020
Pavol Vican85f12022016-03-05 16:30:35 +01002021 /* remove current mandatory value of the target ... */
2022 dev->target->flags &= ~LYS_MAND_MASK;
2023
2024 /* ... and replace it with the value specified in deviation */
2025 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2026
2027 return EXIT_SUCCESS;
2028
2029error:
2030 return EXIT_FAILURE;
2031}
2032
2033int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002034yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002035{
2036 uint32_t *ui32val;
2037
2038 /* check target node type */
2039 if (dev->target->nodetype == LYS_LEAFLIST) {
2040 if (type) {
2041 ui32val = &((struct lys_node_leaflist *)dev->target)->max;
2042 } else {
2043 ui32val = &((struct lys_node_leaflist *)dev->target)->min;
2044 }
2045 } else if (dev->target->nodetype == LYS_LIST) {
2046 if (type) {
2047 ui32val = &((struct lys_node_list *)dev->target)->max;
2048 } else {
2049 ui32val = &((struct lys_node_list *)dev->target)->min;
2050 }
2051 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002052 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2053 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 +01002054 goto error;
2055 }
2056
2057 if (type) {
2058 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002059 dev->deviate->max_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01002060 } else {
2061 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002062 dev->deviate->min_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01002063 }
2064
2065 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2066 /* check that there is no current value */
2067 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002068 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2069 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002070 goto error;
2071 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002072 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2073 /* unfortunately, there is no way to check reliably that there
2074 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002075 }
2076
2077 /* add (already checked) and replace */
2078 /* set new value specified in deviation */
2079 *ui32val = value;
2080
2081 return EXIT_SUCCESS;
2082
2083error:
2084 return EXIT_FAILURE;
2085}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002086
2087int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002088yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002089{
2090 int i;
2091
2092 /* find must to delete, we are ok with just matching conditions */
2093 for (i = 0; i < *dev->trg_must_size; i++) {
2094 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2095 /* we have a match, free the must structure ... */
2096 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2097 /* ... and maintain the array */
2098 (*dev->trg_must_size)--;
2099 if (i != *dev->trg_must_size) {
2100 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2101 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2102 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2103 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2104 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2105 }
2106 if (!(*dev->trg_must_size)) {
2107 free(*dev->trg_must);
2108 *dev->trg_must = NULL;
2109 } else {
2110 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2111 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2112 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2113 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2114 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2115 }
2116
2117 i = -1; /* set match flag */
2118 break;
2119 }
2120 }
2121 if (i != -1) {
2122 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002123 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2124 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002125 return EXIT_FAILURE;
2126 }
2127
2128 return EXIT_SUCCESS;
2129}
2130
2131int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002132yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002133{
2134 struct lys_node_list *list;
2135 int i, j;
2136
2137 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002138 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002139 dev->deviate->unique_size++;
2140 goto error;
2141 }
2142
2143 /* find unique structures to delete */
2144 for (i = 0; i < list->unique_size; i++) {
2145 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2146 continue;
2147 }
2148
2149 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2150 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2151 break;
2152 }
2153 }
2154
2155 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2156 /* we have a match, free the unique structure ... */
2157 for (j = 0; j < list->unique[i].expr_size; j++) {
2158 lydict_remove(module->ctx, list->unique[i].expr[j]);
2159 }
2160 free(list->unique[i].expr);
2161 /* ... and maintain the array */
2162 list->unique_size--;
2163 if (i != list->unique_size) {
2164 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2165 list->unique[i].expr = list->unique[list->unique_size].expr;
2166 }
2167
2168 if (!list->unique_size) {
2169 free(list->unique);
2170 list->unique = NULL;
2171 } else {
2172 list->unique[list->unique_size].expr_size = 0;
2173 list->unique[list->unique_size].expr = NULL;
2174 }
2175
2176 i = -1; /* set match flag */
2177 break;
2178 }
2179 }
2180 dev->deviate->unique_size++;
2181
2182 if (i != -1) {
2183 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002184 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2185 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002186 goto error;
2187 }
2188
2189 free(value);
2190 return EXIT_SUCCESS;
2191
2192error:
2193 free(value);
2194 return EXIT_FAILURE;
2195}
Pavol Vicane92421d2016-03-08 10:12:33 +01002196
2197int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002198yang_check_deviation(struct lys_module *module, struct type_deviation *dev, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002199{
2200 int i, rc;
2201
2202 if (dev->target->nodetype == LYS_LEAF) {
2203 for(i = 0; i < dev->deviation->deviate_size; ++i) {
2204 if (dev->deviation->deviate[i].mod != LY_DEVIATE_DEL) {
2205 if (dev->deviation->deviate[i].dflt || dev->deviation->deviate[i].type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002206 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 +01002207 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002208 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 +01002209 return EXIT_FAILURE;
2210 }
2211 break;
2212 }
2213 }
2214 }
2215 }
2216 return EXIT_SUCCESS;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002217}
2218
2219int
2220yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
Pavol Vicane024ab72016-07-27 14:27:43 +02002221 struct lys_include *inc, struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002222{
Pavol Vican9b89dda2016-03-09 15:36:55 +01002223 struct lys_module *trg;
Pavol Vican55870412016-03-10 12:36:21 +01002224 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002225 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002226 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002227
Pavol Vican55870412016-03-10 12:36:21 +01002228 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002229 trg = (submodule) ? (struct lys_module *)submodule : module;
Pavol Vicane024ab72016-07-27 14:27:43 +02002230 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002231 if (!rc) {
2232 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002233 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002234 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002235 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002236 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002237 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002238
Pavol Vican55870412016-03-10 12:36:21 +01002239 lydict_remove(module->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002240 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002241}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002242
2243int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002244yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002245{
2246 char *prefix;
2247 char *identif;
2248 const char *ns = NULL;
2249 int i;
2250
Pavol Vicanf4717e62016-03-16 11:30:01 +01002251 /* check to the same pointer */
2252 if (data_node != actual) {
2253 return EXIT_SUCCESS;
2254 }
2255
Pavol Vicana302aa62016-03-17 10:45:35 +01002256 prefix = strdup(value);
2257 if (!prefix) {
2258 LOGMEM;
2259 goto error;
2260 }
2261 /* find prefix anf identificator*/
2262 identif = strchr(prefix, ':');
2263 *identif = '\0';
2264 identif++;
2265
Pavol Vicanf4717e62016-03-16 11:30:01 +01002266 for(i = 0; i < module->imp_size; ++i) {
2267 if (!strcmp(module->imp[i].prefix, prefix)) {
2268 ns = module->imp[i].module->ns;
2269 break;
2270 }
2271 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002272 if (!ns && !strcmp(module->prefix, prefix)) {
2273 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2274 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002275 if (ns && !strcmp(ns, LY_NSNACM)) {
2276 if (!strcmp(identif, "default-deny-write")) {
2277 data_node->nacm |= LYS_NACM_DENYW;
2278 } else if (!strcmp(identif, "default-deny-all")) {
2279 data_node->nacm |= LYS_NACM_DENYA;
2280 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002281 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002282 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002283 }
2284 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002285 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002286 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002287
2288error:
2289 free(prefix);
2290 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002291}
2292
2293void
2294nacm_inherit(struct lys_module *module)
2295{
Pavol Vican10ffba52016-04-04 12:21:22 +02002296 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002297
2298 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002299 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002300 if (elem->parent) {
2301 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002302 case LYS_GROUPING:
2303 /* extension nacm not inherited*/
2304 break;
2305 case LYS_CHOICE:
2306 case LYS_ANYXML:
2307 case LYS_USES:
2308 if (elem->parent->nodetype != LYS_GROUPING) {
2309 elem->nacm |= elem->parent->nacm;
2310 }
2311 break;
2312 case LYS_CONTAINER:
2313 case LYS_LIST:
2314 case LYS_CASE:
2315 case LYS_NOTIF:
2316 case LYS_RPC:
2317 case LYS_INPUT:
2318 case LYS_OUTPUT:
2319 case LYS_AUGMENT:
2320 elem->nacm |= elem->parent->nacm;
2321 break;
2322 case LYS_LEAF:
2323 case LYS_LEAFLIST:
2324 tmp_node = elem;
2325 tmp_child = elem->child;
2326 elem->child = NULL;
2327 default:
2328 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002329 }
2330 }
2331 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002332 if (tmp_node) {
2333 tmp_node->child = tmp_child;
2334 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002335 }
2336}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002337
2338void
2339store_flags(struct lys_node *node, uint8_t flags, int config_inherit)
2340{
2341 node->flags |= flags;
2342 if (!(node->flags & LYS_CONFIG_MASK) && config_inherit) {
2343 /* get config flag from parent */
2344 if (node->parent) {
2345 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2346 } else {
2347 /* default config is true */
2348 node->flags |= LYS_CONFIG_W;
2349 }
2350 }
2351}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002352
Pavol Vican1938d882016-04-10 13:36:31 +02002353static int
2354yang_parse(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data,
2355 unsigned int size, struct lys_array_size *size_arrays, int type_read)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002356{
2357 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002358 yyscan_t scanner = NULL;
Pavol Vican1938d882016-04-10 13:36:31 +02002359 int ret = EXIT_SUCCESS;
2360
2361 yylex_init(&scanner);
2362 bp = yy_scan_buffer((char *)data, size, scanner);
2363 yy_switch_to_buffer(bp, scanner);
2364 if (yyparse(scanner, module, submodule, unres, size_arrays, type_read)) {
2365 ret = EXIT_FAILURE;
2366 }
2367 yy_delete_buffer(bp, scanner);
2368 yylex_destroy(scanner);
2369 return ret;
2370}
2371
2372int
2373yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data, unsigned int size_data)
2374{
Pavol Vican8e7110b2016-03-22 17:00:26 +01002375 struct lys_array_size *size_arrays=NULL;
Pavol Vican974377b2016-03-23 00:38:53 +01002376 unsigned int size;
Pavol Vican1938d882016-04-10 13:36:31 +02002377 int ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002378
2379 size_arrays = calloc(1, sizeof *size_arrays);
2380 if (!size_arrays) {
2381 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002382 return EXIT_FAILURE;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002383 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002384 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002385 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ONLY_SIZE);
2386 if (!ret) {
2387 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ALL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002388 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002389 free(size_arrays->node);
2390 free(size_arrays);
Pavol Vican1938d882016-04-10 13:36:31 +02002391 return ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002392}
2393
2394struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002395yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002396{
2397
Pavol Vican10ffba52016-04-04 12:21:22 +02002398 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002399 struct unres_schema *unres = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002400 int i;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002401
2402 unres = calloc(1, sizeof *unres);
2403 if (!unres) {
2404 LOGMEM;
2405 goto error;
2406 }
2407
2408 module = calloc(1, sizeof *module);
2409 if (!module) {
2410 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002411 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002412 }
2413
2414 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002415 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002416 module->type = 0;
2417 module->implemented = (implement ? 1 : 0);
2418
2419 if (yang_parse_mem(module, NULL, unres, data, size)) {
2420 goto error;
2421 }
2422
2423 if (module && unres->count && resolve_unres_schema(module, unres)) {
2424 goto error;
2425 }
2426
2427 if (revision) {
2428 /* check revision of the parsed model */
2429 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2430 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2431 module->name, module->rev[0].date, revision);
2432 goto error;
2433 }
2434 }
2435
Pavol Vican10ffba52016-04-04 12:21:22 +02002436 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002437 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002438 goto error;
2439 }
2440
Pavol Vican10ffba52016-04-04 12:21:22 +02002441 if (module == tmp_module) {
2442 nacm_inherit(module);
2443 }
2444
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002445 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02002446 if (!module->implemented) {
2447 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
2448 }
Michal Vasko26055752016-05-03 11:36:31 +02002449 if (lys_module_set_implement(module)) {
2450 goto error;
2451 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002452
Michal Vasko26055752016-05-03 11:36:31 +02002453 if (lys_sub_module_set_dev_aug_target_implement(module)) {
2454 goto error;
2455 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002456 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02002457 if (!module->inc[i].submodule) {
2458 continue;
2459 }
Michal Vasko26055752016-05-03 11:36:31 +02002460 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
2461 goto error;
2462 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002463 }
2464 }
2465
Pavol Vican8e7110b2016-03-22 17:00:26 +01002466 unres_schema_free(NULL, &unres);
2467 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2468 return module;
2469
2470error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002471 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002472 unres_schema_free(module, &unres);
2473 if (!module || !module->name) {
2474 free(module);
2475 LOGERR(ly_errno, "Module parsing failed.");
2476 return NULL;
2477 }
2478
2479 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002480
2481 lys_sub_module_remove_devs_augs(module);
2482 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002483 return NULL;
2484}
2485
2486struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002487yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002488{
2489 struct lys_submodule *submodule;
2490
2491 submodule = calloc(1, sizeof *submodule);
2492 if (!submodule) {
2493 LOGMEM;
2494 goto error;
2495 }
2496
2497 submodule->ctx = module->ctx;
2498 submodule->type = 1;
2499 submodule->belongsto = module;
2500
2501 if (yang_parse_mem(module, submodule, unres, data, size)) {
2502 goto error;
2503 }
2504
Pavol Vican8e7110b2016-03-22 17:00:26 +01002505 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002506 return submodule;
2507
2508error:
2509 /* cleanup */
2510 unres_schema_free((struct lys_module *)submodule, &unres);
2511
2512 if (!submodule || !submodule->name) {
2513 free(submodule);
2514 LOGERR(ly_errno, "Submodule parsing failed.");
2515 return NULL;
2516 }
2517
2518 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2519
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002520 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2521 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002522 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002523 return NULL;
2524}
Pavol Vican8760bb72016-04-07 09:44:01 +02002525
2526static int
2527count_substring(const char *str, char c)
2528{
2529 const char *tmp = str;
2530 int count = 0;
2531
2532 while ((tmp = strchr(tmp, c))) {
2533 tmp++;
2534 count++;
2535 }
2536 return count;
2537}
2538
2539static int
2540read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2541{
2542 int k = 0, j;
2543
2544 while (in_index < size) {
2545 if (input[in_index] == ' ') {
2546 k++;
2547 } else if (input[in_index] == '\t') {
2548 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2549 k += 8;
2550 } else {
2551 break;
2552 }
2553 ++in_index;
2554 if (k >= indent) {
2555 for (j = k - indent; j > 0; --j) {
2556 output[*out_index] = ' ';
2557 ++(*out_index);
2558 }
2559 break;
2560 }
2561 }
2562 return in_index;
2563}
2564
2565char *
Pavol Vican677b0132016-08-09 15:44:58 +02002566yang_read_string(const char *input, int size, int indent, int version)
Pavol Vican8760bb72016-04-07 09:44:01 +02002567{
2568 int space, count;
2569 int in_index, out_index;
2570 char *value;
2571 char *retval = NULL;
2572
2573 value = malloc(size + 1);
2574 if (!value) {
2575 LOGMEM;
2576 return NULL;
2577 }
2578 /* replace special character in escape sequence */
2579 in_index = out_index = 0;
2580 while (in_index < size) {
2581 if (input[in_index] == '\\') {
2582 if (input[in_index + 1] == 'n') {
2583 value[out_index] = '\n';
2584 ++in_index;
2585 } else if (input[in_index + 1] == 't') {
2586 value[out_index] = '\t';
2587 ++in_index;
2588 } else if (input[in_index + 1] == '\\') {
2589 value[out_index] = '\\';
2590 ++in_index;
2591 } else if ((in_index + 1) != size && input[in_index + 1] == '"') {
2592 value[out_index] = '"';
2593 ++in_index;
2594 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002595 if (version < 2) {
2596 value[out_index] = input[in_index];
2597 } else {
2598 /* YANG 1.1 backslash must not be followed by any other character */
2599 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
2600 goto error;
2601 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002602 }
2603 } else {
2604 value[out_index] = input[in_index];
2605 }
2606 ++in_index;
2607 ++out_index;
2608 }
2609 value[out_index] = '\0';
2610 size = out_index;
2611 count = count_substring(value, '\t');
2612
2613 /* extend size of string due to replacing character '\t' with 8 spaces */
2614 retval = malloc(size + 1 + 7 * count);
2615 if (!retval) {
2616 LOGMEM;
2617 goto error;
2618 }
2619 in_index = out_index = space = 0;
2620 while (in_index < size) {
2621 if (value[in_index] == '\n') {
2622 out_index -= space;
2623 space = 0;
2624 retval[out_index] = '\n';
2625 ++out_index;
2626 ++in_index;
2627 in_index = read_indent(value, indent, size, in_index, &out_index, retval);
2628 continue;
2629 } else {
2630 space = (value[in_index] == ' ' || value[in_index] == '\t') ? space + 1 : 0;
2631 retval[out_index] = value[in_index];
2632 ++out_index;
2633 }
2634 ++in_index;
2635 }
2636 retval[out_index] = '\0';
2637 if (out_index != size) {
2638 retval = ly_realloc(retval, out_index + 1);
2639 }
2640 free(value);
2641 return retval;
2642error:
2643 free(value);
2644 return NULL;
2645}