blob: 396b9f79e1e59ea55911e711eb31e72248cf385d [file] [log] [blame]
Radek Krejci86d106e2018-10-18 09:53:19 +02001/**
2 * @file tree_schema_helpers.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Parsing and validation helper functions
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * 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
13 */
Radek Krejci9ed7a192018-10-31 16:23:51 +010014#include "common.h"
Radek Krejci86d106e2018-10-18 09:53:19 +020015
16#include <ctype.h>
Radek Krejci9ed7a192018-10-31 16:23:51 +010017#include <dirent.h>
18#include <errno.h>
19#include <fcntl.h>
Radek Krejci86d106e2018-10-18 09:53:19 +020020#include <limits.h>
Radek Krejci9ed7a192018-10-31 16:23:51 +010021#include <stdlib.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24#include <unistd.h>
Radek Krejci86d106e2018-10-18 09:53:19 +020025#include <time.h>
26
27#include "libyang.h"
Radek Krejci86d106e2018-10-18 09:53:19 +020028#include "tree_schema_internal.h"
29
Radek Krejcia3045382018-11-22 14:30:31 +010030/**
31 * @brief Parse an identifier.
32 *
33 * ;; An identifier MUST NOT start with (('X'|'x') ('M'|'m') ('L'|'l'))
34 * identifier = (ALPHA / "_")
35 * *(ALPHA / DIGIT / "_" / "-" / ".")
36 *
37 * @param[in,out] id Identifier to parse. When returned, it points to the first character which is not part of the identifier.
38 * @return LY_ERR value: LY_SUCCESS or LY_EINVAL in case of invalid starting character.
39 */
40static LY_ERR
41lys_parse_id(const char **id)
42{
43 assert(id && *id);
44
Radek Krejcia9026eb2018-12-12 16:04:47 +010045 if (!is_yangidentstartchar(**id)) {
Radek Krejcia3045382018-11-22 14:30:31 +010046 return LY_EINVAL;
47 }
48 ++(*id);
49
Radek Krejcia9026eb2018-12-12 16:04:47 +010050 while (is_yangidentchar(**id)) {
Radek Krejcia3045382018-11-22 14:30:31 +010051 ++(*id);
52 }
53 return LY_SUCCESS;
54}
55
56LY_ERR
57lys_parse_nodeid(const char **id, const char **prefix, size_t *prefix_len, const char **name, size_t *name_len)
58{
59 assert(id && *id);
60 assert(prefix && prefix_len);
61 assert(name && name_len);
62
63 *prefix = *id;
64 *prefix_len = 0;
65 *name = NULL;
66 *name_len = 0;
67
68 LY_CHECK_RET(lys_parse_id(id));
69 if (**id == ':') {
70 /* there is prefix */
71 *prefix_len = *id - *prefix;
72 ++(*id);
73 *name = *id;
74
75 LY_CHECK_RET(lys_parse_id(id));
76 *name_len = *id - *name;
77 } else {
78 /* there is no prefix, so what we have as prefix now is actually the name */
79 *name = *prefix;
80 *name_len = *id - *name;
81 *prefix = NULL;
82 }
83
84 return LY_SUCCESS;
85}
86
Radek Krejci86d106e2018-10-18 09:53:19 +020087LY_ERR
Radek Krejci95710c92019-02-11 15:49:55 +010088lys_resolve_schema_nodeid(struct lysc_ctx *ctx, const char *nodeid, size_t nodeid_len, const struct lysc_node *context_node,
89 int nodetype, int implement, const struct lysc_node **target)
Radek Krejci9bb94eb2018-12-04 16:48:35 +010090{
91 LY_ERR ret = LY_EVALID;
92 const char *name, *prefix, *id;
93 const struct lysc_node *context;
94 size_t name_len, prefix_len;
Radek Krejci95710c92019-02-11 15:49:55 +010095 const struct lys_module *mod, *context_module;
96 const char *nodeid_type;
Radek Krejci9bb94eb2018-12-04 16:48:35 +010097
98 assert(nodeid);
Radek Krejci9bb94eb2018-12-04 16:48:35 +010099 assert(target);
100 *target = NULL;
101
102 id = nodeid;
103 context = context_node;
Radek Krejci95710c92019-02-11 15:49:55 +0100104
105 if (context_node) {
106 /* descendant-schema-nodeid */
107 nodeid_type = "descendant";
108 context_module = context_node->module;
Radek Krejci3641f562019-02-13 15:38:40 +0100109
110 if (*id == '/') {
111 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
112 "Invalid descendant-schema-nodeid value \"%.*s\" - absolute-schema-nodeid used.",
113 nodeid_len ? nodeid_len : strlen(nodeid), nodeid);
114 return LY_EVALID;
115 }
Radek Krejci95710c92019-02-11 15:49:55 +0100116 } else {
117 /* absolute-schema-nodeid */
118 nodeid_type = "absolute";
119 context_module = ctx->mod_def;
120
121 if (*id != '/') {
122 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
123 "Invalid absolute-schema-nodeid value \"%.*s\" - missing starting \"/\".",
Radek Krejci3641f562019-02-13 15:38:40 +0100124 nodeid_len ? nodeid_len : strlen(nodeid), nodeid);
Radek Krejci95710c92019-02-11 15:49:55 +0100125 return LY_EVALID;
126 }
127 ++id;
128 }
129
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100130 while (*id && (ret = lys_parse_nodeid(&id, &prefix, &prefix_len, &name, &name_len)) == LY_SUCCESS) {
131 if (prefix) {
Radek Krejci95710c92019-02-11 15:49:55 +0100132 mod = lys_module_find_prefix(context_module, prefix, prefix_len);
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100133 if (!mod) {
134 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejci95710c92019-02-11 15:49:55 +0100135 "Invalid %s-schema-nodeid value \"%.*s\" - prefix \"%.*s\" not defined in module \"%s\".",
136 nodeid_type, id - nodeid, nodeid, prefix_len, prefix, context_module->name);
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100137 return LY_ENOTFOUND;
138 }
139 } else {
Radek Krejci95710c92019-02-11 15:49:55 +0100140 mod = context_module;
141 }
142 if (implement && !mod->implemented) {
143 /* make the module implemented */
144 ly_ctx_module_implement_internal(ctx->ctx, (struct lys_module*)mod, 2);
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100145 }
Radek Krejcia9026eb2018-12-12 16:04:47 +0100146 context = lys_child(context, mod, name, name_len, 0, LYS_GETNEXT_NOSTATECHECK | LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE);
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100147 if (!context) {
148 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejci95710c92019-02-11 15:49:55 +0100149 "Invalid %s-schema-nodeid value \"%.*s\" - target node not found.", nodeid_type, id - nodeid, nodeid);
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100150 return LY_ENOTFOUND;
151 }
Radek Krejci01342af2019-01-03 15:18:08 +0100152 if (!*id || (nodeid_len && ((size_t)(id - nodeid) >= nodeid_len))) {
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100153 break;
154 }
Radek Krejci01342af2019-01-03 15:18:08 +0100155 if (*id != '/') {
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100156 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejci95710c92019-02-11 15:49:55 +0100157 "Invalid %s-schema-nodeid value \"%.*s\" - missing \"/\" as node-identifier separator.",
158 nodeid_type, id - nodeid + 1, nodeid);
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100159 return LY_EVALID;
160 }
161 ++id;
162 }
163
164 if (ret == LY_SUCCESS) {
165 *target = context;
166 if (nodetype && !(context->nodetype & nodetype)) {
167 return LY_EDENIED;
168 }
Radek Krejci95710c92019-02-11 15:49:55 +0100169 } else {
170 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
171 "Invalid %s-schema-nodeid value \"%.*s\" - unexpected end of expression.",
Radek Krejci3641f562019-02-13 15:38:40 +0100172 nodeid_type, nodeid_len ? nodeid_len : strlen(nodeid), nodeid);
Radek Krejci9bb94eb2018-12-04 16:48:35 +0100173 }
174
175 return ret;
176}
177
Radek Krejci86d106e2018-10-18 09:53:19 +0200178LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100179lysp_check_prefix(struct ly_parser_ctx *ctx, struct lysp_import *imports, const char *module_prefix, const char **value)
Radek Krejci86d106e2018-10-18 09:53:19 +0200180{
181 struct lysp_import *i;
182
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100183 if (module_prefix && &module_prefix != value && !strcmp(module_prefix, *value)) {
Radek Krejci86d106e2018-10-18 09:53:19 +0200184 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
185 "Prefix \"%s\" already used as module prefix.", *value);
186 return LY_EEXIST;
187 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100188 LY_ARRAY_FOR(imports, struct lysp_import, i) {
189 if (i->prefix && &i->prefix != value && !strcmp(i->prefix, *value)) {
190 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE, "Prefix \"%s\" already used to import \"%s\" module.",
191 *value, i->name);
192 return LY_EEXIST;
Radek Krejci86d106e2018-10-18 09:53:19 +0200193 }
194 }
195 return LY_SUCCESS;
196}
197
198LY_ERR
Radek Krejci4f28eda2018-11-12 11:46:16 +0100199lysc_check_status(struct lysc_ctx *ctx,
200 uint16_t flags1, void *mod1, const char *name1,
201 uint16_t flags2, void *mod2, const char *name2)
202{
203 uint16_t flg1, flg2;
204
205 flg1 = (flags1 & LYS_STATUS_MASK) ? (flags1 & LYS_STATUS_MASK) : LYS_STATUS_CURR;
206 flg2 = (flags2 & LYS_STATUS_MASK) ? (flags2 & LYS_STATUS_MASK) : LYS_STATUS_CURR;
207
208 if ((flg1 < flg2) && (mod1 == mod2)) {
209 if (ctx) {
210 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
211 "A %s definition \"%s\" is not allowed to reference %s definition \"%s\".",
212 flg1 == LYS_STATUS_CURR ? "current" : "deprecated", name1,
213 flg2 == LYS_STATUS_OBSLT ? "obsolete" : "deprecated", name2);
214 }
215 return LY_EVALID;
216 }
217
218 return LY_SUCCESS;
219}
220
221LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +0100222lysp_check_date(struct ly_parser_ctx *ctx, const char *date, int date_len, const char *stmt)
Radek Krejci86d106e2018-10-18 09:53:19 +0200223{
224 int i;
225 struct tm tm, tm_;
226 char *r;
227
Radek Krejcibbe09a92018-11-08 09:36:54 +0100228 LY_CHECK_ARG_RET(ctx ? ctx->ctx : NULL, date, LY_EINVAL);
229 LY_CHECK_ERR_RET(date_len != LY_REV_SIZE - 1, LOGARG(ctx ? ctx->ctx : NULL, date_len), LY_EINVAL);
Radek Krejci86d106e2018-10-18 09:53:19 +0200230
231 /* check format */
232 for (i = 0; i < date_len; i++) {
233 if (i == 4 || i == 7) {
234 if (date[i] != '-') {
235 goto error;
236 }
237 } else if (!isdigit(date[i])) {
238 goto error;
239 }
240 }
241
242 /* check content, e.g. 2018-02-31 */
243 memset(&tm, 0, sizeof tm);
244 r = strptime(date, "%Y-%m-%d", &tm);
245 if (!r || r != &date[LY_REV_SIZE - 1]) {
246 goto error;
247 }
248 memcpy(&tm_, &tm, sizeof tm);
249 mktime(&tm_); /* mktime modifies tm_ if it refers invalid date */
250 if (tm.tm_mday != tm_.tm_mday) { /* e.g 2018-02-29 -> 2018-03-01 */
251 /* checking days is enough, since other errors
252 * have been checked by strptime() */
253 goto error;
254 }
255
256 return LY_SUCCESS;
257
258error:
Radek Krejcid33273d2018-10-25 14:55:52 +0200259 if (stmt) {
Radek Krejcibbe09a92018-11-08 09:36:54 +0100260 if (ctx) {
261 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LY_VCODE_INVAL, date_len, date, stmt);
262 } else {
263 LOGVAL(NULL, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, date_len, date, stmt);
264 }
Radek Krejcid33273d2018-10-25 14:55:52 +0200265 }
Radek Krejci86d106e2018-10-18 09:53:19 +0200266 return LY_EINVAL;
267}
268
269void
270lysp_sort_revisions(struct lysp_revision *revs)
271{
272 uint8_t i, r;
273 struct lysp_revision rev;
274
275 for (i = 1, r = 0; revs && i < LY_ARRAY_SIZE(revs); i++) {
Radek Krejcib7db73a2018-10-24 14:18:40 +0200276 if (strcmp(revs[i].date, revs[r].date) > 0) {
Radek Krejci86d106e2018-10-18 09:53:19 +0200277 r = i;
278 }
279 }
280
281 if (r) {
282 /* the newest revision is not on position 0, switch them */
Radek Krejci2c4e7172018-10-19 15:56:26 +0200283 memcpy(&rev, &revs[0], sizeof rev);
284 memcpy(&revs[0], &revs[r], sizeof rev);
285 memcpy(&revs[r], &rev, sizeof rev);
Radek Krejci86d106e2018-10-18 09:53:19 +0200286 }
287}
Radek Krejci151a5b72018-10-19 14:21:44 +0200288
Radek Krejcibbe09a92018-11-08 09:36:54 +0100289static const struct lysp_tpdf *
290lysp_type_match(const char *name, struct lysp_node *node)
Radek Krejci151a5b72018-10-19 14:21:44 +0200291{
Radek Krejci0fb28562018-12-13 15:17:37 +0100292 const struct lysp_tpdf *typedefs;
Radek Krejcibbe09a92018-11-08 09:36:54 +0100293 unsigned int u;
Radek Krejci151a5b72018-10-19 14:21:44 +0200294
Radek Krejci0fb28562018-12-13 15:17:37 +0100295 typedefs = lysp_node_typedefs(node);
296 LY_ARRAY_FOR(typedefs, u) {
297 if (!strcmp(name, typedefs[u].name)) {
298 /* match */
299 return &typedefs[u];
Radek Krejci151a5b72018-10-19 14:21:44 +0200300 }
301 }
302
303 return NULL;
304}
David Sedlák23a59a62018-10-26 13:08:02 +0200305
Radek Krejci4f28eda2018-11-12 11:46:16 +0100306static LY_DATA_TYPE
307lysp_type_str2builtin(const char *name, size_t len)
308{
309 if (len >= 4) { /* otherwise it does not match any built-in type */
310 if (name[0] == 'b') {
311 if (name[1] == 'i') {
312 if (len == 6 && !strncmp(&name[2], "nary", 4)) {
313 return LY_TYPE_BINARY;
314 } else if (len == 4 && !strncmp(&name[2], "ts", 2)) {
315 return LY_TYPE_BITS;
316 }
317 } else if (len == 7 && !strncmp(&name[1], "oolean", 6)) {
318 return LY_TYPE_BOOL;
319 }
320 } else if (name[0] == 'd') {
321 if (len == 9 && !strncmp(&name[1], "ecimal64", 8)) {
322 return LY_TYPE_DEC64;
323 }
324 } else if (name[0] == 'e') {
325 if (len == 5 && !strncmp(&name[1], "mpty", 4)) {
326 return LY_TYPE_EMPTY;
327 } else if (len == 11 && !strncmp(&name[1], "numeration", 10)) {
328 return LY_TYPE_ENUM;
329 }
330 } else if (name[0] == 'i') {
331 if (name[1] == 'n') {
332 if (len == 4 && !strncmp(&name[2], "t8", 2)) {
333 return LY_TYPE_INT8;
334 } else if (len == 5) {
335 if (!strncmp(&name[2], "t16", 3)) {
336 return LY_TYPE_INT16;
337 } else if (!strncmp(&name[2], "t32", 3)) {
338 return LY_TYPE_INT32;
339 } else if (!strncmp(&name[2], "t64", 3)) {
340 return LY_TYPE_INT64;
341 }
342 } else if (len == 19 && !strncmp(&name[2], "stance-identifier", 17)) {
343 return LY_TYPE_INST;
344 }
345 } else if (len == 11 && !strncmp(&name[1], "dentityref", 10)) {
346 return LY_TYPE_IDENT;
347 }
348 } else if (name[0] == 'l') {
349 if (len == 7 && !strncmp(&name[1], "eafref", 6)) {
350 return LY_TYPE_LEAFREF;
351 }
352 } else if (name[0] == 's') {
353 if (len == 6 && !strncmp(&name[1], "tring", 5)) {
354 return LY_TYPE_STRING;
355 }
356 } else if (name[0] == 'u') {
357 if (name[1] == 'n') {
358 if (len == 5 && !strncmp(&name[2], "ion", 3)) {
359 return LY_TYPE_UNION;
360 }
361 } else if (name[1] == 'i' && name[2] == 'n' && name[3] == 't') {
362 if (len == 5 && name[4] == '8') {
363 return LY_TYPE_UINT8;
364 } else if (len == 6) {
365 if (!strncmp(&name[4], "16", 2)) {
366 return LY_TYPE_UINT16;
367 } else if (!strncmp(&name[4], "32", 2)) {
368 return LY_TYPE_UINT32;
369 } else if (!strncmp(&name[4], "64", 2)) {
370 return LY_TYPE_UINT64;
371 }
372 }
373 }
374 }
375 }
376
377 return LY_TYPE_UNKNOWN;
378}
379
Radek Krejcibbe09a92018-11-08 09:36:54 +0100380LY_ERR
381lysp_type_find(const char *id, struct lysp_node *start_node, struct lysp_module *start_module,
Radek Krejci4f28eda2018-11-12 11:46:16 +0100382 LY_DATA_TYPE *type, const struct lysp_tpdf **tpdf, struct lysp_node **node, struct lysp_module **module)
Radek Krejcibbe09a92018-11-08 09:36:54 +0100383{
384 const char *str, *name;
385 struct lysp_tpdf *typedefs;
386 unsigned int u, v;
387
388 assert(id);
389 assert(start_module);
390 assert(tpdf);
391 assert(node);
392 assert(module);
393
Radek Krejci4f28eda2018-11-12 11:46:16 +0100394 *node = NULL;
Radek Krejcibbe09a92018-11-08 09:36:54 +0100395 str = strchr(id, ':');
396 if (str) {
397 *module = lysp_module_find_prefix(start_module, id, str - id);
398 name = str + 1;
Radek Krejci4f28eda2018-11-12 11:46:16 +0100399 *type = LY_TYPE_UNKNOWN;
Radek Krejcibbe09a92018-11-08 09:36:54 +0100400 } else {
401 *module = start_module;
402 name = id;
Radek Krejci4f28eda2018-11-12 11:46:16 +0100403
404 /* check for built-in types */
405 *type = lysp_type_str2builtin(name, strlen(name));
406 if (*type) {
407 *tpdf = NULL;
408 return LY_SUCCESS;
409 }
Radek Krejcibbe09a92018-11-08 09:36:54 +0100410 }
411 LY_CHECK_RET(!(*module), LY_ENOTFOUND);
412
413 if (start_node && *module == start_module) {
414 /* search typedefs in parent's nodes */
415 *node = start_node;
416 while (*node) {
417 *tpdf = lysp_type_match(name, *node);
418 if (*tpdf) {
419 /* match */
420 return LY_SUCCESS;
421 }
422 *node = (*node)->parent;
423 }
424 }
425
426 /* search in top-level typedefs */
427 if ((*module)->typedefs) {
428 LY_ARRAY_FOR((*module)->typedefs, u) {
429 if (!strcmp(name, (*module)->typedefs[u].name)) {
430 /* match */
431 *tpdf = &(*module)->typedefs[u];
432 return LY_SUCCESS;
433 }
434 }
435 }
436
437 /* search in submodules' typedefs */
438 LY_ARRAY_FOR((*module)->includes, u) {
439 typedefs = (*module)->includes[u].submodule->typedefs;
Radek Krejci76b3e962018-12-14 17:01:25 +0100440 LY_ARRAY_FOR(typedefs, v) {
441 if (!strcmp(name, typedefs[v].name)) {
442 /* match */
443 *tpdf = &typedefs[v];
444 return LY_SUCCESS;
Radek Krejcibbe09a92018-11-08 09:36:54 +0100445 }
446 }
447 }
448
449 return LY_ENOTFOUND;
450}
451
452/*
453 * @brief Check name of a new type to avoid name collisions.
454 *
455 * @param[in] ctx Parser context, module where the type is being defined is taken from here.
456 * @param[in] node Schema node where the type is being defined, NULL in case of a top-level typedef.
457 * @param[in] tpdf Typedef definition to check.
458 * @param[in,out] tpdfs_global Initialized hash table to store temporary data between calls. When the module's
459 * typedefs are checked, caller is supposed to free the table.
460 * @param[in,out] tpdfs_global Initialized hash table to store temporary data between calls. When the module's
461 * typedefs are checked, caller is supposed to free the table.
462 * @return LY_EEXIST in case of collision, LY_SUCCESS otherwise.
463 */
464static LY_ERR
Radek Krejci0fb28562018-12-13 15:17:37 +0100465lysp_check_typedef(struct ly_parser_ctx *ctx, struct lysp_node *node, const struct lysp_tpdf *tpdf,
Radek Krejcibbe09a92018-11-08 09:36:54 +0100466 struct hash_table *tpdfs_global, struct hash_table *tpdfs_scoped)
467{
468 struct lysp_node *parent;
469 uint32_t hash;
470 size_t name_len;
471 const char *name;
472 unsigned int u;
Radek Krejci0fb28562018-12-13 15:17:37 +0100473 const struct lysp_tpdf *typedefs;
Radek Krejcibbe09a92018-11-08 09:36:54 +0100474
475 assert(ctx);
476 assert(tpdf);
477
478 name = tpdf->name;
479 name_len = strlen(name);
480
Radek Krejci4f28eda2018-11-12 11:46:16 +0100481 if (lysp_type_str2builtin(name, name_len)) {
482 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_SYNTAX_YANG,
483 "Invalid name \"%s\" of typedef - name collision with a built-in type.", name);
484 return LY_EEXIST;
Radek Krejcibbe09a92018-11-08 09:36:54 +0100485 }
486
487 /* check locally scoped typedefs (avoid name shadowing) */
488 if (node) {
Radek Krejci0fb28562018-12-13 15:17:37 +0100489 typedefs = lysp_node_typedefs(node);
490 LY_ARRAY_FOR(typedefs, u) {
491 if (&typedefs[u] == tpdf) {
492 break;
493 }
494 if (!strcmp(name, typedefs[u].name)) {
495 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_SYNTAX_YANG,
496 "Invalid name \"%s\" of typedef - name collision with sibling type.", name);
497 return LY_EEXIST;
Radek Krejcibbe09a92018-11-08 09:36:54 +0100498 }
499 }
500 /* search typedefs in parent's nodes */
501 for (parent = node->parent; parent; parent = node->parent) {
502 if (lysp_type_match(name, parent)) {
503 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_SYNTAX_YANG,
504 "Invalid name \"%s\" of typedef - name collision with another scoped type.", name);
505 return LY_EEXIST;
506 }
507 }
508 }
509
510 /* check collision with the top-level typedefs */
511 hash = dict_hash(name, name_len);
512 if (node) {
513 lyht_insert(tpdfs_scoped, &name, hash, NULL);
514 if (!lyht_find(tpdfs_global, &name, hash, NULL)) {
515 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_SYNTAX_YANG,
516 "Invalid name \"%s\" of typedef - scoped type collide with a top-level type.", name);
517 return LY_EEXIST;
518 }
519 } else {
520 if (lyht_insert(tpdfs_global, &name, hash, NULL)) {
521 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_SYNTAX_YANG,
522 "Invalid name \"%s\" of typedef - name collision with another top-level type.", name);
523 return LY_EEXIST;
524 }
Radek Krejci3b1f9292018-11-08 10:58:35 +0100525 /* it is not necessary to test collision with the scoped types - in lysp_check_typedefs, all the
526 * top-level typedefs are inserted into the tables before the scoped typedefs, so the collision
527 * is detected in the first branch few lines above */
Radek Krejcibbe09a92018-11-08 09:36:54 +0100528 }
529
530 return LY_SUCCESS;
531}
532
533static int
534lysp_id_cmp(void *val1, void *val2, int UNUSED(mod), void *UNUSED(cb_data))
535{
536 return !strcmp(val1, val2);
537}
538
539LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100540lysp_check_typedefs(struct ly_parser_ctx *ctx, struct lysp_module *mod)
Radek Krejcibbe09a92018-11-08 09:36:54 +0100541{
542 struct hash_table *ids_global;
543 struct hash_table *ids_scoped;
Radek Krejci0fb28562018-12-13 15:17:37 +0100544 const struct lysp_tpdf *typedefs;
Radek Krejcibbe09a92018-11-08 09:36:54 +0100545 unsigned int i, u;
546 LY_ERR ret = LY_EVALID;
547
548 /* check name collisions - typedefs and groupings */
549 ids_global = lyht_new(8, sizeof(char*), lysp_id_cmp, NULL, 1);
550 ids_scoped = lyht_new(8, sizeof(char*), lysp_id_cmp, NULL, 1);
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100551 LY_ARRAY_FOR(mod->typedefs, i) {
552 if (lysp_check_typedef(ctx, NULL, &mod->typedefs[i], ids_global, ids_scoped)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +0100553 goto cleanup;
554 }
555 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100556 LY_ARRAY_FOR(mod->includes, i) {
557 LY_ARRAY_FOR(mod->includes[i].submodule->typedefs, u) {
558 if (lysp_check_typedef(ctx, NULL, &mod->includes[i].submodule->typedefs[u], ids_global, ids_scoped)) {
Radek Krejci3b1f9292018-11-08 10:58:35 +0100559 goto cleanup;
560 }
561 }
562 }
Radek Krejcibbe09a92018-11-08 09:36:54 +0100563 for (u = 0; u < ctx->tpdfs_nodes.count; ++u) {
Radek Krejci0fb28562018-12-13 15:17:37 +0100564 typedefs = lysp_node_typedefs((struct lysp_node *)ctx->tpdfs_nodes.objs[u]);
565 LY_ARRAY_FOR(typedefs, i) {
566 if (lysp_check_typedef(ctx, (struct lysp_node *)ctx->tpdfs_nodes.objs[u], &typedefs[i], ids_global, ids_scoped)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +0100567 goto cleanup;
568 }
569 }
570 }
571 ret = LY_SUCCESS;
572cleanup:
573 lyht_free(ids_global);
574 lyht_free(ids_scoped);
575 ly_set_erase(&ctx->tpdfs_nodes, NULL);
576
577 return ret;
578}
579
Radek Krejci9ed7a192018-10-31 16:23:51 +0100580struct lysp_load_module_check_data {
581 const char *name;
582 const char *revision;
583 const char *path;
584 const char* submoduleof;
585};
586
587static LY_ERR
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100588lysp_load_module_check(struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data)
Radek Krejci9ed7a192018-10-31 16:23:51 +0100589{
590 struct lysp_load_module_check_data *info = data;
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100591 const char *filename, *dot, *rev, *name;
Radek Krejci9ed7a192018-10-31 16:23:51 +0100592 size_t len;
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100593 struct lysp_revision *revs;
594
595 name = mod ? mod->mod->name : submod->name;
596 revs = mod ? mod->revs : submod->revs;
Radek Krejci9ed7a192018-10-31 16:23:51 +0100597
598 if (info->name) {
599 /* check name of the parsed model */
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100600 if (strcmp(info->name, name)) {
601 LOGERR(ctx, LY_EINVAL, "Unexpected module \"%s\" parsed instead of \"%s\").", name, info->name);
Radek Krejci9ed7a192018-10-31 16:23:51 +0100602 return LY_EINVAL;
603 }
604 }
605 if (info->revision) {
606 /* check revision of the parsed model */
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100607 if (!revs || strcmp(info->revision, revs[0].date)) {
608 LOGERR(ctx, LY_EINVAL, "Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").", name,
609 revs[0].date, info->revision);
Radek Krejci9ed7a192018-10-31 16:23:51 +0100610 return LY_EINVAL;
611 }
612 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100613 if (submod) {
614 assert(info->submoduleof);
615
Radek Krejci9ed7a192018-10-31 16:23:51 +0100616 /* check that the submodule belongs-to our module */
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100617 if (strcmp(info->submoduleof, submod->belongsto)) {
Radek Krejci9ed7a192018-10-31 16:23:51 +0100618 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Included \"%s\" submodule from \"%s\" belongs-to a different module \"%s\".",
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100619 submod->name, info->submoduleof, submod->belongsto);
Radek Krejci9ed7a192018-10-31 16:23:51 +0100620 return LY_EVALID;
621 }
622 /* check circular dependency */
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100623 if (submod->parsing) {
624 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "A circular dependency (include) for module \"%s\".", submod->name);
Radek Krejci9ed7a192018-10-31 16:23:51 +0100625 return LY_EVALID;
626 }
627 }
628 if (info->path) {
629 /* check that name and revision match filename */
630 filename = strrchr(info->path, '/');
631 if (!filename) {
632 filename = info->path;
633 } else {
634 filename++;
635 }
636 /* name */
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100637 len = strlen(name);
Radek Krejci9ed7a192018-10-31 16:23:51 +0100638 rev = strchr(filename, '@');
639 dot = strrchr(info->path, '.');
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100640 if (strncmp(filename, name, len) ||
Radek Krejci9ed7a192018-10-31 16:23:51 +0100641 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100642 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, name);
Radek Krejci9ed7a192018-10-31 16:23:51 +0100643 }
644 /* revision */
645 if (rev) {
646 len = dot - ++rev;
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100647 if (!revs || len != 10 || strncmp(revs[0].date, rev, len)) {
Radek Krejci9ed7a192018-10-31 16:23:51 +0100648 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100649 revs ? revs[0].date : "none");
Radek Krejci9ed7a192018-10-31 16:23:51 +0100650 }
651 }
652 }
653 return LY_SUCCESS;
654}
655
656LY_ERR
Radek Krejci3b1f9292018-11-08 10:58:35 +0100657lys_module_localfile(struct ly_ctx *ctx, const char *name, const char *revision, int implement, struct ly_parser_ctx *main_ctx,
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100658 void **result)
Radek Krejci9ed7a192018-10-31 16:23:51 +0100659{
660 int fd;
661 char *filepath = NULL;
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100662 const char **fp;
Radek Krejci9ed7a192018-10-31 16:23:51 +0100663 LYS_INFORMAT format;
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100664 void *mod = NULL;
Radek Krejci9ed7a192018-10-31 16:23:51 +0100665 LY_ERR ret = LY_SUCCESS;
666 struct lysp_load_module_check_data check_data = {0};
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100667 char rpath[PATH_MAX];
Radek Krejci9ed7a192018-10-31 16:23:51 +0100668
669 LY_CHECK_RET(lys_search_localfile(ly_ctx_get_searchdirs(ctx), !(ctx->flags & LY_CTX_DISABLE_SEARCHDIR_CWD), name, revision,
670 &filepath, &format));
671 LY_CHECK_ERR_RET(!filepath, LOGERR(ctx, LY_ENOTFOUND, "Data model \"%s%s%s\" not found in local searchdirs.",
672 name, revision ? "@" : "", revision ? revision : ""), LY_ENOTFOUND);
673
674
675 LOGVRB("Loading schema from \"%s\" file.", filepath);
676
677 /* open the file */
678 fd = open(filepath, O_RDONLY);
679 LY_CHECK_ERR_GOTO(fd < 0, LOGERR(ctx, LY_ESYS, "Unable to open data model file \"%s\" (%s).",
680 filepath, strerror(errno)); ret = LY_ESYS, cleanup);
681
682 check_data.name = name;
683 check_data.revision = revision;
684 check_data.path = filepath;
Radek Krejci3b1f9292018-11-08 10:58:35 +0100685 mod = lys_parse_fd_(ctx, fd, format, implement, main_ctx,
Radek Krejci9ed7a192018-10-31 16:23:51 +0100686 lysp_load_module_check, &check_data);
687 close(fd);
688 LY_CHECK_ERR_GOTO(!mod, ly_errcode(ctx), cleanup);
689
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100690 if (main_ctx) {
691 fp = &((struct lysp_submodule*)mod)->filepath;
692 } else {
693 fp = &((struct lys_module*)mod)->filepath;
694 }
695 if (!(*fp)) {
Radek Krejci9ed7a192018-10-31 16:23:51 +0100696 if (realpath(filepath, rpath) != NULL) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100697 (*fp) = lydict_insert(ctx, rpath, 0);
Radek Krejci9ed7a192018-10-31 16:23:51 +0100698 } else {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100699 (*fp) = lydict_insert(ctx, filepath, 0);
Radek Krejci9ed7a192018-10-31 16:23:51 +0100700 }
701 }
702
703 *result = mod;
704
705 /* success */
706cleanup:
707 free(filepath);
708 return ret;
709}
710
Radek Krejcid33273d2018-10-25 14:55:52 +0200711LY_ERR
Radek Krejci6d6e4e42018-10-29 13:28:19 +0100712lysp_load_module(struct ly_ctx *ctx, const char *name, const char *revision, int implement, int require_parsed, struct lys_module **mod)
Radek Krejci086c7132018-10-26 15:29:04 +0200713{
Radek Krejci9ed7a192018-10-31 16:23:51 +0100714 const char *module_data = NULL;
Radek Krejci086c7132018-10-26 15:29:04 +0200715 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Radek Krejci9ed7a192018-10-31 16:23:51 +0100716 void (*module_data_free)(void *module_data, void *user_data) = NULL;
717 struct lysp_load_module_check_data check_data = {0};
Radek Krejci0af46292019-01-11 16:02:31 +0100718 struct lys_module *m;
Radek Krejci086c7132018-10-26 15:29:04 +0200719
Radek Krejci0af46292019-01-11 16:02:31 +0100720 assert(mod);
721
722 if (!*mod) {
723 /* try to get the module from the context */
724 if (revision) {
725 *mod = (struct lys_module*)ly_ctx_get_module(ctx, name, revision);
726 } else {
727 *mod = (struct lys_module*)ly_ctx_get_module_latest(ctx, name);
728 }
Radek Krejci086c7132018-10-26 15:29:04 +0200729 }
730
Radek Krejci6d6e4e42018-10-29 13:28:19 +0100731 if (!(*mod) || (require_parsed && !(*mod)->parsed)) {
732 (*mod) = NULL;
733
Radek Krejci086c7132018-10-26 15:29:04 +0200734 /* check collision with other implemented revision */
735 if (implement && ly_ctx_get_module_implemented(ctx, name)) {
736 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE,
737 "Module \"%s\" is already present in other implemented revision.", name);
738 return LY_EDENIED;
739 }
740
Radek Krejci9ed7a192018-10-31 16:23:51 +0100741 /* module not present in the context, get the input data and parse it */
Radek Krejci086c7132018-10-26 15:29:04 +0200742 if (!(ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
743search_clb:
744 if (ctx->imp_clb) {
745 if (ctx->imp_clb(name, revision, NULL, NULL, ctx->imp_clb_data,
Radek Krejci9ed7a192018-10-31 16:23:51 +0100746 &format, &module_data, &module_data_free) == LY_SUCCESS) {
747 check_data.name = name;
748 check_data.revision = revision;
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100749 *mod = lys_parse_mem_module(ctx, module_data, format, implement,
750 lysp_load_module_check, &check_data);
Radek Krejci9ed7a192018-10-31 16:23:51 +0100751 if (module_data_free) {
752 module_data_free((void*)module_data, ctx->imp_clb_data);
753 }
Radek Krejci096235c2019-01-11 11:12:19 +0100754 if (*mod && implement && lys_compile(*mod, 0)) {
755 ly_set_rm(&ctx->list, *mod, NULL);
756 lys_module_free(*mod, NULL);
757 *mod = NULL;
758 }
Radek Krejci086c7132018-10-26 15:29:04 +0200759 }
760 }
761 if (!(*mod) && !(ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
762 goto search_file;
763 }
764 } else {
765search_file:
766 if (!(ctx->flags & LY_CTX_DISABLE_SEARCHDIRS)) {
767 /* module was not received from the callback or there is no callback set */
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100768 lys_module_localfile(ctx, name, revision, implement, NULL, (void **)mod);
Radek Krejci086c7132018-10-26 15:29:04 +0200769 }
770 if (!(*mod) && (ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
771 goto search_clb;
772 }
773 }
Radek Krejci9ed7a192018-10-31 16:23:51 +0100774
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100775 if ((*mod) && !revision && ((*mod)->latest_revision == 1)) {
Radek Krejci9ed7a192018-10-31 16:23:51 +0100776 /* update the latest_revision flag - here we have selected the latest available schema,
777 * consider that even the callback provides correct latest revision */
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100778 (*mod)->latest_revision = 2;
Radek Krejci9ed7a192018-10-31 16:23:51 +0100779 }
Radek Krejci086c7132018-10-26 15:29:04 +0200780 } else {
781 /* we have module from the current context */
Radek Krejci0af46292019-01-11 16:02:31 +0100782 if (implement) {
783 m = ly_ctx_get_module_implemented(ctx, name);
784 if (m && m != *mod) {
785 /* check collision with other implemented revision */
786 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE,
787 "Module \"%s\" is already present in other implemented revision.", name);
788 *mod = NULL;
789 return LY_EDENIED;
790 }
Radek Krejci086c7132018-10-26 15:29:04 +0200791 }
792
793 /* circular check */
Radek Krejcif8f882a2018-10-31 14:51:15 +0100794 if ((*mod)->parsed && (*mod)->parsed->parsing) {
Radek Krejci086c7132018-10-26 15:29:04 +0200795 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "A circular dependency (import) for module \"%s\".", name);
796 *mod = NULL;
797 return LY_EVALID;
798 }
799 }
800 if (!(*mod)) {
Radek Krejci9ed7a192018-10-31 16:23:51 +0100801 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "%s \"%s\" module failed.", implement ? "Loading" : "Importing", name);
Radek Krejci086c7132018-10-26 15:29:04 +0200802 return LY_EVALID;
803 }
804
805 if (implement) {
806 /* mark the module implemented, check for collision was already done */
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100807 (*mod)->implemented = 1;
Radek Krejci086c7132018-10-26 15:29:04 +0200808 }
Radek Krejci086c7132018-10-26 15:29:04 +0200809
810 return LY_SUCCESS;
811}
812
813LY_ERR
Radek Krejci3b1f9292018-11-08 10:58:35 +0100814lysp_load_submodule(struct ly_parser_ctx *ctx, struct lysp_module *mod, struct lysp_include *inc)
Radek Krejcid33273d2018-10-25 14:55:52 +0200815{
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100816 struct lysp_submodule *submod;
Radek Krejcid33273d2018-10-25 14:55:52 +0200817 const char *submodule_data = NULL;
818 LYS_INFORMAT format = LYS_IN_UNKNOWN;
819 void (*submodule_data_free)(void *module_data, void *user_data) = NULL;
Radek Krejci9ed7a192018-10-31 16:23:51 +0100820 struct lysp_load_module_check_data check_data = {0};
Radek Krejcid33273d2018-10-25 14:55:52 +0200821
Radek Krejcibbe09a92018-11-08 09:36:54 +0100822 /* submodule not present in the context, get the input data and parse it */
Radek Krejci3b1f9292018-11-08 10:58:35 +0100823 if (!(ctx->ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
Radek Krejcid33273d2018-10-25 14:55:52 +0200824search_clb:
Radek Krejci3b1f9292018-11-08 10:58:35 +0100825 if (ctx->ctx->imp_clb) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100826 if (ctx->ctx->imp_clb(mod->mod->name, NULL, inc->name, inc->rev[0] ? inc->rev : NULL, ctx->ctx->imp_clb_data,
Radek Krejcibbe09a92018-11-08 09:36:54 +0100827 &format, &submodule_data, &submodule_data_free) == LY_SUCCESS) {
828 check_data.name = inc->name;
829 check_data.revision = inc->rev[0] ? inc->rev : NULL;
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100830 check_data.submoduleof = mod->mod->name;
831 submod = lys_parse_mem_submodule(ctx->ctx, submodule_data, format, ctx,
832 lysp_load_module_check, &check_data);
Radek Krejcibbe09a92018-11-08 09:36:54 +0100833 if (submodule_data_free) {
Radek Krejci3b1f9292018-11-08 10:58:35 +0100834 submodule_data_free((void*)submodule_data, ctx->ctx->imp_clb_data);
Radek Krejcid33273d2018-10-25 14:55:52 +0200835 }
836 }
Radek Krejcid33273d2018-10-25 14:55:52 +0200837 }
Radek Krejci3b1f9292018-11-08 10:58:35 +0100838 if (!submod && !(ctx->ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +0100839 goto search_file;
Radek Krejcid33273d2018-10-25 14:55:52 +0200840 }
Radek Krejci2d31ea72018-10-25 15:46:42 +0200841 } else {
Radek Krejcibbe09a92018-11-08 09:36:54 +0100842search_file:
Radek Krejci3b1f9292018-11-08 10:58:35 +0100843 if (!(ctx->ctx->flags & LY_CTX_DISABLE_SEARCHDIRS)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100844 /* submodule was not received from the callback or there is no callback set */
845 lys_module_localfile(ctx->ctx, inc->name, inc->rev[0] ? inc->rev : NULL, 0, ctx, (void**)&submod);
Radek Krejcibbe09a92018-11-08 09:36:54 +0100846 }
Radek Krejci3b1f9292018-11-08 10:58:35 +0100847 if (!submod && (ctx->ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +0100848 goto search_clb;
849 }
850 }
851 if (submod) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100852 if (!inc->rev[0] && (submod->latest_revision == 1)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +0100853 /* update the latest_revision flag - here we have selected the latest available schema,
854 * consider that even the callback provides correct latest revision */
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100855 submod->latest_revision = 2;
Radek Krejcibbe09a92018-11-08 09:36:54 +0100856 }
857
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100858 inc->submodule = submod;
Radek Krejcid33273d2018-10-25 14:55:52 +0200859 }
860 if (!inc->submodule) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100861 LOGVAL(ctx->ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Including \"%s\" submodule into \"%s\" failed.",
862 inc->name, mod->mod->name);
Radek Krejcid33273d2018-10-25 14:55:52 +0200863 return LY_EVALID;
864 }
865
866 return LY_SUCCESS;
867}
868
Radek Krejci01342af2019-01-03 15:18:08 +0100869#define FIND_MODULE(TYPE, MOD) \
Radek Krejcice8c1592018-10-29 15:35:51 +0100870 TYPE *imp; \
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100871 if (!strncmp((MOD)->mod->prefix, prefix, len) && (MOD)->mod->prefix[len] == '\0') { \
Radek Krejcice8c1592018-10-29 15:35:51 +0100872 /* it is the prefix of the module itself */ \
Radek Krejci0af46292019-01-11 16:02:31 +0100873 m = ly_ctx_get_module((MOD)->mod->ctx, (MOD)->mod->name, (MOD)->mod->revision); \
Radek Krejcice8c1592018-10-29 15:35:51 +0100874 } \
875 /* search in imports */ \
Radek Krejcibbe09a92018-11-08 09:36:54 +0100876 if (!m) { \
877 LY_ARRAY_FOR((MOD)->imports, TYPE, imp) { \
Radek Krejci01342af2019-01-03 15:18:08 +0100878 if (!strncmp(imp->prefix, prefix, len) && imp->prefix[len] == '\0') { \
Radek Krejcibbe09a92018-11-08 09:36:54 +0100879 m = imp->module; \
880 break; \
881 } \
Radek Krejcice8c1592018-10-29 15:35:51 +0100882 } \
Radek Krejcibbe09a92018-11-08 09:36:54 +0100883 }
Radek Krejcice8c1592018-10-29 15:35:51 +0100884
Radek Krejcibbe09a92018-11-08 09:36:54 +0100885struct lysc_module *
Radek Krejcia3045382018-11-22 14:30:31 +0100886lysc_module_find_prefix(const struct lysc_module *mod, const char *prefix, size_t len)
Radek Krejci86d106e2018-10-18 09:53:19 +0200887{
Radek Krejcibbe09a92018-11-08 09:36:54 +0100888 const struct lys_module *m = NULL;
889
Radek Krejci01342af2019-01-03 15:18:08 +0100890 FIND_MODULE(struct lysc_import, mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +0100891 return m ? m->compiled : NULL;
Radek Krejcice8c1592018-10-29 15:35:51 +0100892}
Radek Krejci86d106e2018-10-18 09:53:19 +0200893
Radek Krejcibbe09a92018-11-08 09:36:54 +0100894struct lysp_module *
Radek Krejcia3045382018-11-22 14:30:31 +0100895lysp_module_find_prefix(const struct lysp_module *mod, const char *prefix, size_t len)
Radek Krejcice8c1592018-10-29 15:35:51 +0100896{
Radek Krejcibbe09a92018-11-08 09:36:54 +0100897 const struct lys_module *m = NULL;
898
Radek Krejci01342af2019-01-03 15:18:08 +0100899 FIND_MODULE(struct lysp_import, mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +0100900 return m ? m->parsed : NULL;
Radek Krejcice8c1592018-10-29 15:35:51 +0100901}
Radek Krejci86d106e2018-10-18 09:53:19 +0200902
Radek Krejcice8c1592018-10-29 15:35:51 +0100903struct lys_module *
Radek Krejcia3045382018-11-22 14:30:31 +0100904lys_module_find_prefix(const struct lys_module *mod, const char *prefix, size_t len)
Radek Krejcice8c1592018-10-29 15:35:51 +0100905{
Radek Krejcibbe09a92018-11-08 09:36:54 +0100906 const struct lys_module *m = NULL;
907
Radek Krejcice8c1592018-10-29 15:35:51 +0100908 if (mod->compiled) {
Radek Krejci01342af2019-01-03 15:18:08 +0100909 FIND_MODULE(struct lysc_import, mod->compiled);
Radek Krejcice8c1592018-10-29 15:35:51 +0100910 } else {
Radek Krejci01342af2019-01-03 15:18:08 +0100911 FIND_MODULE(struct lysp_import, mod->parsed);
Radek Krejcibbe09a92018-11-08 09:36:54 +0100912 }
913 return (struct lys_module*)m;
914}
915
Radek Krejcia3045382018-11-22 14:30:31 +0100916const char *
917lys_nodetype2str(uint16_t nodetype)
918{
919 switch(nodetype) {
920 case LYS_CONTAINER:
921 return "container";
922 case LYS_CHOICE:
923 return "choice";
924 case LYS_LEAF:
925 return "leaf";
926 case LYS_LEAFLIST:
927 return "leaf-list";
928 case LYS_LIST:
929 return "list";
930 case LYS_ANYXML:
931 return "anyxml";
932 case LYS_ANYDATA:
933 return "anydata";
Radek Krejcif12a1f02019-02-11 16:42:08 +0100934 case LYS_CASE:
935 return "case";
Radek Krejcia3045382018-11-22 14:30:31 +0100936 default:
937 return "unknown";
938 }
939}
940
Radek Krejci056d0a82018-12-06 16:57:25 +0100941API const struct lysp_tpdf *
942lysp_node_typedefs(const struct lysp_node *node)
943{
Radek Krejci0fb28562018-12-13 15:17:37 +0100944 switch (node->nodetype) {
945 case LYS_CONTAINER:
946 return ((struct lysp_node_container*)node)->typedefs;
947 case LYS_LIST:
948 return ((struct lysp_node_list*)node)->typedefs;
949 case LYS_GROUPING:
950 return ((struct lysp_grp*)node)->typedefs;
951 case LYS_ACTION:
952 return ((struct lysp_action*)node)->typedefs;
953 case LYS_INOUT:
954 return ((struct lysp_action_inout*)node)->typedefs;
955 case LYS_NOTIF:
956 return ((struct lysp_notif*)node)->typedefs;
957 default:
Radek Krejci056d0a82018-12-06 16:57:25 +0100958 return NULL;
959 }
960}
961
Radek Krejci53ea6152018-12-13 15:21:15 +0100962API const struct lysp_grp *
963lysp_node_groupings(const struct lysp_node *node)
964{
965 switch (node->nodetype) {
966 case LYS_CONTAINER:
967 return ((struct lysp_node_container*)node)->groupings;
968 case LYS_LIST:
969 return ((struct lysp_node_list*)node)->groupings;
970 case LYS_GROUPING:
971 return ((struct lysp_grp*)node)->groupings;
972 case LYS_ACTION:
973 return ((struct lysp_action*)node)->groupings;
974 case LYS_INOUT:
975 return ((struct lysp_action_inout*)node)->groupings;
976 case LYS_NOTIF:
977 return ((struct lysp_notif*)node)->groupings;
978 default:
979 return NULL;
980 }
981}
982
Radek Krejcibbe09a92018-11-08 09:36:54 +0100983struct lysp_action **
Radek Krejci056d0a82018-12-06 16:57:25 +0100984lysp_node_actions_p(struct lysp_node *node)
Radek Krejcibbe09a92018-11-08 09:36:54 +0100985{
986 assert(node);
987 switch (node->nodetype) {
988 case LYS_CONTAINER:
989 return &((struct lysp_node_container*)node)->actions;
990 case LYS_LIST:
991 return &((struct lysp_node_list*)node)->actions;
992 case LYS_GROUPING:
993 return &((struct lysp_grp*)node)->actions;
994 case LYS_AUGMENT:
995 return &((struct lysp_augment*)node)->actions;
996 default:
997 return NULL;
998 }
999}
1000
Radek Krejci056d0a82018-12-06 16:57:25 +01001001API const struct lysp_action *
1002lysp_node_actions(const struct lysp_node *node)
1003{
1004 struct lysp_action **actions;
1005 actions = lysp_node_actions_p((struct lysp_node*)node);
1006 if (actions) {
1007 return *actions;
1008 } else {
1009 return NULL;
1010 }
1011}
1012
Radek Krejcibbe09a92018-11-08 09:36:54 +01001013struct lysp_notif **
Radek Krejci056d0a82018-12-06 16:57:25 +01001014lysp_node_notifs_p(struct lysp_node *node)
Radek Krejcibbe09a92018-11-08 09:36:54 +01001015{
1016 assert(node);
1017 switch (node->nodetype) {
1018 case LYS_CONTAINER:
1019 return &((struct lysp_node_container*)node)->notifs;
1020 case LYS_LIST:
1021 return &((struct lysp_node_list*)node)->notifs;
1022 case LYS_GROUPING:
1023 return &((struct lysp_grp*)node)->notifs;
1024 case LYS_AUGMENT:
1025 return &((struct lysp_augment*)node)->notifs;
1026 default:
1027 return NULL;
1028 }
1029}
1030
Radek Krejci056d0a82018-12-06 16:57:25 +01001031API const struct lysp_notif *
1032lysp_node_notifs(const struct lysp_node *node)
1033{
1034 struct lysp_notif **notifs;
1035 notifs = lysp_node_notifs_p((struct lysp_node*)node);
1036 if (notifs) {
1037 return *notifs;
1038 } else {
1039 return NULL;
1040 }
1041}
1042
Radek Krejcibbe09a92018-11-08 09:36:54 +01001043struct lysp_node **
Radek Krejci056d0a82018-12-06 16:57:25 +01001044lysp_node_children_p(struct lysp_node *node)
Radek Krejcibbe09a92018-11-08 09:36:54 +01001045{
1046 assert(node);
1047 switch (node->nodetype) {
1048 case LYS_CONTAINER:
1049 return &((struct lysp_node_container*)node)->child;
1050 case LYS_CHOICE:
1051 return &((struct lysp_node_choice*)node)->child;
1052 case LYS_LIST:
1053 return &((struct lysp_node_list*)node)->child;
1054 case LYS_CASE:
1055 return &((struct lysp_node_case*)node)->child;
1056 case LYS_GROUPING:
1057 return &((struct lysp_grp*)node)->data;
1058 case LYS_AUGMENT:
1059 return &((struct lysp_augment*)node)->child;
1060 case LYS_INOUT:
1061 return &((struct lysp_action_inout*)node)->data;
1062 case LYS_NOTIF:
1063 return &((struct lysp_notif*)node)->data;
1064 default:
1065 return NULL;
1066 }
1067}
1068
Radek Krejci056d0a82018-12-06 16:57:25 +01001069API const struct lysp_node *
1070lysp_node_children(const struct lysp_node *node)
1071{
1072 struct lysp_node **children;
1073 children = lysp_node_children_p((struct lysp_node*)node);
1074 if (children) {
1075 return *children;
1076 } else {
1077 return NULL;
1078 }
1079}
1080
1081struct lysc_action **
1082lysc_node_actions_p(struct lysc_node *node)
1083{
1084 assert(node);
1085 switch (node->nodetype) {
1086 case LYS_CONTAINER:
1087 return &((struct lysc_node_container*)node)->actions;
1088 case LYS_LIST:
1089 return &((struct lysc_node_list*)node)->actions;
1090 default:
1091 return NULL;
1092 }
1093}
1094
1095API const struct lysc_action *
1096lysc_node_actions(const struct lysc_node *node)
1097{
1098 struct lysc_action **actions;
1099 actions = lysc_node_actions_p((struct lysc_node*)node);
1100 if (actions) {
1101 return *actions;
1102 } else {
1103 return NULL;
1104 }
1105}
1106
1107struct lysc_notif **
1108lysc_node_notifs_p(struct lysc_node *node)
1109{
1110 assert(node);
1111 switch (node->nodetype) {
1112 case LYS_CONTAINER:
1113 return &((struct lysc_node_container*)node)->notifs;
1114 case LYS_LIST:
1115 return &((struct lysc_node_list*)node)->notifs;
1116 default:
1117 return NULL;
1118 }
1119}
1120
1121API const struct lysc_notif *
1122lysc_node_notifs(const struct lysc_node *node)
1123{
1124 struct lysc_notif **notifs;
1125 notifs = lysc_node_notifs_p((struct lysc_node*)node);
1126 if (notifs) {
1127 return *notifs;
1128 } else {
1129 return NULL;
1130 }
1131}
1132
Radek Krejcibbe09a92018-11-08 09:36:54 +01001133struct lysc_node **
Radek Krejci056d0a82018-12-06 16:57:25 +01001134lysc_node_children_p(const struct lysc_node *node)
Radek Krejcibbe09a92018-11-08 09:36:54 +01001135{
1136 assert(node);
1137 switch (node->nodetype) {
1138 case LYS_CONTAINER:
1139 return &((struct lysc_node_container*)node)->child;
1140 case LYS_CHOICE:
Radek Krejcia3045382018-11-22 14:30:31 +01001141 if (((struct lysc_node_choice*)node)->cases) {
Radek Krejci95710c92019-02-11 15:49:55 +01001142 return &((struct lysc_node_choice*)node)->cases->child;
Radek Krejcia3045382018-11-22 14:30:31 +01001143 } else {
1144 return NULL;
1145 }
Radek Krejci01342af2019-01-03 15:18:08 +01001146 case LYS_CASE:
1147 return &((struct lysc_node_case*)node)->child;
Radek Krejcibbe09a92018-11-08 09:36:54 +01001148 case LYS_LIST:
1149 return &((struct lysc_node_list*)node)->child;
Radek Krejcibbe09a92018-11-08 09:36:54 +01001150/* TODO
1151 case LYS_INOUT:
1152 return &((struct lysc_action_inout*)node)->child;
1153 case LYS_NOTIF:
1154 return &((struct lysc_notif*)node)->child;
1155*/
1156 default:
1157 return NULL;
1158 }
1159}
1160
Radek Krejci056d0a82018-12-06 16:57:25 +01001161API const struct lysc_node *
1162lysc_node_children(const struct lysc_node *node)
Radek Krejcia3045382018-11-22 14:30:31 +01001163{
Radek Krejci056d0a82018-12-06 16:57:25 +01001164 struct lysc_node **children;
1165 children = lysc_node_children_p((struct lysc_node*)node);
1166 if (children) {
1167 return *children;
1168 } else {
Radek Krejcia3045382018-11-22 14:30:31 +01001169 return NULL;
1170 }
1171}
1172
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001173struct lys_module *
1174lysp_find_module(struct ly_ctx *ctx, const struct lysp_module *mod)
1175{
1176 unsigned int u;
1177
1178 for (u = 0; u < ctx->list.count; ++u) {
1179 if (((struct lys_module*)ctx->list.objs[u])->parsed == mod) {
1180 return ((struct lys_module*)ctx->list.objs[u]);
1181 }
1182 }
1183 return NULL;
1184}
1185
David Sedlákc10e7902018-12-17 02:17:59 +01001186enum yang_keyword
David Sedlák18e494b2018-12-17 03:58:39 +01001187match_keyword(const char *data)
David Sedlákc10e7902018-12-17 02:17:59 +01001188{
1189/* TODO make this function usable in get_keyword function */
David Sedlák18e494b2018-12-17 03:58:39 +01001190#define MOVE_IN(DATA, COUNT) (data)+=COUNT;
1191#define IF_KEYWORD(STR, LEN, STMT) if (!strncmp((data), STR, LEN)) {MOVE_IN(data, LEN);kw=STMT;}
1192#define IF_KEYWORD_PREFIX(STR, LEN) if (!strncmp((data), STR, LEN)) {MOVE_IN(data, LEN);
1193#define IF_KEYWORD_PREFIX_END }
David Sedlák23a59a62018-10-26 13:08:02 +02001194
David Sedlák23a59a62018-10-26 13:08:02 +02001195 enum yang_keyword kw = YANG_NONE;
1196 /* read the keyword itself */
1197 switch (*data) {
1198 case 'a':
David Sedlák18e494b2018-12-17 03:58:39 +01001199 MOVE_IN(data, 1);
1200 IF_KEYWORD("rgument", 7, YANG_ARGUMENT)
1201 else IF_KEYWORD("ugment", 6, YANG_AUGMENT)
1202 else IF_KEYWORD("ction", 5, YANG_ACTION)
1203 else IF_KEYWORD_PREFIX("ny", 2)
1204 IF_KEYWORD("data", 4, YANG_ANYDATA)
1205 else IF_KEYWORD("xml", 3, YANG_ANYXML)
1206 IF_KEYWORD_PREFIX_END
David Sedlák23a59a62018-10-26 13:08:02 +02001207 break;
1208 case 'b':
David Sedlák18e494b2018-12-17 03:58:39 +01001209 MOVE_IN(data, 1);
1210 IF_KEYWORD("ase", 3, YANG_BASE)
1211 else IF_KEYWORD("elongs-to", 9, YANG_BELONGS_TO)
1212 else IF_KEYWORD("it", 2, YANG_BIT)
David Sedlák23a59a62018-10-26 13:08:02 +02001213 break;
1214 case 'c':
David Sedlák18e494b2018-12-17 03:58:39 +01001215 MOVE_IN(data, 1);
1216 IF_KEYWORD("ase", 3, YANG_CASE)
1217 else IF_KEYWORD("hoice", 5, YANG_CHOICE)
1218 else IF_KEYWORD_PREFIX("on", 2)
1219 IF_KEYWORD("fig", 3, YANG_CONFIG)
1220 else IF_KEYWORD_PREFIX("ta", 2)
1221 IF_KEYWORD("ct", 2, YANG_CONTACT)
1222 else IF_KEYWORD("iner", 4, YANG_CONTAINER)
1223 IF_KEYWORD_PREFIX_END
1224 IF_KEYWORD_PREFIX_END
David Sedlák23a59a62018-10-26 13:08:02 +02001225 break;
1226 case 'd':
David Sedlák18e494b2018-12-17 03:58:39 +01001227 MOVE_IN(data, 1);
1228 IF_KEYWORD_PREFIX("e", 1)
1229 IF_KEYWORD("fault", 5, YANG_DEFAULT)
1230 else IF_KEYWORD("scription", 9, YANG_DESCRIPTION)
1231 else IF_KEYWORD_PREFIX("viat", 4)
1232 IF_KEYWORD("e", 1, YANG_DEVIATE)
1233 else IF_KEYWORD("ion", 3, YANG_DEVIATION)
1234 IF_KEYWORD_PREFIX_END
1235 IF_KEYWORD_PREFIX_END
David Sedlák23a59a62018-10-26 13:08:02 +02001236 break;
1237 case 'e':
David Sedlák18e494b2018-12-17 03:58:39 +01001238 MOVE_IN(data, 1);
1239 IF_KEYWORD("num", 3, YANG_ENUM)
1240 else IF_KEYWORD_PREFIX("rror-", 5)
1241 IF_KEYWORD("app-tag", 7, YANG_ERROR_APP_TAG)
1242 else IF_KEYWORD("message", 7, YANG_ERROR_MESSAGE)
1243 IF_KEYWORD_PREFIX_END
1244 else IF_KEYWORD("xtension", 8, YANG_EXTENSION)
David Sedlák23a59a62018-10-26 13:08:02 +02001245 break;
1246 case 'f':
David Sedlák18e494b2018-12-17 03:58:39 +01001247 MOVE_IN(data, 1);
1248 IF_KEYWORD("eature", 6, YANG_FEATURE)
1249 else IF_KEYWORD("raction-digits", 14, YANG_FRACTION_DIGITS)
David Sedlák23a59a62018-10-26 13:08:02 +02001250 break;
1251 case 'g':
David Sedlák18e494b2018-12-17 03:58:39 +01001252 MOVE_IN(data, 1);
1253 IF_KEYWORD("rouping", 7, YANG_GROUPING)
David Sedlák23a59a62018-10-26 13:08:02 +02001254 break;
1255 case 'i':
David Sedlák18e494b2018-12-17 03:58:39 +01001256 MOVE_IN(data, 1);
1257 IF_KEYWORD("dentity", 7, YANG_IDENTITY)
1258 else IF_KEYWORD("f-feature", 9, YANG_IF_FEATURE)
1259 else IF_KEYWORD("mport", 5, YANG_IMPORT)
1260 else IF_KEYWORD_PREFIX("n", 1)
1261 IF_KEYWORD("clude", 5, YANG_INCLUDE)
1262 else IF_KEYWORD("put", 3, YANG_INPUT)
1263 IF_KEYWORD_PREFIX_END
David Sedlák23a59a62018-10-26 13:08:02 +02001264 break;
1265 case 'k':
David Sedlák18e494b2018-12-17 03:58:39 +01001266 MOVE_IN(data, 1);
1267 IF_KEYWORD("ey", 2, YANG_KEY)
David Sedlák23a59a62018-10-26 13:08:02 +02001268 break;
1269 case 'l':
David Sedlák18e494b2018-12-17 03:58:39 +01001270 MOVE_IN(data, 1);
1271 IF_KEYWORD_PREFIX("e", 1)
1272 IF_KEYWORD("af-list", 7, YANG_LEAF_LIST)
1273 else IF_KEYWORD("af", 2, YANG_LEAF)
1274 else IF_KEYWORD("ngth", 4, YANG_LENGTH)
1275 IF_KEYWORD_PREFIX_END
1276 else IF_KEYWORD("ist", 3, YANG_LIST)
David Sedlák23a59a62018-10-26 13:08:02 +02001277 break;
1278 case 'm':
David Sedlák18e494b2018-12-17 03:58:39 +01001279 MOVE_IN(data, 1);
1280 IF_KEYWORD_PREFIX("a", 1)
1281 IF_KEYWORD("ndatory", 7, YANG_MANDATORY)
1282 else IF_KEYWORD("x-elements", 10, YANG_MAX_ELEMENTS)
1283 IF_KEYWORD_PREFIX_END
1284 else IF_KEYWORD("in-elements", 11, YANG_MIN_ELEMENTS)
1285 else IF_KEYWORD("ust", 3, YANG_MUST)
1286 else IF_KEYWORD_PREFIX("od", 2)
1287 IF_KEYWORD("ule", 3, YANG_MODULE)
1288 else IF_KEYWORD("ifier", 5, YANG_MODIFIER)
1289 IF_KEYWORD_PREFIX_END
David Sedlák23a59a62018-10-26 13:08:02 +02001290 break;
1291 case 'n':
David Sedlák18e494b2018-12-17 03:58:39 +01001292 MOVE_IN(data, 1);
1293 IF_KEYWORD("amespace", 8, YANG_NAMESPACE)
1294 else IF_KEYWORD("otification", 11, YANG_NOTIFICATION)
David Sedlák23a59a62018-10-26 13:08:02 +02001295 break;
1296 case 'o':
David Sedlák18e494b2018-12-17 03:58:39 +01001297 MOVE_IN(data, 1);
1298 IF_KEYWORD_PREFIX("r", 1)
1299 IF_KEYWORD("dered-by", 8, YANG_ORDERED_BY)
1300 else IF_KEYWORD("ganization", 10, YANG_ORGANIZATION)
1301 IF_KEYWORD_PREFIX_END
1302 else IF_KEYWORD("utput", 5, YANG_OUTPUT)
David Sedlák23a59a62018-10-26 13:08:02 +02001303 break;
1304 case 'p':
David Sedlák18e494b2018-12-17 03:58:39 +01001305 MOVE_IN(data, 1);
1306 IF_KEYWORD("ath", 3, YANG_PATH)
1307 else IF_KEYWORD("attern", 6, YANG_PATTERN)
1308 else IF_KEYWORD("osition", 7, YANG_POSITION)
1309 else IF_KEYWORD_PREFIX("re", 2)
1310 IF_KEYWORD("fix", 3, YANG_PREFIX)
1311 else IF_KEYWORD("sence", 5, YANG_PRESENCE)
1312 IF_KEYWORD_PREFIX_END
David Sedlák23a59a62018-10-26 13:08:02 +02001313 break;
1314 case 'r':
David Sedlák18e494b2018-12-17 03:58:39 +01001315 MOVE_IN(data, 1);
1316 IF_KEYWORD("ange", 4, YANG_RANGE)
1317 else IF_KEYWORD_PREFIX("e", 1)
1318 IF_KEYWORD_PREFIX("f", 1)
1319 IF_KEYWORD("erence", 6, YANG_REFERENCE)
1320 else IF_KEYWORD("ine", 3, YANG_REFINE)
1321 IF_KEYWORD_PREFIX_END
1322 else IF_KEYWORD("quire-instance", 14, YANG_REQUIRE_INSTANCE)
1323 else IF_KEYWORD("vision-date", 11, YANG_REVISION_DATE)
1324 else IF_KEYWORD("vision", 6, YANG_REVISION)
1325 IF_KEYWORD_PREFIX_END
1326 else IF_KEYWORD("pc", 2, YANG_RPC)
David Sedlák23a59a62018-10-26 13:08:02 +02001327 break;
1328 case 's':
David Sedlák18e494b2018-12-17 03:58:39 +01001329 MOVE_IN(data, 1);
1330 IF_KEYWORD("tatus", 5, YANG_STATUS)
1331 else IF_KEYWORD("ubmodule", 8, YANG_SUBMODULE)
David Sedlák23a59a62018-10-26 13:08:02 +02001332 break;
1333 case 't':
David Sedlák18e494b2018-12-17 03:58:39 +01001334 MOVE_IN(data, 1);
1335 IF_KEYWORD("ypedef", 6, YANG_TYPEDEF)
1336 else IF_KEYWORD("ype", 3, YANG_TYPE)
David Sedlák23a59a62018-10-26 13:08:02 +02001337 break;
1338 case 'u':
David Sedlák18e494b2018-12-17 03:58:39 +01001339 MOVE_IN(data, 1);
1340 IF_KEYWORD_PREFIX("ni", 2)
1341 IF_KEYWORD("que", 3, YANG_UNIQUE)
1342 else IF_KEYWORD("ts", 2, YANG_UNITS)
1343 IF_KEYWORD_PREFIX_END
1344 else IF_KEYWORD("ses", 3, YANG_USES)
David Sedlák23a59a62018-10-26 13:08:02 +02001345 break;
1346 case 'v':
David Sedlák18e494b2018-12-17 03:58:39 +01001347 MOVE_IN(data, 1);
1348 IF_KEYWORD("alue", 4, YANG_VALUE)
David Sedlák23a59a62018-10-26 13:08:02 +02001349 break;
1350 case 'w':
David Sedlák18e494b2018-12-17 03:58:39 +01001351 MOVE_IN(data, 1);
1352 IF_KEYWORD("hen", 3, YANG_WHEN)
David Sedlák23a59a62018-10-26 13:08:02 +02001353 break;
1354 case 'y':
David Sedlák18e494b2018-12-17 03:58:39 +01001355 MOVE_IN(data, 1);
1356 IF_KEYWORD("ang-version", 11, YANG_YANG_VERSION)
1357 else IF_KEYWORD("in-element", 10, YANG_YIN_ELEMENT)
David Sedlák23a59a62018-10-26 13:08:02 +02001358 break;
1359 case ';':
David Sedlák18e494b2018-12-17 03:58:39 +01001360 MOVE_IN(data, 1);
David Sedlák23a59a62018-10-26 13:08:02 +02001361 kw = YANG_SEMICOLON;
1362 //goto success;
1363 break;
1364 case '{':
David Sedlák18e494b2018-12-17 03:58:39 +01001365 MOVE_IN(data, 1);
David Sedlák23a59a62018-10-26 13:08:02 +02001366 kw = YANG_LEFT_BRACE;
1367 //goto success;
1368 break;
1369 case '}':
David Sedlák18e494b2018-12-17 03:58:39 +01001370 MOVE_IN(data, 1);
David Sedlák23a59a62018-10-26 13:08:02 +02001371 kw = YANG_RIGHT_BRACE;
1372 //goto success;
1373 break;
1374 default:
1375 break;
1376 }
1377
David Sedlákc10e7902018-12-17 02:17:59 +01001378 /* TODO important fix whole keyword must be matched */
David Sedlák23a59a62018-10-26 13:08:02 +02001379 return kw;
1380}