blob: 361c3025696c05bfc89a7daf71ac11f40ae08a82 [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 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
22#include "parser_yang.h"
23#include "parser_yang_bis.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010024#include "parser.h"
Pavol Vican021488a2016-01-25 23:56:12 +010025
Pavol Vican2a064652016-02-02 22:54:34 +010026static int
27yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value, int line)
28{
Pavol Vicanbf805472016-01-26 14:24:56 +010029 if (*target) {
Pavol Vican2a064652016-02-02 22:54:34 +010030 LOGVAL(LYE_TOOMANY, line, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010031 free(value);
32 return 1;
33 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010034 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010035 return 0;
36 }
37}
38
Pavol Vican2a064652016-02-02 22:54:34 +010039int
40yang_read_common(struct lys_module *module, char *value, int type, int line)
41{
Pavol Vican6eb14e82016-02-03 12:27:13 +010042 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010043
44 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010045 case MODULE_KEYWORD:
46 module->name = lydict_insert_zc(module->ctx, value);
47 break;
48 case NAMESPACE_KEYWORD:
49 ret = yang_check_string(module, &module->ns, "namespace", "module", value, line);
50 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010051 case ORGANIZATION_KEYWORD:
52 ret = yang_check_string(module, &module->org, "organization", "module", value, line);
53 break;
54 case CONTACT_KEYWORD:
55 ret = yang_check_string(module, &module->contact, "contact", "module", value, line);
56 break;
Pavol Vican2a064652016-02-02 22:54:34 +010057 }
58
Pavol Vican021488a2016-01-25 23:56:12 +010059 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010060}
61
Pavol Vican2a064652016-02-02 22:54:34 +010062int
63yang_read_prefix(struct lys_module *module, void *save, char *value, int type, int line)
64{
Pavol Vican6eb14e82016-02-03 12:27:13 +010065 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +010066
Pavol Vican6eb14e82016-02-03 12:27:13 +010067 if (lyp_check_identifier(value, LY_IDENT_PREFIX, line, module, NULL)) {
68 free(value);
69 return EXIT_FAILURE;
70 }
Pavol Vicanbf805472016-01-26 14:24:56 +010071 switch (type){
Pavol Vican2a064652016-02-02 22:54:34 +010072 case MODULE_KEYWORD:
73 ret = yang_check_string(module, &module->prefix, "prefix", "module", value, line);
74 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +010075 case IMPORT_KEYWORD:
76 ((struct lys_import *)save)->prefix = lydict_insert_zc(module->ctx, value);
77 break;
Pavol Vican2a064652016-02-02 22:54:34 +010078 }
Pavol Vican6eb14e82016-02-03 12:27:13 +010079
Pavol Vicanbf805472016-01-26 14:24:56 +010080 return ret;
81}
Pavol Vican6eb14e82016-02-03 12:27:13 +010082
83void *
84yang_elem_of_array(void **ptr, uint8_t *act_size, int type, int sizeof_struct)
85{
86 void *retval;
87
88 if (!(*act_size % LY_ARRAY_SIZE) && !(*ptr = ly_realloc(*ptr, (*act_size + LY_ARRAY_SIZE) * sizeof_struct))) {
89 LOGMEM;
90 return NULL;
91 }
92 switch (type) {
93 case IMPORT_KEYWORD:
94 retval = &((struct lys_import *)(*ptr))[*act_size];
95 break;
Pavol Vicanbedff692016-02-03 14:29:17 +010096 case REVISION_KEYWORD:
97 retval = &((struct lys_revision *)(*ptr))[*act_size];
98 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +010099 }
100 (*act_size)++;
101 memset(retval,0,sizeof_struct);
102 return retval;
103}
104
105int
106yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value, int line)
107{
108 int count, i;
109
110 /* check for circular import, store it if passed */
111 if (!module->ctx->models.parsing) {
112 count = 0;
113 } else {
114 for (count = 0; module->ctx->models.parsing[count]; ++count) {
115 if (value == module->ctx->models.parsing[count]) {
116 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
117 goto error;
118 }
119 }
120 }
121 ++count;
122 module->ctx->models.parsing =
123 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
124 if (!module->ctx->models.parsing) {
125 LOGMEM;
126 goto error;
127 }
128 module->ctx->models.parsing[count - 1] = value;
129 module->ctx->models.parsing[count] = NULL;
130
131 /* try to load the module */
132 imp->module = (struct lys_module *)ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
133 if (!imp->module) {
134 /* whether to use a user callback is decided in the function */
135 imp->module = (struct lys_module *)ly_ctx_load_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
136 }
137
138 /* remove the new module name now that its parsing is finished (even if failed) */
139 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
140 LOGINT;
141 }
142 --count;
143 if (count) {
144 module->ctx->models.parsing[count] = NULL;
145 } else {
146 free(module->ctx->models.parsing);
147 module->ctx->models.parsing = NULL;
148 }
149
150 /* check the result */
151 if (!imp->module) {
152 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
153 goto error;
154 }
155
156 module->imp_size++;
157
158 /* check duplicities in imported modules */
159 for (i = 0; i < module->imp_size - 1; i++) {
160 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
161 LOGVAL(LYE_SPEC, line, "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
162 goto error;
163 }
164 }
165
166 free(value);
167 return EXIT_SUCCESS;
168
169 error:
170
171 free(value);
172 return EXIT_FAILURE;
173}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100174
175int
176yang_read_description(struct lys_module *module, void *node, char *value, int type, int line)
177{
178 int ret;
179
180 if (!node) {
181 ret = yang_check_string(module, &module->dsc, "description", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100182 } else {
183 switch (type) {
184 case REVISION_KEYWORD:
185 ret = yang_check_string(module, &((struct lys_revision *) node)->dsc, "description", "revision", value, line);
186 break;
Pavol Vicane1354e92016-02-09 14:02:09 +0100187 case FEATURE_KEYWORD:
188 ret = yang_check_string(module, &((struct lys_feature *) node)->dsc, "description", "feature", value, line);
189 break;
Pavol Vicanbedff692016-02-03 14:29:17 +0100190 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100191 }
192 return ret;
193}
194
195int
196yang_read_reference(struct lys_module *module, void *node, char *value, int type, int line)
197{
198 int ret;
199
200 if (!node) {
201 ret = yang_check_string(module, &module->ref, "reference", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100202 } else {
203 switch (type) {
204 case REVISION_KEYWORD:
205 ret = yang_check_string(module, &((struct lys_revision *) node)->ref, "reference", "revision", value, line);
206 break;
207 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100208 }
209 return ret;
210}
Pavol Vicanbedff692016-02-03 14:29:17 +0100211
212void *
213yang_read_revision(struct lys_module *module, char *value)
214{
215 struct lys_revision *retval;
216
Pavol Vican1eeb1992016-02-09 11:10:45 +0100217 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100218
219 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100220 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100221 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
222 memcpy(module->rev[0].date, value, LY_REV_SIZE);
223 retval->dsc = module->rev[0].dsc;
224 retval->ref = module->rev[0].ref;
225 retval = module->rev;
226 retval->dsc = NULL;
227 retval->ref = NULL;
228 } else {
229 memcpy(retval->date, value, LY_REV_SIZE);
230 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100231 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100232 free(value);
233 return retval;
234}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100235
236int
237yang_add_elem(struct lys_node_array **node, int *size)
238{
239 if (!*size % LY_ARRAY_SIZE) {
240 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
241 LOGMEM;
242 return EXIT_FAILURE;
243 } else {
244 memset(*node+*size,0,LY_ARRAY_SIZE*sizeof **node);
245 }
246 }
247 (*size)++;
248 return EXIT_SUCCESS;
249}
Pavol Vicane1354e92016-02-09 14:02:09 +0100250
251void *
252yang_read_feature(struct lys_module *module, char *value, int line)
253{
254 struct lys_feature *retval;
255
256 /* check uniqueness of feature's names */
257 if (lyp_check_identifier(value, LY_IDENT_FEATURE, line, module, NULL)) {
258 goto error;
259 }
260 retval = &module->features[module->features_size];
261 retval->name = lydict_insert_zc(module->ctx, value);
262 retval->module = module;
263 module->features_size++;
264 return retval;
265
266error:
267 free(value);
268 return NULL;
269}
270
271int
272yang_read_if_feature(struct lys_module *module, struct lys_feature *f, char *value, struct unres_schema *unres, int line)
273{
274 const char *exp;
275 int ret;
276
277 if (!(exp = transform_schema2json(module, value, line))) {
278 free(value);
279 return EXIT_FAILURE;
280 }
281 free(value);
282
283 /* hack - store pointer to the parent node for later status check */
284 f->features[f->features_size] = f;
285 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp, line);
286 f->features_size++;
287
288 lydict_remove(module->ctx, exp);
289 if (ret == -1) {
290
291 return EXIT_FAILURE;
292 }
293 return EXIT_SUCCESS;
294}
295
296static int
297yang_check_flags(uint8_t *flags, uint8_t mask, char *what, char *where, int value, int line)
298{
299 if (*flags & mask) {
300 LOGVAL(LYE_TOOMANY, line, what, where);
301 return EXIT_FAILURE;
302 } else {
303 *flags = value;
304 return EXIT_SUCCESS;
305 }
306}
307
308int
309yang_read_status(void *node, int value, int type, int line)
310{
311 int retval;
312
313 switch (type) {
314 case FEATURE_KEYWORD:
315 retval = yang_check_flags(&((struct lys_feature *) node)->flags, LYS_STATUS_MASK, "status", "feature", value, line);
316 break;
317 }
318 return retval;
319}