blob: ee169b42507304e8778e5f87ec792713c5792f70 [file] [log] [blame]
Radek Krejci3f5e3db2018-10-11 15:57:47 +02001/**
2 * @file tree_schema.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema tree implementation
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 Krejcib7db73a2018-10-24 14:18:40 +020014
15#include "common.h"
Radek Krejci86d106e2018-10-18 09:53:19 +020016
Radek Krejci151a5b72018-10-19 14:21:44 +020017#include <ctype.h>
Radek Krejcid33273d2018-10-25 14:55:52 +020018#include <dirent.h>
Radek Krejci86d106e2018-10-18 09:53:19 +020019#include <errno.h>
20#include <fcntl.h>
21#include <linux/limits.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <sys/stat.h>
25#include <sys/types.h>
26#include <unistd.h>
Radek Krejci3f5e3db2018-10-11 15:57:47 +020027
28#include "libyang.h"
Radek Krejci86d106e2018-10-18 09:53:19 +020029#include "context.h"
Radek Krejci70853c52018-10-15 14:46:16 +020030#include "tree_schema_internal.h"
Radek Krejci4f28eda2018-11-12 11:46:16 +010031#include "xpath.h"
Radek Krejci3f5e3db2018-10-11 15:57:47 +020032
Radek Krejci4f28eda2018-11-12 11:46:16 +010033#define FREE_ARRAY(CTX, ARRAY, FUNC) {uint64_t c__; LY_ARRAY_FOR(ARRAY, c__){FUNC(CTX, &ARRAY[c__]);}LY_ARRAY_FREE(ARRAY);}
34#define FREE_MEMBER(CTX, MEMBER, FUNC) if (MEMBER) {FUNC(CTX, MEMBER);free(MEMBER);}
35#define FREE_STRING(CTX, STRING) if (STRING) {lydict_remove(CTX, STRING);}
36#define FREE_STRINGS(CTX, ARRAY) {uint64_t c__; LY_ARRAY_FOR(ARRAY, c__){FREE_STRING(CTX, ARRAY[c__]);}LY_ARRAY_FREE(ARRAY);}
Radek Krejci6f7feb62018-10-12 15:23:02 +020037
Radek Krejcib31c8992018-11-12 16:29:16 +010038#define DUP_STRING(CTX, DUP, ORIG) if (ORIG) {DUP = lydict_insert(CTX, ORIG, 0);}
39
Radek Krejci6d6e4e42018-10-29 13:28:19 +010040#define COMPILE_ARRAY_GOTO(CTX, ARRAY_P, ARRAY_C, OPTIONS, ITER, FUNC, RET, GOTO) \
41 if (ARRAY_P) { \
Radek Krejcibd8d9ba2018-11-02 16:06:26 +010042 LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, LY_ARRAY_SIZE(ARRAY_P), RET, GOTO); \
Radek Krejci6d6e4e42018-10-29 13:28:19 +010043 for (ITER = 0; ITER < LY_ARRAY_SIZE(ARRAY_P); ++ITER) { \
Radek Krejci87616bb2018-10-31 13:30:52 +010044 LY_ARRAY_INCREMENT(ARRAY_C); \
Radek Krejcice8c1592018-10-29 15:35:51 +010045 RET = FUNC(CTX, &(ARRAY_P)[ITER], OPTIONS, &(ARRAY_C)[ITER]); \
Radek Krejci6d6e4e42018-10-29 13:28:19 +010046 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
Radek Krejci6d6e4e42018-10-29 13:28:19 +010047 } \
48 }
49
Radek Krejci4f28eda2018-11-12 11:46:16 +010050#define COMPILE_MEMBER_GOTO(CTX, MEMBER_P, MEMBER_C, OPTIONS, FUNC, RET, GOTO) \
51 if (MEMBER_P) { \
52 MEMBER_C = calloc(1, sizeof *(MEMBER_C)); \
53 LY_CHECK_ERR_GOTO(!(MEMBER_C), LOGMEM((CTX)->ctx); RET = LY_EMEM, GOTO); \
54 RET = FUNC(CTX, MEMBER_P, OPTIONS, MEMBER_C); \
55 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
56 }
Radek Krejci6f7feb62018-10-12 15:23:02 +020057
Radek Krejci4f28eda2018-11-12 11:46:16 +010058static void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
59static void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
Radek Krejci86d106e2018-10-18 09:53:19 +020060
Radek Krejci6f7feb62018-10-12 15:23:02 +020061static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010062lysp_stmt_free(struct ly_ctx *ctx, struct lysp_stmt *stmt)
Radek Krejci6f7feb62018-10-12 15:23:02 +020063{
64 struct lysp_stmt *child, *next;
65
Radek Krejci4f28eda2018-11-12 11:46:16 +010066 FREE_STRING(ctx, stmt->stmt);
67 FREE_STRING(ctx, stmt->arg);
Radek Krejci6f7feb62018-10-12 15:23:02 +020068
69 LY_LIST_FOR_SAFE(stmt->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +010070 lysp_stmt_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +020071 }
72
73 free(stmt);
74}
75
76static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010077lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext)
Radek Krejci6f7feb62018-10-12 15:23:02 +020078{
79 struct lysp_stmt *stmt, *next;
80
Radek Krejci4f28eda2018-11-12 11:46:16 +010081 FREE_STRING(ctx, ext->name);
82 FREE_STRING(ctx, ext->argument);
Radek Krejci6f7feb62018-10-12 15:23:02 +020083
84 LY_LIST_FOR_SAFE(ext->child, next, stmt) {
Radek Krejci4f28eda2018-11-12 11:46:16 +010085 lysp_stmt_free(ctx, stmt);
Radek Krejci6f7feb62018-10-12 15:23:02 +020086 }
87}
88
89static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010090lysp_import_free(struct ly_ctx *ctx, struct lysp_import *import)
Radek Krejci6f7feb62018-10-12 15:23:02 +020091{
Radek Krejci086c7132018-10-26 15:29:04 +020092 /* imported module is freed directly from the context's list */
Radek Krejci4f28eda2018-11-12 11:46:16 +010093 FREE_STRING(ctx, import->name);
94 FREE_STRING(ctx, import->prefix);
95 FREE_STRING(ctx, import->dsc);
96 FREE_STRING(ctx, import->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +020097 FREE_ARRAY(ctx, import->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +020098}
99
100static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100101lysp_include_free(struct ly_ctx *ctx, struct lysp_include *include)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200102{
Radek Krejcibbe09a92018-11-08 09:36:54 +0100103 if (include->submodule) {
Radek Krejcid33273d2018-10-25 14:55:52 +0200104 lysp_module_free(include->submodule);
105 }
Radek Krejci4f28eda2018-11-12 11:46:16 +0100106 FREE_STRING(ctx, include->name);
107 FREE_STRING(ctx, include->dsc);
108 FREE_STRING(ctx, include->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200109 FREE_ARRAY(ctx, include->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200110}
111
112static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100113lysp_revision_free(struct ly_ctx *ctx, struct lysp_revision *rev)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200114{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100115 FREE_STRING(ctx, rev->dsc);
116 FREE_STRING(ctx, rev->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200117 FREE_ARRAY(ctx, rev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200118}
119
120static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100121lysp_ext_free(struct ly_ctx *ctx, struct lysp_ext *ext)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200122{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100123 FREE_STRING(ctx, ext->name);
124 FREE_STRING(ctx, ext->argument);
125 FREE_STRING(ctx, ext->dsc);
126 FREE_STRING(ctx, ext->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200127 FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200128}
129
130static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100131lysp_feature_free(struct ly_ctx *ctx, struct lysp_feature *feat)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200132{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100133 FREE_STRING(ctx, feat->name);
134 FREE_STRINGS(ctx, feat->iffeatures);
135 FREE_STRING(ctx, feat->dsc);
136 FREE_STRING(ctx, feat->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200137 FREE_ARRAY(ctx, feat->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200138}
139
140static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100141lysp_ident_free(struct ly_ctx *ctx, struct lysp_ident *ident)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200142{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100143 FREE_STRING(ctx, ident->name);
144 FREE_STRINGS(ctx, ident->iffeatures);
145 FREE_STRINGS(ctx, ident->bases);
146 FREE_STRING(ctx, ident->dsc);
147 FREE_STRING(ctx, ident->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200148 FREE_ARRAY(ctx, ident->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200149}
150
151static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100152lysp_restr_free(struct ly_ctx *ctx, struct lysp_restr *restr)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200153{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100154 FREE_STRING(ctx, restr->arg);
155 FREE_STRING(ctx, restr->emsg);
156 FREE_STRING(ctx, restr->eapptag);
157 FREE_STRING(ctx, restr->dsc);
158 FREE_STRING(ctx, restr->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200159 FREE_ARRAY(ctx, restr->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200160}
161
162static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100163lysp_type_enum_free(struct ly_ctx *ctx, struct lysp_type_enum *item)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200164{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100165 FREE_STRING(ctx, item->name);
166 FREE_STRING(ctx, item->dsc);
167 FREE_STRING(ctx, item->ref);
168 FREE_STRINGS(ctx, item->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200169 FREE_ARRAY(ctx, item->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200170}
171
172static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100173lysp_type_free(struct ly_ctx *ctx, struct lysp_type *type)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200174{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100175 FREE_STRING(ctx, type->name);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200176 FREE_MEMBER(ctx, type->range, lysp_restr_free);
177 FREE_MEMBER(ctx, type->length, lysp_restr_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200178 FREE_ARRAY(ctx, type->patterns, lysp_restr_free);
179 FREE_ARRAY(ctx, type->enums, lysp_type_enum_free);
180 FREE_ARRAY(ctx, type->bits, lysp_type_enum_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100181 FREE_STRING(ctx, type->path);
182 FREE_STRINGS(ctx, type->bases);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200183 FREE_ARRAY(ctx, type->types, lysp_type_free);
184 FREE_ARRAY(ctx, type->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200185}
186
Radek Krejcib31c8992018-11-12 16:29:16 +0100187static void lysc_type_free(struct ly_ctx *ctx, struct lysc_type *type);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200188static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100189lysp_tpdf_free(struct ly_ctx *ctx, struct lysp_tpdf *tpdf)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200190{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100191 FREE_STRING(ctx, tpdf->name);
192 FREE_STRING(ctx, tpdf->units);
193 FREE_STRING(ctx, tpdf->dflt);
194 FREE_STRING(ctx, tpdf->dsc);
195 FREE_STRING(ctx, tpdf->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200196 FREE_ARRAY(ctx, tpdf->exts, lysp_ext_instance_free);
Radek Krejcib31c8992018-11-12 16:29:16 +0100197
Radek Krejci4f28eda2018-11-12 11:46:16 +0100198 lysp_type_free(ctx, &tpdf->type);
Radek Krejcib31c8992018-11-12 16:29:16 +0100199 FREE_MEMBER(ctx, tpdf->type.compiled, lysc_type_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200200}
201
202static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100203lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200204{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200205 struct lysp_node *node, *next;
206
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200207 FREE_ARRAY(ctx, inout->musts, lysp_restr_free);
208 FREE_ARRAY(ctx, inout->typedefs, lysp_tpdf_free);
209 FREE_ARRAY(ctx, inout->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200210 LY_LIST_FOR_SAFE(inout->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100211 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200212 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200213 FREE_ARRAY(ctx, inout->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200214
215}
216
217static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100218lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200219{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100220 FREE_STRING(ctx, action->name);
221 FREE_STRING(ctx, action->dsc);
222 FREE_STRING(ctx, action->ref);
223 FREE_STRINGS(ctx, action->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200224 FREE_ARRAY(ctx, action->typedefs, lysp_tpdf_free);
225 FREE_ARRAY(ctx, action->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200226 FREE_MEMBER(ctx, action->input, lysp_action_inout_free);
227 FREE_MEMBER(ctx, action->output, lysp_action_inout_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200228 FREE_ARRAY(ctx, action->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200229}
230
231static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100232lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200233{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200234 struct lysp_node *node, *next;
235
Radek Krejci4f28eda2018-11-12 11:46:16 +0100236 FREE_STRING(ctx, notif->name);
237 FREE_STRING(ctx, notif->dsc);
238 FREE_STRING(ctx, notif->ref);
239 FREE_STRINGS(ctx, notif->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200240 FREE_ARRAY(ctx, notif->musts, lysp_restr_free);
241 FREE_ARRAY(ctx, notif->typedefs, lysp_tpdf_free);
242 FREE_ARRAY(ctx, notif->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200243 LY_LIST_FOR_SAFE(notif->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100244 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200245 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200246 FREE_ARRAY(ctx, notif->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200247}
248
249static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100250lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200251{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200252 struct lysp_node *node, *next;
253
Radek Krejci4f28eda2018-11-12 11:46:16 +0100254 FREE_STRING(ctx, grp->name);
255 FREE_STRING(ctx, grp->dsc);
256 FREE_STRING(ctx, grp->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200257 FREE_ARRAY(ctx, grp->typedefs, lysp_tpdf_free);
258 FREE_ARRAY(ctx, grp->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200259 LY_LIST_FOR_SAFE(grp->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100260 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200261 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200262 FREE_ARRAY(ctx, grp->actions, lysp_action_free);
263 FREE_ARRAY(ctx, grp->notifs, lysp_notif_free);
264 FREE_ARRAY(ctx, grp->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200265}
266
267static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100268lysp_when_free(struct ly_ctx *ctx, struct lysp_when *when)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200269{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100270 FREE_STRING(ctx, when->cond);
271 FREE_STRING(ctx, when->dsc);
272 FREE_STRING(ctx, when->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200273 FREE_ARRAY(ctx, when->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200274}
275
276static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100277lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200278{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200279 struct lysp_node *node, *next;
280
Radek Krejci4f28eda2018-11-12 11:46:16 +0100281 FREE_STRING(ctx, augment->nodeid);
282 FREE_STRING(ctx, augment->dsc);
283 FREE_STRING(ctx, augment->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200284 FREE_MEMBER(ctx, augment->when, lysp_when_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100285 FREE_STRINGS(ctx, augment->iffeatures);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200286 LY_LIST_FOR_SAFE(augment->child, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100287 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200288 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200289 FREE_ARRAY(ctx, augment->actions, lysp_action_free);
290 FREE_ARRAY(ctx, augment->notifs, lysp_notif_free);
291 FREE_ARRAY(ctx, augment->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200292}
293
294static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100295lysp_deviate_free(struct ly_ctx *ctx, struct lysp_deviate *d)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200296{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200297 struct lysp_deviate_add *add = (struct lysp_deviate_add*)d;
298 struct lysp_deviate_rpl *rpl = (struct lysp_deviate_rpl*)d;
299
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200300 FREE_ARRAY(ctx, d->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200301 switch(d->mod) {
302 case LYS_DEV_NOT_SUPPORTED:
303 /* nothing to do */
304 break;
305 case LYS_DEV_ADD:
306 case LYS_DEV_DELETE: /* compatible for dynamically allocated data */
Radek Krejci4f28eda2018-11-12 11:46:16 +0100307 FREE_STRING(ctx, add->units);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200308 FREE_ARRAY(ctx, add->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100309 FREE_STRINGS(ctx, add->uniques);
310 FREE_STRINGS(ctx, add->dflts);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200311 break;
312 case LYS_DEV_REPLACE:
313 FREE_MEMBER(ctx, rpl->type, lysp_type_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100314 FREE_STRING(ctx, rpl->units);
315 FREE_STRING(ctx, rpl->dflt);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200316 break;
317 default:
318 LOGINT(ctx);
319 break;
320 }
321}
322
323static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100324lysp_deviation_free(struct ly_ctx *ctx, struct lysp_deviation *dev)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200325{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200326 struct lysp_deviate *next, *iter;
327
Radek Krejci4f28eda2018-11-12 11:46:16 +0100328 FREE_STRING(ctx, dev->nodeid);
329 FREE_STRING(ctx, dev->dsc);
330 FREE_STRING(ctx, dev->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200331 LY_LIST_FOR_SAFE(dev->deviates, next, iter) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100332 lysp_deviate_free(ctx, iter);
Michal Vasko8447f6a2018-10-15 10:56:16 +0200333 free(iter);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200334 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200335 FREE_ARRAY(ctx, dev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200336}
337
338static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100339lysp_refine_free(struct ly_ctx *ctx, struct lysp_refine *ref)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200340{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100341 FREE_STRING(ctx, ref->nodeid);
342 FREE_STRING(ctx, ref->dsc);
343 FREE_STRING(ctx, ref->ref);
344 FREE_STRINGS(ctx, ref->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200345 FREE_ARRAY(ctx, ref->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100346 FREE_STRING(ctx, ref->presence);
347 FREE_STRINGS(ctx, ref->dflts);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200348 FREE_ARRAY(ctx, ref->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200349}
350
351static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100352lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200353{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200354 struct lysp_node *child, *next;
355
Radek Krejci4f28eda2018-11-12 11:46:16 +0100356 FREE_STRING(ctx, node->name);
357 FREE_STRING(ctx, node->dsc);
358 FREE_STRING(ctx, node->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200359 FREE_MEMBER(ctx, node->when, lysp_when_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100360 FREE_STRINGS(ctx, node->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200361 FREE_ARRAY(ctx, node->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200362
363 switch(node->nodetype) {
364 case LYS_CONTAINER:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200365 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100366 FREE_STRING(ctx, ((struct lysp_node_container*)node)->presence);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200367 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->typedefs, lysp_tpdf_free);
368 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200369 LY_LIST_FOR_SAFE(((struct lysp_node_container*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100370 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200371 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200372 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->actions, lysp_action_free);
373 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->notifs, lysp_notif_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200374 break;
375 case LYS_LEAF:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200376 FREE_ARRAY(ctx, ((struct lysp_node_leaf*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100377 lysp_type_free(ctx, &((struct lysp_node_leaf*)node)->type);
378 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->units);
379 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->dflt);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200380 break;
381 case LYS_LEAFLIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200382 FREE_ARRAY(ctx, ((struct lysp_node_leaflist*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100383 lysp_type_free(ctx, &((struct lysp_node_leaflist*)node)->type);
384 FREE_STRING(ctx, ((struct lysp_node_leaflist*)node)->units);
385 FREE_STRINGS(ctx, ((struct lysp_node_leaflist*)node)->dflts);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200386 break;
387 case LYS_LIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200388 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100389 FREE_STRING(ctx, ((struct lysp_node_list*)node)->key);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200390 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->typedefs, lysp_tpdf_free);
391 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200392 LY_LIST_FOR_SAFE(((struct lysp_node_list*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100393 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200394 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200395 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->actions, lysp_action_free);
396 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->notifs, lysp_notif_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100397 FREE_STRINGS(ctx, ((struct lysp_node_list*)node)->uniques);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200398 break;
399 case LYS_CHOICE:
400 LY_LIST_FOR_SAFE(((struct lysp_node_choice*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100401 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200402 }
Radek Krejci4f28eda2018-11-12 11:46:16 +0100403 FREE_STRING(ctx, ((struct lysp_node_choice*)node)->dflt);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200404 break;
405 case LYS_CASE:
406 LY_LIST_FOR_SAFE(((struct lysp_node_case*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100407 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200408 }
409 break;
410 case LYS_ANYDATA:
411 case LYS_ANYXML:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200412 FREE_ARRAY(ctx, ((struct lysp_node_anydata*)node)->musts, lysp_restr_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200413 break;
414 case LYS_USES:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200415 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->refines, lysp_refine_free);
416 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->augments, lysp_augment_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200417 break;
418 default:
419 LOGINT(ctx);
420 }
421
422 free(node);
423}
424
Radek Krejci4f28eda2018-11-12 11:46:16 +0100425API void
426lysp_module_free(struct lysp_module *module)
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200427{
428 struct ly_ctx *ctx;
Radek Krejci6f7feb62018-10-12 15:23:02 +0200429 struct lysp_node *node, *next;
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200430
431 LY_CHECK_ARG_RET(NULL, module,);
432 ctx = module->ctx;
433
Radek Krejci4f28eda2018-11-12 11:46:16 +0100434 FREE_STRING(ctx, module->name);
435 FREE_STRING(ctx, module->filepath);
436 FREE_STRING(ctx, module->ns); /* or belongs-to */
437 FREE_STRING(ctx, module->prefix);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200438
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200439 FREE_ARRAY(ctx, module->imports, lysp_import_free);
440 FREE_ARRAY(ctx, module->includes, lysp_include_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200441
Radek Krejci4f28eda2018-11-12 11:46:16 +0100442 FREE_STRING(ctx, module->org);
443 FREE_STRING(ctx, module->contact);
444 FREE_STRING(ctx, module->dsc);
445 FREE_STRING(ctx, module->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200446
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200447 FREE_ARRAY(ctx, module->revs, lysp_revision_free);
448 FREE_ARRAY(ctx, module->extensions, lysp_ext_free);
449 FREE_ARRAY(ctx, module->features, lysp_feature_free);
450 FREE_ARRAY(ctx, module->identities, lysp_ident_free);
451 FREE_ARRAY(ctx, module->typedefs, lysp_tpdf_free);
452 FREE_ARRAY(ctx, module->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200453 LY_LIST_FOR_SAFE(module->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100454 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200455 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200456 FREE_ARRAY(ctx, module->augments, lysp_augment_free);
457 FREE_ARRAY(ctx, module->rpcs, lysp_action_free);
458 FREE_ARRAY(ctx, module->notifs, lysp_notif_free);
459 FREE_ARRAY(ctx, module->deviations, lysp_deviation_free);
460 FREE_ARRAY(ctx, module->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200461
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200462 free(module);
463}
464
Radek Krejcib31c8992018-11-12 16:29:16 +0100465static struct lysc_ext_instance *
466lysc_ext_instance_dup(struct ly_ctx *ctx, struct lysc_ext_instance *orig)
467{
468 /* TODO */
469 (void) ctx;
470 (void) orig;
471 return NULL;
472}
473
Radek Krejci151a5b72018-10-19 14:21:44 +0200474static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100475lysc_ext_instance_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
Radek Krejci478020e2018-10-30 16:02:14 +0100476{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100477 FREE_STRING(ctx, ext->argument);
Radek Krejci478020e2018-10-30 16:02:14 +0100478 FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free);
479}
480
481static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100482lysc_iffeature_free(struct ly_ctx *UNUSED(ctx), struct lysc_iffeature *iff)
Radek Krejci151a5b72018-10-19 14:21:44 +0200483{
Radek Krejci2c4e7172018-10-19 15:56:26 +0200484 LY_ARRAY_FREE(iff->features);
Radek Krejci151a5b72018-10-19 14:21:44 +0200485 free(iff->expr);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200486}
487
488static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100489lysc_import_free(struct ly_ctx *ctx, struct lysc_import *import)
Radek Krejci478020e2018-10-30 16:02:14 +0100490{
491 /* imported module is freed directly from the context's list */
Radek Krejci4f28eda2018-11-12 11:46:16 +0100492 FREE_STRING(ctx, import->prefix);
Radek Krejci478020e2018-10-30 16:02:14 +0100493 FREE_ARRAY(ctx, import->exts, lysc_ext_instance_free);
494}
495
496static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100497lysc_ident_free(struct ly_ctx *ctx, struct lysc_ident *ident)
Radek Krejci478020e2018-10-30 16:02:14 +0100498{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100499 FREE_STRING(ctx, ident->name);
Radek Krejci478020e2018-10-30 16:02:14 +0100500 FREE_ARRAY(ctx, ident->iffeatures, lysc_iffeature_free);
501 LY_ARRAY_FREE(ident->derived);
502 FREE_ARRAY(ctx, ident->exts, lysc_ext_instance_free);
503}
504
505static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100506lysc_feature_free(struct ly_ctx *ctx, struct lysc_feature *feat)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200507{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100508 FREE_STRING(ctx, feat->name);
Radek Krejci151a5b72018-10-19 14:21:44 +0200509 FREE_ARRAY(ctx, feat->iffeatures, lysc_iffeature_free);
Radek Krejci2c4e7172018-10-19 15:56:26 +0200510 LY_ARRAY_FREE(feat->depfeatures);
Radek Krejci478020e2018-10-30 16:02:14 +0100511 FREE_ARRAY(ctx, feat->exts, lysc_ext_instance_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200512}
513
Radek Krejcib31c8992018-11-12 16:29:16 +0100514struct lysc_range*
515lysc_range_dup(struct ly_ctx *ctx, const struct lysc_range *orig)
516{
517 struct lysc_range *dup;
518 LY_ERR ret;
519
520 dup = calloc(1, sizeof *dup);
521 LY_CHECK_ERR_RET(!dup, LOGMEM(ctx), NULL);
522 if (orig->parts) {
523 LY_ARRAY_CREATE_GOTO(ctx, dup->parts, LY_ARRAY_SIZE(orig->parts), ret, cleanup);
524 LY_ARRAY_SIZE(dup->parts) = LY_ARRAY_SIZE(orig->parts);
525 memcpy(dup->parts, orig->parts, LY_ARRAY_SIZE(dup->parts) * sizeof *dup->parts);
526 }
527 DUP_STRING(ctx, dup->eapptag, orig->eapptag);
528 DUP_STRING(ctx, dup->emsg, orig->emsg);
529 dup->exts = lysc_ext_instance_dup(ctx, orig->exts);
530
531 return dup;
532cleanup:
533 free(dup);
534 (void) ret; /* set but not used due to the return type */
535 return NULL;
536}
537
Radek Krejci4f28eda2018-11-12 11:46:16 +0100538static void
539lysc_range_free(struct ly_ctx *ctx, struct lysc_range *range)
540{
541 LY_ARRAY_FREE(range->parts);
542 FREE_STRING(ctx, range->eapptag);
543 FREE_STRING(ctx, range->emsg);
544 FREE_ARRAY(ctx, range->exts, lysc_ext_instance_free);
545}
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100546
547static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100548lysc_type_free(struct ly_ctx *ctx, struct lysc_type *type)
549{
550 switch(type->basetype) {
551 case LY_TYPE_BINARY:
552 FREE_MEMBER(ctx, ((struct lysc_type_bin*)type)->length, lysc_range_free);
553 break;
554 }
555 FREE_ARRAY(ctx, type->exts, lysc_ext_instance_free);
556}
557
558static void lysc_node_free(struct ly_ctx *ctx, struct lysc_node *node);
559
560static void
561lysc_node_container_free(struct ly_ctx *ctx, struct lysc_node_container *node)
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100562{
563 struct lysc_node *child, *child_next;
564
565 LY_LIST_FOR_SAFE(node->child, child_next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100566 lysc_node_free(ctx, child);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100567 }
568}
569
570static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100571lysc_node_leaf_free(struct ly_ctx *ctx, struct lysc_node_leaf *node)
572{
573 FREE_MEMBER(ctx, node->type, lysc_type_free);
574}
575
576static void
577lysc_node_free(struct ly_ctx *ctx, struct lysc_node *node)
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100578{
579 /* common part */
Radek Krejci4f28eda2018-11-12 11:46:16 +0100580 FREE_STRING(ctx, node->name);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100581
582 /* nodetype-specific part */
583 switch(node->nodetype) {
584 case LYS_CONTAINER:
Radek Krejci4f28eda2018-11-12 11:46:16 +0100585 lysc_node_container_free(ctx, (struct lysc_node_container*)node);
586 break;
587 case LYS_LEAF:
588 lysc_node_leaf_free(ctx, (struct lysc_node_leaf*)node);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100589 break;
590 default:
591 LOGINT(ctx);
592 }
593
594 free(node);
595}
596
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200597static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100598lysc_module_free_(struct lysc_module *module)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200599{
600 struct ly_ctx *ctx;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100601 struct lysc_node *node, *node_next;
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200602
603 LY_CHECK_ARG_RET(NULL, module,);
604 ctx = module->ctx;
605
Radek Krejci4f28eda2018-11-12 11:46:16 +0100606 FREE_STRING(ctx, module->name);
607 FREE_STRING(ctx, module->ns);
608 FREE_STRING(ctx, module->prefix);
609 FREE_STRING(ctx, module->revision);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200610
Radek Krejci478020e2018-10-30 16:02:14 +0100611 FREE_ARRAY(ctx, module->imports, lysc_import_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200612 FREE_ARRAY(ctx, module->features, lysc_feature_free);
Radek Krejci478020e2018-10-30 16:02:14 +0100613 FREE_ARRAY(ctx, module->identities, lysc_ident_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200614
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100615 LY_LIST_FOR_SAFE(module->data, node_next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100616 lysc_node_free(ctx, node);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100617 }
618
Radek Krejci478020e2018-10-30 16:02:14 +0100619 FREE_ARRAY(ctx, module->exts, lysc_ext_instance_free);
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200620
621 free(module);
622}
Radek Krejci70853c52018-10-15 14:46:16 +0200623
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200624API void
Radek Krejci86d106e2018-10-18 09:53:19 +0200625lysc_module_free(struct lysc_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200626{
Radek Krejci151a5b72018-10-19 14:21:44 +0200627 if (module) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100628 lysc_module_free_(module);
Radek Krejci151a5b72018-10-19 14:21:44 +0200629 }
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200630}
631
Radek Krejci86d106e2018-10-18 09:53:19 +0200632void
633lys_module_free(struct lys_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejci70853c52018-10-15 14:46:16 +0200634{
Radek Krejci86d106e2018-10-18 09:53:19 +0200635 if (!module) {
636 return;
637 }
Radek Krejci70853c52018-10-15 14:46:16 +0200638
Radek Krejci86d106e2018-10-18 09:53:19 +0200639 lysc_module_free(module->compiled, private_destructor);
640 lysp_module_free(module->parsed);
641 free(module);
642}
643
Radek Krejci151a5b72018-10-19 14:21:44 +0200644struct iff_stack {
645 int size;
646 int index; /* first empty item */
647 uint8_t *stack;
648};
649
Radek Krejci86d106e2018-10-18 09:53:19 +0200650static LY_ERR
Radek Krejci151a5b72018-10-19 14:21:44 +0200651iff_stack_push(struct iff_stack *stack, uint8_t value)
Radek Krejci86d106e2018-10-18 09:53:19 +0200652{
Radek Krejci151a5b72018-10-19 14:21:44 +0200653 if (stack->index == stack->size) {
654 stack->size += 4;
655 stack->stack = ly_realloc(stack->stack, stack->size * sizeof *stack->stack);
656 LY_CHECK_ERR_RET(!stack->stack, LOGMEM(NULL); stack->size = 0, LY_EMEM);
Radek Krejci70853c52018-10-15 14:46:16 +0200657 }
Radek Krejci151a5b72018-10-19 14:21:44 +0200658 stack->stack[stack->index++] = value;
Radek Krejci70853c52018-10-15 14:46:16 +0200659 return LY_SUCCESS;
660}
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200661
Radek Krejci151a5b72018-10-19 14:21:44 +0200662static uint8_t
663iff_stack_pop(struct iff_stack *stack)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200664{
Radek Krejci151a5b72018-10-19 14:21:44 +0200665 stack->index--;
666 return stack->stack[stack->index];
667}
668
669static void
670iff_stack_clean(struct iff_stack *stack)
671{
672 stack->size = 0;
673 free(stack->stack);
674}
675
676static void
677iff_setop(uint8_t *list, uint8_t op, int pos)
678{
679 uint8_t *item;
680 uint8_t mask = 3;
681
682 assert(pos >= 0);
683 assert(op <= 3); /* max 2 bits */
684
685 item = &list[pos / 4];
686 mask = mask << 2 * (pos % 4);
687 *item = (*item) & ~mask;
688 *item = (*item) | (op << 2 * (pos % 4));
689}
690
691static uint8_t
692iff_getop(uint8_t *list, int pos)
693{
694 uint8_t *item;
695 uint8_t mask = 3, result;
696
697 assert(pos >= 0);
698
699 item = &list[pos / 4];
700 result = (*item) & (mask << 2 * (pos % 4));
701 return result >> 2 * (pos % 4);
702}
703
704#define LYS_IFF_LP 0x04 /* ( */
705#define LYS_IFF_RP 0x08 /* ) */
706
707API int
708lysc_feature_value(const struct lysc_feature *feature)
709{
710 LY_CHECK_ARG_RET(NULL, feature, -1);
711 return feature->flags & LYS_FENABLED ? 1 : 0;
712}
713
714static struct lysc_feature *
715lysc_feature_find(struct lysc_module *mod, const char *name, size_t len)
716{
717 size_t i;
718 struct lysc_feature *f;
719
720 for (i = 0; i < len; ++i) {
721 if (name[i] == ':') {
722 /* we have a prefixed feature */
Radek Krejcibbe09a92018-11-08 09:36:54 +0100723 mod = lysc_module_find_prefix(mod, name, i);
Radek Krejci151a5b72018-10-19 14:21:44 +0200724 LY_CHECK_RET(!mod, NULL);
725
726 name = &name[i + 1];
727 len = len - i - 1;
728 }
729 }
730
731 /* we have the correct module, get the feature */
732 LY_ARRAY_FOR(mod->features, i) {
Radek Krejci2c4e7172018-10-19 15:56:26 +0200733 f = &mod->features[i];
Radek Krejci151a5b72018-10-19 14:21:44 +0200734 if (!strncmp(f->name, name, len) && f->name[len] == '\0') {
735 return f;
736 }
737 }
738
739 return NULL;
740}
741
742static int
743lysc_iffeature_value_(const struct lysc_iffeature *iff, int *index_e, int *index_f)
744{
745 uint8_t op;
746 int a, b;
747
748 op = iff_getop(iff->expr, *index_e);
749 (*index_e)++;
750
751 switch (op) {
752 case LYS_IFF_F:
753 /* resolve feature */
Radek Krejci2c4e7172018-10-19 15:56:26 +0200754 return lysc_feature_value(iff->features[(*index_f)++]);
Radek Krejci151a5b72018-10-19 14:21:44 +0200755 case LYS_IFF_NOT:
756 /* invert result */
757 return lysc_iffeature_value_(iff, index_e, index_f) ? 0 : 1;
758 case LYS_IFF_AND:
759 case LYS_IFF_OR:
760 a = lysc_iffeature_value_(iff, index_e, index_f);
761 b = lysc_iffeature_value_(iff, index_e, index_f);
762 if (op == LYS_IFF_AND) {
763 return a && b;
764 } else { /* LYS_IFF_OR */
765 return a || b;
766 }
767 }
768
769 return 0;
770}
771
772API int
773lysc_iffeature_value(const struct lysc_iffeature *iff)
774{
775 int index_e = 0, index_f = 0;
776
777 LY_CHECK_ARG_RET(NULL, iff, -1);
778
779 if (iff->expr) {
780 return lysc_iffeature_value_(iff, &index_e, &index_f);
781 }
782 return 0;
783}
784
785/*
786 * op: 1 - enable, 0 - disable
787 */
788/**
789 * @brief Enable/Disable the specified feature in the module.
790 *
791 * If the feature is already set to the desired value, LY_SUCCESS is returned.
792 * By changing the feature, also all the feature which depends on it via their
793 * if-feature statements are again evaluated (disabled if a if-feature statemen
794 * evaluates to false).
795 *
796 * @param[in] mod Compiled module where to set (search for) the feature.
797 * @param[in] name Name of the feature to set. Asterisk ('*') can be used to
798 * set all the features in the module.
799 * @param[in] value Desired value of the feature: 1 (enable) or 0 (disable).
800 * @return LY_ERR value.
801 */
802static LY_ERR
803lys_feature_change(const struct lysc_module *mod, const char *name, int value)
804{
805 int all = 0;
Radek Krejcica3db002018-11-01 10:31:01 +0100806 unsigned int u, changed_count, disabled_count;
Radek Krejci151a5b72018-10-19 14:21:44 +0200807 struct lysc_feature *f, **df;
808 struct lysc_iffeature *iff;
809 struct ly_set *changed;
810
811 if (!mod->features) {
812 LOGERR(mod->ctx, LY_EINVAL, "Unable to switch feature since the module \"%s\" has no features.", mod->name);
813 return LY_EINVAL;
814 }
815
816 if (!strcmp(name, "*")) {
817 /* enable all */
818 all = 1;
819 }
820 changed = ly_set_new();
Radek Krejcica3db002018-11-01 10:31:01 +0100821 changed_count = 0;
Radek Krejci151a5b72018-10-19 14:21:44 +0200822
Radek Krejcica3db002018-11-01 10:31:01 +0100823run:
824 for (disabled_count = u = 0; u < LY_ARRAY_SIZE(mod->features); ++u) {
Radek Krejci2c4e7172018-10-19 15:56:26 +0200825 f = &mod->features[u];
Radek Krejci151a5b72018-10-19 14:21:44 +0200826 if (all || !strcmp(f->name, name)) {
827 if ((value && (f->flags & LYS_FENABLED)) || (!value && !(f->flags & LYS_FENABLED))) {
828 if (all) {
829 /* skip already set features */
830 continue;
831 } else {
832 /* feature already set correctly */
833 ly_set_free(changed, NULL);
834 return LY_SUCCESS;
835 }
836 }
837
838 if (value) { /* enable */
839 /* check referenced features if they are enabled */
840 LY_ARRAY_FOR(f->iffeatures, struct lysc_iffeature, iff) {
841 if (!lysc_iffeature_value(iff)) {
842 if (all) {
Radek Krejcica3db002018-11-01 10:31:01 +0100843 ++disabled_count;
Radek Krejci151a5b72018-10-19 14:21:44 +0200844 goto next;
845 } else {
846 LOGERR(mod->ctx, LY_EDENIED,
847 "Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
848 f->name);
849 ly_set_free(changed, NULL);
850 return LY_EDENIED;
851 }
852 }
853 }
854 /* enable the feature */
855 f->flags |= LYS_FENABLED;
856 } else { /* disable */
857 /* disable the feature */
858 f->flags &= ~LYS_FENABLED;
859 }
860
861 /* remember the changed feature */
862 ly_set_add(changed, f, LY_SET_OPT_USEASLIST);
863
864 if (!all) {
865 /* stop in case changing a single feature */
866 break;
867 }
868 }
869next:
870 ;
871 }
872
873 if (!all && !changed->count) {
874 LOGERR(mod->ctx, LY_EINVAL, "Feature \"%s\" not found in module \"%s\".", name, mod->name);
875 ly_set_free(changed, NULL);
876 return LY_EINVAL;
877 }
878
Radek Krejcica3db002018-11-01 10:31:01 +0100879 if (value && all && disabled_count) {
880 if (changed_count == changed->count) {
881 /* no change in last run -> not able to enable all ... */
882 /* ... print errors */
883 for (u = 0; disabled_count && u < LY_ARRAY_SIZE(mod->features); ++u) {
884 if (!(mod->features[u].flags & LYS_FENABLED)) {
885 LOGERR(mod->ctx, LY_EDENIED,
886 "Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
887 mod->features[u].name);
888 --disabled_count;
889 }
890 }
891 /* ... restore the original state */
892 for (u = 0; u < changed->count; ++u) {
893 f = changed->objs[u];
894 /* re-disable the feature */
895 f->flags &= ~LYS_FENABLED;
896 }
897
898 ly_set_free(changed, NULL);
899 return LY_EDENIED;
900 } else {
901 /* we did some change in last run, try it again */
902 changed_count = changed->count;
903 goto run;
904 }
905 }
906
Radek Krejci151a5b72018-10-19 14:21:44 +0200907 /* reflect change(s) in the dependent features */
908 for (u = 0; u < changed->count; ++u) {
909 /* If a dependent feature is enabled, it can be now changed by the change (to false) of the value of
910 * its if-feature statements. The reverse logic, automatically enable feature when its feature is enabled
911 * is not done - by default, features are disabled and must be explicitely enabled. */
912 f = changed->objs[u];
913 LY_ARRAY_FOR(f->depfeatures, struct lysc_feature*, df) {
914 if (!((*df)->flags & LYS_FENABLED)) {
915 /* not enabled, nothing to do */
916 continue;
917 }
918 /* check the feature's if-features which could change by the previous change of our feature */
919 LY_ARRAY_FOR((*df)->iffeatures, struct lysc_iffeature, iff) {
920 if (!lysc_iffeature_value(iff)) {
921 /* the feature must be disabled now */
922 (*df)->flags &= ~LYS_FENABLED;
923 /* add the feature into the list of changed features */
924 ly_set_add(changed, *df, LY_SET_OPT_USEASLIST);
925 break;
926 }
927 }
928 }
929 }
930
931 ly_set_free(changed, NULL);
932 return LY_SUCCESS;
933}
934
935API LY_ERR
936lys_feature_enable(struct lys_module *module, const char *feature)
937{
938 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, LY_EINVAL);
939
940 return lys_feature_change(module->compiled, feature, 1);
941}
942
943API LY_ERR
944lys_feature_disable(struct lys_module *module, const char *feature)
945{
946 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, LY_EINVAL);
947
948 return lys_feature_change(module->compiled, feature, 0);
949}
950
951API int
952lys_feature_value(const struct lys_module *module, const char *feature)
953{
954 struct lysc_feature *f;
955 struct lysc_module *mod;
956 unsigned int u;
957
958 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, -1);
959 mod = module->compiled;
960
961 /* search for the specified feature */
962 for (u = 0; u < LY_ARRAY_SIZE(mod->features); ++u) {
Radek Krejci2c4e7172018-10-19 15:56:26 +0200963 f = &mod->features[u];
Radek Krejci151a5b72018-10-19 14:21:44 +0200964 if (!strcmp(f->name, feature)) {
965 if (f->flags & LYS_FENABLED) {
966 return 1;
967 } else {
968 return 0;
969 }
970 }
971 }
972
973 /* feature definition not found */
974 return -1;
975}
976
977static LY_ERR
Radek Krejci4f28eda2018-11-12 11:46:16 +0100978lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *ext_p, int UNUSED(options), struct lysc_ext_instance *ext)
Radek Krejci151a5b72018-10-19 14:21:44 +0200979{
Radek Krejcice8c1592018-10-29 15:35:51 +0100980 const char *name;
981 unsigned int u;
982 const struct lys_module *mod;
Radek Krejci4f28eda2018-11-12 11:46:16 +0100983 struct lysp_ext *edef = NULL;
Radek Krejcice8c1592018-10-29 15:35:51 +0100984
Radek Krejci4f28eda2018-11-12 11:46:16 +0100985 ext->argument = lydict_insert(ctx->ctx, ext_p->argument, 0);
Radek Krejcice8c1592018-10-29 15:35:51 +0100986 ext->insubstmt = ext_p->insubstmt;
987 ext->insubstmt_index = ext_p->insubstmt_index;
988
989 /* get module where the extension definition should be placed */
990 for (u = 0; ext_p->name[u] != ':'; ++u);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100991 mod = lys_module_find_prefix(ctx->mod, ext_p->name, u);
992 LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcice8c1592018-10-29 15:35:51 +0100993 "Invalid prefix \"%.*s\" used for extension instance identifier.", u, ext_p->name),
994 LY_EVALID);
995 LY_CHECK_ERR_RET(!mod->parsed->extensions,
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100996 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcice8c1592018-10-29 15:35:51 +0100997 "Extension instance \"%s\" refers \"%s\" module that does not contain extension definitions.",
998 ext_p->name, mod->parsed->name),
999 LY_EVALID);
1000 name = &ext_p->name[u + 1];
1001 /* find the extension definition there */
1002 for (ext = NULL, u = 0; u < LY_ARRAY_SIZE(mod->parsed->extensions); ++u) {
1003 if (!strcmp(name, mod->parsed->extensions[u].name)) {
1004 edef = &mod->parsed->extensions[u];
1005 break;
1006 }
1007 }
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001008 LY_CHECK_ERR_RET(!edef, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcice8c1592018-10-29 15:35:51 +01001009 "Extension definition of extension instance \"%s\" not found.", ext_p->name),
1010 LY_EVALID);
1011 /* TODO plugins */
1012
1013 return LY_SUCCESS;
1014}
1015
Radek Krejcice8c1592018-10-29 15:35:51 +01001016static LY_ERR
1017lys_compile_iffeature(struct lysc_ctx *ctx, const char **value, int UNUSED(options), struct lysc_iffeature *iff)
1018{
1019 const char *c = *value;
Radek Krejci151a5b72018-10-19 14:21:44 +02001020 int r, rc = EXIT_FAILURE;
1021 int i, j, last_not, checkversion = 0;
1022 unsigned int f_size = 0, expr_size = 0, f_exp = 1;
1023 uint8_t op;
1024 struct iff_stack stack = {0, 0, NULL};
Radek Krejcice8c1592018-10-29 15:35:51 +01001025 struct lysc_feature *f;
Radek Krejci151a5b72018-10-19 14:21:44 +02001026
1027 assert(c);
1028
1029 /* pre-parse the expression to get sizes for arrays, also do some syntax checks of the expression */
1030 for (i = j = last_not = 0; c[i]; i++) {
1031 if (c[i] == '(') {
1032 j++;
1033 checkversion = 1;
1034 continue;
1035 } else if (c[i] == ')') {
1036 j--;
1037 continue;
1038 } else if (isspace(c[i])) {
1039 checkversion = 1;
1040 continue;
1041 }
1042
1043 if (!strncmp(&c[i], "not", r = 3) || !strncmp(&c[i], "and", r = 3) || !strncmp(&c[i], "or", r = 2)) {
1044 if (c[i + r] == '\0') {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001045 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001046 "Invalid value \"%s\" of if-feature - unexpected end of expression.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001047 return LY_EVALID;
1048 } else if (!isspace(c[i + r])) {
1049 /* feature name starting with the not/and/or */
1050 last_not = 0;
1051 f_size++;
1052 } else if (c[i] == 'n') { /* not operation */
1053 if (last_not) {
1054 /* double not */
1055 expr_size = expr_size - 2;
1056 last_not = 0;
1057 } else {
1058 last_not = 1;
1059 }
1060 } else { /* and, or */
1061 f_exp++;
1062 /* not a not operation */
1063 last_not = 0;
1064 }
1065 i += r;
1066 } else {
1067 f_size++;
1068 last_not = 0;
1069 }
1070 expr_size++;
1071
1072 while (!isspace(c[i])) {
1073 if (!c[i] || c[i] == ')') {
1074 i--;
1075 break;
1076 }
1077 i++;
1078 }
1079 }
1080 if (j || f_exp != f_size) {
1081 /* not matching count of ( and ) */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001082 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001083 "Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001084 return LY_EVALID;
1085 }
1086
1087 if (checkversion || expr_size > 1) {
1088 /* check that we have 1.1 module */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001089 if (ctx->mod->compiled->version != LYS_VERSION_1_1) {
1090 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001091 "Invalid value \"%s\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001092 return LY_EVALID;
1093 }
1094 }
1095
1096 /* allocate the memory */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001097 LY_ARRAY_CREATE_RET(ctx->ctx, iff->features, f_size, LY_EMEM);
Radek Krejci151a5b72018-10-19 14:21:44 +02001098 iff->expr = calloc((j = (expr_size / 4) + ((expr_size % 4) ? 1 : 0)), sizeof *iff->expr);
Radek Krejci151a5b72018-10-19 14:21:44 +02001099 stack.stack = malloc(expr_size * sizeof *stack.stack);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001100 LY_CHECK_ERR_GOTO(!stack.stack || !iff->expr, LOGMEM(ctx->ctx), error);
Radek Krejci151a5b72018-10-19 14:21:44 +02001101
Radek Krejci151a5b72018-10-19 14:21:44 +02001102 stack.size = expr_size;
1103 f_size--; expr_size--; /* used as indexes from now */
1104
1105 for (i--; i >= 0; i--) {
1106 if (c[i] == ')') {
1107 /* push it on stack */
1108 iff_stack_push(&stack, LYS_IFF_RP);
1109 continue;
1110 } else if (c[i] == '(') {
1111 /* pop from the stack into result all operators until ) */
1112 while((op = iff_stack_pop(&stack)) != LYS_IFF_RP) {
1113 iff_setop(iff->expr, op, expr_size--);
1114 }
1115 continue;
1116 } else if (isspace(c[i])) {
1117 continue;
1118 }
1119
1120 /* end of operator or operand -> find beginning and get what is it */
1121 j = i + 1;
1122 while (i >= 0 && !isspace(c[i]) && c[i] != '(') {
1123 i--;
1124 }
1125 i++; /* go back by one step */
1126
1127 if (!strncmp(&c[i], "not", 3) && isspace(c[i + 3])) {
1128 if (stack.index && stack.stack[stack.index - 1] == LYS_IFF_NOT) {
1129 /* double not */
1130 iff_stack_pop(&stack);
1131 } else {
1132 /* not has the highest priority, so do not pop from the stack
1133 * as in case of AND and OR */
1134 iff_stack_push(&stack, LYS_IFF_NOT);
1135 }
1136 } else if (!strncmp(&c[i], "and", 3) && isspace(c[i + 3])) {
1137 /* as for OR - pop from the stack all operators with the same or higher
1138 * priority and store them to the result, then push the AND to the stack */
1139 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_AND) {
1140 op = iff_stack_pop(&stack);
1141 iff_setop(iff->expr, op, expr_size--);
1142 }
1143 iff_stack_push(&stack, LYS_IFF_AND);
1144 } else if (!strncmp(&c[i], "or", 2) && isspace(c[i + 2])) {
1145 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_OR) {
1146 op = iff_stack_pop(&stack);
1147 iff_setop(iff->expr, op, expr_size--);
1148 }
1149 iff_stack_push(&stack, LYS_IFF_OR);
1150 } else {
1151 /* feature name, length is j - i */
1152
1153 /* add it to the expression */
1154 iff_setop(iff->expr, LYS_IFF_F, expr_size--);
1155
1156 /* now get the link to the feature definition */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001157 f = lysc_feature_find(ctx->mod->compiled, &c[i], j - i);
Radek Krejci151a5b72018-10-19 14:21:44 +02001158 LY_CHECK_ERR_GOTO(!f,
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001159 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001160 "Invalid value \"%s\" of if-feature - unable to find feature \"%.*s\".", *value, j - i, &c[i]);
Radek Krejci87616bb2018-10-31 13:30:52 +01001161 rc = LY_EVALID,
Radek Krejci151a5b72018-10-19 14:21:44 +02001162 error)
Radek Krejci2c4e7172018-10-19 15:56:26 +02001163 iff->features[f_size] = f;
1164 LY_ARRAY_INCREMENT(iff->features);
Radek Krejci151a5b72018-10-19 14:21:44 +02001165 f_size--;
1166 }
1167 }
1168 while (stack.index) {
1169 op = iff_stack_pop(&stack);
1170 iff_setop(iff->expr, op, expr_size--);
1171 }
1172
1173 if (++expr_size || ++f_size) {
1174 /* not all expected operators and operands found */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001175 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001176 "Invalid value \"%s\" of if-feature - processing error.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001177 rc = LY_EINT;
1178 } else {
1179 rc = LY_SUCCESS;
1180 }
1181
1182error:
1183 /* cleanup */
1184 iff_stack_clean(&stack);
1185
1186 return rc;
1187}
1188
1189static LY_ERR
Radek Krejci4f28eda2018-11-12 11:46:16 +01001190lys_compile_when(struct lysc_ctx *ctx, struct lysp_when *when_p, int options, struct lysc_when *when)
1191{
1192 unsigned int u;
1193 LY_ERR ret = LY_SUCCESS;
1194
1195 when->cond = lyxp_expr_parse(ctx->ctx, when_p->cond);
1196 LY_CHECK_ERR_GOTO(!when->cond, ret = ly_errcode(ctx->ctx), done);
1197 COMPILE_ARRAY_GOTO(ctx, when_p->exts, when->exts, options, u, lys_compile_ext, ret, done);
1198
1199done:
1200 return ret;
1201}
1202
1203static LY_ERR
1204lys_compile_must(struct lysc_ctx *ctx, struct lysp_restr *must_p, int options, struct lysc_must *must)
1205{
1206 unsigned int u;
1207 LY_ERR ret = LY_SUCCESS;
1208
1209 must->cond = lyxp_expr_parse(ctx->ctx, must_p->arg);
1210 LY_CHECK_ERR_GOTO(!must->cond, ret = ly_errcode(ctx->ctx), done);
1211
1212 must->eapptag = lydict_insert(ctx->ctx, must_p->eapptag, 0);
1213 must->emsg = lydict_insert(ctx->ctx, must_p->emsg, 0);
1214 COMPILE_ARRAY_GOTO(ctx, must_p->exts, must->exts, options, u, lys_compile_ext, ret, done);
1215
1216done:
1217 return ret;
1218}
1219
1220static LY_ERR
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001221lys_compile_import(struct lysc_ctx *ctx, struct lysp_import *imp_p, int options, struct lysc_import *imp)
1222{
Radek Krejcice8c1592018-10-29 15:35:51 +01001223 unsigned int u;
Radek Krejcif8f882a2018-10-31 14:51:15 +01001224 struct lys_module *mod = NULL;
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001225 struct lysc_module *comp;
Radek Krejcice8c1592018-10-29 15:35:51 +01001226 LY_ERR ret = LY_SUCCESS;
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001227
Radek Krejci4f28eda2018-11-12 11:46:16 +01001228 imp->prefix = lydict_insert(ctx->ctx, imp_p->prefix, 0);
Radek Krejcice8c1592018-10-29 15:35:51 +01001229 COMPILE_ARRAY_GOTO(ctx, imp_p->exts, imp->exts, options, u, lys_compile_ext, ret, done);
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001230 imp->module = imp_p->module;
1231
1232 /* make sure that we have both versions (lysp_ and lysc_) of the imported module. To import groupings or
1233 * typedefs, the lysp_ is needed. To augment or deviate imported module, we need the lysc_ structure */
1234 if (!imp->module->parsed) {
1235 comp = imp->module->compiled;
1236 /* try to get filepath from the compiled version */
1237 if (comp->filepath) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001238 mod = (struct lys_module*)lys_parse_path(ctx->ctx, comp->filepath,
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001239 !strcmp(&comp->filepath[strlen(comp->filepath - 4)], ".yin") ? LYS_IN_YIN : LYS_IN_YANG);
1240 if (mod != imp->module) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001241 LOGERR(ctx->ctx, LY_EINT, "Filepath \"%s\" of the module \"%s\" does not match.",
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001242 comp->filepath, comp->name);
1243 mod = NULL;
1244 }
1245 }
1246 if (!mod) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001247 if (lysp_load_module(ctx->ctx, comp->name, comp->revision, 0, 1, &mod)) {
1248 LOGERR(ctx->ctx, LY_ENOTFOUND, "Unable to reload \"%s\" module to import it into \"%s\", source data not found.",
1249 comp->name, ctx->mod->compiled->name);
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001250 return LY_ENOTFOUND;
1251 }
1252 }
1253 } else if (!imp->module->compiled) {
Radek Krejcif8f882a2018-10-31 14:51:15 +01001254 return lys_compile(imp->module, options);
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001255 }
1256
Radek Krejcice8c1592018-10-29 15:35:51 +01001257done:
1258 return ret;
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001259}
1260
1261static LY_ERR
Radek Krejci2a408df2018-10-29 16:32:26 +01001262lys_compile_identity(struct lysc_ctx *ctx, struct lysp_ident *ident_p, int options, struct lysc_ident *ident)
1263{
1264 unsigned int u;
1265 LY_ERR ret = LY_SUCCESS;
1266
Radek Krejci4f28eda2018-11-12 11:46:16 +01001267 ident->name = lydict_insert(ctx->ctx, ident_p->name, 0);
Radek Krejci2a408df2018-10-29 16:32:26 +01001268 COMPILE_ARRAY_GOTO(ctx, ident_p->iffeatures, ident->iffeatures, options, u, lys_compile_iffeature, ret, done);
1269 /* backlings (derived) can be added no sooner than when all the identities in the current module are present */
1270 COMPILE_ARRAY_GOTO(ctx, ident_p->exts, ident->exts, options, u, lys_compile_ext, ret, done);
1271 ident->flags = ident_p->flags;
1272
1273done:
1274 return ret;
1275}
1276
1277static LY_ERR
1278lys_compile_identities_derived(struct lysc_ctx *ctx, struct lysp_ident *idents_p, struct lysc_ident *idents)
1279{
1280 unsigned int i, u, v;
1281 const char *s, *name;
1282 struct lysc_module *mod;
1283 struct lysc_ident **dident;
1284
1285 for (i = 0; i < LY_ARRAY_SIZE(idents_p); ++i) {
Radek Krejci478020e2018-10-30 16:02:14 +01001286 if (!idents_p[i].bases) {
1287 continue;
1288 }
Radek Krejci2a408df2018-10-29 16:32:26 +01001289 for (u = 0; u < LY_ARRAY_SIZE(idents_p[i].bases); ++u) {
1290 s = strchr(idents_p[i].bases[u], ':');
1291 if (s) {
1292 /* prefixed identity */
1293 name = &s[1];
Radek Krejcibbe09a92018-11-08 09:36:54 +01001294 mod = lysc_module_find_prefix(ctx->mod->compiled, idents_p[i].bases[u], s - idents_p[i].bases[u]);
Radek Krejci2a408df2018-10-29 16:32:26 +01001295 } else {
1296 name = idents_p[i].bases[u];
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001297 mod = ctx->mod->compiled;
Radek Krejci2a408df2018-10-29 16:32:26 +01001298 }
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001299 LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejci2a408df2018-10-29 16:32:26 +01001300 "Invalid prefix used for base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
1301 LY_EVALID);
1302 if (mod->identities) {
1303 for (v = 0; v < LY_ARRAY_SIZE(mod->identities); ++v) {
1304 if (!strcmp(name, mod->identities[v].name)) {
1305 /* we have match! store the backlink */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001306 LY_ARRAY_NEW_RET(ctx->ctx, mod->identities[v].derived, dident, LY_EMEM);
Radek Krejci2a408df2018-10-29 16:32:26 +01001307 *dident = &idents[i];
1308 break;
1309 }
1310 }
1311 }
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001312 LY_CHECK_ERR_RET(!dident, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejci2a408df2018-10-29 16:32:26 +01001313 "Unable to find base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
1314 LY_EVALID);
1315 }
1316 }
1317 return LY_SUCCESS;
1318}
1319
1320static LY_ERR
Radek Krejci151a5b72018-10-19 14:21:44 +02001321lys_compile_feature(struct lysc_ctx *ctx, struct lysp_feature *feature_p, int options, struct lysc_feature *feature)
1322{
Radek Krejcice8c1592018-10-29 15:35:51 +01001323 unsigned int u, v;
1324 LY_ERR ret = LY_SUCCESS;
1325 struct lysc_feature **df;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001326
Radek Krejci4f28eda2018-11-12 11:46:16 +01001327 feature->name = lydict_insert(ctx->ctx, feature_p->name, 0);
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001328 feature->flags = feature_p->flags;
1329
Radek Krejcice8c1592018-10-29 15:35:51 +01001330 COMPILE_ARRAY_GOTO(ctx, feature_p->exts, feature->exts, options, u, lys_compile_ext, ret, done);
1331 COMPILE_ARRAY_GOTO(ctx, feature_p->iffeatures, feature->iffeatures, options, u, lys_compile_iffeature, ret, done);
1332 if (feature->iffeatures) {
1333 for (u = 0; u < LY_ARRAY_SIZE(feature->iffeatures); ++u) {
1334 if (feature->iffeatures[u].features) {
1335 for (v = 0; v < LY_ARRAY_SIZE(feature->iffeatures[u].features); ++v) {
1336 /* add itself into the dependants list */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001337 LY_ARRAY_NEW_RET(ctx->ctx, feature->iffeatures[u].features[v]->depfeatures, df, LY_EMEM);
Radek Krejcice8c1592018-10-29 15:35:51 +01001338 *df = feature;
1339 }
1340 /* TODO check for circular dependency */
1341 }
Radek Krejci151a5b72018-10-19 14:21:44 +02001342 }
Radek Krejci86d106e2018-10-18 09:53:19 +02001343 }
Radek Krejcice8c1592018-10-29 15:35:51 +01001344done:
1345 return ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001346}
1347
Radek Krejci4f28eda2018-11-12 11:46:16 +01001348static LY_ERR
1349range_part_check_value_syntax(struct lysc_ctx *ctx, LY_DATA_TYPE basetype, const char *value, size_t *len, char **valcopy)
1350{
1351 size_t fraction = 0;
1352 *len = 0;
1353
1354 assert(value);
1355 /* parse value */
1356 if (!isdigit(value[*len]) && (value[*len] != '-') && (value[*len] != '+')) {
1357 return LY_EVALID;
1358 }
1359
1360 if ((value[*len] == '-') || (value[*len] == '+')) {
1361 ++(*len);
1362 }
1363
1364 while (isdigit(value[*len])) {
1365 ++(*len);
1366 }
1367
1368 if ((basetype != LY_TYPE_DEC64) || (value[*len] != '.') || !isdigit(value[*len + 1])) {
1369 *valcopy = strndup(value, *len);
1370 return LY_SUCCESS;
1371 }
1372 fraction = *len;
1373
1374 ++(*len);
1375 while (isdigit(value[*len])) {
1376 ++(*len);
1377 }
1378
1379 if (fraction) {
1380 *valcopy = malloc(((*len) - 1) * sizeof **valcopy);
1381 LY_CHECK_ERR_RET(!(*valcopy), LOGMEM(ctx->ctx), LY_EMEM);
1382
1383 *valcopy[(*len) - 1] = '\0';
1384 memcpy(&(*valcopy)[0], &value[0], fraction);
1385 memcpy(&(*valcopy)[fraction], &value[fraction + 1], (*len) - 1 - (fraction + 1));
1386 }
1387 return LY_SUCCESS;
1388}
1389
1390static LY_ERR
1391range_part_check_ascendance(int unsigned_value, int64_t value, int64_t prev_value)
1392{
1393 if (unsigned_value) {
1394 if ((uint64_t)prev_value >= (uint64_t)value) {
1395 return LY_EEXIST;
1396 }
1397 } else {
1398 if (prev_value >= value) {
1399 return LY_EEXIST;
1400 }
1401 }
1402 return LY_SUCCESS;
1403}
1404
1405static LY_ERR
1406range_part_minmax(struct lysc_ctx *ctx, struct lysc_range_part *part, int max, int64_t prev, LY_DATA_TYPE basetype, int first, int length_restr,
1407 const char **value)
1408{
1409 LY_ERR ret = LY_SUCCESS;
1410 char *valcopy = NULL;
1411 size_t len;
1412
1413 if (value) {
1414 ret = range_part_check_value_syntax(ctx, basetype, *value, &len, &valcopy);
1415 LY_CHECK_GOTO(ret, error);
1416 }
1417
1418 switch (basetype) {
1419 case LY_TYPE_BINARY: /* length */
1420 if (valcopy) {
1421 ret = ly_parse_uint(valcopy, __UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
1422 } else if (max) {
1423 part->max_u64 = __UINT64_C(18446744073709551615);
1424 } else {
1425 part->min_u64 = __UINT64_C(0);
1426 }
1427 if (!first) {
1428 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1429 }
1430 break;
1431 case LY_TYPE_DEC64: /* range */
1432 if (valcopy) {
1433 ret = ly_parse_int(valcopy, __INT64_C(-9223372036854775807) - __INT64_C(1), __INT64_C(9223372036854775807), 10,
1434 max ? &part->max_64 : &part->min_64);
1435 } else if (max) {
1436 part->max_64 = __INT64_C(9223372036854775807);
1437 } else {
1438 part->min_64 = __INT64_C(-9223372036854775807) - __INT64_C(1);
1439 }
1440 if (!first) {
1441 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1442 }
1443 break;
1444 case LY_TYPE_INT8: /* range */
1445 if (valcopy) {
1446 ret = ly_parse_int(valcopy, __INT64_C(-128), INT64_C(127), 10, max ? &part->max_64 : &part->min_64);
1447 } else if (max) {
1448 part->max_64 = __INT64_C(127);
1449 } else {
1450 part->min_64 = __INT64_C(-128);
1451 }
1452 if (!first) {
1453 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1454 }
1455 break;
1456 case LY_TYPE_INT16: /* range */
1457 if (valcopy) {
1458 ret = ly_parse_int(valcopy, __INT64_C(-32768), INT64_C(32767), 10, max ? &part->max_64 : &part->min_64);
1459 } else if (max) {
1460 part->max_64 = __INT64_C(32767);
1461 } else {
1462 part->min_64 = __INT64_C(-32768);
1463 }
1464 if (!first) {
1465 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1466 }
1467 break;
1468 case LY_TYPE_INT32: /* range */
1469 if (valcopy) {
1470 ret = ly_parse_int(valcopy, __INT64_C(-2147483648), INT64_C(2147483647), 10, max ? &part->max_64 : &part->min_64);
1471 } else if (max) {
1472 part->max_64 = __INT64_C(2147483647);
1473 } else {
1474 part->min_64 = __INT64_C(-2147483648);
1475 }
1476 if (!first) {
1477 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1478 }
1479 break;
1480 case LY_TYPE_INT64: /* range */
1481 if (valcopy) {
1482 ret = ly_parse_int(valcopy, __INT64_C(-9223372036854775807) - __INT64_C(1), INT64_C(9223372036854775807), 10,
1483 max ? &part->max_64 : &part->min_64);
1484 } else if (max) {
1485 part->max_64 = __INT64_C(9223372036854775807);
1486 } else {
1487 part->min_64 = __INT64_C(-9223372036854775807) - __INT64_C(1);
1488 }
1489 if (!first) {
1490 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1491 }
1492 break;
1493 case LY_TYPE_UINT8: /* range */
1494 if (valcopy) {
1495 ret = ly_parse_uint(valcopy, __UINT64_C(255), 10, max ? &part->max_u64 : &part->min_u64);
1496 } else if (max) {
1497 part->max_u64 = __UINT64_C(255);
1498 } else {
1499 part->min_u64 = __UINT64_C(0);
1500 }
1501 if (!first) {
1502 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1503 }
1504 break;
1505 case LY_TYPE_UINT16: /* range */
1506 if (valcopy) {
1507 ret = ly_parse_uint(valcopy, __UINT64_C(65535), 10, max ? &part->max_u64 : &part->min_u64);
1508 } else if (max) {
1509 part->max_u64 = __UINT64_C(65535);
1510 } else {
1511 part->min_u64 = __UINT64_C(0);
1512 }
1513 if (!first) {
1514 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1515 }
1516 break;
1517 case LY_TYPE_UINT32: /* range */
1518 if (valcopy) {
1519 ret = ly_parse_uint(valcopy, __UINT64_C(4294967295), 10, max ? &part->max_u64 : &part->min_u64);
1520 } else if (max) {
1521 part->max_u64 = __UINT64_C(4294967295);
1522 } else {
1523 part->min_u64 = __UINT64_C(0);
1524 }
1525 if (!first) {
1526 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1527 }
1528 break;
1529 case LY_TYPE_UINT64: /* range */
1530 if (valcopy) {
1531 ret = ly_parse_uint(valcopy, __UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
1532 } else if (max) {
1533 part->max_u64 = __UINT64_C(18446744073709551615);
1534 } else {
1535 part->min_u64 = __UINT64_C(0);
1536 }
1537 if (!first) {
1538 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1539 }
1540 break;
1541 case LY_TYPE_STRING: /* length */
1542 if (valcopy) {
1543 ret = ly_parse_uint(valcopy, __UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
1544 } else if (max) {
1545 part->max_u64 = __UINT64_C(18446744073709551615);
1546 } else {
1547 part->min_u64 = __UINT64_C(0);
1548 }
1549 if (!first) {
1550 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1551 }
1552 break;
1553 default:
1554 LOGINT(ctx->ctx);
1555 ret = LY_EINT;
1556 }
1557
1558error:
1559 if (ret == LY_EDENIED) {
1560 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1561 "Invalid %s restriction - value \"%s\" does not fit the type limitations.",
1562 length_restr ? "length" : "range", valcopy ? valcopy : *value);
1563 } else if (ret == LY_EVALID) {
1564 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1565 "Invalid %s restriction - invalid value \"%s\".",
1566 length_restr ? "length" : "range", valcopy ? valcopy : *value);
1567 } else if (ret == LY_EEXIST) {
1568 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1569 "Invalid %s restriction - values are not in ascending order (%s).",
1570 length_restr ? "length" : "range", valcopy ? valcopy : *value);
1571 } else if (!ret && value) {
1572 *value = *value + len;
1573 }
1574 free(valcopy);
1575 return ret;
1576}
1577
1578static LY_ERR
1579lys_compile_type_range(struct lysc_ctx *ctx, struct lysp_restr *range_p, LY_DATA_TYPE basetype, int length_restr,
Radek Krejcib31c8992018-11-12 16:29:16 +01001580 struct lysc_range *base_range, struct lysc_range **range)
Radek Krejci4f28eda2018-11-12 11:46:16 +01001581{
1582 LY_ERR ret = LY_EVALID;
1583 const char *expr;
1584 struct lysc_range_part *parts = NULL, *part;
Radek Krejcib31c8992018-11-12 16:29:16 +01001585 int range_expected = 0, uns;
1586 unsigned int parts_done = 0, u, v;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001587
1588 assert(range);
1589 assert(range_p);
1590
Radek Krejci4f28eda2018-11-12 11:46:16 +01001591 expr = range_p->arg;
1592 while(1) {
1593 if (isspace(*expr)) {
1594 ++expr;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001595 } else if (*expr == '\0') {
Radek Krejcib31c8992018-11-12 16:29:16 +01001596 if (range_expected) {
1597 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1598 "Invalid %s restriction - unexpected end of the expression after \"..\" (%s).",
1599 length_restr ? "length" : "range", range_p->arg);
1600 goto cleanup;
1601 } else if (!parts || parts_done == LY_ARRAY_SIZE(parts)) {
1602 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1603 "Invalid %s restriction - unexpected end of the expression (%s).",
1604 length_restr ? "length" : "range", range_p->arg);
1605 goto cleanup;
1606 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01001607 parts_done++;
1608 break;
1609 } else if (!strncmp(expr, "min", 3)) {
1610 if (parts) {
1611 /* min cannot be used elsewhere than in the first part */
1612 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1613 "Invalid %s restriction - unexpected data before min keyword (%.*s).", length_restr ? "length" : "range",
1614 expr - range_p->arg, range_p->arg);
1615 goto cleanup;
1616 }
1617 expr += 3;
1618
1619 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1620 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, 0, basetype, 1, length_restr, NULL), cleanup);
1621 part->max_64 = part->min_64;
1622 } else if (*expr == '|') {
1623 if (!parts || range_expected) {
1624 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1625 "Invalid %s restriction - unexpected beginning of the expression (%s).", length_restr ? "length" : "range", expr);
1626 goto cleanup;
1627 }
1628 expr++;
1629 parts_done++;
1630 /* process next part of the expression */
Radek Krejci4f28eda2018-11-12 11:46:16 +01001631 } else if (!strncmp(expr, "..", 2)) {
1632 expr += 2;
1633 while (isspace(*expr)) {
1634 expr++;
1635 }
Radek Krejcib31c8992018-11-12 16:29:16 +01001636 if (!parts || LY_ARRAY_SIZE(parts) == parts_done) {
Radek Krejci4f28eda2018-11-12 11:46:16 +01001637 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1638 "Invalid %s restriction - unexpected \"..\" without a lower bound.", length_restr ? "length" : "range");
1639 goto cleanup;
1640 }
1641 /* continue expecting the upper boundary */
1642 range_expected = 1;
1643 } else if (isdigit(*expr) || (*expr == '-') || (*expr == '+')) {
1644 /* number */
1645 if (range_expected) {
1646 part = &parts[LY_ARRAY_SIZE(parts) - 1];
1647 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, &expr), cleanup);
Radek Krejcib31c8992018-11-12 16:29:16 +01001648 range_expected = 0;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001649 } else {
1650 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1651 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
1652 basetype, parts_done ? 0 : 1, length_restr, &expr), cleanup);
1653 part->max_64 = part->min_64;
1654 }
1655
1656 /* continue with possible another expression part */
Radek Krejci4f28eda2018-11-12 11:46:16 +01001657 } else if (!strncmp(expr, "max", 3)) {
1658 expr += 3;
1659 while (isspace(*expr)) {
1660 expr++;
1661 }
1662 if (*expr != '\0') {
1663 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data after max keyword (%s).",
1664 length_restr ? "length" : "range", expr);
1665 goto cleanup;
1666 }
1667 if (range_expected) {
1668 part = &parts[LY_ARRAY_SIZE(parts) - 1];
1669 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, NULL), cleanup);
Radek Krejcib31c8992018-11-12 16:29:16 +01001670 range_expected = 0;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001671 } else {
1672 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1673 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
1674 basetype, parts_done ? 0 : 1, length_restr, NULL), cleanup);
1675 part->min_64 = part->max_64;
1676 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01001677 } else {
1678 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data (%s).",
1679 length_restr ? "length" : "range", expr);
1680 goto cleanup;
1681 }
1682 }
1683
Radek Krejcib31c8992018-11-12 16:29:16 +01001684 /* check with the previous range/length restriction */
1685 if (base_range) {
1686 switch (basetype) {
1687 case LY_TYPE_BINARY:
1688 case LY_TYPE_UINT8:
1689 case LY_TYPE_UINT16:
1690 case LY_TYPE_UINT32:
1691 case LY_TYPE_UINT64:
1692 case LY_TYPE_STRING:
1693 uns = 1;
1694 break;
1695 case LY_TYPE_DEC64:
1696 case LY_TYPE_INT8:
1697 case LY_TYPE_INT16:
1698 case LY_TYPE_INT32:
1699 case LY_TYPE_INT64:
1700 uns = 0;
1701 break;
1702 default:
1703 LOGINT(ctx->ctx);
1704 ret = LY_EINT;
1705 goto cleanup;
1706 }
1707 for (u = v = 0; u < parts_done && v < LY_ARRAY_SIZE(base_range->parts); ++u) {
1708 if ((uns && parts[u].min_u64 < base_range->parts[v].min_u64) || (!uns && parts[u].min_64 < base_range->parts[v].min_64)) {
1709 goto baseerror;
1710 }
1711 /* current lower bound is not lower than the base */
1712 if (base_range->parts[v].min_64 == base_range->parts[v].max_64) {
1713 /* base has single value */
1714 if (base_range->parts[v].min_64 == parts[u].min_64) {
1715 /* both lower bounds are the same */
1716 if (parts[u].min_64 != parts[u].max_64) {
1717 /* current continues with a range */
1718 goto baseerror;
1719 } else {
1720 /* equal single values, move both forward */
1721 ++v;
1722 continue;
1723 }
1724 } else {
1725 /* base is single value lower than current range, so the
1726 * value from base range is removed in the current,
1727 * move only base and repeat checking */
1728 ++v;
1729 --u;
1730 continue;
1731 }
1732 } else {
1733 /* base is the range */
1734 if (parts[u].min_64 == parts[u].max_64) {
1735 /* current is a single value */
1736 if ((uns && parts[u].max_u64 > base_range->parts[v].max_u64) || (!uns && parts[u].max_64 > base_range->parts[v].max_64)) {
1737 /* current is behind the base range, so base range is omitted,
1738 * move the base and keep the current for further check */
1739 ++v;
1740 --u;
1741 } /* else it is within the base range, so move the current, but keep the base */
1742 continue;
1743 } else {
1744 /* both are ranges - check the higher bound, the lower was already checked */
1745 if ((uns && parts[u].max_u64 > base_range->parts[v].max_u64) || (!uns && parts[u].max_64 > base_range->parts[v].max_64)) {
1746 /* higher bound is higher than the current higher bound */
1747 if ((uns && parts[u].min_u64 > base_range->parts[v].max_u64) || (!uns && parts[u].min_64 > base_range->parts[v].max_64)) {
1748 /* but the current lower bound is also higher, so the base range is omitted,
1749 * continue with the same current, but move the base */
1750 --u;
1751 ++v;
1752 continue;
1753 }
1754 /* current range starts within the base range but end behind it */
1755 goto baseerror;
1756 } else {
1757 /* current range is smaller than the base,
1758 * move current, but stay with the base */
1759 continue;
1760 }
1761 }
1762 }
1763 }
1764 if (u != parts_done) {
1765baseerror:
1766 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1767 "Invalid %s restriction - the derived restriction (%s) is not equally or more limiting.",
1768 length_restr ? "length" : "range", range_p->arg);
1769 goto cleanup;
1770 }
1771 }
1772
1773 if (!(*range)) {
1774 *range = calloc(1, sizeof **range);
1775 LY_CHECK_ERR_RET(!(*range), LOGMEM(ctx->ctx), LY_EMEM);
1776 }
1777
1778 if (range_p->eapptag) {
1779 lydict_remove(ctx->ctx, (*range)->eapptag);
1780 (*range)->eapptag = lydict_insert(ctx->ctx, range_p->eapptag, 0);
1781 }
1782 if (range_p->emsg) {
1783 lydict_remove(ctx->ctx, (*range)->emsg);
1784 (*range)->emsg = lydict_insert(ctx->ctx, range_p->emsg, 0);
1785 }
1786 /* extensions are taken only from the last range by the caller */
1787
Radek Krejci4f28eda2018-11-12 11:46:16 +01001788 (*range)->parts = parts;
1789 parts = NULL;
1790 ret = LY_SUCCESS;
1791cleanup:
1792 /* TODO clean up */
1793 LY_ARRAY_FREE(parts);
1794
1795 return ret;
1796}
1797
1798static LY_ERR
1799lys_compile_type(struct lysc_ctx *ctx, struct lysp_node_leaf *leaf_p, int options, struct lysc_type **type)
1800{
1801 LY_ERR ret = LY_SUCCESS;
1802 unsigned int u;
1803 struct lysp_type *type_p = &leaf_p->type;
1804 struct type_context {
1805 const struct lysp_tpdf *tpdf;
1806 struct lysp_node *node;
1807 struct lysp_module *mod;
1808 } *tctx, *tctx_prev = NULL;
1809 LY_DATA_TYPE basetype = LY_TYPE_UNKNOWN;
Radek Krejcib31c8992018-11-12 16:29:16 +01001810 struct lysc_type *base = NULL;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001811 struct ly_set tpdf_chain = {0};
1812 struct lysc_type_bin* bin;
1813
1814
1815 tctx = calloc(1, sizeof *tctx);
1816 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
1817 for (ret = lysp_type_find(type_p->name, (struct lysp_node*)leaf_p, ctx->mod->parsed,
1818 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod);
Radek Krejcib31c8992018-11-12 16:29:16 +01001819 ret == LY_SUCCESS;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001820 ret = lysp_type_find(tctx_prev->tpdf->type.name, tctx_prev->node, tctx_prev->mod,
1821 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod)) {
1822 if (basetype) {
1823 break;
1824 }
1825
1826 /* check status */
1827 if (lysc_check_status(ctx, leaf_p->flags, ctx->mod->parsed, leaf_p->name,
1828 tctx->tpdf->flags, tctx->mod, tctx->node ? tctx->node->name : tctx->mod->name)) {
1829 free(tctx);
1830 goto cleanup;
1831 }
1832
Radek Krejcib31c8992018-11-12 16:29:16 +01001833 if (tctx->tpdf->type.compiled) {
1834 /* it is not necessary to continue, the rest of the chain was already compiled */
1835 basetype = tctx->tpdf->type.compiled->basetype;
1836 ly_set_add(&tpdf_chain, tctx, LY_SET_OPT_USEASLIST);
1837 tctx = NULL;
1838 break;
1839 } else if (!(tctx->tpdf->type.flags & LYS_TYPE_MODIFIED)) {
Radek Krejci4f28eda2018-11-12 11:46:16 +01001840 /* no change in comparison to the following (actually preceding in the chain of type derivations) type */
1841 memset(tctx, 0, sizeof *tctx);
1842 continue;
1843 }
1844
1845 /* store information for the following processing */
1846 ly_set_add(&tpdf_chain, tctx, LY_SET_OPT_USEASLIST);
1847
1848 /* prepare next loop */
Radek Krejcib31c8992018-11-12 16:29:16 +01001849 tctx_prev = tctx;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001850 tctx = calloc(1, sizeof *tctx);
1851 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
1852 }
1853 free(tctx);
1854
1855 /* allocate type according to the basetype */
1856 switch (basetype) {
1857 case LY_TYPE_BINARY:
1858 *type = calloc(1, sizeof(struct lysc_type_bin));
1859 bin = (struct lysc_type_bin*)(*type);
1860 break;
1861 case LY_TYPE_BITS:
1862 *type = calloc(1, sizeof(struct lysc_type_bits));
1863 break;
1864 case LY_TYPE_BOOL:
1865 case LY_TYPE_EMPTY:
1866 *type = calloc(1, sizeof(struct lysc_type));
1867 break;
1868 case LY_TYPE_DEC64:
1869 *type = calloc(1, sizeof(struct lysc_type_dec));
1870 break;
1871 case LY_TYPE_ENUM:
1872 *type = calloc(1, sizeof(struct lysc_type_enum));
1873 break;
1874 case LY_TYPE_IDENT:
1875 *type = calloc(1, sizeof(struct lysc_type_identityref));
1876 break;
1877 case LY_TYPE_INST:
1878 *type = calloc(1, sizeof(struct lysc_type_instanceid));
1879 break;
1880 case LY_TYPE_LEAFREF:
1881 *type = calloc(1, sizeof(struct lysc_type_leafref));
1882 break;
1883 case LY_TYPE_STRING:
1884 *type = calloc(1, sizeof(struct lysc_type_str));
1885 break;
1886 case LY_TYPE_UNION:
1887 *type = calloc(1, sizeof(struct lysc_type_union));
1888 break;
1889 case LY_TYPE_INT8:
1890 case LY_TYPE_UINT8:
1891 case LY_TYPE_INT16:
1892 case LY_TYPE_UINT16:
1893 case LY_TYPE_INT32:
1894 case LY_TYPE_UINT32:
1895 case LY_TYPE_INT64:
1896 case LY_TYPE_UINT64:
1897 *type = calloc(1, sizeof(struct lysc_type_num));
1898 break;
Radek Krejcib31c8992018-11-12 16:29:16 +01001899 case LY_TYPE_UNKNOWN:
1900 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1901 "Referenced type \"%s\" not found.", tctx_prev ? tctx_prev->tpdf->type.name : type_p->name);
1902 goto cleanup;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001903 }
1904 LY_CHECK_ERR_GOTO(!(*type), LOGMEM(ctx->ctx), cleanup);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001905
1906
1907 /* get restrictions from the referred typedefs */
1908 for (u = tpdf_chain.count - 1; u + 1 > 0; --u) {
1909 tctx = (struct type_context*)tpdf_chain.objs[u];
Radek Krejcib31c8992018-11-12 16:29:16 +01001910 if (tctx->tpdf->type.compiled) {
1911 base = tctx->tpdf->type.compiled;
1912 continue;
1913 } else if ((u != tpdf_chain.count - 1) && (tctx->tpdf->type.flags & LYS_TYPE_MODIFIED)) {
1914 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = ((struct type_context*)tpdf_chain.objs[u + 1])->tpdf->type.compiled;
1915 ++base->refcount;
1916 continue;
1917 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01001918
Radek Krejcib31c8992018-11-12 16:29:16 +01001919 ++(*type)->refcount;
1920 (*type)->basetype = basetype;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001921 switch (basetype) {
1922 case LY_TYPE_BINARY:
1923 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
1924 if (tctx->tpdf->type.length) {
Radek Krejcib31c8992018-11-12 16:29:16 +01001925 ret = lys_compile_type_range(ctx, tctx->tpdf->type.length, basetype, 1,
1926 base ? ((struct lysc_type_bin*)base)->length : NULL, &bin->length);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001927 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcib31c8992018-11-12 16:29:16 +01001928 } else if (base && ((struct lysc_type_bin*)base)->length) {
1929 bin->length = lysc_range_dup(ctx->ctx, ((struct lysc_type_bin*)base)->length);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001930 }
Radek Krejcib31c8992018-11-12 16:29:16 +01001931
1932 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = *type;
1933 *type = calloc(1, sizeof(struct lysc_type_bin));
1934 bin = (struct lysc_type_bin*)(*type);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001935 break;
1936 }
Radek Krejcib31c8992018-11-12 16:29:16 +01001937 LY_CHECK_ERR_GOTO(!(*type), LOGMEM(ctx->ctx), cleanup);
1938
Radek Krejci4f28eda2018-11-12 11:46:16 +01001939 }
1940
1941 /* get restrictions from the node itself, finalize the type structure */
Radek Krejcib31c8992018-11-12 16:29:16 +01001942 (*type)->basetype = basetype;
1943 switch (basetype) {
Radek Krejci4f28eda2018-11-12 11:46:16 +01001944 case LY_TYPE_BINARY:
1945 if (leaf_p->type.length) {
Radek Krejcib31c8992018-11-12 16:29:16 +01001946 ret = lys_compile_type_range(ctx, leaf_p->type.length, basetype, 1,
1947 base ? ((struct lysc_type_bin*)base)->length : NULL, &bin->length);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001948 LY_CHECK_GOTO(ret, cleanup);
1949 COMPILE_ARRAY_GOTO(ctx, leaf_p->type.length->exts, bin->length->exts,
1950 options, u, lys_compile_ext, ret, cleanup);
Radek Krejcib31c8992018-11-12 16:29:16 +01001951 } else if (base && ((struct lysc_type_bin*)base)->length) {
1952 bin->length = lysc_range_dup(ctx->ctx, ((struct lysc_type_bin*)base)->length);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001953 }
1954 break;
1955 }
1956
Radek Krejcib31c8992018-11-12 16:29:16 +01001957 COMPILE_ARRAY_GOTO(ctx, type_p->exts, (*type)->exts, options, u, lys_compile_ext, ret, cleanup);
1958
Radek Krejci4f28eda2018-11-12 11:46:16 +01001959cleanup:
1960 ly_set_erase(&tpdf_chain, free);
1961
1962 return ret;
1963}
1964
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001965static LY_ERR lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent);
1966
1967static LY_ERR
1968lys_compile_node_container(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
1969{
1970 struct lysp_node_container *cont_p = (struct lysp_node_container*)node_p;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001971 struct lysc_node_container *cont = (struct lysc_node_container*)node;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001972 struct lysp_node *child_p;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001973 unsigned int u;
1974 LY_ERR ret = LY_SUCCESS;
1975
1976 COMPILE_MEMBER_GOTO(ctx, cont_p->when, cont->when, options, lys_compile_when, ret, done);
1977 COMPILE_ARRAY_GOTO(ctx, cont_p->iffeatures, cont->iffeatures, options, u, lys_compile_iffeature, ret, done);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001978
1979 LY_LIST_FOR(cont_p->child, child_p) {
1980 LY_CHECK_RET(lys_compile_node(ctx, child_p, options, node));
1981 }
1982
Radek Krejci4f28eda2018-11-12 11:46:16 +01001983 COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, options, u, lys_compile_must, ret, done);
1984 //COMPILE_ARRAY_GOTO(ctx, cont_p->actions, cont->actions, options, u, lys_compile_action, ret, done);
1985 //COMPILE_ARRAY_GOTO(ctx, cont_p->notifs, cont->notifs, options, u, lys_compile_notif, ret, done);
1986
1987done:
1988 return ret;
1989}
1990
1991static LY_ERR
1992lys_compile_node_leaf(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
1993{
1994 struct lysp_node_leaf *leaf_p = (struct lysp_node_leaf*)node_p;
1995 struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)node;
1996 unsigned int u;
1997 LY_ERR ret = LY_SUCCESS;
1998
1999 COMPILE_MEMBER_GOTO(ctx, leaf_p->when, leaf->when, options, lys_compile_when, ret, done);
2000 COMPILE_ARRAY_GOTO(ctx, leaf_p->iffeatures, leaf->iffeatures, options, u, lys_compile_iffeature, ret, done);
2001
2002 COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, options, u, lys_compile_must, ret, done);
2003 ret = lys_compile_type(ctx, leaf_p, options, &leaf->type);
2004 LY_CHECK_GOTO(ret, done);
2005
2006 leaf->units = lydict_insert(ctx->ctx, leaf_p->units, 0);
2007 leaf->dflt = lydict_insert(ctx->ctx, leaf_p->dflt, 0);
2008done:
2009 return ret;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002010}
2011
2012static LY_ERR
2013lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent)
2014{
2015 LY_ERR ret = LY_EVALID;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002016 struct lysc_node *node, **children;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002017 unsigned int u;
2018 LY_ERR (*node_compile_spec)(struct lysc_ctx*, struct lysp_node*, int, struct lysc_node*);
2019
2020 switch (node_p->nodetype) {
2021 case LYS_CONTAINER:
2022 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_container));
2023 node_compile_spec = lys_compile_node_container;
2024 break;
2025 case LYS_LEAF:
2026 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaf));
Radek Krejci4f28eda2018-11-12 11:46:16 +01002027 node_compile_spec = lys_compile_node_leaf;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002028 break;
2029 case LYS_LIST:
2030 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_list));
2031 break;
2032 case LYS_LEAFLIST:
2033 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaflist));
2034 break;
2035 case LYS_CASE:
2036 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_case));
2037 break;
2038 case LYS_CHOICE:
2039 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_choice));
2040 break;
2041 case LYS_USES:
2042 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_uses));
2043 break;
2044 case LYS_ANYXML:
2045 case LYS_ANYDATA:
2046 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_anydata));
2047 break;
2048 default:
2049 LOGINT(ctx->ctx);
2050 return LY_EINT;
2051 }
2052 LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
2053 node->nodetype = node_p->nodetype;
2054 node->module = ctx->mod;
2055 node->prev = node;
2056 node->flags = node_p->flags;
2057
2058 /* config */
2059 if (!(node->flags & LYS_CONFIG_MASK)) {
2060 /* config not explicitely set, inherit it from parent */
2061 if (parent) {
2062 node->flags |= parent->flags & LYS_CONFIG_MASK;
2063 } else {
2064 /* default is config true */
2065 node->flags |= LYS_CONFIG_W;
2066 }
2067 }
2068
2069 /* status - it is not inherited by specification, but it does not make sense to have
2070 * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
2071 if (!(node->flags & LYS_STATUS_MASK)) {
2072 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
Radek Krejci98094b32018-11-02 16:21:47 +01002073 LOGWRN(ctx->ctx, "Missing explicit \"%s\" status that was already specified in parent, inheriting.",
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002074 (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
2075 node->flags |= parent->flags & LYS_STATUS_MASK;
2076 } else {
2077 node->flags |= LYS_STATUS_CURR;
2078 }
2079 } else if (parent) {
2080 /* check status compatibility with the parent */
2081 if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
2082 if (node->flags & LYS_STATUS_CURR) {
2083 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
2084 "A \"current\" status is in conflict with the parent's \"%s\" status.",
2085 (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
2086 } else { /* LYS_STATUS_DEPRC */
2087 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
2088 "A \"deprecated\" status is in conflict with the parent's \"obsolete\" status.");
2089 }
2090 goto error;
2091 }
2092 }
2093
Radek Krejci4f28eda2018-11-12 11:46:16 +01002094 if (!(options & LYSC_OPT_FREE_SP)) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002095 node->sp = node_p;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002096 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01002097 node->name = lydict_insert(ctx->ctx, node_p->name, 0);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002098 COMPILE_ARRAY_GOTO(ctx, node_p->exts, node->exts, options, u, lys_compile_ext, ret, error);
2099
2100 /* nodetype-specific part */
2101 LY_CHECK_GOTO(node_compile_spec(ctx, node_p, options, node), error);
2102
2103 /* insert into parent's children */
Radek Krejci4f28eda2018-11-12 11:46:16 +01002104 if (parent && (children = lysc_node_children(parent))) {
2105 if (!(*children)) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002106 /* first child */
Radek Krejci4f28eda2018-11-12 11:46:16 +01002107 *children = node;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002108 } else {
2109 /* insert at the end of the parent's children list */
Radek Krejci4f28eda2018-11-12 11:46:16 +01002110 (*children)->prev->next = node;
2111 node->prev = (*children)->prev;
2112 (*children)->prev = node;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002113 }
2114 } else {
2115 /* top-level element */
2116 if (!ctx->mod->compiled->data) {
2117 ctx->mod->compiled->data = node;
2118 } else {
2119 /* insert at the end of the module's top-level nodes list */
2120 ctx->mod->compiled->data->prev->next = node;
2121 node->prev = ctx->mod->compiled->data->prev;
2122 ctx->mod->compiled->data->prev = node;
2123 }
2124 }
2125
2126 return LY_SUCCESS;
2127
2128error:
Radek Krejci4f28eda2018-11-12 11:46:16 +01002129 lysc_node_free(ctx->ctx, node);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002130 return ret;
2131}
2132
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002133LY_ERR
Radek Krejcid14e9692018-11-01 11:00:37 +01002134lys_compile(struct lys_module *mod, int options)
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002135{
Radek Krejci86d106e2018-10-18 09:53:19 +02002136 struct lysc_ctx ctx = {0};
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002137 struct lysc_module *mod_c;
Radek Krejcif8f882a2018-10-31 14:51:15 +01002138 struct lysp_module *sp;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002139 struct lysp_node *node_p;
Radek Krejci151a5b72018-10-19 14:21:44 +02002140 unsigned int u;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002141 LY_ERR ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002142
Radek Krejcif8f882a2018-10-31 14:51:15 +01002143 LY_CHECK_ARG_RET(NULL, mod, mod->parsed, mod->parsed->ctx, LY_EINVAL);
2144 sp = mod->parsed;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002145
2146 if (sp->submodule) {
Radek Krejci86d106e2018-10-18 09:53:19 +02002147 LOGERR(sp->ctx, LY_EINVAL, "Submodules (%s) are not supposed to be compiled, compile only the main modules.", sp->name);
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002148 return LY_EINVAL;
2149 }
2150
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002151 ctx.ctx = sp->ctx;
2152 ctx.mod = mod;
2153
2154 mod->compiled = mod_c = calloc(1, sizeof *mod_c);
Radek Krejci86d106e2018-10-18 09:53:19 +02002155 LY_CHECK_ERR_RET(!mod_c, LOGMEM(sp->ctx), LY_EMEM);
2156 mod_c->ctx = sp->ctx;
Radek Krejcid14e9692018-11-01 11:00:37 +01002157 mod_c->implemented = sp->implemented;
2158 mod_c->latest_revision = sp->latest_revision;
Radek Krejci86d106e2018-10-18 09:53:19 +02002159 mod_c->version = sp->version;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002160
Radek Krejci4f28eda2018-11-12 11:46:16 +01002161 mod_c->name = lydict_insert(sp->ctx, sp->name, 0);
2162 mod_c->ns = lydict_insert(sp->ctx, sp->ns, 0);
2163 mod_c->prefix = lydict_insert(sp->ctx, sp->prefix, 0);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002164 if (sp->revs) {
2165 mod_c->revision = lydict_insert(sp->ctx, sp->revs[0].date, 10);
2166 }
Radek Krejcice8c1592018-10-29 15:35:51 +01002167 COMPILE_ARRAY_GOTO(&ctx, sp->imports, mod_c->imports, options, u, lys_compile_import, ret, error);
2168 COMPILE_ARRAY_GOTO(&ctx, sp->features, mod_c->features, options, u, lys_compile_feature, ret, error);
Radek Krejci2a408df2018-10-29 16:32:26 +01002169 COMPILE_ARRAY_GOTO(&ctx, sp->identities, mod_c->identities, options, u, lys_compile_identity, ret, error);
2170 if (sp->identities) {
2171 LY_CHECK_RET(lys_compile_identities_derived(&ctx, sp->identities, mod_c->identities));
2172 }
Radek Krejcice8c1592018-10-29 15:35:51 +01002173
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002174 LY_LIST_FOR(sp->data, node_p) {
2175 ret = lys_compile_node(&ctx, node_p, options, NULL);
2176 LY_CHECK_GOTO(ret, error);
2177 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01002178 //COMPILE_ARRAY_GOTO(ctx, sp->rpcs, mod_c->rpcs, options, u, lys_compile_action, ret, error);
2179 //COMPILE_ARRAY_GOTO(ctx, sp->notifs, mod_c->notifs, options, u, lys_compile_notif, ret, error);
2180
2181 COMPILE_ARRAY_GOTO(&ctx, sp->exts, mod_c->exts, options, u, lys_compile_ext, ret, error);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002182
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002183 if (options & LYSC_OPT_FREE_SP) {
Radek Krejci4f28eda2018-11-12 11:46:16 +01002184 lysp_module_free(mod->parsed);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002185 ((struct lys_module*)mod)->parsed = NULL;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002186 }
2187
Radek Krejcif8f882a2018-10-31 14:51:15 +01002188 ((struct lys_module*)mod)->compiled = mod_c;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002189 return LY_SUCCESS;
2190
2191error:
Radek Krejci4f28eda2018-11-12 11:46:16 +01002192 lysc_module_free(mod_c, NULL);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002193 ((struct lys_module*)mod)->compiled = NULL;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002194 return ret;
2195}
Radek Krejci86d106e2018-10-18 09:53:19 +02002196
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002197static void
Radek Krejci086c7132018-10-26 15:29:04 +02002198lys_latest_switch(struct lys_module *old, struct lysp_module *new)
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002199{
Radek Krejci086c7132018-10-26 15:29:04 +02002200 if (old->parsed) {
2201 new->latest_revision = old->parsed->latest_revision;
2202 old->parsed->latest_revision = 0;
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002203 }
Radek Krejci086c7132018-10-26 15:29:04 +02002204 if (old->compiled) {
2205 new->latest_revision = old->parsed->latest_revision;
2206 old->compiled->latest_revision = 0;
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002207 }
2208}
2209
Radek Krejcid33273d2018-10-25 14:55:52 +02002210struct lys_module *
Radek Krejci3b1f9292018-11-08 10:58:35 +01002211lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int implement, struct ly_parser_ctx *main_ctx,
Radek Krejci9ed7a192018-10-31 16:23:51 +01002212 LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
Radek Krejci86d106e2018-10-18 09:53:19 +02002213{
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002214 struct lys_module *mod = NULL, *latest, *mod_dup;
Radek Krejcid33273d2018-10-25 14:55:52 +02002215 struct lysp_module *latest_p;
Radek Krejci086c7132018-10-26 15:29:04 +02002216 struct lysp_import *imp;
2217 struct lysp_include *inc;
Radek Krejci9ed7a192018-10-31 16:23:51 +01002218 LY_ERR ret = LY_EINVAL;
Radek Krejci086c7132018-10-26 15:29:04 +02002219 unsigned int u, i;
Radek Krejcibbe09a92018-11-08 09:36:54 +01002220 struct ly_parser_ctx context = {0};
Radek Krejci86d106e2018-10-18 09:53:19 +02002221
2222 LY_CHECK_ARG_RET(ctx, ctx, data, NULL);
2223
Radek Krejcibbe09a92018-11-08 09:36:54 +01002224 context.ctx = ctx;
2225 context.line = 1;
2226
Radek Krejci3b1f9292018-11-08 10:58:35 +01002227 if (main_ctx) {
2228 /* map the typedefs and groupings list from main context to the submodule's context */
2229 memcpy(&context.tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
2230 memcpy(&context.grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
2231 }
2232
Radek Krejci86d106e2018-10-18 09:53:19 +02002233 mod = calloc(1, sizeof *mod);
2234 LY_CHECK_ERR_RET(!mod, LOGMEM(ctx), NULL);
2235
2236 switch (format) {
2237 case LYS_IN_YIN:
2238 /* TODO not yet supported
2239 mod = yin_read_module(ctx, data, revision, implement);
2240 */
2241 break;
2242 case LYS_IN_YANG:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002243 ret = yang_parse(&context, data, &mod->parsed);
Radek Krejci86d106e2018-10-18 09:53:19 +02002244 break;
2245 default:
2246 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
2247 break;
2248 }
Radek Krejcifaa1eac2018-10-30 14:34:55 +01002249 LY_CHECK_ERR_RET(ret, free(mod), NULL);
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002250
2251 /* make sure that the newest revision is at position 0 */
2252 lysp_sort_revisions(mod->parsed->revs);
Radek Krejci86d106e2018-10-18 09:53:19 +02002253
2254 if (implement) {
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002255 /* mark the loaded module implemented */
Radek Krejcib7db73a2018-10-24 14:18:40 +02002256 if (ly_ctx_get_module_implemented(ctx, mod->parsed->name)) {
2257 LOGERR(ctx, LY_EDENIED, "Module \"%s\" is already implemented in the context.", mod->parsed->name);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002258 goto error;
Radek Krejcib7db73a2018-10-24 14:18:40 +02002259 }
Radek Krejci86d106e2018-10-18 09:53:19 +02002260 mod->parsed->implemented = 1;
2261 }
2262
Radek Krejci9ed7a192018-10-31 16:23:51 +01002263 if (custom_check) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002264 LY_CHECK_GOTO(custom_check(ctx, mod->parsed, check_data), error);
Radek Krejci86d106e2018-10-18 09:53:19 +02002265 }
2266
Radek Krejcid33273d2018-10-25 14:55:52 +02002267 if (mod->parsed->submodule) { /* submodule */
Radek Krejci3b1f9292018-11-08 10:58:35 +01002268 if (!main_ctx) {
2269 LOGERR(ctx, LY_EDENIED, "Input data contains submodule \"%s\" which cannot be parsed directly without its main module.",
2270 mod->parsed->name);
2271 goto error;
2272 }
Radek Krejcid33273d2018-10-25 14:55:52 +02002273 /* decide the latest revision */
2274 latest_p = ly_ctx_get_submodule(ctx, mod->parsed->belongsto, mod->parsed->name, NULL);
2275 if (latest_p) {
2276 if (mod->parsed->revs) {
2277 if (!latest_p->revs) {
2278 /* latest has no revision, so mod is anyway newer */
Radek Krejci9ed7a192018-10-31 16:23:51 +01002279 mod->parsed->latest_revision = latest_p->latest_revision;
Radek Krejcid33273d2018-10-25 14:55:52 +02002280 latest_p->latest_revision = 0;
2281 } else {
2282 if (strcmp(mod->parsed->revs[0].date, latest_p->revs[0].date) > 0) {
Radek Krejci9ed7a192018-10-31 16:23:51 +01002283 mod->parsed->latest_revision = latest_p->latest_revision;
Radek Krejcid33273d2018-10-25 14:55:52 +02002284 latest_p->latest_revision = 0;
2285 }
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002286 }
2287 }
Radek Krejcid33273d2018-10-25 14:55:52 +02002288 } else {
Radek Krejci9ed7a192018-10-31 16:23:51 +01002289 mod->parsed->latest_revision = 1;
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002290 }
Radek Krejci3b1f9292018-11-08 10:58:35 +01002291 /* remap possibly changed and reallocated typedefs and groupings list back to the main context */
2292 memcpy(&main_ctx->tpdfs_nodes, &context.tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
2293 memcpy(&main_ctx->grps_nodes, &context.grps_nodes, sizeof main_ctx->grps_nodes);
Radek Krejcid33273d2018-10-25 14:55:52 +02002294 } else { /* module */
2295 /* check for duplicity in the context */
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002296 mod_dup = (struct lys_module*)ly_ctx_get_module(ctx, mod->parsed->name, mod->parsed->revs ? mod->parsed->revs[0].date : NULL);
2297 if (mod_dup) {
2298 if (mod_dup->parsed) {
2299 /* error */
2300 if (mod->parsed->revs) {
2301 LOGERR(ctx, LY_EEXIST, "Module \"%s\" of revision \"%s\" is already present in the context.",
2302 mod->parsed->name, mod->parsed->revs[0].date);
2303 } else {
2304 LOGERR(ctx, LY_EEXIST, "Module \"%s\" with no revision is already present in the context.",
2305 mod->parsed->name);
2306 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01002307 goto error;
Radek Krejcid33273d2018-10-25 14:55:52 +02002308 } else {
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002309 /* add the parsed data to the currently compiled-only module in the context */
2310 mod_dup->parsed = mod->parsed;
2311 free(mod);
2312 mod = mod_dup;
2313 goto finish_parsing;
Radek Krejcid33273d2018-10-25 14:55:52 +02002314 }
Radek Krejcid33273d2018-10-25 14:55:52 +02002315 }
Radek Krejci86d106e2018-10-18 09:53:19 +02002316
2317#if 0
2318 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
2319 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
2320 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
2321 * the anotation definitions available in the internal schema structure. There is another hack in schema
2322 * printers to do not print this internally added annotation. */
2323 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
2324 if (lyp_add_ietf_netconf_annotations(mod)) {
2325 lys_free(mod, NULL, 1, 1);
2326 return NULL;
2327 }
2328 }
2329#endif
2330
Radek Krejcid33273d2018-10-25 14:55:52 +02002331 /* decide the latest revision */
2332 latest = (struct lys_module*)ly_ctx_get_module_latest(ctx, mod->parsed->name);
2333 if (latest) {
2334 if (mod->parsed->revs) {
Radek Krejcif8f882a2018-10-31 14:51:15 +01002335 if ((latest->parsed && !latest->parsed->revs) || (!latest->parsed && !latest->compiled->revision)) {
Radek Krejcid33273d2018-10-25 14:55:52 +02002336 /* latest has no revision, so mod is anyway newer */
Radek Krejci086c7132018-10-26 15:29:04 +02002337 lys_latest_switch(latest, mod->parsed);
Radek Krejcid33273d2018-10-25 14:55:52 +02002338 } else {
Radek Krejcif8f882a2018-10-31 14:51:15 +01002339 if (strcmp(mod->parsed->revs[0].date, latest->parsed ? latest->parsed->revs[0].date : latest->compiled->revision) > 0) {
Radek Krejci086c7132018-10-26 15:29:04 +02002340 lys_latest_switch(latest, mod->parsed);
Radek Krejcid33273d2018-10-25 14:55:52 +02002341 }
2342 }
2343 }
2344 } else {
2345 mod->parsed->latest_revision = 1;
2346 }
2347
2348 /* add into context */
2349 ly_set_add(&ctx->list, mod, LY_SET_OPT_USEASLIST);
2350
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002351finish_parsing:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002352 /* resolve imports */
Radek Krejci086c7132018-10-26 15:29:04 +02002353 mod->parsed->parsing = 1;
2354 LY_ARRAY_FOR(mod->parsed->imports, u) {
2355 imp = &mod->parsed->imports[u];
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002356 if (!imp->module && lysp_load_module(ctx, imp->name, imp->rev[0] ? imp->rev : NULL, 0, 0, &imp->module)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002357 goto error_ctx;
Radek Krejci086c7132018-10-26 15:29:04 +02002358 }
2359 /* check for importing the same module twice */
2360 for (i = 0; i < u; ++i) {
2361 if (imp->module == mod->parsed->imports[i].module) {
2362 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Single revision of the module \"%s\" referred twice.", imp->name);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002363 goto error_ctx;
Radek Krejci086c7132018-10-26 15:29:04 +02002364 }
2365 }
2366 }
2367 LY_ARRAY_FOR(mod->parsed->includes, u) {
2368 inc = &mod->parsed->includes[u];
Radek Krejci3b1f9292018-11-08 10:58:35 +01002369 if (!inc->submodule && lysp_load_submodule(&context, mod->parsed, inc)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002370 goto error_ctx;
Radek Krejci086c7132018-10-26 15:29:04 +02002371 }
2372 }
2373 mod->parsed->parsing = 0;
Radek Krejcibbe09a92018-11-08 09:36:54 +01002374
2375 /* check name collisions - typedefs and groupings */
2376 LY_CHECK_GOTO(lysp_check_typedefs(&context), error_ctx);
Radek Krejcid33273d2018-10-25 14:55:52 +02002377 }
2378
Radek Krejci86d106e2018-10-18 09:53:19 +02002379 return mod;
Radek Krejcibbe09a92018-11-08 09:36:54 +01002380
2381error_ctx:
2382 ly_set_rm(&ctx->list, mod, NULL);
2383error:
2384 lys_module_free(mod, NULL);
2385 ly_set_erase(&context.tpdfs_nodes, NULL);
2386 return NULL;
Radek Krejci86d106e2018-10-18 09:53:19 +02002387}
2388
Radek Krejcid14e9692018-11-01 11:00:37 +01002389API struct lys_module *
Radek Krejci86d106e2018-10-18 09:53:19 +02002390lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
2391{
Radek Krejci3b1f9292018-11-08 10:58:35 +01002392 return lys_parse_mem_(ctx, data, format, 1, NULL, NULL, NULL);
Radek Krejci86d106e2018-10-18 09:53:19 +02002393}
2394
2395static void
2396lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
2397{
2398#ifdef __APPLE__
2399 char path[MAXPATHLEN];
2400#else
2401 int len;
2402 char path[PATH_MAX], proc_path[32];
2403#endif
2404
2405#ifdef __APPLE__
2406 if (fcntl(fd, F_GETPATH, path) != -1) {
2407 *filename = lydict_insert(ctx, path, 0);
2408 }
2409#else
2410 /* get URI if there is /proc */
2411 sprintf(proc_path, "/proc/self/fd/%d", fd);
2412 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
2413 *filename = lydict_insert(ctx, path, len);
2414 }
2415#endif
2416}
2417
Radek Krejcid33273d2018-10-25 14:55:52 +02002418struct lys_module *
Radek Krejci3b1f9292018-11-08 10:58:35 +01002419lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, int implement, struct ly_parser_ctx *main_ctx,
Radek Krejci9ed7a192018-10-31 16:23:51 +01002420 LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
Radek Krejci86d106e2018-10-18 09:53:19 +02002421{
Radek Krejcid33273d2018-10-25 14:55:52 +02002422 struct lys_module *mod;
Radek Krejci86d106e2018-10-18 09:53:19 +02002423 size_t length;
2424 char *addr;
2425
2426 LY_CHECK_ARG_RET(ctx, ctx, NULL);
2427 if (fd < 0) {
2428 LOGARG(ctx, fd);
2429 return NULL;
2430 }
2431
2432 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
2433 if (!addr) {
2434 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
2435 return NULL;
2436 }
2437
Radek Krejci3b1f9292018-11-08 10:58:35 +01002438 mod = lys_parse_mem_(ctx, addr, format, implement, main_ctx, custom_check, check_data);
Radek Krejci86d106e2018-10-18 09:53:19 +02002439 ly_munmap(addr, length);
2440
2441 if (mod && !mod->parsed->filepath) {
2442 lys_parse_set_filename(ctx, &mod->parsed->filepath, fd);
2443 }
2444
2445 return mod;
2446}
2447
Radek Krejcid14e9692018-11-01 11:00:37 +01002448API struct lys_module *
Radek Krejci86d106e2018-10-18 09:53:19 +02002449lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
2450{
Radek Krejci3b1f9292018-11-08 10:58:35 +01002451 return lys_parse_fd_(ctx, fd, format, 1, NULL, NULL, NULL);
Radek Krejci86d106e2018-10-18 09:53:19 +02002452}
2453
Radek Krejcid33273d2018-10-25 14:55:52 +02002454struct lys_module *
Radek Krejci3b1f9292018-11-08 10:58:35 +01002455lys_parse_path_(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format, int implement, struct ly_parser_ctx *main_ctx,
Radek Krejci9ed7a192018-10-31 16:23:51 +01002456 LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
Radek Krejci86d106e2018-10-18 09:53:19 +02002457{
2458 int fd;
Radek Krejcid33273d2018-10-25 14:55:52 +02002459 struct lys_module *mod;
Radek Krejci86d106e2018-10-18 09:53:19 +02002460 const char *rev, *dot, *filename;
2461 size_t len;
2462
2463 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
2464
2465 fd = open(path, O_RDONLY);
2466 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
2467
Radek Krejci3b1f9292018-11-08 10:58:35 +01002468 mod = lys_parse_fd_(ctx, fd, format, implement, main_ctx, custom_check, check_data);
Radek Krejci86d106e2018-10-18 09:53:19 +02002469 close(fd);
2470 LY_CHECK_RET(!mod, NULL);
2471
2472 /* check that name and revision match filename */
2473 filename = strrchr(path, '/');
2474 if (!filename) {
2475 filename = path;
2476 } else {
2477 filename++;
2478 }
2479 rev = strchr(filename, '@');
2480 dot = strrchr(filename, '.');
2481
2482 /* name */
2483 len = strlen(mod->parsed->name);
2484 if (strncmp(filename, mod->parsed->name, len) ||
2485 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
2486 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, mod->parsed->name);
2487 }
2488 if (rev) {
2489 len = dot - ++rev;
Radek Krejcib7db73a2018-10-24 14:18:40 +02002490 if (!mod->parsed->revs || len != 10 || strncmp(mod->parsed->revs[0].date, rev, len)) {
Radek Krejci86d106e2018-10-18 09:53:19 +02002491 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
Radek Krejcib7db73a2018-10-24 14:18:40 +02002492 mod->parsed->revs ? mod->parsed->revs[0].date : "none");
Radek Krejci86d106e2018-10-18 09:53:19 +02002493 }
2494 }
2495
2496 if (!mod->parsed->filepath) {
2497 /* store URI */
2498 char rpath[PATH_MAX];
2499 if (realpath(path, rpath) != NULL) {
2500 mod->parsed->filepath = lydict_insert(ctx, rpath, 0);
2501 } else {
2502 mod->parsed->filepath = lydict_insert(ctx, path, 0);
2503 }
2504 }
2505
2506 return mod;
2507}
2508
Radek Krejcid14e9692018-11-01 11:00:37 +01002509API struct lys_module *
Radek Krejcid33273d2018-10-25 14:55:52 +02002510lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
2511{
Radek Krejci3b1f9292018-11-08 10:58:35 +01002512 return lys_parse_path_(ctx, path, format, 1, NULL, NULL, NULL);
Radek Krejcid33273d2018-10-25 14:55:52 +02002513}
2514
2515API LY_ERR
2516lys_search_localfile(const char * const *searchpaths, int cwd, const char *name, const char *revision,
2517 char **localfile, LYS_INFORMAT *format)
2518{
2519 size_t len, flen, match_len = 0, dir_len;
2520 int i, implicit_cwd = 0, ret = EXIT_FAILURE;
2521 char *wd, *wn = NULL;
2522 DIR *dir = NULL;
2523 struct dirent *file;
2524 char *match_name = NULL;
2525 LYS_INFORMAT format_aux, match_format = 0;
2526 struct ly_set *dirs;
2527 struct stat st;
2528
2529 LY_CHECK_ARG_RET(NULL, localfile, LY_EINVAL);
2530
2531 /* start to fill the dir fifo with the context's search path (if set)
2532 * and the current working directory */
2533 dirs = ly_set_new();
2534 if (!dirs) {
2535 LOGMEM(NULL);
2536 return EXIT_FAILURE;
2537 }
2538
2539 len = strlen(name);
2540 if (cwd) {
2541 wd = get_current_dir_name();
2542 if (!wd) {
2543 LOGMEM(NULL);
2544 goto cleanup;
2545 } else {
2546 /* add implicit current working directory (./) to be searched,
2547 * this directory is not searched recursively */
2548 if (ly_set_add(dirs, wd, 0) == -1) {
2549 goto cleanup;
2550 }
2551 implicit_cwd = 1;
2552 }
2553 }
2554 if (searchpaths) {
2555 for (i = 0; searchpaths[i]; i++) {
2556 /* check for duplicities with the implicit current working directory */
2557 if (implicit_cwd && !strcmp(dirs->objs[0], searchpaths[i])) {
2558 implicit_cwd = 0;
2559 continue;
2560 }
2561 wd = strdup(searchpaths[i]);
2562 if (!wd) {
2563 LOGMEM(NULL);
2564 goto cleanup;
2565 } else if (ly_set_add(dirs, wd, 0) == -1) {
2566 goto cleanup;
2567 }
2568 }
2569 }
2570 wd = NULL;
2571
2572 /* start searching */
2573 while (dirs->count) {
2574 free(wd);
2575 free(wn); wn = NULL;
2576
2577 dirs->count--;
2578 wd = (char *)dirs->objs[dirs->count];
2579 dirs->objs[dirs->count] = NULL;
2580 LOGVRB("Searching for \"%s\" in %s.", name, wd);
2581
2582 if (dir) {
2583 closedir(dir);
2584 }
2585 dir = opendir(wd);
2586 dir_len = strlen(wd);
2587 if (!dir) {
2588 LOGWRN(NULL, "Unable to open directory \"%s\" for searching (sub)modules (%s).", wd, strerror(errno));
2589 } else {
2590 while ((file = readdir(dir))) {
2591 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
2592 /* skip . and .. */
2593 continue;
2594 }
2595 free(wn);
2596 if (asprintf(&wn, "%s/%s", wd, file->d_name) == -1) {
2597 LOGMEM(NULL);
2598 goto cleanup;
2599 }
2600 if (stat(wn, &st) == -1) {
2601 LOGWRN(NULL, "Unable to get information about \"%s\" file in \"%s\" when searching for (sub)modules (%s)",
2602 file->d_name, wd, strerror(errno));
2603 continue;
2604 }
2605 if (S_ISDIR(st.st_mode) && (dirs->count || !implicit_cwd)) {
2606 /* we have another subdirectory in searchpath to explore,
2607 * subdirectories are not taken into account in current working dir (dirs->set.g[0]) */
2608 if (ly_set_add(dirs, wn, 0) == -1) {
2609 goto cleanup;
2610 }
2611 /* continue with the next item in current directory */
2612 wn = NULL;
2613 continue;
2614 } else if (!S_ISREG(st.st_mode)) {
2615 /* not a regular file (note that we see the target of symlinks instead of symlinks */
2616 continue;
2617 }
2618
2619 /* here we know that the item is a file which can contain a module */
2620 if (strncmp(name, file->d_name, len) ||
2621 (file->d_name[len] != '.' && file->d_name[len] != '@')) {
2622 /* different filename than the module we search for */
2623 continue;
2624 }
2625
2626 /* get type according to filename suffix */
2627 flen = strlen(file->d_name);
2628 if (!strcmp(&file->d_name[flen - 4], ".yin")) {
2629 format_aux = LYS_IN_YIN;
2630 } else if (!strcmp(&file->d_name[flen - 5], ".yang")) {
2631 format_aux = LYS_IN_YANG;
2632 } else {
2633 /* not supportde suffix/file format */
2634 continue;
2635 }
2636
2637 if (revision) {
2638 /* we look for the specific revision, try to get it from the filename */
2639 if (file->d_name[len] == '@') {
2640 /* check revision from the filename */
2641 if (strncmp(revision, &file->d_name[len + 1], strlen(revision))) {
2642 /* another revision */
2643 continue;
2644 } else {
2645 /* exact revision */
2646 free(match_name);
2647 match_name = wn;
2648 wn = NULL;
2649 match_len = dir_len + 1 + len;
2650 match_format = format_aux;
2651 goto success;
2652 }
2653 } else {
2654 /* continue trying to find exact revision match, use this only if not found */
2655 free(match_name);
2656 match_name = wn;
2657 wn = NULL;
2658 match_len = dir_len + 1 +len;
2659 match_format = format_aux;
2660 continue;
2661 }
2662 } else {
2663 /* remember the revision and try to find the newest one */
2664 if (match_name) {
2665 if (file->d_name[len] != '@' ||
2666 lysp_check_date(NULL, &file->d_name[len + 1], flen - (format_aux == LYS_IN_YANG ? 5 : 4) - len - 1, NULL)) {
2667 continue;
2668 } else if (match_name[match_len] == '@' &&
2669 (strncmp(&match_name[match_len + 1], &file->d_name[len + 1], LY_REV_SIZE - 1) >= 0)) {
2670 continue;
2671 }
2672 free(match_name);
2673 }
2674
2675 match_name = wn;
2676 wn = NULL;
2677 match_len = dir_len + 1 + len;
2678 match_format = format_aux;
2679 continue;
2680 }
2681 }
2682 }
2683 }
2684
2685success:
2686 (*localfile) = match_name;
2687 match_name = NULL;
2688 if (format) {
2689 (*format) = match_format;
2690 }
2691 ret = EXIT_SUCCESS;
2692
2693cleanup:
2694 free(wn);
2695 free(wd);
2696 if (dir) {
2697 closedir(dir);
2698 }
2699 free(match_name);
2700 ly_set_free(dirs, free);
2701
2702 return ret;
2703}
2704