blob: 56b4c4cf18f1fd5dfaa5a9ea8d25ae6bb13b328c [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 Krejci6d6e4e42018-10-29 13:28:19 +010038#define COMPILE_ARRAY_GOTO(CTX, ARRAY_P, ARRAY_C, OPTIONS, ITER, FUNC, RET, GOTO) \
39 if (ARRAY_P) { \
Radek Krejcibd8d9ba2018-11-02 16:06:26 +010040 LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, LY_ARRAY_SIZE(ARRAY_P), RET, GOTO); \
Radek Krejci6d6e4e42018-10-29 13:28:19 +010041 for (ITER = 0; ITER < LY_ARRAY_SIZE(ARRAY_P); ++ITER) { \
Radek Krejci87616bb2018-10-31 13:30:52 +010042 LY_ARRAY_INCREMENT(ARRAY_C); \
Radek Krejcice8c1592018-10-29 15:35:51 +010043 RET = FUNC(CTX, &(ARRAY_P)[ITER], OPTIONS, &(ARRAY_C)[ITER]); \
Radek Krejci6d6e4e42018-10-29 13:28:19 +010044 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
Radek Krejci6d6e4e42018-10-29 13:28:19 +010045 } \
46 }
47
Radek Krejci4f28eda2018-11-12 11:46:16 +010048#define COMPILE_MEMBER_GOTO(CTX, MEMBER_P, MEMBER_C, OPTIONS, FUNC, RET, GOTO) \
49 if (MEMBER_P) { \
50 MEMBER_C = calloc(1, sizeof *(MEMBER_C)); \
51 LY_CHECK_ERR_GOTO(!(MEMBER_C), LOGMEM((CTX)->ctx); RET = LY_EMEM, GOTO); \
52 RET = FUNC(CTX, MEMBER_P, OPTIONS, MEMBER_C); \
53 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
54 }
Radek Krejci6f7feb62018-10-12 15:23:02 +020055
Radek Krejci4f28eda2018-11-12 11:46:16 +010056static void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
57static void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
Radek Krejci86d106e2018-10-18 09:53:19 +020058
Radek Krejci6f7feb62018-10-12 15:23:02 +020059static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010060lysp_stmt_free(struct ly_ctx *ctx, struct lysp_stmt *stmt)
Radek Krejci6f7feb62018-10-12 15:23:02 +020061{
62 struct lysp_stmt *child, *next;
63
Radek Krejci4f28eda2018-11-12 11:46:16 +010064 FREE_STRING(ctx, stmt->stmt);
65 FREE_STRING(ctx, stmt->arg);
Radek Krejci6f7feb62018-10-12 15:23:02 +020066
67 LY_LIST_FOR_SAFE(stmt->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +010068 lysp_stmt_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +020069 }
70
71 free(stmt);
72}
73
74static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010075lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext)
Radek Krejci6f7feb62018-10-12 15:23:02 +020076{
77 struct lysp_stmt *stmt, *next;
78
Radek Krejci4f28eda2018-11-12 11:46:16 +010079 FREE_STRING(ctx, ext->name);
80 FREE_STRING(ctx, ext->argument);
Radek Krejci6f7feb62018-10-12 15:23:02 +020081
82 LY_LIST_FOR_SAFE(ext->child, next, stmt) {
Radek Krejci4f28eda2018-11-12 11:46:16 +010083 lysp_stmt_free(ctx, stmt);
Radek Krejci6f7feb62018-10-12 15:23:02 +020084 }
85}
86
87static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010088lysp_import_free(struct ly_ctx *ctx, struct lysp_import *import)
Radek Krejci6f7feb62018-10-12 15:23:02 +020089{
Radek Krejci086c7132018-10-26 15:29:04 +020090 /* imported module is freed directly from the context's list */
Radek Krejci4f28eda2018-11-12 11:46:16 +010091 FREE_STRING(ctx, import->name);
92 FREE_STRING(ctx, import->prefix);
93 FREE_STRING(ctx, import->dsc);
94 FREE_STRING(ctx, import->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +020095 FREE_ARRAY(ctx, import->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +020096}
97
98static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010099lysp_include_free(struct ly_ctx *ctx, struct lysp_include *include)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200100{
Radek Krejcibbe09a92018-11-08 09:36:54 +0100101 if (include->submodule) {
Radek Krejcid33273d2018-10-25 14:55:52 +0200102 lysp_module_free(include->submodule);
103 }
Radek Krejci4f28eda2018-11-12 11:46:16 +0100104 FREE_STRING(ctx, include->name);
105 FREE_STRING(ctx, include->dsc);
106 FREE_STRING(ctx, include->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200107 FREE_ARRAY(ctx, include->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200108}
109
110static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100111lysp_revision_free(struct ly_ctx *ctx, struct lysp_revision *rev)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200112{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100113 FREE_STRING(ctx, rev->dsc);
114 FREE_STRING(ctx, rev->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200115 FREE_ARRAY(ctx, rev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200116}
117
118static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100119lysp_ext_free(struct ly_ctx *ctx, struct lysp_ext *ext)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200120{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100121 FREE_STRING(ctx, ext->name);
122 FREE_STRING(ctx, ext->argument);
123 FREE_STRING(ctx, ext->dsc);
124 FREE_STRING(ctx, ext->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200125 FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200126}
127
128static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100129lysp_feature_free(struct ly_ctx *ctx, struct lysp_feature *feat)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200130{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100131 FREE_STRING(ctx, feat->name);
132 FREE_STRINGS(ctx, feat->iffeatures);
133 FREE_STRING(ctx, feat->dsc);
134 FREE_STRING(ctx, feat->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200135 FREE_ARRAY(ctx, feat->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200136}
137
138static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100139lysp_ident_free(struct ly_ctx *ctx, struct lysp_ident *ident)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200140{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100141 FREE_STRING(ctx, ident->name);
142 FREE_STRINGS(ctx, ident->iffeatures);
143 FREE_STRINGS(ctx, ident->bases);
144 FREE_STRING(ctx, ident->dsc);
145 FREE_STRING(ctx, ident->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200146 FREE_ARRAY(ctx, ident->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200147}
148
149static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100150lysp_restr_free(struct ly_ctx *ctx, struct lysp_restr *restr)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200151{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100152 FREE_STRING(ctx, restr->arg);
153 FREE_STRING(ctx, restr->emsg);
154 FREE_STRING(ctx, restr->eapptag);
155 FREE_STRING(ctx, restr->dsc);
156 FREE_STRING(ctx, restr->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200157 FREE_ARRAY(ctx, restr->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200158}
159
160static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100161lysp_type_enum_free(struct ly_ctx *ctx, struct lysp_type_enum *item)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200162{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100163 FREE_STRING(ctx, item->name);
164 FREE_STRING(ctx, item->dsc);
165 FREE_STRING(ctx, item->ref);
166 FREE_STRINGS(ctx, item->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200167 FREE_ARRAY(ctx, item->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200168}
169
170static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100171lysp_type_free(struct ly_ctx *ctx, struct lysp_type *type)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200172{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100173 FREE_STRING(ctx, type->name);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200174 FREE_MEMBER(ctx, type->range, lysp_restr_free);
175 FREE_MEMBER(ctx, type->length, lysp_restr_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200176 FREE_ARRAY(ctx, type->patterns, lysp_restr_free);
177 FREE_ARRAY(ctx, type->enums, lysp_type_enum_free);
178 FREE_ARRAY(ctx, type->bits, lysp_type_enum_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100179 FREE_STRING(ctx, type->path);
180 FREE_STRINGS(ctx, type->bases);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200181 FREE_ARRAY(ctx, type->types, lysp_type_free);
182 FREE_ARRAY(ctx, type->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200183}
184
185static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100186lysp_tpdf_free(struct ly_ctx *ctx, struct lysp_tpdf *tpdf)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200187{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100188 FREE_STRING(ctx, tpdf->name);
189 FREE_STRING(ctx, tpdf->units);
190 FREE_STRING(ctx, tpdf->dflt);
191 FREE_STRING(ctx, tpdf->dsc);
192 FREE_STRING(ctx, tpdf->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200193 FREE_ARRAY(ctx, tpdf->exts, lysp_ext_instance_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100194 lysp_type_free(ctx, &tpdf->type);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200195}
196
197static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100198lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200199{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200200 struct lysp_node *node, *next;
201
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200202 FREE_ARRAY(ctx, inout->musts, lysp_restr_free);
203 FREE_ARRAY(ctx, inout->typedefs, lysp_tpdf_free);
204 FREE_ARRAY(ctx, inout->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200205 LY_LIST_FOR_SAFE(inout->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100206 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200207 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200208 FREE_ARRAY(ctx, inout->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200209
210}
211
212static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100213lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200214{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100215 FREE_STRING(ctx, action->name);
216 FREE_STRING(ctx, action->dsc);
217 FREE_STRING(ctx, action->ref);
218 FREE_STRINGS(ctx, action->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200219 FREE_ARRAY(ctx, action->typedefs, lysp_tpdf_free);
220 FREE_ARRAY(ctx, action->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200221 FREE_MEMBER(ctx, action->input, lysp_action_inout_free);
222 FREE_MEMBER(ctx, action->output, lysp_action_inout_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200223 FREE_ARRAY(ctx, action->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200224}
225
226static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100227lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200228{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200229 struct lysp_node *node, *next;
230
Radek Krejci4f28eda2018-11-12 11:46:16 +0100231 FREE_STRING(ctx, notif->name);
232 FREE_STRING(ctx, notif->dsc);
233 FREE_STRING(ctx, notif->ref);
234 FREE_STRINGS(ctx, notif->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200235 FREE_ARRAY(ctx, notif->musts, lysp_restr_free);
236 FREE_ARRAY(ctx, notif->typedefs, lysp_tpdf_free);
237 FREE_ARRAY(ctx, notif->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200238 LY_LIST_FOR_SAFE(notif->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100239 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200240 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200241 FREE_ARRAY(ctx, notif->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200242}
243
244static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100245lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200246{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200247 struct lysp_node *node, *next;
248
Radek Krejci4f28eda2018-11-12 11:46:16 +0100249 FREE_STRING(ctx, grp->name);
250 FREE_STRING(ctx, grp->dsc);
251 FREE_STRING(ctx, grp->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200252 FREE_ARRAY(ctx, grp->typedefs, lysp_tpdf_free);
253 FREE_ARRAY(ctx, grp->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200254 LY_LIST_FOR_SAFE(grp->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100255 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200256 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200257 FREE_ARRAY(ctx, grp->actions, lysp_action_free);
258 FREE_ARRAY(ctx, grp->notifs, lysp_notif_free);
259 FREE_ARRAY(ctx, grp->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200260}
261
262static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100263lysp_when_free(struct ly_ctx *ctx, struct lysp_when *when)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200264{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100265 FREE_STRING(ctx, when->cond);
266 FREE_STRING(ctx, when->dsc);
267 FREE_STRING(ctx, when->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200268 FREE_ARRAY(ctx, when->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200269}
270
271static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100272lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200273{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200274 struct lysp_node *node, *next;
275
Radek Krejci4f28eda2018-11-12 11:46:16 +0100276 FREE_STRING(ctx, augment->nodeid);
277 FREE_STRING(ctx, augment->dsc);
278 FREE_STRING(ctx, augment->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200279 FREE_MEMBER(ctx, augment->when, lysp_when_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100280 FREE_STRINGS(ctx, augment->iffeatures);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200281 LY_LIST_FOR_SAFE(augment->child, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100282 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200283 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200284 FREE_ARRAY(ctx, augment->actions, lysp_action_free);
285 FREE_ARRAY(ctx, augment->notifs, lysp_notif_free);
286 FREE_ARRAY(ctx, augment->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200287}
288
289static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100290lysp_deviate_free(struct ly_ctx *ctx, struct lysp_deviate *d)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200291{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200292 struct lysp_deviate_add *add = (struct lysp_deviate_add*)d;
293 struct lysp_deviate_rpl *rpl = (struct lysp_deviate_rpl*)d;
294
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200295 FREE_ARRAY(ctx, d->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200296 switch(d->mod) {
297 case LYS_DEV_NOT_SUPPORTED:
298 /* nothing to do */
299 break;
300 case LYS_DEV_ADD:
301 case LYS_DEV_DELETE: /* compatible for dynamically allocated data */
Radek Krejci4f28eda2018-11-12 11:46:16 +0100302 FREE_STRING(ctx, add->units);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200303 FREE_ARRAY(ctx, add->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100304 FREE_STRINGS(ctx, add->uniques);
305 FREE_STRINGS(ctx, add->dflts);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200306 break;
307 case LYS_DEV_REPLACE:
308 FREE_MEMBER(ctx, rpl->type, lysp_type_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100309 FREE_STRING(ctx, rpl->units);
310 FREE_STRING(ctx, rpl->dflt);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200311 break;
312 default:
313 LOGINT(ctx);
314 break;
315 }
316}
317
318static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100319lysp_deviation_free(struct ly_ctx *ctx, struct lysp_deviation *dev)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200320{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200321 struct lysp_deviate *next, *iter;
322
Radek Krejci4f28eda2018-11-12 11:46:16 +0100323 FREE_STRING(ctx, dev->nodeid);
324 FREE_STRING(ctx, dev->dsc);
325 FREE_STRING(ctx, dev->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200326 LY_LIST_FOR_SAFE(dev->deviates, next, iter) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100327 lysp_deviate_free(ctx, iter);
Michal Vasko8447f6a2018-10-15 10:56:16 +0200328 free(iter);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200329 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200330 FREE_ARRAY(ctx, dev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200331}
332
333static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100334lysp_refine_free(struct ly_ctx *ctx, struct lysp_refine *ref)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200335{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100336 FREE_STRING(ctx, ref->nodeid);
337 FREE_STRING(ctx, ref->dsc);
338 FREE_STRING(ctx, ref->ref);
339 FREE_STRINGS(ctx, ref->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200340 FREE_ARRAY(ctx, ref->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100341 FREE_STRING(ctx, ref->presence);
342 FREE_STRINGS(ctx, ref->dflts);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200343 FREE_ARRAY(ctx, ref->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200344}
345
346static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100347lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200348{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200349 struct lysp_node *child, *next;
350
Radek Krejci4f28eda2018-11-12 11:46:16 +0100351 FREE_STRING(ctx, node->name);
352 FREE_STRING(ctx, node->dsc);
353 FREE_STRING(ctx, node->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200354 FREE_MEMBER(ctx, node->when, lysp_when_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100355 FREE_STRINGS(ctx, node->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200356 FREE_ARRAY(ctx, node->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200357
358 switch(node->nodetype) {
359 case LYS_CONTAINER:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200360 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100361 FREE_STRING(ctx, ((struct lysp_node_container*)node)->presence);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200362 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->typedefs, lysp_tpdf_free);
363 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200364 LY_LIST_FOR_SAFE(((struct lysp_node_container*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100365 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200366 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200367 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->actions, lysp_action_free);
368 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->notifs, lysp_notif_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200369 break;
370 case LYS_LEAF:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200371 FREE_ARRAY(ctx, ((struct lysp_node_leaf*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100372 lysp_type_free(ctx, &((struct lysp_node_leaf*)node)->type);
373 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->units);
374 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->dflt);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200375 break;
376 case LYS_LEAFLIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200377 FREE_ARRAY(ctx, ((struct lysp_node_leaflist*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100378 lysp_type_free(ctx, &((struct lysp_node_leaflist*)node)->type);
379 FREE_STRING(ctx, ((struct lysp_node_leaflist*)node)->units);
380 FREE_STRINGS(ctx, ((struct lysp_node_leaflist*)node)->dflts);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200381 break;
382 case LYS_LIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200383 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100384 FREE_STRING(ctx, ((struct lysp_node_list*)node)->key);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200385 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->typedefs, lysp_tpdf_free);
386 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200387 LY_LIST_FOR_SAFE(((struct lysp_node_list*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100388 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200389 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200390 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->actions, lysp_action_free);
391 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->notifs, lysp_notif_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100392 FREE_STRINGS(ctx, ((struct lysp_node_list*)node)->uniques);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200393 break;
394 case LYS_CHOICE:
395 LY_LIST_FOR_SAFE(((struct lysp_node_choice*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100396 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200397 }
Radek Krejci4f28eda2018-11-12 11:46:16 +0100398 FREE_STRING(ctx, ((struct lysp_node_choice*)node)->dflt);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200399 break;
400 case LYS_CASE:
401 LY_LIST_FOR_SAFE(((struct lysp_node_case*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100402 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200403 }
404 break;
405 case LYS_ANYDATA:
406 case LYS_ANYXML:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200407 FREE_ARRAY(ctx, ((struct lysp_node_anydata*)node)->musts, lysp_restr_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200408 break;
409 case LYS_USES:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200410 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->refines, lysp_refine_free);
411 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->augments, lysp_augment_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200412 break;
413 default:
414 LOGINT(ctx);
415 }
416
417 free(node);
418}
419
Radek Krejci4f28eda2018-11-12 11:46:16 +0100420API void
421lysp_module_free(struct lysp_module *module)
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200422{
423 struct ly_ctx *ctx;
Radek Krejci6f7feb62018-10-12 15:23:02 +0200424 struct lysp_node *node, *next;
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200425
426 LY_CHECK_ARG_RET(NULL, module,);
427 ctx = module->ctx;
428
Radek Krejci4f28eda2018-11-12 11:46:16 +0100429 FREE_STRING(ctx, module->name);
430 FREE_STRING(ctx, module->filepath);
431 FREE_STRING(ctx, module->ns); /* or belongs-to */
432 FREE_STRING(ctx, module->prefix);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200433
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200434 FREE_ARRAY(ctx, module->imports, lysp_import_free);
435 FREE_ARRAY(ctx, module->includes, lysp_include_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200436
Radek Krejci4f28eda2018-11-12 11:46:16 +0100437 FREE_STRING(ctx, module->org);
438 FREE_STRING(ctx, module->contact);
439 FREE_STRING(ctx, module->dsc);
440 FREE_STRING(ctx, module->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200441
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200442 FREE_ARRAY(ctx, module->revs, lysp_revision_free);
443 FREE_ARRAY(ctx, module->extensions, lysp_ext_free);
444 FREE_ARRAY(ctx, module->features, lysp_feature_free);
445 FREE_ARRAY(ctx, module->identities, lysp_ident_free);
446 FREE_ARRAY(ctx, module->typedefs, lysp_tpdf_free);
447 FREE_ARRAY(ctx, module->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200448 LY_LIST_FOR_SAFE(module->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100449 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200450 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200451 FREE_ARRAY(ctx, module->augments, lysp_augment_free);
452 FREE_ARRAY(ctx, module->rpcs, lysp_action_free);
453 FREE_ARRAY(ctx, module->notifs, lysp_notif_free);
454 FREE_ARRAY(ctx, module->deviations, lysp_deviation_free);
455 FREE_ARRAY(ctx, module->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200456
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200457 free(module);
458}
459
Radek Krejci151a5b72018-10-19 14:21:44 +0200460static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100461lysc_ext_instance_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
Radek Krejci478020e2018-10-30 16:02:14 +0100462{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100463 FREE_STRING(ctx, ext->argument);
Radek Krejci478020e2018-10-30 16:02:14 +0100464 FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free);
465}
466
467static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100468lysc_iffeature_free(struct ly_ctx *UNUSED(ctx), struct lysc_iffeature *iff)
Radek Krejci151a5b72018-10-19 14:21:44 +0200469{
Radek Krejci2c4e7172018-10-19 15:56:26 +0200470 LY_ARRAY_FREE(iff->features);
Radek Krejci151a5b72018-10-19 14:21:44 +0200471 free(iff->expr);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200472}
473
474static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100475lysc_import_free(struct ly_ctx *ctx, struct lysc_import *import)
Radek Krejci478020e2018-10-30 16:02:14 +0100476{
477 /* imported module is freed directly from the context's list */
Radek Krejci4f28eda2018-11-12 11:46:16 +0100478 FREE_STRING(ctx, import->prefix);
Radek Krejci478020e2018-10-30 16:02:14 +0100479 FREE_ARRAY(ctx, import->exts, lysc_ext_instance_free);
480}
481
482static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100483lysc_ident_free(struct ly_ctx *ctx, struct lysc_ident *ident)
Radek Krejci478020e2018-10-30 16:02:14 +0100484{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100485 FREE_STRING(ctx, ident->name);
Radek Krejci478020e2018-10-30 16:02:14 +0100486 FREE_ARRAY(ctx, ident->iffeatures, lysc_iffeature_free);
487 LY_ARRAY_FREE(ident->derived);
488 FREE_ARRAY(ctx, ident->exts, lysc_ext_instance_free);
489}
490
491static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100492lysc_feature_free(struct ly_ctx *ctx, struct lysc_feature *feat)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200493{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100494 FREE_STRING(ctx, feat->name);
Radek Krejci151a5b72018-10-19 14:21:44 +0200495 FREE_ARRAY(ctx, feat->iffeatures, lysc_iffeature_free);
Radek Krejci2c4e7172018-10-19 15:56:26 +0200496 LY_ARRAY_FREE(feat->depfeatures);
Radek Krejci478020e2018-10-30 16:02:14 +0100497 FREE_ARRAY(ctx, feat->exts, lysc_ext_instance_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200498}
499
Radek Krejci4f28eda2018-11-12 11:46:16 +0100500static void
501lysc_range_free(struct ly_ctx *ctx, struct lysc_range *range)
502{
503 LY_ARRAY_FREE(range->parts);
504 FREE_STRING(ctx, range->eapptag);
505 FREE_STRING(ctx, range->emsg);
506 FREE_ARRAY(ctx, range->exts, lysc_ext_instance_free);
507}
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100508
509static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100510lysc_type_free(struct ly_ctx *ctx, struct lysc_type *type)
511{
512 switch(type->basetype) {
513 case LY_TYPE_BINARY:
514 FREE_MEMBER(ctx, ((struct lysc_type_bin*)type)->length, lysc_range_free);
515 break;
516 }
517 FREE_ARRAY(ctx, type->exts, lysc_ext_instance_free);
518}
519
520static void lysc_node_free(struct ly_ctx *ctx, struct lysc_node *node);
521
522static void
523lysc_node_container_free(struct ly_ctx *ctx, struct lysc_node_container *node)
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100524{
525 struct lysc_node *child, *child_next;
526
527 LY_LIST_FOR_SAFE(node->child, child_next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100528 lysc_node_free(ctx, child);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100529 }
530}
531
532static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100533lysc_node_leaf_free(struct ly_ctx *ctx, struct lysc_node_leaf *node)
534{
535 FREE_MEMBER(ctx, node->type, lysc_type_free);
536}
537
538static void
539lysc_node_free(struct ly_ctx *ctx, struct lysc_node *node)
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100540{
541 /* common part */
Radek Krejci4f28eda2018-11-12 11:46:16 +0100542 FREE_STRING(ctx, node->name);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100543
544 /* nodetype-specific part */
545 switch(node->nodetype) {
546 case LYS_CONTAINER:
Radek Krejci4f28eda2018-11-12 11:46:16 +0100547 lysc_node_container_free(ctx, (struct lysc_node_container*)node);
548 break;
549 case LYS_LEAF:
550 lysc_node_leaf_free(ctx, (struct lysc_node_leaf*)node);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100551 break;
552 default:
553 LOGINT(ctx);
554 }
555
556 free(node);
557}
558
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200559static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100560lysc_module_free_(struct lysc_module *module)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200561{
562 struct ly_ctx *ctx;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100563 struct lysc_node *node, *node_next;
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200564
565 LY_CHECK_ARG_RET(NULL, module,);
566 ctx = module->ctx;
567
Radek Krejci4f28eda2018-11-12 11:46:16 +0100568 FREE_STRING(ctx, module->name);
569 FREE_STRING(ctx, module->ns);
570 FREE_STRING(ctx, module->prefix);
571 FREE_STRING(ctx, module->revision);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200572
Radek Krejci478020e2018-10-30 16:02:14 +0100573 FREE_ARRAY(ctx, module->imports, lysc_import_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200574 FREE_ARRAY(ctx, module->features, lysc_feature_free);
Radek Krejci478020e2018-10-30 16:02:14 +0100575 FREE_ARRAY(ctx, module->identities, lysc_ident_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200576
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100577 LY_LIST_FOR_SAFE(module->data, node_next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100578 lysc_node_free(ctx, node);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100579 }
580
Radek Krejci478020e2018-10-30 16:02:14 +0100581 FREE_ARRAY(ctx, module->exts, lysc_ext_instance_free);
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200582
583 free(module);
584}
Radek Krejci70853c52018-10-15 14:46:16 +0200585
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200586API void
Radek Krejci86d106e2018-10-18 09:53:19 +0200587lysc_module_free(struct lysc_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200588{
Radek Krejci151a5b72018-10-19 14:21:44 +0200589 if (module) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100590 lysc_module_free_(module);
Radek Krejci151a5b72018-10-19 14:21:44 +0200591 }
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200592}
593
Radek Krejci86d106e2018-10-18 09:53:19 +0200594void
595lys_module_free(struct lys_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejci70853c52018-10-15 14:46:16 +0200596{
Radek Krejci86d106e2018-10-18 09:53:19 +0200597 if (!module) {
598 return;
599 }
Radek Krejci70853c52018-10-15 14:46:16 +0200600
Radek Krejci86d106e2018-10-18 09:53:19 +0200601 lysc_module_free(module->compiled, private_destructor);
602 lysp_module_free(module->parsed);
603 free(module);
604}
605
Radek Krejci151a5b72018-10-19 14:21:44 +0200606struct iff_stack {
607 int size;
608 int index; /* first empty item */
609 uint8_t *stack;
610};
611
Radek Krejci86d106e2018-10-18 09:53:19 +0200612static LY_ERR
Radek Krejci151a5b72018-10-19 14:21:44 +0200613iff_stack_push(struct iff_stack *stack, uint8_t value)
Radek Krejci86d106e2018-10-18 09:53:19 +0200614{
Radek Krejci151a5b72018-10-19 14:21:44 +0200615 if (stack->index == stack->size) {
616 stack->size += 4;
617 stack->stack = ly_realloc(stack->stack, stack->size * sizeof *stack->stack);
618 LY_CHECK_ERR_RET(!stack->stack, LOGMEM(NULL); stack->size = 0, LY_EMEM);
Radek Krejci70853c52018-10-15 14:46:16 +0200619 }
Radek Krejci151a5b72018-10-19 14:21:44 +0200620 stack->stack[stack->index++] = value;
Radek Krejci70853c52018-10-15 14:46:16 +0200621 return LY_SUCCESS;
622}
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200623
Radek Krejci151a5b72018-10-19 14:21:44 +0200624static uint8_t
625iff_stack_pop(struct iff_stack *stack)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200626{
Radek Krejci151a5b72018-10-19 14:21:44 +0200627 stack->index--;
628 return stack->stack[stack->index];
629}
630
631static void
632iff_stack_clean(struct iff_stack *stack)
633{
634 stack->size = 0;
635 free(stack->stack);
636}
637
638static void
639iff_setop(uint8_t *list, uint8_t op, int pos)
640{
641 uint8_t *item;
642 uint8_t mask = 3;
643
644 assert(pos >= 0);
645 assert(op <= 3); /* max 2 bits */
646
647 item = &list[pos / 4];
648 mask = mask << 2 * (pos % 4);
649 *item = (*item) & ~mask;
650 *item = (*item) | (op << 2 * (pos % 4));
651}
652
653static uint8_t
654iff_getop(uint8_t *list, int pos)
655{
656 uint8_t *item;
657 uint8_t mask = 3, result;
658
659 assert(pos >= 0);
660
661 item = &list[pos / 4];
662 result = (*item) & (mask << 2 * (pos % 4));
663 return result >> 2 * (pos % 4);
664}
665
666#define LYS_IFF_LP 0x04 /* ( */
667#define LYS_IFF_RP 0x08 /* ) */
668
669API int
670lysc_feature_value(const struct lysc_feature *feature)
671{
672 LY_CHECK_ARG_RET(NULL, feature, -1);
673 return feature->flags & LYS_FENABLED ? 1 : 0;
674}
675
676static struct lysc_feature *
677lysc_feature_find(struct lysc_module *mod, const char *name, size_t len)
678{
679 size_t i;
680 struct lysc_feature *f;
681
682 for (i = 0; i < len; ++i) {
683 if (name[i] == ':') {
684 /* we have a prefixed feature */
Radek Krejcibbe09a92018-11-08 09:36:54 +0100685 mod = lysc_module_find_prefix(mod, name, i);
Radek Krejci151a5b72018-10-19 14:21:44 +0200686 LY_CHECK_RET(!mod, NULL);
687
688 name = &name[i + 1];
689 len = len - i - 1;
690 }
691 }
692
693 /* we have the correct module, get the feature */
694 LY_ARRAY_FOR(mod->features, i) {
Radek Krejci2c4e7172018-10-19 15:56:26 +0200695 f = &mod->features[i];
Radek Krejci151a5b72018-10-19 14:21:44 +0200696 if (!strncmp(f->name, name, len) && f->name[len] == '\0') {
697 return f;
698 }
699 }
700
701 return NULL;
702}
703
704static int
705lysc_iffeature_value_(const struct lysc_iffeature *iff, int *index_e, int *index_f)
706{
707 uint8_t op;
708 int a, b;
709
710 op = iff_getop(iff->expr, *index_e);
711 (*index_e)++;
712
713 switch (op) {
714 case LYS_IFF_F:
715 /* resolve feature */
Radek Krejci2c4e7172018-10-19 15:56:26 +0200716 return lysc_feature_value(iff->features[(*index_f)++]);
Radek Krejci151a5b72018-10-19 14:21:44 +0200717 case LYS_IFF_NOT:
718 /* invert result */
719 return lysc_iffeature_value_(iff, index_e, index_f) ? 0 : 1;
720 case LYS_IFF_AND:
721 case LYS_IFF_OR:
722 a = lysc_iffeature_value_(iff, index_e, index_f);
723 b = lysc_iffeature_value_(iff, index_e, index_f);
724 if (op == LYS_IFF_AND) {
725 return a && b;
726 } else { /* LYS_IFF_OR */
727 return a || b;
728 }
729 }
730
731 return 0;
732}
733
734API int
735lysc_iffeature_value(const struct lysc_iffeature *iff)
736{
737 int index_e = 0, index_f = 0;
738
739 LY_CHECK_ARG_RET(NULL, iff, -1);
740
741 if (iff->expr) {
742 return lysc_iffeature_value_(iff, &index_e, &index_f);
743 }
744 return 0;
745}
746
747/*
748 * op: 1 - enable, 0 - disable
749 */
750/**
751 * @brief Enable/Disable the specified feature in the module.
752 *
753 * If the feature is already set to the desired value, LY_SUCCESS is returned.
754 * By changing the feature, also all the feature which depends on it via their
755 * if-feature statements are again evaluated (disabled if a if-feature statemen
756 * evaluates to false).
757 *
758 * @param[in] mod Compiled module where to set (search for) the feature.
759 * @param[in] name Name of the feature to set. Asterisk ('*') can be used to
760 * set all the features in the module.
761 * @param[in] value Desired value of the feature: 1 (enable) or 0 (disable).
762 * @return LY_ERR value.
763 */
764static LY_ERR
765lys_feature_change(const struct lysc_module *mod, const char *name, int value)
766{
767 int all = 0;
Radek Krejcica3db002018-11-01 10:31:01 +0100768 unsigned int u, changed_count, disabled_count;
Radek Krejci151a5b72018-10-19 14:21:44 +0200769 struct lysc_feature *f, **df;
770 struct lysc_iffeature *iff;
771 struct ly_set *changed;
772
773 if (!mod->features) {
774 LOGERR(mod->ctx, LY_EINVAL, "Unable to switch feature since the module \"%s\" has no features.", mod->name);
775 return LY_EINVAL;
776 }
777
778 if (!strcmp(name, "*")) {
779 /* enable all */
780 all = 1;
781 }
782 changed = ly_set_new();
Radek Krejcica3db002018-11-01 10:31:01 +0100783 changed_count = 0;
Radek Krejci151a5b72018-10-19 14:21:44 +0200784
Radek Krejcica3db002018-11-01 10:31:01 +0100785run:
786 for (disabled_count = u = 0; u < LY_ARRAY_SIZE(mod->features); ++u) {
Radek Krejci2c4e7172018-10-19 15:56:26 +0200787 f = &mod->features[u];
Radek Krejci151a5b72018-10-19 14:21:44 +0200788 if (all || !strcmp(f->name, name)) {
789 if ((value && (f->flags & LYS_FENABLED)) || (!value && !(f->flags & LYS_FENABLED))) {
790 if (all) {
791 /* skip already set features */
792 continue;
793 } else {
794 /* feature already set correctly */
795 ly_set_free(changed, NULL);
796 return LY_SUCCESS;
797 }
798 }
799
800 if (value) { /* enable */
801 /* check referenced features if they are enabled */
802 LY_ARRAY_FOR(f->iffeatures, struct lysc_iffeature, iff) {
803 if (!lysc_iffeature_value(iff)) {
804 if (all) {
Radek Krejcica3db002018-11-01 10:31:01 +0100805 ++disabled_count;
Radek Krejci151a5b72018-10-19 14:21:44 +0200806 goto next;
807 } else {
808 LOGERR(mod->ctx, LY_EDENIED,
809 "Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
810 f->name);
811 ly_set_free(changed, NULL);
812 return LY_EDENIED;
813 }
814 }
815 }
816 /* enable the feature */
817 f->flags |= LYS_FENABLED;
818 } else { /* disable */
819 /* disable the feature */
820 f->flags &= ~LYS_FENABLED;
821 }
822
823 /* remember the changed feature */
824 ly_set_add(changed, f, LY_SET_OPT_USEASLIST);
825
826 if (!all) {
827 /* stop in case changing a single feature */
828 break;
829 }
830 }
831next:
832 ;
833 }
834
835 if (!all && !changed->count) {
836 LOGERR(mod->ctx, LY_EINVAL, "Feature \"%s\" not found in module \"%s\".", name, mod->name);
837 ly_set_free(changed, NULL);
838 return LY_EINVAL;
839 }
840
Radek Krejcica3db002018-11-01 10:31:01 +0100841 if (value && all && disabled_count) {
842 if (changed_count == changed->count) {
843 /* no change in last run -> not able to enable all ... */
844 /* ... print errors */
845 for (u = 0; disabled_count && u < LY_ARRAY_SIZE(mod->features); ++u) {
846 if (!(mod->features[u].flags & LYS_FENABLED)) {
847 LOGERR(mod->ctx, LY_EDENIED,
848 "Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
849 mod->features[u].name);
850 --disabled_count;
851 }
852 }
853 /* ... restore the original state */
854 for (u = 0; u < changed->count; ++u) {
855 f = changed->objs[u];
856 /* re-disable the feature */
857 f->flags &= ~LYS_FENABLED;
858 }
859
860 ly_set_free(changed, NULL);
861 return LY_EDENIED;
862 } else {
863 /* we did some change in last run, try it again */
864 changed_count = changed->count;
865 goto run;
866 }
867 }
868
Radek Krejci151a5b72018-10-19 14:21:44 +0200869 /* reflect change(s) in the dependent features */
870 for (u = 0; u < changed->count; ++u) {
871 /* If a dependent feature is enabled, it can be now changed by the change (to false) of the value of
872 * its if-feature statements. The reverse logic, automatically enable feature when its feature is enabled
873 * is not done - by default, features are disabled and must be explicitely enabled. */
874 f = changed->objs[u];
875 LY_ARRAY_FOR(f->depfeatures, struct lysc_feature*, df) {
876 if (!((*df)->flags & LYS_FENABLED)) {
877 /* not enabled, nothing to do */
878 continue;
879 }
880 /* check the feature's if-features which could change by the previous change of our feature */
881 LY_ARRAY_FOR((*df)->iffeatures, struct lysc_iffeature, iff) {
882 if (!lysc_iffeature_value(iff)) {
883 /* the feature must be disabled now */
884 (*df)->flags &= ~LYS_FENABLED;
885 /* add the feature into the list of changed features */
886 ly_set_add(changed, *df, LY_SET_OPT_USEASLIST);
887 break;
888 }
889 }
890 }
891 }
892
893 ly_set_free(changed, NULL);
894 return LY_SUCCESS;
895}
896
897API LY_ERR
898lys_feature_enable(struct lys_module *module, const char *feature)
899{
900 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, LY_EINVAL);
901
902 return lys_feature_change(module->compiled, feature, 1);
903}
904
905API LY_ERR
906lys_feature_disable(struct lys_module *module, const char *feature)
907{
908 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, LY_EINVAL);
909
910 return lys_feature_change(module->compiled, feature, 0);
911}
912
913API int
914lys_feature_value(const struct lys_module *module, const char *feature)
915{
916 struct lysc_feature *f;
917 struct lysc_module *mod;
918 unsigned int u;
919
920 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, -1);
921 mod = module->compiled;
922
923 /* search for the specified feature */
924 for (u = 0; u < LY_ARRAY_SIZE(mod->features); ++u) {
Radek Krejci2c4e7172018-10-19 15:56:26 +0200925 f = &mod->features[u];
Radek Krejci151a5b72018-10-19 14:21:44 +0200926 if (!strcmp(f->name, feature)) {
927 if (f->flags & LYS_FENABLED) {
928 return 1;
929 } else {
930 return 0;
931 }
932 }
933 }
934
935 /* feature definition not found */
936 return -1;
937}
938
939static LY_ERR
Radek Krejci4f28eda2018-11-12 11:46:16 +0100940lys_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 +0200941{
Radek Krejcice8c1592018-10-29 15:35:51 +0100942 const char *name;
943 unsigned int u;
944 const struct lys_module *mod;
Radek Krejci4f28eda2018-11-12 11:46:16 +0100945 struct lysp_ext *edef = NULL;
Radek Krejcice8c1592018-10-29 15:35:51 +0100946
Radek Krejci4f28eda2018-11-12 11:46:16 +0100947 ext->argument = lydict_insert(ctx->ctx, ext_p->argument, 0);
Radek Krejcice8c1592018-10-29 15:35:51 +0100948 ext->insubstmt = ext_p->insubstmt;
949 ext->insubstmt_index = ext_p->insubstmt_index;
950
951 /* get module where the extension definition should be placed */
952 for (u = 0; ext_p->name[u] != ':'; ++u);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100953 mod = lys_module_find_prefix(ctx->mod, ext_p->name, u);
954 LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcice8c1592018-10-29 15:35:51 +0100955 "Invalid prefix \"%.*s\" used for extension instance identifier.", u, ext_p->name),
956 LY_EVALID);
957 LY_CHECK_ERR_RET(!mod->parsed->extensions,
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100958 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcice8c1592018-10-29 15:35:51 +0100959 "Extension instance \"%s\" refers \"%s\" module that does not contain extension definitions.",
960 ext_p->name, mod->parsed->name),
961 LY_EVALID);
962 name = &ext_p->name[u + 1];
963 /* find the extension definition there */
964 for (ext = NULL, u = 0; u < LY_ARRAY_SIZE(mod->parsed->extensions); ++u) {
965 if (!strcmp(name, mod->parsed->extensions[u].name)) {
966 edef = &mod->parsed->extensions[u];
967 break;
968 }
969 }
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100970 LY_CHECK_ERR_RET(!edef, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcice8c1592018-10-29 15:35:51 +0100971 "Extension definition of extension instance \"%s\" not found.", ext_p->name),
972 LY_EVALID);
973 /* TODO plugins */
974
975 return LY_SUCCESS;
976}
977
Radek Krejcice8c1592018-10-29 15:35:51 +0100978static LY_ERR
979lys_compile_iffeature(struct lysc_ctx *ctx, const char **value, int UNUSED(options), struct lysc_iffeature *iff)
980{
981 const char *c = *value;
Radek Krejci151a5b72018-10-19 14:21:44 +0200982 int r, rc = EXIT_FAILURE;
983 int i, j, last_not, checkversion = 0;
984 unsigned int f_size = 0, expr_size = 0, f_exp = 1;
985 uint8_t op;
986 struct iff_stack stack = {0, 0, NULL};
Radek Krejcice8c1592018-10-29 15:35:51 +0100987 struct lysc_feature *f;
Radek Krejci151a5b72018-10-19 14:21:44 +0200988
989 assert(c);
990
991 /* pre-parse the expression to get sizes for arrays, also do some syntax checks of the expression */
992 for (i = j = last_not = 0; c[i]; i++) {
993 if (c[i] == '(') {
994 j++;
995 checkversion = 1;
996 continue;
997 } else if (c[i] == ')') {
998 j--;
999 continue;
1000 } else if (isspace(c[i])) {
1001 checkversion = 1;
1002 continue;
1003 }
1004
1005 if (!strncmp(&c[i], "not", r = 3) || !strncmp(&c[i], "and", r = 3) || !strncmp(&c[i], "or", r = 2)) {
1006 if (c[i + r] == '\0') {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001007 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001008 "Invalid value \"%s\" of if-feature - unexpected end of expression.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001009 return LY_EVALID;
1010 } else if (!isspace(c[i + r])) {
1011 /* feature name starting with the not/and/or */
1012 last_not = 0;
1013 f_size++;
1014 } else if (c[i] == 'n') { /* not operation */
1015 if (last_not) {
1016 /* double not */
1017 expr_size = expr_size - 2;
1018 last_not = 0;
1019 } else {
1020 last_not = 1;
1021 }
1022 } else { /* and, or */
1023 f_exp++;
1024 /* not a not operation */
1025 last_not = 0;
1026 }
1027 i += r;
1028 } else {
1029 f_size++;
1030 last_not = 0;
1031 }
1032 expr_size++;
1033
1034 while (!isspace(c[i])) {
1035 if (!c[i] || c[i] == ')') {
1036 i--;
1037 break;
1038 }
1039 i++;
1040 }
1041 }
1042 if (j || f_exp != f_size) {
1043 /* not matching count of ( and ) */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001044 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001045 "Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001046 return LY_EVALID;
1047 }
1048
1049 if (checkversion || expr_size > 1) {
1050 /* check that we have 1.1 module */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001051 if (ctx->mod->compiled->version != LYS_VERSION_1_1) {
1052 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001053 "Invalid value \"%s\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001054 return LY_EVALID;
1055 }
1056 }
1057
1058 /* allocate the memory */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001059 LY_ARRAY_CREATE_RET(ctx->ctx, iff->features, f_size, LY_EMEM);
Radek Krejci151a5b72018-10-19 14:21:44 +02001060 iff->expr = calloc((j = (expr_size / 4) + ((expr_size % 4) ? 1 : 0)), sizeof *iff->expr);
Radek Krejci151a5b72018-10-19 14:21:44 +02001061 stack.stack = malloc(expr_size * sizeof *stack.stack);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001062 LY_CHECK_ERR_GOTO(!stack.stack || !iff->expr, LOGMEM(ctx->ctx), error);
Radek Krejci151a5b72018-10-19 14:21:44 +02001063
Radek Krejci151a5b72018-10-19 14:21:44 +02001064 stack.size = expr_size;
1065 f_size--; expr_size--; /* used as indexes from now */
1066
1067 for (i--; i >= 0; i--) {
1068 if (c[i] == ')') {
1069 /* push it on stack */
1070 iff_stack_push(&stack, LYS_IFF_RP);
1071 continue;
1072 } else if (c[i] == '(') {
1073 /* pop from the stack into result all operators until ) */
1074 while((op = iff_stack_pop(&stack)) != LYS_IFF_RP) {
1075 iff_setop(iff->expr, op, expr_size--);
1076 }
1077 continue;
1078 } else if (isspace(c[i])) {
1079 continue;
1080 }
1081
1082 /* end of operator or operand -> find beginning and get what is it */
1083 j = i + 1;
1084 while (i >= 0 && !isspace(c[i]) && c[i] != '(') {
1085 i--;
1086 }
1087 i++; /* go back by one step */
1088
1089 if (!strncmp(&c[i], "not", 3) && isspace(c[i + 3])) {
1090 if (stack.index && stack.stack[stack.index - 1] == LYS_IFF_NOT) {
1091 /* double not */
1092 iff_stack_pop(&stack);
1093 } else {
1094 /* not has the highest priority, so do not pop from the stack
1095 * as in case of AND and OR */
1096 iff_stack_push(&stack, LYS_IFF_NOT);
1097 }
1098 } else if (!strncmp(&c[i], "and", 3) && isspace(c[i + 3])) {
1099 /* as for OR - pop from the stack all operators with the same or higher
1100 * priority and store them to the result, then push the AND to the stack */
1101 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_AND) {
1102 op = iff_stack_pop(&stack);
1103 iff_setop(iff->expr, op, expr_size--);
1104 }
1105 iff_stack_push(&stack, LYS_IFF_AND);
1106 } else if (!strncmp(&c[i], "or", 2) && isspace(c[i + 2])) {
1107 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_OR) {
1108 op = iff_stack_pop(&stack);
1109 iff_setop(iff->expr, op, expr_size--);
1110 }
1111 iff_stack_push(&stack, LYS_IFF_OR);
1112 } else {
1113 /* feature name, length is j - i */
1114
1115 /* add it to the expression */
1116 iff_setop(iff->expr, LYS_IFF_F, expr_size--);
1117
1118 /* now get the link to the feature definition */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001119 f = lysc_feature_find(ctx->mod->compiled, &c[i], j - i);
Radek Krejci151a5b72018-10-19 14:21:44 +02001120 LY_CHECK_ERR_GOTO(!f,
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001121 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001122 "Invalid value \"%s\" of if-feature - unable to find feature \"%.*s\".", *value, j - i, &c[i]);
Radek Krejci87616bb2018-10-31 13:30:52 +01001123 rc = LY_EVALID,
Radek Krejci151a5b72018-10-19 14:21:44 +02001124 error)
Radek Krejci2c4e7172018-10-19 15:56:26 +02001125 iff->features[f_size] = f;
1126 LY_ARRAY_INCREMENT(iff->features);
Radek Krejci151a5b72018-10-19 14:21:44 +02001127 f_size--;
1128 }
1129 }
1130 while (stack.index) {
1131 op = iff_stack_pop(&stack);
1132 iff_setop(iff->expr, op, expr_size--);
1133 }
1134
1135 if (++expr_size || ++f_size) {
1136 /* not all expected operators and operands found */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001137 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001138 "Invalid value \"%s\" of if-feature - processing error.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001139 rc = LY_EINT;
1140 } else {
1141 rc = LY_SUCCESS;
1142 }
1143
1144error:
1145 /* cleanup */
1146 iff_stack_clean(&stack);
1147
1148 return rc;
1149}
1150
1151static LY_ERR
Radek Krejci4f28eda2018-11-12 11:46:16 +01001152lys_compile_when(struct lysc_ctx *ctx, struct lysp_when *when_p, int options, struct lysc_when *when)
1153{
1154 unsigned int u;
1155 LY_ERR ret = LY_SUCCESS;
1156
1157 when->cond = lyxp_expr_parse(ctx->ctx, when_p->cond);
1158 LY_CHECK_ERR_GOTO(!when->cond, ret = ly_errcode(ctx->ctx), done);
1159 COMPILE_ARRAY_GOTO(ctx, when_p->exts, when->exts, options, u, lys_compile_ext, ret, done);
1160
1161done:
1162 return ret;
1163}
1164
1165static LY_ERR
1166lys_compile_must(struct lysc_ctx *ctx, struct lysp_restr *must_p, int options, struct lysc_must *must)
1167{
1168 unsigned int u;
1169 LY_ERR ret = LY_SUCCESS;
1170
1171 must->cond = lyxp_expr_parse(ctx->ctx, must_p->arg);
1172 LY_CHECK_ERR_GOTO(!must->cond, ret = ly_errcode(ctx->ctx), done);
1173
1174 must->eapptag = lydict_insert(ctx->ctx, must_p->eapptag, 0);
1175 must->emsg = lydict_insert(ctx->ctx, must_p->emsg, 0);
1176 COMPILE_ARRAY_GOTO(ctx, must_p->exts, must->exts, options, u, lys_compile_ext, ret, done);
1177
1178done:
1179 return ret;
1180}
1181
1182static LY_ERR
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001183lys_compile_import(struct lysc_ctx *ctx, struct lysp_import *imp_p, int options, struct lysc_import *imp)
1184{
Radek Krejcice8c1592018-10-29 15:35:51 +01001185 unsigned int u;
Radek Krejcif8f882a2018-10-31 14:51:15 +01001186 struct lys_module *mod = NULL;
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001187 struct lysc_module *comp;
Radek Krejcice8c1592018-10-29 15:35:51 +01001188 LY_ERR ret = LY_SUCCESS;
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001189
Radek Krejci4f28eda2018-11-12 11:46:16 +01001190 imp->prefix = lydict_insert(ctx->ctx, imp_p->prefix, 0);
Radek Krejcice8c1592018-10-29 15:35:51 +01001191 COMPILE_ARRAY_GOTO(ctx, imp_p->exts, imp->exts, options, u, lys_compile_ext, ret, done);
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001192 imp->module = imp_p->module;
1193
1194 /* make sure that we have both versions (lysp_ and lysc_) of the imported module. To import groupings or
1195 * typedefs, the lysp_ is needed. To augment or deviate imported module, we need the lysc_ structure */
1196 if (!imp->module->parsed) {
1197 comp = imp->module->compiled;
1198 /* try to get filepath from the compiled version */
1199 if (comp->filepath) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001200 mod = (struct lys_module*)lys_parse_path(ctx->ctx, comp->filepath,
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001201 !strcmp(&comp->filepath[strlen(comp->filepath - 4)], ".yin") ? LYS_IN_YIN : LYS_IN_YANG);
1202 if (mod != imp->module) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001203 LOGERR(ctx->ctx, LY_EINT, "Filepath \"%s\" of the module \"%s\" does not match.",
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001204 comp->filepath, comp->name);
1205 mod = NULL;
1206 }
1207 }
1208 if (!mod) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001209 if (lysp_load_module(ctx->ctx, comp->name, comp->revision, 0, 1, &mod)) {
1210 LOGERR(ctx->ctx, LY_ENOTFOUND, "Unable to reload \"%s\" module to import it into \"%s\", source data not found.",
1211 comp->name, ctx->mod->compiled->name);
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001212 return LY_ENOTFOUND;
1213 }
1214 }
1215 } else if (!imp->module->compiled) {
Radek Krejcif8f882a2018-10-31 14:51:15 +01001216 return lys_compile(imp->module, options);
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001217 }
1218
Radek Krejcice8c1592018-10-29 15:35:51 +01001219done:
1220 return ret;
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001221}
1222
1223static LY_ERR
Radek Krejci2a408df2018-10-29 16:32:26 +01001224lys_compile_identity(struct lysc_ctx *ctx, struct lysp_ident *ident_p, int options, struct lysc_ident *ident)
1225{
1226 unsigned int u;
1227 LY_ERR ret = LY_SUCCESS;
1228
Radek Krejci4f28eda2018-11-12 11:46:16 +01001229 ident->name = lydict_insert(ctx->ctx, ident_p->name, 0);
Radek Krejci2a408df2018-10-29 16:32:26 +01001230 COMPILE_ARRAY_GOTO(ctx, ident_p->iffeatures, ident->iffeatures, options, u, lys_compile_iffeature, ret, done);
1231 /* backlings (derived) can be added no sooner than when all the identities in the current module are present */
1232 COMPILE_ARRAY_GOTO(ctx, ident_p->exts, ident->exts, options, u, lys_compile_ext, ret, done);
1233 ident->flags = ident_p->flags;
1234
1235done:
1236 return ret;
1237}
1238
1239static LY_ERR
1240lys_compile_identities_derived(struct lysc_ctx *ctx, struct lysp_ident *idents_p, struct lysc_ident *idents)
1241{
1242 unsigned int i, u, v;
1243 const char *s, *name;
1244 struct lysc_module *mod;
1245 struct lysc_ident **dident;
1246
1247 for (i = 0; i < LY_ARRAY_SIZE(idents_p); ++i) {
Radek Krejci478020e2018-10-30 16:02:14 +01001248 if (!idents_p[i].bases) {
1249 continue;
1250 }
Radek Krejci2a408df2018-10-29 16:32:26 +01001251 for (u = 0; u < LY_ARRAY_SIZE(idents_p[i].bases); ++u) {
1252 s = strchr(idents_p[i].bases[u], ':');
1253 if (s) {
1254 /* prefixed identity */
1255 name = &s[1];
Radek Krejcibbe09a92018-11-08 09:36:54 +01001256 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 +01001257 } else {
1258 name = idents_p[i].bases[u];
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001259 mod = ctx->mod->compiled;
Radek Krejci2a408df2018-10-29 16:32:26 +01001260 }
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001261 LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejci2a408df2018-10-29 16:32:26 +01001262 "Invalid prefix used for base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
1263 LY_EVALID);
1264 if (mod->identities) {
1265 for (v = 0; v < LY_ARRAY_SIZE(mod->identities); ++v) {
1266 if (!strcmp(name, mod->identities[v].name)) {
1267 /* we have match! store the backlink */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001268 LY_ARRAY_NEW_RET(ctx->ctx, mod->identities[v].derived, dident, LY_EMEM);
Radek Krejci2a408df2018-10-29 16:32:26 +01001269 *dident = &idents[i];
1270 break;
1271 }
1272 }
1273 }
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001274 LY_CHECK_ERR_RET(!dident, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejci2a408df2018-10-29 16:32:26 +01001275 "Unable to find base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
1276 LY_EVALID);
1277 }
1278 }
1279 return LY_SUCCESS;
1280}
1281
1282static LY_ERR
Radek Krejci151a5b72018-10-19 14:21:44 +02001283lys_compile_feature(struct lysc_ctx *ctx, struct lysp_feature *feature_p, int options, struct lysc_feature *feature)
1284{
Radek Krejcice8c1592018-10-29 15:35:51 +01001285 unsigned int u, v;
1286 LY_ERR ret = LY_SUCCESS;
1287 struct lysc_feature **df;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001288
Radek Krejci4f28eda2018-11-12 11:46:16 +01001289 feature->name = lydict_insert(ctx->ctx, feature_p->name, 0);
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001290 feature->flags = feature_p->flags;
1291
Radek Krejcice8c1592018-10-29 15:35:51 +01001292 COMPILE_ARRAY_GOTO(ctx, feature_p->exts, feature->exts, options, u, lys_compile_ext, ret, done);
1293 COMPILE_ARRAY_GOTO(ctx, feature_p->iffeatures, feature->iffeatures, options, u, lys_compile_iffeature, ret, done);
1294 if (feature->iffeatures) {
1295 for (u = 0; u < LY_ARRAY_SIZE(feature->iffeatures); ++u) {
1296 if (feature->iffeatures[u].features) {
1297 for (v = 0; v < LY_ARRAY_SIZE(feature->iffeatures[u].features); ++v) {
1298 /* add itself into the dependants list */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001299 LY_ARRAY_NEW_RET(ctx->ctx, feature->iffeatures[u].features[v]->depfeatures, df, LY_EMEM);
Radek Krejcice8c1592018-10-29 15:35:51 +01001300 *df = feature;
1301 }
1302 /* TODO check for circular dependency */
1303 }
Radek Krejci151a5b72018-10-19 14:21:44 +02001304 }
Radek Krejci86d106e2018-10-18 09:53:19 +02001305 }
Radek Krejcice8c1592018-10-29 15:35:51 +01001306done:
1307 return ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001308}
1309
Radek Krejci4f28eda2018-11-12 11:46:16 +01001310static LY_ERR
1311range_part_check_value_syntax(struct lysc_ctx *ctx, LY_DATA_TYPE basetype, const char *value, size_t *len, char **valcopy)
1312{
1313 size_t fraction = 0;
1314 *len = 0;
1315
1316 assert(value);
1317 /* parse value */
1318 if (!isdigit(value[*len]) && (value[*len] != '-') && (value[*len] != '+')) {
1319 return LY_EVALID;
1320 }
1321
1322 if ((value[*len] == '-') || (value[*len] == '+')) {
1323 ++(*len);
1324 }
1325
1326 while (isdigit(value[*len])) {
1327 ++(*len);
1328 }
1329
1330 if ((basetype != LY_TYPE_DEC64) || (value[*len] != '.') || !isdigit(value[*len + 1])) {
1331 *valcopy = strndup(value, *len);
1332 return LY_SUCCESS;
1333 }
1334 fraction = *len;
1335
1336 ++(*len);
1337 while (isdigit(value[*len])) {
1338 ++(*len);
1339 }
1340
1341 if (fraction) {
1342 *valcopy = malloc(((*len) - 1) * sizeof **valcopy);
1343 LY_CHECK_ERR_RET(!(*valcopy), LOGMEM(ctx->ctx), LY_EMEM);
1344
1345 *valcopy[(*len) - 1] = '\0';
1346 memcpy(&(*valcopy)[0], &value[0], fraction);
1347 memcpy(&(*valcopy)[fraction], &value[fraction + 1], (*len) - 1 - (fraction + 1));
1348 }
1349 return LY_SUCCESS;
1350}
1351
1352static LY_ERR
1353range_part_check_ascendance(int unsigned_value, int64_t value, int64_t prev_value)
1354{
1355 if (unsigned_value) {
1356 if ((uint64_t)prev_value >= (uint64_t)value) {
1357 return LY_EEXIST;
1358 }
1359 } else {
1360 if (prev_value >= value) {
1361 return LY_EEXIST;
1362 }
1363 }
1364 return LY_SUCCESS;
1365}
1366
1367static LY_ERR
1368range_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,
1369 const char **value)
1370{
1371 LY_ERR ret = LY_SUCCESS;
1372 char *valcopy = NULL;
1373 size_t len;
1374
1375 if (value) {
1376 ret = range_part_check_value_syntax(ctx, basetype, *value, &len, &valcopy);
1377 LY_CHECK_GOTO(ret, error);
1378 }
1379
1380 switch (basetype) {
1381 case LY_TYPE_BINARY: /* length */
1382 if (valcopy) {
1383 ret = ly_parse_uint(valcopy, __UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
1384 } else if (max) {
1385 part->max_u64 = __UINT64_C(18446744073709551615);
1386 } else {
1387 part->min_u64 = __UINT64_C(0);
1388 }
1389 if (!first) {
1390 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1391 }
1392 break;
1393 case LY_TYPE_DEC64: /* range */
1394 if (valcopy) {
1395 ret = ly_parse_int(valcopy, __INT64_C(-9223372036854775807) - __INT64_C(1), __INT64_C(9223372036854775807), 10,
1396 max ? &part->max_64 : &part->min_64);
1397 } else if (max) {
1398 part->max_64 = __INT64_C(9223372036854775807);
1399 } else {
1400 part->min_64 = __INT64_C(-9223372036854775807) - __INT64_C(1);
1401 }
1402 if (!first) {
1403 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1404 }
1405 break;
1406 case LY_TYPE_INT8: /* range */
1407 if (valcopy) {
1408 ret = ly_parse_int(valcopy, __INT64_C(-128), INT64_C(127), 10, max ? &part->max_64 : &part->min_64);
1409 } else if (max) {
1410 part->max_64 = __INT64_C(127);
1411 } else {
1412 part->min_64 = __INT64_C(-128);
1413 }
1414 if (!first) {
1415 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1416 }
1417 break;
1418 case LY_TYPE_INT16: /* range */
1419 if (valcopy) {
1420 ret = ly_parse_int(valcopy, __INT64_C(-32768), INT64_C(32767), 10, max ? &part->max_64 : &part->min_64);
1421 } else if (max) {
1422 part->max_64 = __INT64_C(32767);
1423 } else {
1424 part->min_64 = __INT64_C(-32768);
1425 }
1426 if (!first) {
1427 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1428 }
1429 break;
1430 case LY_TYPE_INT32: /* range */
1431 if (valcopy) {
1432 ret = ly_parse_int(valcopy, __INT64_C(-2147483648), INT64_C(2147483647), 10, max ? &part->max_64 : &part->min_64);
1433 } else if (max) {
1434 part->max_64 = __INT64_C(2147483647);
1435 } else {
1436 part->min_64 = __INT64_C(-2147483648);
1437 }
1438 if (!first) {
1439 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1440 }
1441 break;
1442 case LY_TYPE_INT64: /* range */
1443 if (valcopy) {
1444 ret = ly_parse_int(valcopy, __INT64_C(-9223372036854775807) - __INT64_C(1), INT64_C(9223372036854775807), 10,
1445 max ? &part->max_64 : &part->min_64);
1446 } else if (max) {
1447 part->max_64 = __INT64_C(9223372036854775807);
1448 } else {
1449 part->min_64 = __INT64_C(-9223372036854775807) - __INT64_C(1);
1450 }
1451 if (!first) {
1452 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1453 }
1454 break;
1455 case LY_TYPE_UINT8: /* range */
1456 if (valcopy) {
1457 ret = ly_parse_uint(valcopy, __UINT64_C(255), 10, max ? &part->max_u64 : &part->min_u64);
1458 } else if (max) {
1459 part->max_u64 = __UINT64_C(255);
1460 } else {
1461 part->min_u64 = __UINT64_C(0);
1462 }
1463 if (!first) {
1464 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1465 }
1466 break;
1467 case LY_TYPE_UINT16: /* range */
1468 if (valcopy) {
1469 ret = ly_parse_uint(valcopy, __UINT64_C(65535), 10, max ? &part->max_u64 : &part->min_u64);
1470 } else if (max) {
1471 part->max_u64 = __UINT64_C(65535);
1472 } else {
1473 part->min_u64 = __UINT64_C(0);
1474 }
1475 if (!first) {
1476 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1477 }
1478 break;
1479 case LY_TYPE_UINT32: /* range */
1480 if (valcopy) {
1481 ret = ly_parse_uint(valcopy, __UINT64_C(4294967295), 10, max ? &part->max_u64 : &part->min_u64);
1482 } else if (max) {
1483 part->max_u64 = __UINT64_C(4294967295);
1484 } else {
1485 part->min_u64 = __UINT64_C(0);
1486 }
1487 if (!first) {
1488 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1489 }
1490 break;
1491 case LY_TYPE_UINT64: /* range */
1492 if (valcopy) {
1493 ret = ly_parse_uint(valcopy, __UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
1494 } else if (max) {
1495 part->max_u64 = __UINT64_C(18446744073709551615);
1496 } else {
1497 part->min_u64 = __UINT64_C(0);
1498 }
1499 if (!first) {
1500 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1501 }
1502 break;
1503 case LY_TYPE_STRING: /* length */
1504 if (valcopy) {
1505 ret = ly_parse_uint(valcopy, __UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
1506 } else if (max) {
1507 part->max_u64 = __UINT64_C(18446744073709551615);
1508 } else {
1509 part->min_u64 = __UINT64_C(0);
1510 }
1511 if (!first) {
1512 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1513 }
1514 break;
1515 default:
1516 LOGINT(ctx->ctx);
1517 ret = LY_EINT;
1518 }
1519
1520error:
1521 if (ret == LY_EDENIED) {
1522 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1523 "Invalid %s restriction - value \"%s\" does not fit the type limitations.",
1524 length_restr ? "length" : "range", valcopy ? valcopy : *value);
1525 } else if (ret == LY_EVALID) {
1526 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1527 "Invalid %s restriction - invalid value \"%s\".",
1528 length_restr ? "length" : "range", valcopy ? valcopy : *value);
1529 } else if (ret == LY_EEXIST) {
1530 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1531 "Invalid %s restriction - values are not in ascending order (%s).",
1532 length_restr ? "length" : "range", valcopy ? valcopy : *value);
1533 } else if (!ret && value) {
1534 *value = *value + len;
1535 }
1536 free(valcopy);
1537 return ret;
1538}
1539
1540static LY_ERR
1541lys_compile_type_range(struct lysc_ctx *ctx, struct lysp_restr *range_p, LY_DATA_TYPE basetype, int length_restr,
1542 struct lysc_range **range)
1543{
1544 LY_ERR ret = LY_EVALID;
1545 const char *expr;
1546 struct lysc_range_part *parts = NULL, *part;
1547 size_t parts_done = 0;
1548 int range_expected = 0;
1549
1550 assert(range);
1551 assert(range_p);
1552
1553 if (!(*range)) {
1554 *range = calloc(1, sizeof **range);
1555 LY_CHECK_ERR_RET(!(*range), LOGMEM(ctx->ctx), LY_EMEM);
1556 }
1557
1558 if (range_p->eapptag) {
1559 lydict_remove(ctx->ctx, (*range)->eapptag);
Radek Krejcic5ddcc02018-11-12 13:28:18 +01001560 (*range)->eapptag = lydict_insert(ctx->ctx, range_p->eapptag, 0);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001561 }
1562 if (range_p->emsg) {
1563 lydict_remove(ctx->ctx, (*range)->emsg);
Radek Krejcic5ddcc02018-11-12 13:28:18 +01001564 (*range)->emsg = lydict_insert(ctx->ctx, range_p->emsg, 0);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001565 }
1566 /* extensions are taken only from the last range by the caller */
1567
1568 expr = range_p->arg;
1569 while(1) {
1570 if (isspace(*expr)) {
1571 ++expr;
1572 continue;
1573 } else if (*expr == '\0') {
1574 parts_done++;
1575 break;
1576 } else if (!strncmp(expr, "min", 3)) {
1577 if (parts) {
1578 /* min cannot be used elsewhere than in the first part */
1579 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1580 "Invalid %s restriction - unexpected data before min keyword (%.*s).", length_restr ? "length" : "range",
1581 expr - range_p->arg, range_p->arg);
1582 goto cleanup;
1583 }
1584 expr += 3;
1585
1586 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1587 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, 0, basetype, 1, length_restr, NULL), cleanup);
1588 part->max_64 = part->min_64;
1589 } else if (*expr == '|') {
1590 if (!parts || range_expected) {
1591 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1592 "Invalid %s restriction - unexpected beginning of the expression (%s).", length_restr ? "length" : "range", expr);
1593 goto cleanup;
1594 }
1595 expr++;
1596 parts_done++;
1597 /* process next part of the expression */
1598 continue;
1599 } else if (!strncmp(expr, "..", 2)) {
1600 expr += 2;
1601 while (isspace(*expr)) {
1602 expr++;
1603 }
1604 if (*expr == '\0') {
1605 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1606 "Invalid %s restriction - unexpected end of the expression after \"..\".", length_restr ? "length" : "range");
1607 goto cleanup;
1608 } else if (!parts || LY_ARRAY_SIZE(parts) == parts_done) {
1609 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1610 "Invalid %s restriction - unexpected \"..\" without a lower bound.", length_restr ? "length" : "range");
1611 goto cleanup;
1612 }
1613 /* continue expecting the upper boundary */
1614 range_expected = 1;
1615 } else if (isdigit(*expr) || (*expr == '-') || (*expr == '+')) {
1616 /* number */
1617 if (range_expected) {
1618 part = &parts[LY_ARRAY_SIZE(parts) - 1];
1619 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, &expr), cleanup);
1620 } else {
1621 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1622 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
1623 basetype, parts_done ? 0 : 1, length_restr, &expr), cleanup);
1624 part->max_64 = part->min_64;
1625 }
1626
1627 /* continue with possible another expression part */
1628 range_expected = 0;
1629 continue;
1630 } else if (!strncmp(expr, "max", 3)) {
1631 expr += 3;
1632 while (isspace(*expr)) {
1633 expr++;
1634 }
1635 if (*expr != '\0') {
1636 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data after max keyword (%s).",
1637 length_restr ? "length" : "range", expr);
1638 goto cleanup;
1639 }
1640 if (range_expected) {
1641 part = &parts[LY_ARRAY_SIZE(parts) - 1];
1642 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, NULL), cleanup);
1643 parts_done++;
1644 } else {
1645 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1646 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
1647 basetype, parts_done ? 0 : 1, length_restr, NULL), cleanup);
1648 part->min_64 = part->max_64;
1649 }
1650 /* done */
1651 break;
1652 } else {
1653 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data (%s).",
1654 length_restr ? "length" : "range", expr);
1655 goto cleanup;
1656 }
1657 }
1658
1659 (*range)->parts = parts;
1660 parts = NULL;
1661 ret = LY_SUCCESS;
1662cleanup:
1663 /* TODO clean up */
1664 LY_ARRAY_FREE(parts);
1665
1666 return ret;
1667}
1668
1669static LY_ERR
1670lys_compile_type(struct lysc_ctx *ctx, struct lysp_node_leaf *leaf_p, int options, struct lysc_type **type)
1671{
1672 LY_ERR ret = LY_SUCCESS;
1673 unsigned int u;
1674 struct lysp_type *type_p = &leaf_p->type;
1675 struct type_context {
1676 const struct lysp_tpdf *tpdf;
1677 struct lysp_node *node;
1678 struct lysp_module *mod;
1679 } *tctx, *tctx_prev = NULL;
1680 LY_DATA_TYPE basetype = LY_TYPE_UNKNOWN;
1681 struct ly_set tpdf_chain = {0};
1682 struct lysc_type_bin* bin;
1683
1684
1685 tctx = calloc(1, sizeof *tctx);
1686 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
1687 for (ret = lysp_type_find(type_p->name, (struct lysp_node*)leaf_p, ctx->mod->parsed,
1688 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod);
1689 ret;
1690 ret = lysp_type_find(tctx_prev->tpdf->type.name, tctx_prev->node, tctx_prev->mod,
1691 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod)) {
1692 if (basetype) {
1693 break;
1694 }
1695
1696 /* check status */
1697 if (lysc_check_status(ctx, leaf_p->flags, ctx->mod->parsed, leaf_p->name,
1698 tctx->tpdf->flags, tctx->mod, tctx->node ? tctx->node->name : tctx->mod->name)) {
1699 free(tctx);
1700 goto cleanup;
1701 }
1702
1703 if (!(tctx->tpdf->flags & LYS_TYPE_MODIFIED)) {
1704 /* no change in comparison to the following (actually preceding in the chain of type derivations) type */
1705 memset(tctx, 0, sizeof *tctx);
1706 continue;
1707 }
1708
1709 /* store information for the following processing */
1710 ly_set_add(&tpdf_chain, tctx, LY_SET_OPT_USEASLIST);
1711
1712 /* prepare next loop */
1713 tctx = calloc(1, sizeof *tctx);
1714 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
1715 }
1716 free(tctx);
1717
1718 /* allocate type according to the basetype */
1719 switch (basetype) {
1720 case LY_TYPE_BINARY:
1721 *type = calloc(1, sizeof(struct lysc_type_bin));
1722 bin = (struct lysc_type_bin*)(*type);
1723 break;
1724 case LY_TYPE_BITS:
1725 *type = calloc(1, sizeof(struct lysc_type_bits));
1726 break;
1727 case LY_TYPE_BOOL:
1728 case LY_TYPE_EMPTY:
1729 *type = calloc(1, sizeof(struct lysc_type));
1730 break;
1731 case LY_TYPE_DEC64:
1732 *type = calloc(1, sizeof(struct lysc_type_dec));
1733 break;
1734 case LY_TYPE_ENUM:
1735 *type = calloc(1, sizeof(struct lysc_type_enum));
1736 break;
1737 case LY_TYPE_IDENT:
1738 *type = calloc(1, sizeof(struct lysc_type_identityref));
1739 break;
1740 case LY_TYPE_INST:
1741 *type = calloc(1, sizeof(struct lysc_type_instanceid));
1742 break;
1743 case LY_TYPE_LEAFREF:
1744 *type = calloc(1, sizeof(struct lysc_type_leafref));
1745 break;
1746 case LY_TYPE_STRING:
1747 *type = calloc(1, sizeof(struct lysc_type_str));
1748 break;
1749 case LY_TYPE_UNION:
1750 *type = calloc(1, sizeof(struct lysc_type_union));
1751 break;
1752 case LY_TYPE_INT8:
1753 case LY_TYPE_UINT8:
1754 case LY_TYPE_INT16:
1755 case LY_TYPE_UINT16:
1756 case LY_TYPE_INT32:
1757 case LY_TYPE_UINT32:
1758 case LY_TYPE_INT64:
1759 case LY_TYPE_UINT64:
1760 *type = calloc(1, sizeof(struct lysc_type_num));
1761 break;
1762 default:
1763 LOGINT(ctx->ctx);
1764 }
1765 LY_CHECK_ERR_GOTO(!(*type), LOGMEM(ctx->ctx), cleanup);
1766 (*type)->basetype = basetype;
1767 COMPILE_ARRAY_GOTO(ctx, type_p->exts, (*type)->exts, options, u, lys_compile_ext, ret, cleanup);
1768
1769
1770 /* get restrictions from the referred typedefs */
1771 for (u = tpdf_chain.count - 1; u + 1 > 0; --u) {
1772 tctx = (struct type_context*)tpdf_chain.objs[u];
1773
1774 switch (basetype) {
1775 case LY_TYPE_BINARY:
1776 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
1777 if (tctx->tpdf->type.length) {
1778 ret = lys_compile_type_range(ctx, tctx->tpdf->type.length, basetype, 1, &bin->length);
1779 LY_CHECK_GOTO(ret, cleanup);
1780 }
1781 break;
1782 }
1783 }
1784
1785 /* get restrictions from the node itself, finalize the type structure */
1786 switch ((*type)->basetype) {
1787 case LY_TYPE_BINARY:
1788 if (leaf_p->type.length) {
1789 ret = lys_compile_type_range(ctx, leaf_p->type.length, basetype, 1, &bin->length);
1790 LY_CHECK_GOTO(ret, cleanup);
1791 COMPILE_ARRAY_GOTO(ctx, leaf_p->type.length->exts, bin->length->exts,
1792 options, u, lys_compile_ext, ret, cleanup);
1793 }
1794 break;
1795 }
1796
1797cleanup:
1798 ly_set_erase(&tpdf_chain, free);
1799
1800 return ret;
1801}
1802
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001803static LY_ERR lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent);
1804
1805static LY_ERR
1806lys_compile_node_container(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
1807{
1808 struct lysp_node_container *cont_p = (struct lysp_node_container*)node_p;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001809 struct lysc_node_container *cont = (struct lysc_node_container*)node;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001810 struct lysp_node *child_p;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001811 unsigned int u;
1812 LY_ERR ret = LY_SUCCESS;
1813
1814 COMPILE_MEMBER_GOTO(ctx, cont_p->when, cont->when, options, lys_compile_when, ret, done);
1815 COMPILE_ARRAY_GOTO(ctx, cont_p->iffeatures, cont->iffeatures, options, u, lys_compile_iffeature, ret, done);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001816
1817 LY_LIST_FOR(cont_p->child, child_p) {
1818 LY_CHECK_RET(lys_compile_node(ctx, child_p, options, node));
1819 }
1820
Radek Krejci4f28eda2018-11-12 11:46:16 +01001821 COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, options, u, lys_compile_must, ret, done);
1822 //COMPILE_ARRAY_GOTO(ctx, cont_p->actions, cont->actions, options, u, lys_compile_action, ret, done);
1823 //COMPILE_ARRAY_GOTO(ctx, cont_p->notifs, cont->notifs, options, u, lys_compile_notif, ret, done);
1824
1825done:
1826 return ret;
1827}
1828
1829static LY_ERR
1830lys_compile_node_leaf(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
1831{
1832 struct lysp_node_leaf *leaf_p = (struct lysp_node_leaf*)node_p;
1833 struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)node;
1834 unsigned int u;
1835 LY_ERR ret = LY_SUCCESS;
1836
1837 COMPILE_MEMBER_GOTO(ctx, leaf_p->when, leaf->when, options, lys_compile_when, ret, done);
1838 COMPILE_ARRAY_GOTO(ctx, leaf_p->iffeatures, leaf->iffeatures, options, u, lys_compile_iffeature, ret, done);
1839
1840 COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, options, u, lys_compile_must, ret, done);
1841 ret = lys_compile_type(ctx, leaf_p, options, &leaf->type);
1842 LY_CHECK_GOTO(ret, done);
1843
1844 leaf->units = lydict_insert(ctx->ctx, leaf_p->units, 0);
1845 leaf->dflt = lydict_insert(ctx->ctx, leaf_p->dflt, 0);
1846done:
1847 return ret;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001848}
1849
1850static LY_ERR
1851lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent)
1852{
1853 LY_ERR ret = LY_EVALID;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001854 struct lysc_node *node, **children;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001855 unsigned int u;
1856 LY_ERR (*node_compile_spec)(struct lysc_ctx*, struct lysp_node*, int, struct lysc_node*);
1857
1858 switch (node_p->nodetype) {
1859 case LYS_CONTAINER:
1860 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_container));
1861 node_compile_spec = lys_compile_node_container;
1862 break;
1863 case LYS_LEAF:
1864 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaf));
Radek Krejci4f28eda2018-11-12 11:46:16 +01001865 node_compile_spec = lys_compile_node_leaf;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001866 break;
1867 case LYS_LIST:
1868 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_list));
1869 break;
1870 case LYS_LEAFLIST:
1871 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaflist));
1872 break;
1873 case LYS_CASE:
1874 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_case));
1875 break;
1876 case LYS_CHOICE:
1877 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_choice));
1878 break;
1879 case LYS_USES:
1880 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_uses));
1881 break;
1882 case LYS_ANYXML:
1883 case LYS_ANYDATA:
1884 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_anydata));
1885 break;
1886 default:
1887 LOGINT(ctx->ctx);
1888 return LY_EINT;
1889 }
1890 LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
1891 node->nodetype = node_p->nodetype;
1892 node->module = ctx->mod;
1893 node->prev = node;
1894 node->flags = node_p->flags;
1895
1896 /* config */
1897 if (!(node->flags & LYS_CONFIG_MASK)) {
1898 /* config not explicitely set, inherit it from parent */
1899 if (parent) {
1900 node->flags |= parent->flags & LYS_CONFIG_MASK;
1901 } else {
1902 /* default is config true */
1903 node->flags |= LYS_CONFIG_W;
1904 }
1905 }
1906
1907 /* status - it is not inherited by specification, but it does not make sense to have
1908 * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
1909 if (!(node->flags & LYS_STATUS_MASK)) {
1910 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
Radek Krejci98094b32018-11-02 16:21:47 +01001911 LOGWRN(ctx->ctx, "Missing explicit \"%s\" status that was already specified in parent, inheriting.",
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001912 (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
1913 node->flags |= parent->flags & LYS_STATUS_MASK;
1914 } else {
1915 node->flags |= LYS_STATUS_CURR;
1916 }
1917 } else if (parent) {
1918 /* check status compatibility with the parent */
1919 if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
1920 if (node->flags & LYS_STATUS_CURR) {
1921 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
1922 "A \"current\" status is in conflict with the parent's \"%s\" status.",
1923 (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
1924 } else { /* LYS_STATUS_DEPRC */
1925 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
1926 "A \"deprecated\" status is in conflict with the parent's \"obsolete\" status.");
1927 }
1928 goto error;
1929 }
1930 }
1931
Radek Krejci4f28eda2018-11-12 11:46:16 +01001932 if (!(options & LYSC_OPT_FREE_SP)) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001933 node->sp = node_p;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001934 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01001935 node->name = lydict_insert(ctx->ctx, node_p->name, 0);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001936 COMPILE_ARRAY_GOTO(ctx, node_p->exts, node->exts, options, u, lys_compile_ext, ret, error);
1937
1938 /* nodetype-specific part */
1939 LY_CHECK_GOTO(node_compile_spec(ctx, node_p, options, node), error);
1940
1941 /* insert into parent's children */
Radek Krejci4f28eda2018-11-12 11:46:16 +01001942 if (parent && (children = lysc_node_children(parent))) {
1943 if (!(*children)) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001944 /* first child */
Radek Krejci4f28eda2018-11-12 11:46:16 +01001945 *children = node;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001946 } else {
1947 /* insert at the end of the parent's children list */
Radek Krejci4f28eda2018-11-12 11:46:16 +01001948 (*children)->prev->next = node;
1949 node->prev = (*children)->prev;
1950 (*children)->prev = node;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001951 }
1952 } else {
1953 /* top-level element */
1954 if (!ctx->mod->compiled->data) {
1955 ctx->mod->compiled->data = node;
1956 } else {
1957 /* insert at the end of the module's top-level nodes list */
1958 ctx->mod->compiled->data->prev->next = node;
1959 node->prev = ctx->mod->compiled->data->prev;
1960 ctx->mod->compiled->data->prev = node;
1961 }
1962 }
1963
1964 return LY_SUCCESS;
1965
1966error:
Radek Krejci4f28eda2018-11-12 11:46:16 +01001967 lysc_node_free(ctx->ctx, node);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001968 return ret;
1969}
1970
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001971LY_ERR
Radek Krejcid14e9692018-11-01 11:00:37 +01001972lys_compile(struct lys_module *mod, int options)
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001973{
Radek Krejci86d106e2018-10-18 09:53:19 +02001974 struct lysc_ctx ctx = {0};
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001975 struct lysc_module *mod_c;
Radek Krejcif8f882a2018-10-31 14:51:15 +01001976 struct lysp_module *sp;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001977 struct lysp_node *node_p;
Radek Krejci151a5b72018-10-19 14:21:44 +02001978 unsigned int u;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001979 LY_ERR ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001980
Radek Krejcif8f882a2018-10-31 14:51:15 +01001981 LY_CHECK_ARG_RET(NULL, mod, mod->parsed, mod->parsed->ctx, LY_EINVAL);
1982 sp = mod->parsed;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001983
1984 if (sp->submodule) {
Radek Krejci86d106e2018-10-18 09:53:19 +02001985 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 +02001986 return LY_EINVAL;
1987 }
1988
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001989 ctx.ctx = sp->ctx;
1990 ctx.mod = mod;
1991
1992 mod->compiled = mod_c = calloc(1, sizeof *mod_c);
Radek Krejci86d106e2018-10-18 09:53:19 +02001993 LY_CHECK_ERR_RET(!mod_c, LOGMEM(sp->ctx), LY_EMEM);
1994 mod_c->ctx = sp->ctx;
Radek Krejcid14e9692018-11-01 11:00:37 +01001995 mod_c->implemented = sp->implemented;
1996 mod_c->latest_revision = sp->latest_revision;
Radek Krejci86d106e2018-10-18 09:53:19 +02001997 mod_c->version = sp->version;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001998
Radek Krejci4f28eda2018-11-12 11:46:16 +01001999 mod_c->name = lydict_insert(sp->ctx, sp->name, 0);
2000 mod_c->ns = lydict_insert(sp->ctx, sp->ns, 0);
2001 mod_c->prefix = lydict_insert(sp->ctx, sp->prefix, 0);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002002 if (sp->revs) {
2003 mod_c->revision = lydict_insert(sp->ctx, sp->revs[0].date, 10);
2004 }
Radek Krejcice8c1592018-10-29 15:35:51 +01002005 COMPILE_ARRAY_GOTO(&ctx, sp->imports, mod_c->imports, options, u, lys_compile_import, ret, error);
2006 COMPILE_ARRAY_GOTO(&ctx, sp->features, mod_c->features, options, u, lys_compile_feature, ret, error);
Radek Krejci2a408df2018-10-29 16:32:26 +01002007 COMPILE_ARRAY_GOTO(&ctx, sp->identities, mod_c->identities, options, u, lys_compile_identity, ret, error);
2008 if (sp->identities) {
2009 LY_CHECK_RET(lys_compile_identities_derived(&ctx, sp->identities, mod_c->identities));
2010 }
Radek Krejcice8c1592018-10-29 15:35:51 +01002011
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002012 LY_LIST_FOR(sp->data, node_p) {
2013 ret = lys_compile_node(&ctx, node_p, options, NULL);
2014 LY_CHECK_GOTO(ret, error);
2015 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01002016 //COMPILE_ARRAY_GOTO(ctx, sp->rpcs, mod_c->rpcs, options, u, lys_compile_action, ret, error);
2017 //COMPILE_ARRAY_GOTO(ctx, sp->notifs, mod_c->notifs, options, u, lys_compile_notif, ret, error);
2018
2019 COMPILE_ARRAY_GOTO(&ctx, sp->exts, mod_c->exts, options, u, lys_compile_ext, ret, error);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002020
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002021 if (options & LYSC_OPT_FREE_SP) {
Radek Krejci4f28eda2018-11-12 11:46:16 +01002022 lysp_module_free(mod->parsed);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002023 ((struct lys_module*)mod)->parsed = NULL;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002024 }
2025
Radek Krejcif8f882a2018-10-31 14:51:15 +01002026 ((struct lys_module*)mod)->compiled = mod_c;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002027 return LY_SUCCESS;
2028
2029error:
Radek Krejci4f28eda2018-11-12 11:46:16 +01002030 lysc_module_free(mod_c, NULL);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002031 ((struct lys_module*)mod)->compiled = NULL;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002032 return ret;
2033}
Radek Krejci86d106e2018-10-18 09:53:19 +02002034
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002035static void
Radek Krejci086c7132018-10-26 15:29:04 +02002036lys_latest_switch(struct lys_module *old, struct lysp_module *new)
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002037{
Radek Krejci086c7132018-10-26 15:29:04 +02002038 if (old->parsed) {
2039 new->latest_revision = old->parsed->latest_revision;
2040 old->parsed->latest_revision = 0;
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002041 }
Radek Krejci086c7132018-10-26 15:29:04 +02002042 if (old->compiled) {
2043 new->latest_revision = old->parsed->latest_revision;
2044 old->compiled->latest_revision = 0;
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002045 }
2046}
2047
Radek Krejcid33273d2018-10-25 14:55:52 +02002048struct lys_module *
Radek Krejci3b1f9292018-11-08 10:58:35 +01002049lys_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 +01002050 LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
Radek Krejci86d106e2018-10-18 09:53:19 +02002051{
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002052 struct lys_module *mod = NULL, *latest, *mod_dup;
Radek Krejcid33273d2018-10-25 14:55:52 +02002053 struct lysp_module *latest_p;
Radek Krejci086c7132018-10-26 15:29:04 +02002054 struct lysp_import *imp;
2055 struct lysp_include *inc;
Radek Krejci9ed7a192018-10-31 16:23:51 +01002056 LY_ERR ret = LY_EINVAL;
Radek Krejci086c7132018-10-26 15:29:04 +02002057 unsigned int u, i;
Radek Krejcibbe09a92018-11-08 09:36:54 +01002058 struct ly_parser_ctx context = {0};
Radek Krejci86d106e2018-10-18 09:53:19 +02002059
2060 LY_CHECK_ARG_RET(ctx, ctx, data, NULL);
2061
Radek Krejcibbe09a92018-11-08 09:36:54 +01002062 context.ctx = ctx;
2063 context.line = 1;
2064
Radek Krejci3b1f9292018-11-08 10:58:35 +01002065 if (main_ctx) {
2066 /* map the typedefs and groupings list from main context to the submodule's context */
2067 memcpy(&context.tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
2068 memcpy(&context.grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
2069 }
2070
Radek Krejci86d106e2018-10-18 09:53:19 +02002071 mod = calloc(1, sizeof *mod);
2072 LY_CHECK_ERR_RET(!mod, LOGMEM(ctx), NULL);
2073
2074 switch (format) {
2075 case LYS_IN_YIN:
2076 /* TODO not yet supported
2077 mod = yin_read_module(ctx, data, revision, implement);
2078 */
2079 break;
2080 case LYS_IN_YANG:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002081 ret = yang_parse(&context, data, &mod->parsed);
Radek Krejci86d106e2018-10-18 09:53:19 +02002082 break;
2083 default:
2084 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
2085 break;
2086 }
Radek Krejcifaa1eac2018-10-30 14:34:55 +01002087 LY_CHECK_ERR_RET(ret, free(mod), NULL);
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002088
2089 /* make sure that the newest revision is at position 0 */
2090 lysp_sort_revisions(mod->parsed->revs);
Radek Krejci86d106e2018-10-18 09:53:19 +02002091
2092 if (implement) {
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002093 /* mark the loaded module implemented */
Radek Krejcib7db73a2018-10-24 14:18:40 +02002094 if (ly_ctx_get_module_implemented(ctx, mod->parsed->name)) {
2095 LOGERR(ctx, LY_EDENIED, "Module \"%s\" is already implemented in the context.", mod->parsed->name);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002096 goto error;
Radek Krejcib7db73a2018-10-24 14:18:40 +02002097 }
Radek Krejci86d106e2018-10-18 09:53:19 +02002098 mod->parsed->implemented = 1;
2099 }
2100
Radek Krejci9ed7a192018-10-31 16:23:51 +01002101 if (custom_check) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002102 LY_CHECK_GOTO(custom_check(ctx, mod->parsed, check_data), error);
Radek Krejci86d106e2018-10-18 09:53:19 +02002103 }
2104
Radek Krejcid33273d2018-10-25 14:55:52 +02002105 if (mod->parsed->submodule) { /* submodule */
Radek Krejci3b1f9292018-11-08 10:58:35 +01002106 if (!main_ctx) {
2107 LOGERR(ctx, LY_EDENIED, "Input data contains submodule \"%s\" which cannot be parsed directly without its main module.",
2108 mod->parsed->name);
2109 goto error;
2110 }
Radek Krejcid33273d2018-10-25 14:55:52 +02002111 /* decide the latest revision */
2112 latest_p = ly_ctx_get_submodule(ctx, mod->parsed->belongsto, mod->parsed->name, NULL);
2113 if (latest_p) {
2114 if (mod->parsed->revs) {
2115 if (!latest_p->revs) {
2116 /* latest has no revision, so mod is anyway newer */
Radek Krejci9ed7a192018-10-31 16:23:51 +01002117 mod->parsed->latest_revision = latest_p->latest_revision;
Radek Krejcid33273d2018-10-25 14:55:52 +02002118 latest_p->latest_revision = 0;
2119 } else {
2120 if (strcmp(mod->parsed->revs[0].date, latest_p->revs[0].date) > 0) {
Radek Krejci9ed7a192018-10-31 16:23:51 +01002121 mod->parsed->latest_revision = latest_p->latest_revision;
Radek Krejcid33273d2018-10-25 14:55:52 +02002122 latest_p->latest_revision = 0;
2123 }
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002124 }
2125 }
Radek Krejcid33273d2018-10-25 14:55:52 +02002126 } else {
Radek Krejci9ed7a192018-10-31 16:23:51 +01002127 mod->parsed->latest_revision = 1;
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002128 }
Radek Krejci3b1f9292018-11-08 10:58:35 +01002129 /* remap possibly changed and reallocated typedefs and groupings list back to the main context */
2130 memcpy(&main_ctx->tpdfs_nodes, &context.tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
2131 memcpy(&main_ctx->grps_nodes, &context.grps_nodes, sizeof main_ctx->grps_nodes);
Radek Krejcid33273d2018-10-25 14:55:52 +02002132 } else { /* module */
2133 /* check for duplicity in the context */
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002134 mod_dup = (struct lys_module*)ly_ctx_get_module(ctx, mod->parsed->name, mod->parsed->revs ? mod->parsed->revs[0].date : NULL);
2135 if (mod_dup) {
2136 if (mod_dup->parsed) {
2137 /* error */
2138 if (mod->parsed->revs) {
2139 LOGERR(ctx, LY_EEXIST, "Module \"%s\" of revision \"%s\" is already present in the context.",
2140 mod->parsed->name, mod->parsed->revs[0].date);
2141 } else {
2142 LOGERR(ctx, LY_EEXIST, "Module \"%s\" with no revision is already present in the context.",
2143 mod->parsed->name);
2144 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01002145 goto error;
Radek Krejcid33273d2018-10-25 14:55:52 +02002146 } else {
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002147 /* add the parsed data to the currently compiled-only module in the context */
2148 mod_dup->parsed = mod->parsed;
2149 free(mod);
2150 mod = mod_dup;
2151 goto finish_parsing;
Radek Krejcid33273d2018-10-25 14:55:52 +02002152 }
Radek Krejcid33273d2018-10-25 14:55:52 +02002153 }
Radek Krejci86d106e2018-10-18 09:53:19 +02002154
2155#if 0
2156 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
2157 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
2158 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
2159 * the anotation definitions available in the internal schema structure. There is another hack in schema
2160 * printers to do not print this internally added annotation. */
2161 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
2162 if (lyp_add_ietf_netconf_annotations(mod)) {
2163 lys_free(mod, NULL, 1, 1);
2164 return NULL;
2165 }
2166 }
2167#endif
2168
Radek Krejcid33273d2018-10-25 14:55:52 +02002169 /* decide the latest revision */
2170 latest = (struct lys_module*)ly_ctx_get_module_latest(ctx, mod->parsed->name);
2171 if (latest) {
2172 if (mod->parsed->revs) {
Radek Krejcif8f882a2018-10-31 14:51:15 +01002173 if ((latest->parsed && !latest->parsed->revs) || (!latest->parsed && !latest->compiled->revision)) {
Radek Krejcid33273d2018-10-25 14:55:52 +02002174 /* latest has no revision, so mod is anyway newer */
Radek Krejci086c7132018-10-26 15:29:04 +02002175 lys_latest_switch(latest, mod->parsed);
Radek Krejcid33273d2018-10-25 14:55:52 +02002176 } else {
Radek Krejcif8f882a2018-10-31 14:51:15 +01002177 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 +02002178 lys_latest_switch(latest, mod->parsed);
Radek Krejcid33273d2018-10-25 14:55:52 +02002179 }
2180 }
2181 }
2182 } else {
2183 mod->parsed->latest_revision = 1;
2184 }
2185
2186 /* add into context */
2187 ly_set_add(&ctx->list, mod, LY_SET_OPT_USEASLIST);
2188
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002189finish_parsing:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002190 /* resolve imports */
Radek Krejci086c7132018-10-26 15:29:04 +02002191 mod->parsed->parsing = 1;
2192 LY_ARRAY_FOR(mod->parsed->imports, u) {
2193 imp = &mod->parsed->imports[u];
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002194 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 +01002195 goto error_ctx;
Radek Krejci086c7132018-10-26 15:29:04 +02002196 }
2197 /* check for importing the same module twice */
2198 for (i = 0; i < u; ++i) {
2199 if (imp->module == mod->parsed->imports[i].module) {
2200 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 +01002201 goto error_ctx;
Radek Krejci086c7132018-10-26 15:29:04 +02002202 }
2203 }
2204 }
2205 LY_ARRAY_FOR(mod->parsed->includes, u) {
2206 inc = &mod->parsed->includes[u];
Radek Krejci3b1f9292018-11-08 10:58:35 +01002207 if (!inc->submodule && lysp_load_submodule(&context, mod->parsed, inc)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002208 goto error_ctx;
Radek Krejci086c7132018-10-26 15:29:04 +02002209 }
2210 }
2211 mod->parsed->parsing = 0;
Radek Krejcibbe09a92018-11-08 09:36:54 +01002212
2213 /* check name collisions - typedefs and groupings */
2214 LY_CHECK_GOTO(lysp_check_typedefs(&context), error_ctx);
Radek Krejcid33273d2018-10-25 14:55:52 +02002215 }
2216
Radek Krejci86d106e2018-10-18 09:53:19 +02002217 return mod;
Radek Krejcibbe09a92018-11-08 09:36:54 +01002218
2219error_ctx:
2220 ly_set_rm(&ctx->list, mod, NULL);
2221error:
2222 lys_module_free(mod, NULL);
2223 ly_set_erase(&context.tpdfs_nodes, NULL);
2224 return NULL;
Radek Krejci86d106e2018-10-18 09:53:19 +02002225}
2226
Radek Krejcid14e9692018-11-01 11:00:37 +01002227API struct lys_module *
Radek Krejci86d106e2018-10-18 09:53:19 +02002228lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
2229{
Radek Krejci3b1f9292018-11-08 10:58:35 +01002230 return lys_parse_mem_(ctx, data, format, 1, NULL, NULL, NULL);
Radek Krejci86d106e2018-10-18 09:53:19 +02002231}
2232
2233static void
2234lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
2235{
2236#ifdef __APPLE__
2237 char path[MAXPATHLEN];
2238#else
2239 int len;
2240 char path[PATH_MAX], proc_path[32];
2241#endif
2242
2243#ifdef __APPLE__
2244 if (fcntl(fd, F_GETPATH, path) != -1) {
2245 *filename = lydict_insert(ctx, path, 0);
2246 }
2247#else
2248 /* get URI if there is /proc */
2249 sprintf(proc_path, "/proc/self/fd/%d", fd);
2250 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
2251 *filename = lydict_insert(ctx, path, len);
2252 }
2253#endif
2254}
2255
Radek Krejcid33273d2018-10-25 14:55:52 +02002256struct lys_module *
Radek Krejci3b1f9292018-11-08 10:58:35 +01002257lys_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 +01002258 LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
Radek Krejci86d106e2018-10-18 09:53:19 +02002259{
Radek Krejcid33273d2018-10-25 14:55:52 +02002260 struct lys_module *mod;
Radek Krejci86d106e2018-10-18 09:53:19 +02002261 size_t length;
2262 char *addr;
2263
2264 LY_CHECK_ARG_RET(ctx, ctx, NULL);
2265 if (fd < 0) {
2266 LOGARG(ctx, fd);
2267 return NULL;
2268 }
2269
2270 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
2271 if (!addr) {
2272 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
2273 return NULL;
2274 }
2275
Radek Krejci3b1f9292018-11-08 10:58:35 +01002276 mod = lys_parse_mem_(ctx, addr, format, implement, main_ctx, custom_check, check_data);
Radek Krejci86d106e2018-10-18 09:53:19 +02002277 ly_munmap(addr, length);
2278
2279 if (mod && !mod->parsed->filepath) {
2280 lys_parse_set_filename(ctx, &mod->parsed->filepath, fd);
2281 }
2282
2283 return mod;
2284}
2285
Radek Krejcid14e9692018-11-01 11:00:37 +01002286API struct lys_module *
Radek Krejci86d106e2018-10-18 09:53:19 +02002287lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
2288{
Radek Krejci3b1f9292018-11-08 10:58:35 +01002289 return lys_parse_fd_(ctx, fd, format, 1, NULL, NULL, NULL);
Radek Krejci86d106e2018-10-18 09:53:19 +02002290}
2291
Radek Krejcid33273d2018-10-25 14:55:52 +02002292struct lys_module *
Radek Krejci3b1f9292018-11-08 10:58:35 +01002293lys_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 +01002294 LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
Radek Krejci86d106e2018-10-18 09:53:19 +02002295{
2296 int fd;
Radek Krejcid33273d2018-10-25 14:55:52 +02002297 struct lys_module *mod;
Radek Krejci86d106e2018-10-18 09:53:19 +02002298 const char *rev, *dot, *filename;
2299 size_t len;
2300
2301 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
2302
2303 fd = open(path, O_RDONLY);
2304 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
2305
Radek Krejci3b1f9292018-11-08 10:58:35 +01002306 mod = lys_parse_fd_(ctx, fd, format, implement, main_ctx, custom_check, check_data);
Radek Krejci86d106e2018-10-18 09:53:19 +02002307 close(fd);
2308 LY_CHECK_RET(!mod, NULL);
2309
2310 /* check that name and revision match filename */
2311 filename = strrchr(path, '/');
2312 if (!filename) {
2313 filename = path;
2314 } else {
2315 filename++;
2316 }
2317 rev = strchr(filename, '@');
2318 dot = strrchr(filename, '.');
2319
2320 /* name */
2321 len = strlen(mod->parsed->name);
2322 if (strncmp(filename, mod->parsed->name, len) ||
2323 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
2324 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, mod->parsed->name);
2325 }
2326 if (rev) {
2327 len = dot - ++rev;
Radek Krejcib7db73a2018-10-24 14:18:40 +02002328 if (!mod->parsed->revs || len != 10 || strncmp(mod->parsed->revs[0].date, rev, len)) {
Radek Krejci86d106e2018-10-18 09:53:19 +02002329 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
Radek Krejcib7db73a2018-10-24 14:18:40 +02002330 mod->parsed->revs ? mod->parsed->revs[0].date : "none");
Radek Krejci86d106e2018-10-18 09:53:19 +02002331 }
2332 }
2333
2334 if (!mod->parsed->filepath) {
2335 /* store URI */
2336 char rpath[PATH_MAX];
2337 if (realpath(path, rpath) != NULL) {
2338 mod->parsed->filepath = lydict_insert(ctx, rpath, 0);
2339 } else {
2340 mod->parsed->filepath = lydict_insert(ctx, path, 0);
2341 }
2342 }
2343
2344 return mod;
2345}
2346
Radek Krejcid14e9692018-11-01 11:00:37 +01002347API struct lys_module *
Radek Krejcid33273d2018-10-25 14:55:52 +02002348lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
2349{
Radek Krejci3b1f9292018-11-08 10:58:35 +01002350 return lys_parse_path_(ctx, path, format, 1, NULL, NULL, NULL);
Radek Krejcid33273d2018-10-25 14:55:52 +02002351}
2352
2353API LY_ERR
2354lys_search_localfile(const char * const *searchpaths, int cwd, const char *name, const char *revision,
2355 char **localfile, LYS_INFORMAT *format)
2356{
2357 size_t len, flen, match_len = 0, dir_len;
2358 int i, implicit_cwd = 0, ret = EXIT_FAILURE;
2359 char *wd, *wn = NULL;
2360 DIR *dir = NULL;
2361 struct dirent *file;
2362 char *match_name = NULL;
2363 LYS_INFORMAT format_aux, match_format = 0;
2364 struct ly_set *dirs;
2365 struct stat st;
2366
2367 LY_CHECK_ARG_RET(NULL, localfile, LY_EINVAL);
2368
2369 /* start to fill the dir fifo with the context's search path (if set)
2370 * and the current working directory */
2371 dirs = ly_set_new();
2372 if (!dirs) {
2373 LOGMEM(NULL);
2374 return EXIT_FAILURE;
2375 }
2376
2377 len = strlen(name);
2378 if (cwd) {
2379 wd = get_current_dir_name();
2380 if (!wd) {
2381 LOGMEM(NULL);
2382 goto cleanup;
2383 } else {
2384 /* add implicit current working directory (./) to be searched,
2385 * this directory is not searched recursively */
2386 if (ly_set_add(dirs, wd, 0) == -1) {
2387 goto cleanup;
2388 }
2389 implicit_cwd = 1;
2390 }
2391 }
2392 if (searchpaths) {
2393 for (i = 0; searchpaths[i]; i++) {
2394 /* check for duplicities with the implicit current working directory */
2395 if (implicit_cwd && !strcmp(dirs->objs[0], searchpaths[i])) {
2396 implicit_cwd = 0;
2397 continue;
2398 }
2399 wd = strdup(searchpaths[i]);
2400 if (!wd) {
2401 LOGMEM(NULL);
2402 goto cleanup;
2403 } else if (ly_set_add(dirs, wd, 0) == -1) {
2404 goto cleanup;
2405 }
2406 }
2407 }
2408 wd = NULL;
2409
2410 /* start searching */
2411 while (dirs->count) {
2412 free(wd);
2413 free(wn); wn = NULL;
2414
2415 dirs->count--;
2416 wd = (char *)dirs->objs[dirs->count];
2417 dirs->objs[dirs->count] = NULL;
2418 LOGVRB("Searching for \"%s\" in %s.", name, wd);
2419
2420 if (dir) {
2421 closedir(dir);
2422 }
2423 dir = opendir(wd);
2424 dir_len = strlen(wd);
2425 if (!dir) {
2426 LOGWRN(NULL, "Unable to open directory \"%s\" for searching (sub)modules (%s).", wd, strerror(errno));
2427 } else {
2428 while ((file = readdir(dir))) {
2429 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
2430 /* skip . and .. */
2431 continue;
2432 }
2433 free(wn);
2434 if (asprintf(&wn, "%s/%s", wd, file->d_name) == -1) {
2435 LOGMEM(NULL);
2436 goto cleanup;
2437 }
2438 if (stat(wn, &st) == -1) {
2439 LOGWRN(NULL, "Unable to get information about \"%s\" file in \"%s\" when searching for (sub)modules (%s)",
2440 file->d_name, wd, strerror(errno));
2441 continue;
2442 }
2443 if (S_ISDIR(st.st_mode) && (dirs->count || !implicit_cwd)) {
2444 /* we have another subdirectory in searchpath to explore,
2445 * subdirectories are not taken into account in current working dir (dirs->set.g[0]) */
2446 if (ly_set_add(dirs, wn, 0) == -1) {
2447 goto cleanup;
2448 }
2449 /* continue with the next item in current directory */
2450 wn = NULL;
2451 continue;
2452 } else if (!S_ISREG(st.st_mode)) {
2453 /* not a regular file (note that we see the target of symlinks instead of symlinks */
2454 continue;
2455 }
2456
2457 /* here we know that the item is a file which can contain a module */
2458 if (strncmp(name, file->d_name, len) ||
2459 (file->d_name[len] != '.' && file->d_name[len] != '@')) {
2460 /* different filename than the module we search for */
2461 continue;
2462 }
2463
2464 /* get type according to filename suffix */
2465 flen = strlen(file->d_name);
2466 if (!strcmp(&file->d_name[flen - 4], ".yin")) {
2467 format_aux = LYS_IN_YIN;
2468 } else if (!strcmp(&file->d_name[flen - 5], ".yang")) {
2469 format_aux = LYS_IN_YANG;
2470 } else {
2471 /* not supportde suffix/file format */
2472 continue;
2473 }
2474
2475 if (revision) {
2476 /* we look for the specific revision, try to get it from the filename */
2477 if (file->d_name[len] == '@') {
2478 /* check revision from the filename */
2479 if (strncmp(revision, &file->d_name[len + 1], strlen(revision))) {
2480 /* another revision */
2481 continue;
2482 } else {
2483 /* exact revision */
2484 free(match_name);
2485 match_name = wn;
2486 wn = NULL;
2487 match_len = dir_len + 1 + len;
2488 match_format = format_aux;
2489 goto success;
2490 }
2491 } else {
2492 /* continue trying to find exact revision match, use this only if not found */
2493 free(match_name);
2494 match_name = wn;
2495 wn = NULL;
2496 match_len = dir_len + 1 +len;
2497 match_format = format_aux;
2498 continue;
2499 }
2500 } else {
2501 /* remember the revision and try to find the newest one */
2502 if (match_name) {
2503 if (file->d_name[len] != '@' ||
2504 lysp_check_date(NULL, &file->d_name[len + 1], flen - (format_aux == LYS_IN_YANG ? 5 : 4) - len - 1, NULL)) {
2505 continue;
2506 } else if (match_name[match_len] == '@' &&
2507 (strncmp(&match_name[match_len + 1], &file->d_name[len + 1], LY_REV_SIZE - 1) >= 0)) {
2508 continue;
2509 }
2510 free(match_name);
2511 }
2512
2513 match_name = wn;
2514 wn = NULL;
2515 match_len = dir_len + 1 + len;
2516 match_format = format_aux;
2517 continue;
2518 }
2519 }
2520 }
2521 }
2522
2523success:
2524 (*localfile) = match_name;
2525 match_name = NULL;
2526 if (format) {
2527 (*format) = match_format;
2528 }
2529 ret = EXIT_SUCCESS;
2530
2531cleanup:
2532 free(wn);
2533 free(wd);
2534 if (dir) {
2535 closedir(dir);
2536 }
2537 free(match_name);
2538 ly_set_free(dirs, free);
2539
2540 return ret;
2541}
2542