blob: 052b87adf48ebb3c2f3a6cdbb9168edacbd31dfb [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 Krejcid505e3d2018-11-13 09:04:17 +010033const char* ly_data_type2str[LY_DATA_TYPE_COUNT] = {"unknown", "binary", "bits", "boolean", "decimal64", "empty", "enumeration",
34 "identityref", "instance-identifier", "leafref", "string", "union", "8bit integer", "8bit unsigned integer", "16bit integer",
35 "16bit unsigned integer", "32bit integer", "32bit unsigned integer", "64bit integer", "64bit unsigned integer"
36};
37
Radek Krejci8b764662018-11-14 14:15:13 +010038#define FREE_ARRAY(CTX, ARRAY, FUNC) {uint64_t c__; LY_ARRAY_FOR(ARRAY, c__){FUNC(CTX, &(ARRAY)[c__]);}LY_ARRAY_FREE(ARRAY);}
Radek Krejci4f28eda2018-11-12 11:46:16 +010039#define FREE_MEMBER(CTX, MEMBER, FUNC) if (MEMBER) {FUNC(CTX, MEMBER);free(MEMBER);}
40#define FREE_STRING(CTX, STRING) if (STRING) {lydict_remove(CTX, STRING);}
41#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 +020042
Radek Krejcib31c8992018-11-12 16:29:16 +010043#define DUP_STRING(CTX, DUP, ORIG) if (ORIG) {DUP = lydict_insert(CTX, ORIG, 0);}
44
Radek Krejci6d6e4e42018-10-29 13:28:19 +010045#define COMPILE_ARRAY_GOTO(CTX, ARRAY_P, ARRAY_C, OPTIONS, ITER, FUNC, RET, GOTO) \
46 if (ARRAY_P) { \
Radek Krejcibd8d9ba2018-11-02 16:06:26 +010047 LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, LY_ARRAY_SIZE(ARRAY_P), RET, GOTO); \
Radek Krejci6d6e4e42018-10-29 13:28:19 +010048 for (ITER = 0; ITER < LY_ARRAY_SIZE(ARRAY_P); ++ITER) { \
Radek Krejci87616bb2018-10-31 13:30:52 +010049 LY_ARRAY_INCREMENT(ARRAY_C); \
Radek Krejcice8c1592018-10-29 15:35:51 +010050 RET = FUNC(CTX, &(ARRAY_P)[ITER], OPTIONS, &(ARRAY_C)[ITER]); \
Radek Krejci6d6e4e42018-10-29 13:28:19 +010051 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
Radek Krejci6d6e4e42018-10-29 13:28:19 +010052 } \
53 }
54
Radek Krejci4f28eda2018-11-12 11:46:16 +010055#define COMPILE_MEMBER_GOTO(CTX, MEMBER_P, MEMBER_C, OPTIONS, FUNC, RET, GOTO) \
56 if (MEMBER_P) { \
57 MEMBER_C = calloc(1, sizeof *(MEMBER_C)); \
58 LY_CHECK_ERR_GOTO(!(MEMBER_C), LOGMEM((CTX)->ctx); RET = LY_EMEM, GOTO); \
59 RET = FUNC(CTX, MEMBER_P, OPTIONS, MEMBER_C); \
60 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
61 }
Radek Krejci6f7feb62018-10-12 15:23:02 +020062
Radek Krejci4f28eda2018-11-12 11:46:16 +010063static void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
64static void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
Radek Krejci86d106e2018-10-18 09:53:19 +020065
Radek Krejci6f7feb62018-10-12 15:23:02 +020066static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010067lysp_stmt_free(struct ly_ctx *ctx, struct lysp_stmt *stmt)
Radek Krejci6f7feb62018-10-12 15:23:02 +020068{
69 struct lysp_stmt *child, *next;
70
Radek Krejci4f28eda2018-11-12 11:46:16 +010071 FREE_STRING(ctx, stmt->stmt);
72 FREE_STRING(ctx, stmt->arg);
Radek Krejci6f7feb62018-10-12 15:23:02 +020073
74 LY_LIST_FOR_SAFE(stmt->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +010075 lysp_stmt_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +020076 }
77
78 free(stmt);
79}
80
81static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010082lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext)
Radek Krejci6f7feb62018-10-12 15:23:02 +020083{
84 struct lysp_stmt *stmt, *next;
85
Radek Krejci4f28eda2018-11-12 11:46:16 +010086 FREE_STRING(ctx, ext->name);
87 FREE_STRING(ctx, ext->argument);
Radek Krejci6f7feb62018-10-12 15:23:02 +020088
89 LY_LIST_FOR_SAFE(ext->child, next, stmt) {
Radek Krejci4f28eda2018-11-12 11:46:16 +010090 lysp_stmt_free(ctx, stmt);
Radek Krejci6f7feb62018-10-12 15:23:02 +020091 }
92}
93
94static void
Radek Krejci4f28eda2018-11-12 11:46:16 +010095lysp_import_free(struct ly_ctx *ctx, struct lysp_import *import)
Radek Krejci6f7feb62018-10-12 15:23:02 +020096{
Radek Krejci086c7132018-10-26 15:29:04 +020097 /* imported module is freed directly from the context's list */
Radek Krejci4f28eda2018-11-12 11:46:16 +010098 FREE_STRING(ctx, import->name);
99 FREE_STRING(ctx, import->prefix);
100 FREE_STRING(ctx, import->dsc);
101 FREE_STRING(ctx, import->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200102 FREE_ARRAY(ctx, import->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200103}
104
105static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100106lysp_include_free(struct ly_ctx *ctx, struct lysp_include *include)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200107{
Radek Krejcibbe09a92018-11-08 09:36:54 +0100108 if (include->submodule) {
Radek Krejcid33273d2018-10-25 14:55:52 +0200109 lysp_module_free(include->submodule);
110 }
Radek Krejci4f28eda2018-11-12 11:46:16 +0100111 FREE_STRING(ctx, include->name);
112 FREE_STRING(ctx, include->dsc);
113 FREE_STRING(ctx, include->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200114 FREE_ARRAY(ctx, include->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200115}
116
117static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100118lysp_revision_free(struct ly_ctx *ctx, struct lysp_revision *rev)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200119{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100120 FREE_STRING(ctx, rev->dsc);
121 FREE_STRING(ctx, rev->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200122 FREE_ARRAY(ctx, rev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200123}
124
125static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100126lysp_ext_free(struct ly_ctx *ctx, struct lysp_ext *ext)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200127{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100128 FREE_STRING(ctx, ext->name);
129 FREE_STRING(ctx, ext->argument);
130 FREE_STRING(ctx, ext->dsc);
131 FREE_STRING(ctx, ext->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200132 FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200133}
134
135static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100136lysp_feature_free(struct ly_ctx *ctx, struct lysp_feature *feat)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200137{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100138 FREE_STRING(ctx, feat->name);
139 FREE_STRINGS(ctx, feat->iffeatures);
140 FREE_STRING(ctx, feat->dsc);
141 FREE_STRING(ctx, feat->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200142 FREE_ARRAY(ctx, feat->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200143}
144
145static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100146lysp_ident_free(struct ly_ctx *ctx, struct lysp_ident *ident)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200147{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100148 FREE_STRING(ctx, ident->name);
149 FREE_STRINGS(ctx, ident->iffeatures);
150 FREE_STRINGS(ctx, ident->bases);
151 FREE_STRING(ctx, ident->dsc);
152 FREE_STRING(ctx, ident->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200153 FREE_ARRAY(ctx, ident->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200154}
155
156static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100157lysp_restr_free(struct ly_ctx *ctx, struct lysp_restr *restr)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200158{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100159 FREE_STRING(ctx, restr->arg);
160 FREE_STRING(ctx, restr->emsg);
161 FREE_STRING(ctx, restr->eapptag);
162 FREE_STRING(ctx, restr->dsc);
163 FREE_STRING(ctx, restr->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200164 FREE_ARRAY(ctx, restr->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200165}
166
167static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100168lysp_type_enum_free(struct ly_ctx *ctx, struct lysp_type_enum *item)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200169{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100170 FREE_STRING(ctx, item->name);
171 FREE_STRING(ctx, item->dsc);
172 FREE_STRING(ctx, item->ref);
173 FREE_STRINGS(ctx, item->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200174 FREE_ARRAY(ctx, item->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200175}
176
Radek Krejci9a191e62018-11-13 13:19:56 +0100177static void lysc_type_free(struct ly_ctx *ctx, struct lysc_type *type);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200178static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100179lysp_type_free(struct ly_ctx *ctx, struct lysp_type *type)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200180{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100181 FREE_STRING(ctx, type->name);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200182 FREE_MEMBER(ctx, type->range, lysp_restr_free);
183 FREE_MEMBER(ctx, type->length, lysp_restr_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200184 FREE_ARRAY(ctx, type->patterns, lysp_restr_free);
185 FREE_ARRAY(ctx, type->enums, lysp_type_enum_free);
186 FREE_ARRAY(ctx, type->bits, lysp_type_enum_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100187 FREE_STRING(ctx, type->path);
188 FREE_STRINGS(ctx, type->bases);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200189 FREE_ARRAY(ctx, type->types, lysp_type_free);
190 FREE_ARRAY(ctx, type->exts, lysp_ext_instance_free);
Radek Krejci9a191e62018-11-13 13:19:56 +0100191 if (type->compiled) {
192 lysc_type_free(ctx, type->compiled);
193 }
Radek Krejci6f7feb62018-10-12 15:23:02 +0200194}
195
196static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100197lysp_tpdf_free(struct ly_ctx *ctx, struct lysp_tpdf *tpdf)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200198{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100199 FREE_STRING(ctx, tpdf->name);
200 FREE_STRING(ctx, tpdf->units);
201 FREE_STRING(ctx, tpdf->dflt);
202 FREE_STRING(ctx, tpdf->dsc);
203 FREE_STRING(ctx, tpdf->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200204 FREE_ARRAY(ctx, tpdf->exts, lysp_ext_instance_free);
Radek Krejcib31c8992018-11-12 16:29:16 +0100205
Radek Krejci4f28eda2018-11-12 11:46:16 +0100206 lysp_type_free(ctx, &tpdf->type);
Radek Krejci9a191e62018-11-13 13:19:56 +0100207
Radek Krejci6f7feb62018-10-12 15:23:02 +0200208}
209
210static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100211lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200212{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200213 struct lysp_node *node, *next;
214
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200215 FREE_ARRAY(ctx, inout->musts, lysp_restr_free);
216 FREE_ARRAY(ctx, inout->typedefs, lysp_tpdf_free);
217 FREE_ARRAY(ctx, inout->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200218 LY_LIST_FOR_SAFE(inout->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100219 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200220 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200221 FREE_ARRAY(ctx, inout->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200222
223}
224
225static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100226lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200227{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100228 FREE_STRING(ctx, action->name);
229 FREE_STRING(ctx, action->dsc);
230 FREE_STRING(ctx, action->ref);
231 FREE_STRINGS(ctx, action->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200232 FREE_ARRAY(ctx, action->typedefs, lysp_tpdf_free);
233 FREE_ARRAY(ctx, action->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200234 FREE_MEMBER(ctx, action->input, lysp_action_inout_free);
235 FREE_MEMBER(ctx, action->output, lysp_action_inout_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200236 FREE_ARRAY(ctx, action->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200237}
238
239static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100240lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200241{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200242 struct lysp_node *node, *next;
243
Radek Krejci4f28eda2018-11-12 11:46:16 +0100244 FREE_STRING(ctx, notif->name);
245 FREE_STRING(ctx, notif->dsc);
246 FREE_STRING(ctx, notif->ref);
247 FREE_STRINGS(ctx, notif->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200248 FREE_ARRAY(ctx, notif->musts, lysp_restr_free);
249 FREE_ARRAY(ctx, notif->typedefs, lysp_tpdf_free);
250 FREE_ARRAY(ctx, notif->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200251 LY_LIST_FOR_SAFE(notif->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100252 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200253 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200254 FREE_ARRAY(ctx, notif->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200255}
256
257static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100258lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200259{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200260 struct lysp_node *node, *next;
261
Radek Krejci4f28eda2018-11-12 11:46:16 +0100262 FREE_STRING(ctx, grp->name);
263 FREE_STRING(ctx, grp->dsc);
264 FREE_STRING(ctx, grp->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200265 FREE_ARRAY(ctx, grp->typedefs, lysp_tpdf_free);
266 FREE_ARRAY(ctx, grp->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200267 LY_LIST_FOR_SAFE(grp->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100268 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200269 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200270 FREE_ARRAY(ctx, grp->actions, lysp_action_free);
271 FREE_ARRAY(ctx, grp->notifs, lysp_notif_free);
272 FREE_ARRAY(ctx, grp->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200273}
274
275static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100276lysp_when_free(struct ly_ctx *ctx, struct lysp_when *when)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200277{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100278 FREE_STRING(ctx, when->cond);
279 FREE_STRING(ctx, when->dsc);
280 FREE_STRING(ctx, when->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200281 FREE_ARRAY(ctx, when->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200282}
283
284static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100285lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200286{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200287 struct lysp_node *node, *next;
288
Radek Krejci4f28eda2018-11-12 11:46:16 +0100289 FREE_STRING(ctx, augment->nodeid);
290 FREE_STRING(ctx, augment->dsc);
291 FREE_STRING(ctx, augment->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200292 FREE_MEMBER(ctx, augment->when, lysp_when_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100293 FREE_STRINGS(ctx, augment->iffeatures);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200294 LY_LIST_FOR_SAFE(augment->child, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100295 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200296 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200297 FREE_ARRAY(ctx, augment->actions, lysp_action_free);
298 FREE_ARRAY(ctx, augment->notifs, lysp_notif_free);
299 FREE_ARRAY(ctx, augment->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200300}
301
302static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100303lysp_deviate_free(struct ly_ctx *ctx, struct lysp_deviate *d)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200304{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200305 struct lysp_deviate_add *add = (struct lysp_deviate_add*)d;
306 struct lysp_deviate_rpl *rpl = (struct lysp_deviate_rpl*)d;
307
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200308 FREE_ARRAY(ctx, d->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200309 switch(d->mod) {
310 case LYS_DEV_NOT_SUPPORTED:
311 /* nothing to do */
312 break;
313 case LYS_DEV_ADD:
314 case LYS_DEV_DELETE: /* compatible for dynamically allocated data */
Radek Krejci4f28eda2018-11-12 11:46:16 +0100315 FREE_STRING(ctx, add->units);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200316 FREE_ARRAY(ctx, add->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100317 FREE_STRINGS(ctx, add->uniques);
318 FREE_STRINGS(ctx, add->dflts);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200319 break;
320 case LYS_DEV_REPLACE:
321 FREE_MEMBER(ctx, rpl->type, lysp_type_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100322 FREE_STRING(ctx, rpl->units);
323 FREE_STRING(ctx, rpl->dflt);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200324 break;
325 default:
326 LOGINT(ctx);
327 break;
328 }
329}
330
331static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100332lysp_deviation_free(struct ly_ctx *ctx, struct lysp_deviation *dev)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200333{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200334 struct lysp_deviate *next, *iter;
335
Radek Krejci4f28eda2018-11-12 11:46:16 +0100336 FREE_STRING(ctx, dev->nodeid);
337 FREE_STRING(ctx, dev->dsc);
338 FREE_STRING(ctx, dev->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200339 LY_LIST_FOR_SAFE(dev->deviates, next, iter) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100340 lysp_deviate_free(ctx, iter);
Michal Vasko8447f6a2018-10-15 10:56:16 +0200341 free(iter);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200342 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200343 FREE_ARRAY(ctx, dev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200344}
345
346static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100347lysp_refine_free(struct ly_ctx *ctx, struct lysp_refine *ref)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200348{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100349 FREE_STRING(ctx, ref->nodeid);
350 FREE_STRING(ctx, ref->dsc);
351 FREE_STRING(ctx, ref->ref);
352 FREE_STRINGS(ctx, ref->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200353 FREE_ARRAY(ctx, ref->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100354 FREE_STRING(ctx, ref->presence);
355 FREE_STRINGS(ctx, ref->dflts);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200356 FREE_ARRAY(ctx, ref->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200357}
358
359static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100360lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200361{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200362 struct lysp_node *child, *next;
363
Radek Krejci4f28eda2018-11-12 11:46:16 +0100364 FREE_STRING(ctx, node->name);
365 FREE_STRING(ctx, node->dsc);
366 FREE_STRING(ctx, node->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200367 FREE_MEMBER(ctx, node->when, lysp_when_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100368 FREE_STRINGS(ctx, node->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200369 FREE_ARRAY(ctx, node->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200370
371 switch(node->nodetype) {
372 case LYS_CONTAINER:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200373 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100374 FREE_STRING(ctx, ((struct lysp_node_container*)node)->presence);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200375 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->typedefs, lysp_tpdf_free);
376 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200377 LY_LIST_FOR_SAFE(((struct lysp_node_container*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100378 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200379 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200380 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->actions, lysp_action_free);
381 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->notifs, lysp_notif_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200382 break;
383 case LYS_LEAF:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200384 FREE_ARRAY(ctx, ((struct lysp_node_leaf*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100385 lysp_type_free(ctx, &((struct lysp_node_leaf*)node)->type);
386 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->units);
387 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->dflt);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200388 break;
389 case LYS_LEAFLIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200390 FREE_ARRAY(ctx, ((struct lysp_node_leaflist*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100391 lysp_type_free(ctx, &((struct lysp_node_leaflist*)node)->type);
392 FREE_STRING(ctx, ((struct lysp_node_leaflist*)node)->units);
393 FREE_STRINGS(ctx, ((struct lysp_node_leaflist*)node)->dflts);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200394 break;
395 case LYS_LIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200396 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->musts, lysp_restr_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100397 FREE_STRING(ctx, ((struct lysp_node_list*)node)->key);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200398 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->typedefs, lysp_tpdf_free);
399 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200400 LY_LIST_FOR_SAFE(((struct lysp_node_list*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100401 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200402 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200403 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->actions, lysp_action_free);
404 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->notifs, lysp_notif_free);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100405 FREE_STRINGS(ctx, ((struct lysp_node_list*)node)->uniques);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200406 break;
407 case LYS_CHOICE:
408 LY_LIST_FOR_SAFE(((struct lysp_node_choice*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100409 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200410 }
Radek Krejci4f28eda2018-11-12 11:46:16 +0100411 FREE_STRING(ctx, ((struct lysp_node_choice*)node)->dflt);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200412 break;
413 case LYS_CASE:
414 LY_LIST_FOR_SAFE(((struct lysp_node_case*)node)->child, next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100415 lysp_node_free(ctx, child);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200416 }
417 break;
418 case LYS_ANYDATA:
419 case LYS_ANYXML:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200420 FREE_ARRAY(ctx, ((struct lysp_node_anydata*)node)->musts, lysp_restr_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200421 break;
422 case LYS_USES:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200423 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->refines, lysp_refine_free);
424 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->augments, lysp_augment_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200425 break;
426 default:
427 LOGINT(ctx);
428 }
429
430 free(node);
431}
432
Radek Krejci4f28eda2018-11-12 11:46:16 +0100433API void
434lysp_module_free(struct lysp_module *module)
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200435{
436 struct ly_ctx *ctx;
Radek Krejci6f7feb62018-10-12 15:23:02 +0200437 struct lysp_node *node, *next;
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200438
439 LY_CHECK_ARG_RET(NULL, module,);
440 ctx = module->ctx;
441
Radek Krejci4f28eda2018-11-12 11:46:16 +0100442 FREE_STRING(ctx, module->name);
443 FREE_STRING(ctx, module->filepath);
444 FREE_STRING(ctx, module->ns); /* or belongs-to */
445 FREE_STRING(ctx, module->prefix);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200446
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200447 FREE_ARRAY(ctx, module->imports, lysp_import_free);
448 FREE_ARRAY(ctx, module->includes, lysp_include_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200449
Radek Krejci4f28eda2018-11-12 11:46:16 +0100450 FREE_STRING(ctx, module->org);
451 FREE_STRING(ctx, module->contact);
452 FREE_STRING(ctx, module->dsc);
453 FREE_STRING(ctx, module->ref);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200454
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200455 FREE_ARRAY(ctx, module->revs, lysp_revision_free);
456 FREE_ARRAY(ctx, module->extensions, lysp_ext_free);
457 FREE_ARRAY(ctx, module->features, lysp_feature_free);
458 FREE_ARRAY(ctx, module->identities, lysp_ident_free);
459 FREE_ARRAY(ctx, module->typedefs, lysp_tpdf_free);
460 FREE_ARRAY(ctx, module->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200461 LY_LIST_FOR_SAFE(module->data, next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100462 lysp_node_free(ctx, node);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200463 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200464 FREE_ARRAY(ctx, module->augments, lysp_augment_free);
465 FREE_ARRAY(ctx, module->rpcs, lysp_action_free);
466 FREE_ARRAY(ctx, module->notifs, lysp_notif_free);
467 FREE_ARRAY(ctx, module->deviations, lysp_deviation_free);
468 FREE_ARRAY(ctx, module->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200469
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200470 free(module);
471}
472
Radek Krejcib31c8992018-11-12 16:29:16 +0100473static struct lysc_ext_instance *
474lysc_ext_instance_dup(struct ly_ctx *ctx, struct lysc_ext_instance *orig)
475{
476 /* TODO */
477 (void) ctx;
478 (void) orig;
479 return NULL;
480}
481
Radek Krejci151a5b72018-10-19 14:21:44 +0200482static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100483lysc_ext_instance_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
Radek Krejci478020e2018-10-30 16:02:14 +0100484{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100485 FREE_STRING(ctx, ext->argument);
Radek Krejci478020e2018-10-30 16:02:14 +0100486 FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free);
487}
488
489static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100490lysc_iffeature_free(struct ly_ctx *UNUSED(ctx), struct lysc_iffeature *iff)
Radek Krejci151a5b72018-10-19 14:21:44 +0200491{
Radek Krejci2c4e7172018-10-19 15:56:26 +0200492 LY_ARRAY_FREE(iff->features);
Radek Krejci151a5b72018-10-19 14:21:44 +0200493 free(iff->expr);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200494}
495
496static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100497lysc_import_free(struct ly_ctx *ctx, struct lysc_import *import)
Radek Krejci478020e2018-10-30 16:02:14 +0100498{
499 /* imported module is freed directly from the context's list */
Radek Krejci4f28eda2018-11-12 11:46:16 +0100500 FREE_STRING(ctx, import->prefix);
Radek Krejci478020e2018-10-30 16:02:14 +0100501 FREE_ARRAY(ctx, import->exts, lysc_ext_instance_free);
502}
503
504static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100505lysc_ident_free(struct ly_ctx *ctx, struct lysc_ident *ident)
Radek Krejci478020e2018-10-30 16:02:14 +0100506{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100507 FREE_STRING(ctx, ident->name);
Radek Krejci478020e2018-10-30 16:02:14 +0100508 FREE_ARRAY(ctx, ident->iffeatures, lysc_iffeature_free);
509 LY_ARRAY_FREE(ident->derived);
510 FREE_ARRAY(ctx, ident->exts, lysc_ext_instance_free);
511}
512
513static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100514lysc_feature_free(struct ly_ctx *ctx, struct lysc_feature *feat)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200515{
Radek Krejci4f28eda2018-11-12 11:46:16 +0100516 FREE_STRING(ctx, feat->name);
Radek Krejci151a5b72018-10-19 14:21:44 +0200517 FREE_ARRAY(ctx, feat->iffeatures, lysc_iffeature_free);
Radek Krejci2c4e7172018-10-19 15:56:26 +0200518 LY_ARRAY_FREE(feat->depfeatures);
Radek Krejci478020e2018-10-30 16:02:14 +0100519 FREE_ARRAY(ctx, feat->exts, lysc_ext_instance_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200520}
521
Radek Krejcib31c8992018-11-12 16:29:16 +0100522struct lysc_range*
523lysc_range_dup(struct ly_ctx *ctx, const struct lysc_range *orig)
524{
525 struct lysc_range *dup;
526 LY_ERR ret;
527
528 dup = calloc(1, sizeof *dup);
529 LY_CHECK_ERR_RET(!dup, LOGMEM(ctx), NULL);
530 if (orig->parts) {
531 LY_ARRAY_CREATE_GOTO(ctx, dup->parts, LY_ARRAY_SIZE(orig->parts), ret, cleanup);
532 LY_ARRAY_SIZE(dup->parts) = LY_ARRAY_SIZE(orig->parts);
533 memcpy(dup->parts, orig->parts, LY_ARRAY_SIZE(dup->parts) * sizeof *dup->parts);
534 }
535 DUP_STRING(ctx, dup->eapptag, orig->eapptag);
536 DUP_STRING(ctx, dup->emsg, orig->emsg);
537 dup->exts = lysc_ext_instance_dup(ctx, orig->exts);
538
539 return dup;
540cleanup:
541 free(dup);
542 (void) ret; /* set but not used due to the return type */
543 return NULL;
544}
545
Radek Krejci4f28eda2018-11-12 11:46:16 +0100546static void
547lysc_range_free(struct ly_ctx *ctx, struct lysc_range *range)
548{
549 LY_ARRAY_FREE(range->parts);
550 FREE_STRING(ctx, range->eapptag);
551 FREE_STRING(ctx, range->emsg);
552 FREE_ARRAY(ctx, range->exts, lysc_ext_instance_free);
553}
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100554
Radek Krejci4586a022018-11-13 11:29:26 +0100555struct lysc_pattern*
556lysc_pattern_dup(struct lysc_pattern *orig)
557{
558 ++orig->refcount;
559 return orig;
560}
561
562struct lysc_pattern**
563lysc_patterns_dup(struct ly_ctx *ctx, struct lysc_pattern **orig)
564{
565 struct lysc_pattern **dup;
566 unsigned int u;
567
568 LY_ARRAY_CREATE_RET(ctx, dup, LY_ARRAY_SIZE(orig), NULL);
569 LY_ARRAY_FOR(orig, u) {
570 dup[u] = lysc_pattern_dup(orig[u]);
571 LY_ARRAY_INCREMENT(dup);
572 }
573 return dup;
574}
575
576static void
577lysc_pattern_free(struct ly_ctx *ctx, struct lysc_pattern **pattern)
578{
579 if (--(*pattern)->refcount) {
580 return;
581 }
582 pcre_free((*pattern)->expr);
583 pcre_free_study((*pattern)->expr_extra);
584 FREE_STRING(ctx, (*pattern)->eapptag);
585 FREE_STRING(ctx, (*pattern)->emsg);
586 FREE_ARRAY(ctx, (*pattern)->exts, lysc_ext_instance_free);
587 free(*pattern);
588}
589
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100590static void
Radek Krejci8b764662018-11-14 14:15:13 +0100591lysc_enum_item_free(struct ly_ctx *ctx, struct lysc_type_enum_item *item)
592{
593 FREE_STRING(ctx, item->name);
594 FREE_ARRAY(ctx, item->iffeatures, lysc_iffeature_free);
595 FREE_ARRAY(ctx, item->exts, lysc_ext_instance_free);
596}
597
598static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100599lysc_type_free(struct ly_ctx *ctx, struct lysc_type *type)
600{
Radek Krejci9a191e62018-11-13 13:19:56 +0100601 if (--type->refcount) {
602 return;
603 }
Radek Krejci4f28eda2018-11-12 11:46:16 +0100604 switch(type->basetype) {
605 case LY_TYPE_BINARY:
606 FREE_MEMBER(ctx, ((struct lysc_type_bin*)type)->length, lysc_range_free);
607 break;
Radek Krejci8b764662018-11-14 14:15:13 +0100608 case LY_TYPE_BITS:
609 FREE_ARRAY(ctx, (struct lysc_type_enum_item*)((struct lysc_type_bits*)type)->bits, lysc_enum_item_free);
610 break;
Radek Krejci4586a022018-11-13 11:29:26 +0100611 case LY_TYPE_STRING:
612 FREE_MEMBER(ctx, ((struct lysc_type_str*)type)->length, lysc_range_free);
613 FREE_ARRAY(ctx, ((struct lysc_type_str*)type)->patterns, lysc_pattern_free);
614 break;
Radek Krejci8b764662018-11-14 14:15:13 +0100615 case LY_TYPE_ENUM:
616 FREE_ARRAY(ctx, ((struct lysc_type_enum*)type)->enums, lysc_enum_item_free);
617 break;
Radek Krejci4586a022018-11-13 11:29:26 +0100618 case LY_TYPE_INT8:
619 case LY_TYPE_UINT8:
620 case LY_TYPE_INT16:
621 case LY_TYPE_UINT16:
622 case LY_TYPE_INT32:
623 case LY_TYPE_UINT32:
624 case LY_TYPE_INT64:
625 case LY_TYPE_UINT64:
626 FREE_MEMBER(ctx, ((struct lysc_type_num*)type)->range, lysc_range_free);
627 break;
628 case LY_TYPE_BOOL:
629 case LY_TYPE_EMPTY:
630 case LY_TYPE_UNKNOWN: /* just to complete switch */
631 /* nothing to do */
632 break;
Radek Krejci4f28eda2018-11-12 11:46:16 +0100633 }
634 FREE_ARRAY(ctx, type->exts, lysc_ext_instance_free);
Radek Krejci9a191e62018-11-13 13:19:56 +0100635
636 free(type);
Radek Krejci4f28eda2018-11-12 11:46:16 +0100637}
638
639static void lysc_node_free(struct ly_ctx *ctx, struct lysc_node *node);
640
641static void
642lysc_node_container_free(struct ly_ctx *ctx, struct lysc_node_container *node)
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100643{
644 struct lysc_node *child, *child_next;
645
646 LY_LIST_FOR_SAFE(node->child, child_next, child) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100647 lysc_node_free(ctx, child);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100648 }
649}
650
651static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100652lysc_node_leaf_free(struct ly_ctx *ctx, struct lysc_node_leaf *node)
653{
Radek Krejci9a191e62018-11-13 13:19:56 +0100654 if (node->type) {
655 lysc_type_free(ctx, node->type);
656 }
Radek Krejci4f28eda2018-11-12 11:46:16 +0100657}
658
659static void
660lysc_node_free(struct ly_ctx *ctx, struct lysc_node *node)
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100661{
662 /* common part */
Radek Krejci4f28eda2018-11-12 11:46:16 +0100663 FREE_STRING(ctx, node->name);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100664
665 /* nodetype-specific part */
666 switch(node->nodetype) {
667 case LYS_CONTAINER:
Radek Krejci4f28eda2018-11-12 11:46:16 +0100668 lysc_node_container_free(ctx, (struct lysc_node_container*)node);
669 break;
670 case LYS_LEAF:
671 lysc_node_leaf_free(ctx, (struct lysc_node_leaf*)node);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100672 break;
673 default:
674 LOGINT(ctx);
675 }
676
677 free(node);
678}
679
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200680static void
Radek Krejci4f28eda2018-11-12 11:46:16 +0100681lysc_module_free_(struct lysc_module *module)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200682{
683 struct ly_ctx *ctx;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100684 struct lysc_node *node, *node_next;
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200685
686 LY_CHECK_ARG_RET(NULL, module,);
687 ctx = module->ctx;
688
Radek Krejci4f28eda2018-11-12 11:46:16 +0100689 FREE_STRING(ctx, module->name);
690 FREE_STRING(ctx, module->ns);
691 FREE_STRING(ctx, module->prefix);
692 FREE_STRING(ctx, module->revision);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200693
Radek Krejci478020e2018-10-30 16:02:14 +0100694 FREE_ARRAY(ctx, module->imports, lysc_import_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200695 FREE_ARRAY(ctx, module->features, lysc_feature_free);
Radek Krejci478020e2018-10-30 16:02:14 +0100696 FREE_ARRAY(ctx, module->identities, lysc_ident_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200697
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100698 LY_LIST_FOR_SAFE(module->data, node_next, node) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100699 lysc_node_free(ctx, node);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +0100700 }
701
Radek Krejci478020e2018-10-30 16:02:14 +0100702 FREE_ARRAY(ctx, module->exts, lysc_ext_instance_free);
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200703
704 free(module);
705}
Radek Krejci70853c52018-10-15 14:46:16 +0200706
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200707API void
Radek Krejci86d106e2018-10-18 09:53:19 +0200708lysc_module_free(struct lysc_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200709{
Radek Krejci151a5b72018-10-19 14:21:44 +0200710 if (module) {
Radek Krejci4f28eda2018-11-12 11:46:16 +0100711 lysc_module_free_(module);
Radek Krejci151a5b72018-10-19 14:21:44 +0200712 }
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200713}
714
Radek Krejci86d106e2018-10-18 09:53:19 +0200715void
716lys_module_free(struct lys_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejci70853c52018-10-15 14:46:16 +0200717{
Radek Krejci86d106e2018-10-18 09:53:19 +0200718 if (!module) {
719 return;
720 }
Radek Krejci70853c52018-10-15 14:46:16 +0200721
Radek Krejci86d106e2018-10-18 09:53:19 +0200722 lysc_module_free(module->compiled, private_destructor);
723 lysp_module_free(module->parsed);
724 free(module);
725}
726
Radek Krejci151a5b72018-10-19 14:21:44 +0200727struct iff_stack {
728 int size;
729 int index; /* first empty item */
730 uint8_t *stack;
731};
732
Radek Krejci86d106e2018-10-18 09:53:19 +0200733static LY_ERR
Radek Krejci151a5b72018-10-19 14:21:44 +0200734iff_stack_push(struct iff_stack *stack, uint8_t value)
Radek Krejci86d106e2018-10-18 09:53:19 +0200735{
Radek Krejci151a5b72018-10-19 14:21:44 +0200736 if (stack->index == stack->size) {
737 stack->size += 4;
738 stack->stack = ly_realloc(stack->stack, stack->size * sizeof *stack->stack);
739 LY_CHECK_ERR_RET(!stack->stack, LOGMEM(NULL); stack->size = 0, LY_EMEM);
Radek Krejci70853c52018-10-15 14:46:16 +0200740 }
Radek Krejci151a5b72018-10-19 14:21:44 +0200741 stack->stack[stack->index++] = value;
Radek Krejci70853c52018-10-15 14:46:16 +0200742 return LY_SUCCESS;
743}
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200744
Radek Krejci151a5b72018-10-19 14:21:44 +0200745static uint8_t
746iff_stack_pop(struct iff_stack *stack)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200747{
Radek Krejci151a5b72018-10-19 14:21:44 +0200748 stack->index--;
749 return stack->stack[stack->index];
750}
751
752static void
753iff_stack_clean(struct iff_stack *stack)
754{
755 stack->size = 0;
756 free(stack->stack);
757}
758
759static void
760iff_setop(uint8_t *list, uint8_t op, int pos)
761{
762 uint8_t *item;
763 uint8_t mask = 3;
764
765 assert(pos >= 0);
766 assert(op <= 3); /* max 2 bits */
767
768 item = &list[pos / 4];
769 mask = mask << 2 * (pos % 4);
770 *item = (*item) & ~mask;
771 *item = (*item) | (op << 2 * (pos % 4));
772}
773
774static uint8_t
775iff_getop(uint8_t *list, int pos)
776{
777 uint8_t *item;
778 uint8_t mask = 3, result;
779
780 assert(pos >= 0);
781
782 item = &list[pos / 4];
783 result = (*item) & (mask << 2 * (pos % 4));
784 return result >> 2 * (pos % 4);
785}
786
787#define LYS_IFF_LP 0x04 /* ( */
788#define LYS_IFF_RP 0x08 /* ) */
789
790API int
791lysc_feature_value(const struct lysc_feature *feature)
792{
793 LY_CHECK_ARG_RET(NULL, feature, -1);
794 return feature->flags & LYS_FENABLED ? 1 : 0;
795}
796
797static struct lysc_feature *
798lysc_feature_find(struct lysc_module *mod, const char *name, size_t len)
799{
800 size_t i;
801 struct lysc_feature *f;
802
803 for (i = 0; i < len; ++i) {
804 if (name[i] == ':') {
805 /* we have a prefixed feature */
Radek Krejcibbe09a92018-11-08 09:36:54 +0100806 mod = lysc_module_find_prefix(mod, name, i);
Radek Krejci151a5b72018-10-19 14:21:44 +0200807 LY_CHECK_RET(!mod, NULL);
808
809 name = &name[i + 1];
810 len = len - i - 1;
811 }
812 }
813
814 /* we have the correct module, get the feature */
815 LY_ARRAY_FOR(mod->features, i) {
Radek Krejci2c4e7172018-10-19 15:56:26 +0200816 f = &mod->features[i];
Radek Krejci151a5b72018-10-19 14:21:44 +0200817 if (!strncmp(f->name, name, len) && f->name[len] == '\0') {
818 return f;
819 }
820 }
821
822 return NULL;
823}
824
825static int
826lysc_iffeature_value_(const struct lysc_iffeature *iff, int *index_e, int *index_f)
827{
828 uint8_t op;
829 int a, b;
830
831 op = iff_getop(iff->expr, *index_e);
832 (*index_e)++;
833
834 switch (op) {
835 case LYS_IFF_F:
836 /* resolve feature */
Radek Krejci2c4e7172018-10-19 15:56:26 +0200837 return lysc_feature_value(iff->features[(*index_f)++]);
Radek Krejci151a5b72018-10-19 14:21:44 +0200838 case LYS_IFF_NOT:
839 /* invert result */
840 return lysc_iffeature_value_(iff, index_e, index_f) ? 0 : 1;
841 case LYS_IFF_AND:
842 case LYS_IFF_OR:
843 a = lysc_iffeature_value_(iff, index_e, index_f);
844 b = lysc_iffeature_value_(iff, index_e, index_f);
845 if (op == LYS_IFF_AND) {
846 return a && b;
847 } else { /* LYS_IFF_OR */
848 return a || b;
849 }
850 }
851
852 return 0;
853}
854
855API int
856lysc_iffeature_value(const struct lysc_iffeature *iff)
857{
858 int index_e = 0, index_f = 0;
859
860 LY_CHECK_ARG_RET(NULL, iff, -1);
861
862 if (iff->expr) {
863 return lysc_iffeature_value_(iff, &index_e, &index_f);
864 }
865 return 0;
866}
867
868/*
869 * op: 1 - enable, 0 - disable
870 */
871/**
872 * @brief Enable/Disable the specified feature in the module.
873 *
874 * If the feature is already set to the desired value, LY_SUCCESS is returned.
875 * By changing the feature, also all the feature which depends on it via their
876 * if-feature statements are again evaluated (disabled if a if-feature statemen
877 * evaluates to false).
878 *
879 * @param[in] mod Compiled module where to set (search for) the feature.
880 * @param[in] name Name of the feature to set. Asterisk ('*') can be used to
881 * set all the features in the module.
882 * @param[in] value Desired value of the feature: 1 (enable) or 0 (disable).
883 * @return LY_ERR value.
884 */
885static LY_ERR
886lys_feature_change(const struct lysc_module *mod, const char *name, int value)
887{
888 int all = 0;
Radek Krejcica3db002018-11-01 10:31:01 +0100889 unsigned int u, changed_count, disabled_count;
Radek Krejci151a5b72018-10-19 14:21:44 +0200890 struct lysc_feature *f, **df;
891 struct lysc_iffeature *iff;
892 struct ly_set *changed;
893
894 if (!mod->features) {
895 LOGERR(mod->ctx, LY_EINVAL, "Unable to switch feature since the module \"%s\" has no features.", mod->name);
896 return LY_EINVAL;
897 }
898
899 if (!strcmp(name, "*")) {
900 /* enable all */
901 all = 1;
902 }
903 changed = ly_set_new();
Radek Krejcica3db002018-11-01 10:31:01 +0100904 changed_count = 0;
Radek Krejci151a5b72018-10-19 14:21:44 +0200905
Radek Krejcica3db002018-11-01 10:31:01 +0100906run:
907 for (disabled_count = u = 0; u < LY_ARRAY_SIZE(mod->features); ++u) {
Radek Krejci2c4e7172018-10-19 15:56:26 +0200908 f = &mod->features[u];
Radek Krejci151a5b72018-10-19 14:21:44 +0200909 if (all || !strcmp(f->name, name)) {
910 if ((value && (f->flags & LYS_FENABLED)) || (!value && !(f->flags & LYS_FENABLED))) {
911 if (all) {
912 /* skip already set features */
913 continue;
914 } else {
915 /* feature already set correctly */
916 ly_set_free(changed, NULL);
917 return LY_SUCCESS;
918 }
919 }
920
921 if (value) { /* enable */
922 /* check referenced features if they are enabled */
923 LY_ARRAY_FOR(f->iffeatures, struct lysc_iffeature, iff) {
924 if (!lysc_iffeature_value(iff)) {
925 if (all) {
Radek Krejcica3db002018-11-01 10:31:01 +0100926 ++disabled_count;
Radek Krejci151a5b72018-10-19 14:21:44 +0200927 goto next;
928 } else {
929 LOGERR(mod->ctx, LY_EDENIED,
930 "Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
931 f->name);
932 ly_set_free(changed, NULL);
933 return LY_EDENIED;
934 }
935 }
936 }
937 /* enable the feature */
938 f->flags |= LYS_FENABLED;
939 } else { /* disable */
940 /* disable the feature */
941 f->flags &= ~LYS_FENABLED;
942 }
943
944 /* remember the changed feature */
945 ly_set_add(changed, f, LY_SET_OPT_USEASLIST);
946
947 if (!all) {
948 /* stop in case changing a single feature */
949 break;
950 }
951 }
952next:
953 ;
954 }
955
956 if (!all && !changed->count) {
957 LOGERR(mod->ctx, LY_EINVAL, "Feature \"%s\" not found in module \"%s\".", name, mod->name);
958 ly_set_free(changed, NULL);
959 return LY_EINVAL;
960 }
961
Radek Krejcica3db002018-11-01 10:31:01 +0100962 if (value && all && disabled_count) {
963 if (changed_count == changed->count) {
964 /* no change in last run -> not able to enable all ... */
965 /* ... print errors */
966 for (u = 0; disabled_count && u < LY_ARRAY_SIZE(mod->features); ++u) {
967 if (!(mod->features[u].flags & LYS_FENABLED)) {
968 LOGERR(mod->ctx, LY_EDENIED,
969 "Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
970 mod->features[u].name);
971 --disabled_count;
972 }
973 }
974 /* ... restore the original state */
975 for (u = 0; u < changed->count; ++u) {
976 f = changed->objs[u];
977 /* re-disable the feature */
978 f->flags &= ~LYS_FENABLED;
979 }
980
981 ly_set_free(changed, NULL);
982 return LY_EDENIED;
983 } else {
984 /* we did some change in last run, try it again */
985 changed_count = changed->count;
986 goto run;
987 }
988 }
989
Radek Krejci151a5b72018-10-19 14:21:44 +0200990 /* reflect change(s) in the dependent features */
991 for (u = 0; u < changed->count; ++u) {
992 /* If a dependent feature is enabled, it can be now changed by the change (to false) of the value of
993 * its if-feature statements. The reverse logic, automatically enable feature when its feature is enabled
994 * is not done - by default, features are disabled and must be explicitely enabled. */
995 f = changed->objs[u];
996 LY_ARRAY_FOR(f->depfeatures, struct lysc_feature*, df) {
997 if (!((*df)->flags & LYS_FENABLED)) {
998 /* not enabled, nothing to do */
999 continue;
1000 }
1001 /* check the feature's if-features which could change by the previous change of our feature */
1002 LY_ARRAY_FOR((*df)->iffeatures, struct lysc_iffeature, iff) {
1003 if (!lysc_iffeature_value(iff)) {
1004 /* the feature must be disabled now */
1005 (*df)->flags &= ~LYS_FENABLED;
1006 /* add the feature into the list of changed features */
1007 ly_set_add(changed, *df, LY_SET_OPT_USEASLIST);
1008 break;
1009 }
1010 }
1011 }
1012 }
1013
1014 ly_set_free(changed, NULL);
1015 return LY_SUCCESS;
1016}
1017
1018API LY_ERR
1019lys_feature_enable(struct lys_module *module, const char *feature)
1020{
1021 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, LY_EINVAL);
1022
1023 return lys_feature_change(module->compiled, feature, 1);
1024}
1025
1026API LY_ERR
1027lys_feature_disable(struct lys_module *module, const char *feature)
1028{
1029 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, LY_EINVAL);
1030
1031 return lys_feature_change(module->compiled, feature, 0);
1032}
1033
1034API int
1035lys_feature_value(const struct lys_module *module, const char *feature)
1036{
1037 struct lysc_feature *f;
1038 struct lysc_module *mod;
1039 unsigned int u;
1040
1041 LY_CHECK_ARG_RET(NULL, module, module->compiled, feature, -1);
1042 mod = module->compiled;
1043
1044 /* search for the specified feature */
1045 for (u = 0; u < LY_ARRAY_SIZE(mod->features); ++u) {
Radek Krejci2c4e7172018-10-19 15:56:26 +02001046 f = &mod->features[u];
Radek Krejci151a5b72018-10-19 14:21:44 +02001047 if (!strcmp(f->name, feature)) {
1048 if (f->flags & LYS_FENABLED) {
1049 return 1;
1050 } else {
1051 return 0;
1052 }
1053 }
1054 }
1055
1056 /* feature definition not found */
1057 return -1;
1058}
1059
1060static LY_ERR
Radek Krejci4f28eda2018-11-12 11:46:16 +01001061lys_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 +02001062{
Radek Krejcice8c1592018-10-29 15:35:51 +01001063 const char *name;
1064 unsigned int u;
1065 const struct lys_module *mod;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001066 struct lysp_ext *edef = NULL;
Radek Krejcice8c1592018-10-29 15:35:51 +01001067
Radek Krejci0f07bed2018-11-13 14:01:40 +01001068 DUP_STRING(ctx->ctx, ext->argument, ext_p->argument);
Radek Krejcice8c1592018-10-29 15:35:51 +01001069 ext->insubstmt = ext_p->insubstmt;
1070 ext->insubstmt_index = ext_p->insubstmt_index;
1071
1072 /* get module where the extension definition should be placed */
1073 for (u = 0; ext_p->name[u] != ':'; ++u);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001074 mod = lys_module_find_prefix(ctx->mod, ext_p->name, u);
1075 LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcice8c1592018-10-29 15:35:51 +01001076 "Invalid prefix \"%.*s\" used for extension instance identifier.", u, ext_p->name),
1077 LY_EVALID);
1078 LY_CHECK_ERR_RET(!mod->parsed->extensions,
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001079 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcice8c1592018-10-29 15:35:51 +01001080 "Extension instance \"%s\" refers \"%s\" module that does not contain extension definitions.",
1081 ext_p->name, mod->parsed->name),
1082 LY_EVALID);
1083 name = &ext_p->name[u + 1];
1084 /* find the extension definition there */
1085 for (ext = NULL, u = 0; u < LY_ARRAY_SIZE(mod->parsed->extensions); ++u) {
1086 if (!strcmp(name, mod->parsed->extensions[u].name)) {
1087 edef = &mod->parsed->extensions[u];
1088 break;
1089 }
1090 }
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001091 LY_CHECK_ERR_RET(!edef, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcice8c1592018-10-29 15:35:51 +01001092 "Extension definition of extension instance \"%s\" not found.", ext_p->name),
1093 LY_EVALID);
1094 /* TODO plugins */
1095
1096 return LY_SUCCESS;
1097}
1098
Radek Krejcice8c1592018-10-29 15:35:51 +01001099static LY_ERR
1100lys_compile_iffeature(struct lysc_ctx *ctx, const char **value, int UNUSED(options), struct lysc_iffeature *iff)
1101{
1102 const char *c = *value;
Radek Krejci151a5b72018-10-19 14:21:44 +02001103 int r, rc = EXIT_FAILURE;
1104 int i, j, last_not, checkversion = 0;
1105 unsigned int f_size = 0, expr_size = 0, f_exp = 1;
1106 uint8_t op;
1107 struct iff_stack stack = {0, 0, NULL};
Radek Krejcice8c1592018-10-29 15:35:51 +01001108 struct lysc_feature *f;
Radek Krejci151a5b72018-10-19 14:21:44 +02001109
1110 assert(c);
1111
1112 /* pre-parse the expression to get sizes for arrays, also do some syntax checks of the expression */
1113 for (i = j = last_not = 0; c[i]; i++) {
1114 if (c[i] == '(') {
1115 j++;
1116 checkversion = 1;
1117 continue;
1118 } else if (c[i] == ')') {
1119 j--;
1120 continue;
1121 } else if (isspace(c[i])) {
1122 checkversion = 1;
1123 continue;
1124 }
1125
1126 if (!strncmp(&c[i], "not", r = 3) || !strncmp(&c[i], "and", r = 3) || !strncmp(&c[i], "or", r = 2)) {
1127 if (c[i + r] == '\0') {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001128 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001129 "Invalid value \"%s\" of if-feature - unexpected end of expression.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001130 return LY_EVALID;
1131 } else if (!isspace(c[i + r])) {
1132 /* feature name starting with the not/and/or */
1133 last_not = 0;
1134 f_size++;
1135 } else if (c[i] == 'n') { /* not operation */
1136 if (last_not) {
1137 /* double not */
1138 expr_size = expr_size - 2;
1139 last_not = 0;
1140 } else {
1141 last_not = 1;
1142 }
1143 } else { /* and, or */
1144 f_exp++;
1145 /* not a not operation */
1146 last_not = 0;
1147 }
1148 i += r;
1149 } else {
1150 f_size++;
1151 last_not = 0;
1152 }
1153 expr_size++;
1154
1155 while (!isspace(c[i])) {
1156 if (!c[i] || c[i] == ')') {
1157 i--;
1158 break;
1159 }
1160 i++;
1161 }
1162 }
1163 if (j || f_exp != f_size) {
1164 /* not matching count of ( and ) */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001165 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001166 "Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001167 return LY_EVALID;
1168 }
1169
1170 if (checkversion || expr_size > 1) {
1171 /* check that we have 1.1 module */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001172 if (ctx->mod->compiled->version != LYS_VERSION_1_1) {
1173 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001174 "Invalid value \"%s\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001175 return LY_EVALID;
1176 }
1177 }
1178
1179 /* allocate the memory */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001180 LY_ARRAY_CREATE_RET(ctx->ctx, iff->features, f_size, LY_EMEM);
Radek Krejci151a5b72018-10-19 14:21:44 +02001181 iff->expr = calloc((j = (expr_size / 4) + ((expr_size % 4) ? 1 : 0)), sizeof *iff->expr);
Radek Krejci151a5b72018-10-19 14:21:44 +02001182 stack.stack = malloc(expr_size * sizeof *stack.stack);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001183 LY_CHECK_ERR_GOTO(!stack.stack || !iff->expr, LOGMEM(ctx->ctx), error);
Radek Krejci151a5b72018-10-19 14:21:44 +02001184
Radek Krejci151a5b72018-10-19 14:21:44 +02001185 stack.size = expr_size;
1186 f_size--; expr_size--; /* used as indexes from now */
1187
1188 for (i--; i >= 0; i--) {
1189 if (c[i] == ')') {
1190 /* push it on stack */
1191 iff_stack_push(&stack, LYS_IFF_RP);
1192 continue;
1193 } else if (c[i] == '(') {
1194 /* pop from the stack into result all operators until ) */
1195 while((op = iff_stack_pop(&stack)) != LYS_IFF_RP) {
1196 iff_setop(iff->expr, op, expr_size--);
1197 }
1198 continue;
1199 } else if (isspace(c[i])) {
1200 continue;
1201 }
1202
1203 /* end of operator or operand -> find beginning and get what is it */
1204 j = i + 1;
1205 while (i >= 0 && !isspace(c[i]) && c[i] != '(') {
1206 i--;
1207 }
1208 i++; /* go back by one step */
1209
1210 if (!strncmp(&c[i], "not", 3) && isspace(c[i + 3])) {
1211 if (stack.index && stack.stack[stack.index - 1] == LYS_IFF_NOT) {
1212 /* double not */
1213 iff_stack_pop(&stack);
1214 } else {
1215 /* not has the highest priority, so do not pop from the stack
1216 * as in case of AND and OR */
1217 iff_stack_push(&stack, LYS_IFF_NOT);
1218 }
1219 } else if (!strncmp(&c[i], "and", 3) && isspace(c[i + 3])) {
1220 /* as for OR - pop from the stack all operators with the same or higher
1221 * priority and store them to the result, then push the AND to the stack */
1222 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_AND) {
1223 op = iff_stack_pop(&stack);
1224 iff_setop(iff->expr, op, expr_size--);
1225 }
1226 iff_stack_push(&stack, LYS_IFF_AND);
1227 } else if (!strncmp(&c[i], "or", 2) && isspace(c[i + 2])) {
1228 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_OR) {
1229 op = iff_stack_pop(&stack);
1230 iff_setop(iff->expr, op, expr_size--);
1231 }
1232 iff_stack_push(&stack, LYS_IFF_OR);
1233 } else {
1234 /* feature name, length is j - i */
1235
1236 /* add it to the expression */
1237 iff_setop(iff->expr, LYS_IFF_F, expr_size--);
1238
1239 /* now get the link to the feature definition */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001240 f = lysc_feature_find(ctx->mod->compiled, &c[i], j - i);
Radek Krejci151a5b72018-10-19 14:21:44 +02001241 LY_CHECK_ERR_GOTO(!f,
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001242 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001243 "Invalid value \"%s\" of if-feature - unable to find feature \"%.*s\".", *value, j - i, &c[i]);
Radek Krejci87616bb2018-10-31 13:30:52 +01001244 rc = LY_EVALID,
Radek Krejci151a5b72018-10-19 14:21:44 +02001245 error)
Radek Krejci2c4e7172018-10-19 15:56:26 +02001246 iff->features[f_size] = f;
1247 LY_ARRAY_INCREMENT(iff->features);
Radek Krejci151a5b72018-10-19 14:21:44 +02001248 f_size--;
1249 }
1250 }
1251 while (stack.index) {
1252 op = iff_stack_pop(&stack);
1253 iff_setop(iff->expr, op, expr_size--);
1254 }
1255
1256 if (++expr_size || ++f_size) {
1257 /* not all expected operators and operands found */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001258 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejcice8c1592018-10-29 15:35:51 +01001259 "Invalid value \"%s\" of if-feature - processing error.", *value);
Radek Krejci151a5b72018-10-19 14:21:44 +02001260 rc = LY_EINT;
1261 } else {
1262 rc = LY_SUCCESS;
1263 }
1264
1265error:
1266 /* cleanup */
1267 iff_stack_clean(&stack);
1268
1269 return rc;
1270}
1271
1272static LY_ERR
Radek Krejci4f28eda2018-11-12 11:46:16 +01001273lys_compile_when(struct lysc_ctx *ctx, struct lysp_when *when_p, int options, struct lysc_when *when)
1274{
1275 unsigned int u;
1276 LY_ERR ret = LY_SUCCESS;
1277
1278 when->cond = lyxp_expr_parse(ctx->ctx, when_p->cond);
1279 LY_CHECK_ERR_GOTO(!when->cond, ret = ly_errcode(ctx->ctx), done);
1280 COMPILE_ARRAY_GOTO(ctx, when_p->exts, when->exts, options, u, lys_compile_ext, ret, done);
1281
1282done:
1283 return ret;
1284}
1285
1286static LY_ERR
1287lys_compile_must(struct lysc_ctx *ctx, struct lysp_restr *must_p, int options, struct lysc_must *must)
1288{
1289 unsigned int u;
1290 LY_ERR ret = LY_SUCCESS;
1291
1292 must->cond = lyxp_expr_parse(ctx->ctx, must_p->arg);
1293 LY_CHECK_ERR_GOTO(!must->cond, ret = ly_errcode(ctx->ctx), done);
1294
Radek Krejci0f07bed2018-11-13 14:01:40 +01001295 DUP_STRING(ctx->ctx, must->eapptag, must_p->eapptag);
1296 DUP_STRING(ctx->ctx, must->emsg, must_p->emsg);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001297 COMPILE_ARRAY_GOTO(ctx, must_p->exts, must->exts, options, u, lys_compile_ext, ret, done);
1298
1299done:
1300 return ret;
1301}
1302
1303static LY_ERR
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001304lys_compile_import(struct lysc_ctx *ctx, struct lysp_import *imp_p, int options, struct lysc_import *imp)
1305{
Radek Krejcice8c1592018-10-29 15:35:51 +01001306 unsigned int u;
Radek Krejcif8f882a2018-10-31 14:51:15 +01001307 struct lys_module *mod = NULL;
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001308 struct lysc_module *comp;
Radek Krejcice8c1592018-10-29 15:35:51 +01001309 LY_ERR ret = LY_SUCCESS;
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001310
Radek Krejci0f07bed2018-11-13 14:01:40 +01001311 DUP_STRING(ctx->ctx, imp->prefix, imp_p->prefix);
Radek Krejcice8c1592018-10-29 15:35:51 +01001312 COMPILE_ARRAY_GOTO(ctx, imp_p->exts, imp->exts, options, u, lys_compile_ext, ret, done);
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001313 imp->module = imp_p->module;
1314
1315 /* make sure that we have both versions (lysp_ and lysc_) of the imported module. To import groupings or
1316 * typedefs, the lysp_ is needed. To augment or deviate imported module, we need the lysc_ structure */
1317 if (!imp->module->parsed) {
1318 comp = imp->module->compiled;
1319 /* try to get filepath from the compiled version */
1320 if (comp->filepath) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001321 mod = (struct lys_module*)lys_parse_path(ctx->ctx, comp->filepath,
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001322 !strcmp(&comp->filepath[strlen(comp->filepath - 4)], ".yin") ? LYS_IN_YIN : LYS_IN_YANG);
1323 if (mod != imp->module) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001324 LOGERR(ctx->ctx, LY_EINT, "Filepath \"%s\" of the module \"%s\" does not match.",
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001325 comp->filepath, comp->name);
1326 mod = NULL;
1327 }
1328 }
1329 if (!mod) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001330 if (lysp_load_module(ctx->ctx, comp->name, comp->revision, 0, 1, &mod)) {
1331 LOGERR(ctx->ctx, LY_ENOTFOUND, "Unable to reload \"%s\" module to import it into \"%s\", source data not found.",
1332 comp->name, ctx->mod->compiled->name);
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001333 return LY_ENOTFOUND;
1334 }
1335 }
1336 } else if (!imp->module->compiled) {
Radek Krejcif8f882a2018-10-31 14:51:15 +01001337 return lys_compile(imp->module, options);
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001338 }
1339
Radek Krejcice8c1592018-10-29 15:35:51 +01001340done:
1341 return ret;
Radek Krejci6d6e4e42018-10-29 13:28:19 +01001342}
1343
1344static LY_ERR
Radek Krejci2a408df2018-10-29 16:32:26 +01001345lys_compile_identity(struct lysc_ctx *ctx, struct lysp_ident *ident_p, int options, struct lysc_ident *ident)
1346{
1347 unsigned int u;
1348 LY_ERR ret = LY_SUCCESS;
1349
Radek Krejci0f07bed2018-11-13 14:01:40 +01001350 DUP_STRING(ctx->ctx, ident->name, ident_p->name);
Radek Krejci2a408df2018-10-29 16:32:26 +01001351 COMPILE_ARRAY_GOTO(ctx, ident_p->iffeatures, ident->iffeatures, options, u, lys_compile_iffeature, ret, done);
1352 /* backlings (derived) can be added no sooner than when all the identities in the current module are present */
1353 COMPILE_ARRAY_GOTO(ctx, ident_p->exts, ident->exts, options, u, lys_compile_ext, ret, done);
1354 ident->flags = ident_p->flags;
1355
1356done:
1357 return ret;
1358}
1359
1360static LY_ERR
1361lys_compile_identities_derived(struct lysc_ctx *ctx, struct lysp_ident *idents_p, struct lysc_ident *idents)
1362{
1363 unsigned int i, u, v;
1364 const char *s, *name;
1365 struct lysc_module *mod;
1366 struct lysc_ident **dident;
1367
1368 for (i = 0; i < LY_ARRAY_SIZE(idents_p); ++i) {
Radek Krejci478020e2018-10-30 16:02:14 +01001369 if (!idents_p[i].bases) {
1370 continue;
1371 }
Radek Krejci2a408df2018-10-29 16:32:26 +01001372 for (u = 0; u < LY_ARRAY_SIZE(idents_p[i].bases); ++u) {
1373 s = strchr(idents_p[i].bases[u], ':');
1374 if (s) {
1375 /* prefixed identity */
1376 name = &s[1];
Radek Krejcibbe09a92018-11-08 09:36:54 +01001377 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 +01001378 } else {
1379 name = idents_p[i].bases[u];
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001380 mod = ctx->mod->compiled;
Radek Krejci2a408df2018-10-29 16:32:26 +01001381 }
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001382 LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejci2a408df2018-10-29 16:32:26 +01001383 "Invalid prefix used for base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
1384 LY_EVALID);
1385 if (mod->identities) {
1386 for (v = 0; v < LY_ARRAY_SIZE(mod->identities); ++v) {
1387 if (!strcmp(name, mod->identities[v].name)) {
1388 /* we have match! store the backlink */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001389 LY_ARRAY_NEW_RET(ctx->ctx, mod->identities[v].derived, dident, LY_EMEM);
Radek Krejci2a408df2018-10-29 16:32:26 +01001390 *dident = &idents[i];
1391 break;
1392 }
1393 }
1394 }
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001395 LY_CHECK_ERR_RET(!dident, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Radek Krejci2a408df2018-10-29 16:32:26 +01001396 "Unable to find base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
1397 LY_EVALID);
1398 }
1399 }
1400 return LY_SUCCESS;
1401}
1402
1403static LY_ERR
Radek Krejci151a5b72018-10-19 14:21:44 +02001404lys_compile_feature(struct lysc_ctx *ctx, struct lysp_feature *feature_p, int options, struct lysc_feature *feature)
1405{
Radek Krejcice8c1592018-10-29 15:35:51 +01001406 unsigned int u, v;
1407 LY_ERR ret = LY_SUCCESS;
1408 struct lysc_feature **df;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001409
Radek Krejci0f07bed2018-11-13 14:01:40 +01001410 DUP_STRING(ctx->ctx, feature->name, feature_p->name);
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001411 feature->flags = feature_p->flags;
1412
Radek Krejcice8c1592018-10-29 15:35:51 +01001413 COMPILE_ARRAY_GOTO(ctx, feature_p->exts, feature->exts, options, u, lys_compile_ext, ret, done);
1414 COMPILE_ARRAY_GOTO(ctx, feature_p->iffeatures, feature->iffeatures, options, u, lys_compile_iffeature, ret, done);
1415 if (feature->iffeatures) {
1416 for (u = 0; u < LY_ARRAY_SIZE(feature->iffeatures); ++u) {
1417 if (feature->iffeatures[u].features) {
1418 for (v = 0; v < LY_ARRAY_SIZE(feature->iffeatures[u].features); ++v) {
1419 /* add itself into the dependants list */
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01001420 LY_ARRAY_NEW_RET(ctx->ctx, feature->iffeatures[u].features[v]->depfeatures, df, LY_EMEM);
Radek Krejcice8c1592018-10-29 15:35:51 +01001421 *df = feature;
1422 }
1423 /* TODO check for circular dependency */
1424 }
Radek Krejci151a5b72018-10-19 14:21:44 +02001425 }
Radek Krejci86d106e2018-10-18 09:53:19 +02001426 }
Radek Krejcice8c1592018-10-29 15:35:51 +01001427done:
1428 return ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001429}
1430
Radek Krejci4f28eda2018-11-12 11:46:16 +01001431static LY_ERR
1432range_part_check_value_syntax(struct lysc_ctx *ctx, LY_DATA_TYPE basetype, const char *value, size_t *len, char **valcopy)
1433{
1434 size_t fraction = 0;
1435 *len = 0;
1436
1437 assert(value);
1438 /* parse value */
1439 if (!isdigit(value[*len]) && (value[*len] != '-') && (value[*len] != '+')) {
1440 return LY_EVALID;
1441 }
1442
1443 if ((value[*len] == '-') || (value[*len] == '+')) {
1444 ++(*len);
1445 }
1446
1447 while (isdigit(value[*len])) {
1448 ++(*len);
1449 }
1450
1451 if ((basetype != LY_TYPE_DEC64) || (value[*len] != '.') || !isdigit(value[*len + 1])) {
1452 *valcopy = strndup(value, *len);
1453 return LY_SUCCESS;
1454 }
1455 fraction = *len;
1456
1457 ++(*len);
1458 while (isdigit(value[*len])) {
1459 ++(*len);
1460 }
1461
1462 if (fraction) {
1463 *valcopy = malloc(((*len) - 1) * sizeof **valcopy);
1464 LY_CHECK_ERR_RET(!(*valcopy), LOGMEM(ctx->ctx), LY_EMEM);
1465
1466 *valcopy[(*len) - 1] = '\0';
1467 memcpy(&(*valcopy)[0], &value[0], fraction);
1468 memcpy(&(*valcopy)[fraction], &value[fraction + 1], (*len) - 1 - (fraction + 1));
1469 }
1470 return LY_SUCCESS;
1471}
1472
1473static LY_ERR
1474range_part_check_ascendance(int unsigned_value, int64_t value, int64_t prev_value)
1475{
1476 if (unsigned_value) {
1477 if ((uint64_t)prev_value >= (uint64_t)value) {
1478 return LY_EEXIST;
1479 }
1480 } else {
1481 if (prev_value >= value) {
1482 return LY_EEXIST;
1483 }
1484 }
1485 return LY_SUCCESS;
1486}
1487
1488static LY_ERR
1489range_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,
1490 const char **value)
1491{
1492 LY_ERR ret = LY_SUCCESS;
1493 char *valcopy = NULL;
1494 size_t len;
1495
1496 if (value) {
1497 ret = range_part_check_value_syntax(ctx, basetype, *value, &len, &valcopy);
1498 LY_CHECK_GOTO(ret, error);
1499 }
1500
1501 switch (basetype) {
1502 case LY_TYPE_BINARY: /* length */
1503 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001504 ret = ly_parse_uint(valcopy, UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001505 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001506 part->max_u64 = UINT64_C(18446744073709551615);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001507 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001508 part->min_u64 = UINT64_C(0);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001509 }
1510 if (!first) {
1511 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1512 }
1513 break;
1514 case LY_TYPE_DEC64: /* range */
1515 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001516 ret = ly_parse_int(valcopy, INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807), 10,
Radek Krejci4f28eda2018-11-12 11:46:16 +01001517 max ? &part->max_64 : &part->min_64);
1518 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001519 part->max_64 = INT64_C(9223372036854775807);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001520 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001521 part->min_64 = INT64_C(-9223372036854775807) - INT64_C(1);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001522 }
1523 if (!first) {
1524 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1525 }
1526 break;
1527 case LY_TYPE_INT8: /* range */
1528 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001529 ret = ly_parse_int(valcopy, INT64_C(-128), INT64_C(127), 10, max ? &part->max_64 : &part->min_64);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001530 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001531 part->max_64 = INT64_C(127);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001532 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001533 part->min_64 = INT64_C(-128);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001534 }
1535 if (!first) {
1536 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1537 }
1538 break;
1539 case LY_TYPE_INT16: /* range */
1540 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001541 ret = ly_parse_int(valcopy, INT64_C(-32768), INT64_C(32767), 10, max ? &part->max_64 : &part->min_64);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001542 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001543 part->max_64 = INT64_C(32767);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001544 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001545 part->min_64 = INT64_C(-32768);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001546 }
1547 if (!first) {
1548 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1549 }
1550 break;
1551 case LY_TYPE_INT32: /* range */
1552 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001553 ret = ly_parse_int(valcopy, INT64_C(-2147483648), INT64_C(2147483647), 10, max ? &part->max_64 : &part->min_64);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001554 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001555 part->max_64 = INT64_C(2147483647);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001556 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001557 part->min_64 = INT64_C(-2147483648);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001558 }
1559 if (!first) {
1560 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1561 }
1562 break;
1563 case LY_TYPE_INT64: /* range */
1564 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001565 ret = ly_parse_int(valcopy, INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807), 10,
Radek Krejci4f28eda2018-11-12 11:46:16 +01001566 max ? &part->max_64 : &part->min_64);
1567 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001568 part->max_64 = INT64_C(9223372036854775807);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001569 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001570 part->min_64 = INT64_C(-9223372036854775807) - INT64_C(1);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001571 }
1572 if (!first) {
1573 ret = range_part_check_ascendance(0, max ? part->max_64 : part->min_64, prev);
1574 }
1575 break;
1576 case LY_TYPE_UINT8: /* range */
1577 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001578 ret = ly_parse_uint(valcopy, UINT64_C(255), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001579 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001580 part->max_u64 = UINT64_C(255);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001581 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001582 part->min_u64 = UINT64_C(0);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001583 }
1584 if (!first) {
1585 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1586 }
1587 break;
1588 case LY_TYPE_UINT16: /* range */
1589 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001590 ret = ly_parse_uint(valcopy, UINT64_C(65535), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001591 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001592 part->max_u64 = UINT64_C(65535);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001593 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001594 part->min_u64 = UINT64_C(0);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001595 }
1596 if (!first) {
1597 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1598 }
1599 break;
1600 case LY_TYPE_UINT32: /* range */
1601 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001602 ret = ly_parse_uint(valcopy, UINT64_C(4294967295), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001603 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001604 part->max_u64 = UINT64_C(4294967295);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001605 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001606 part->min_u64 = UINT64_C(0);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001607 }
1608 if (!first) {
1609 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1610 }
1611 break;
1612 case LY_TYPE_UINT64: /* range */
1613 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001614 ret = ly_parse_uint(valcopy, UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001615 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001616 part->max_u64 = UINT64_C(18446744073709551615);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001617 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001618 part->min_u64 = UINT64_C(0);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001619 }
1620 if (!first) {
1621 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1622 }
1623 break;
1624 case LY_TYPE_STRING: /* length */
1625 if (valcopy) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001626 ret = ly_parse_uint(valcopy, UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001627 } else if (max) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001628 part->max_u64 = UINT64_C(18446744073709551615);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001629 } else {
Radek Krejci0f07bed2018-11-13 14:01:40 +01001630 part->min_u64 = UINT64_C(0);
Radek Krejci4f28eda2018-11-12 11:46:16 +01001631 }
1632 if (!first) {
1633 ret = range_part_check_ascendance(1, max ? part->max_64 : part->min_64, prev);
1634 }
1635 break;
1636 default:
1637 LOGINT(ctx->ctx);
1638 ret = LY_EINT;
1639 }
1640
1641error:
1642 if (ret == LY_EDENIED) {
1643 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1644 "Invalid %s restriction - value \"%s\" does not fit the type limitations.",
1645 length_restr ? "length" : "range", valcopy ? valcopy : *value);
1646 } else if (ret == LY_EVALID) {
1647 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1648 "Invalid %s restriction - invalid value \"%s\".",
1649 length_restr ? "length" : "range", valcopy ? valcopy : *value);
1650 } else if (ret == LY_EEXIST) {
1651 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1652 "Invalid %s restriction - values are not in ascending order (%s).",
1653 length_restr ? "length" : "range", valcopy ? valcopy : *value);
1654 } else if (!ret && value) {
1655 *value = *value + len;
1656 }
1657 free(valcopy);
1658 return ret;
1659}
1660
1661static LY_ERR
1662lys_compile_type_range(struct lysc_ctx *ctx, struct lysp_restr *range_p, LY_DATA_TYPE basetype, int length_restr,
Radek Krejcib31c8992018-11-12 16:29:16 +01001663 struct lysc_range *base_range, struct lysc_range **range)
Radek Krejci4f28eda2018-11-12 11:46:16 +01001664{
1665 LY_ERR ret = LY_EVALID;
1666 const char *expr;
1667 struct lysc_range_part *parts = NULL, *part;
Radek Krejcib31c8992018-11-12 16:29:16 +01001668 int range_expected = 0, uns;
1669 unsigned int parts_done = 0, u, v;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001670
1671 assert(range);
1672 assert(range_p);
1673
Radek Krejci4f28eda2018-11-12 11:46:16 +01001674 expr = range_p->arg;
1675 while(1) {
1676 if (isspace(*expr)) {
1677 ++expr;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001678 } else if (*expr == '\0') {
Radek Krejcib31c8992018-11-12 16:29:16 +01001679 if (range_expected) {
1680 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1681 "Invalid %s restriction - unexpected end of the expression after \"..\" (%s).",
1682 length_restr ? "length" : "range", range_p->arg);
1683 goto cleanup;
1684 } else if (!parts || parts_done == LY_ARRAY_SIZE(parts)) {
1685 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1686 "Invalid %s restriction - unexpected end of the expression (%s).",
1687 length_restr ? "length" : "range", range_p->arg);
1688 goto cleanup;
1689 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01001690 parts_done++;
1691 break;
1692 } else if (!strncmp(expr, "min", 3)) {
1693 if (parts) {
1694 /* min cannot be used elsewhere than in the first part */
1695 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1696 "Invalid %s restriction - unexpected data before min keyword (%.*s).", length_restr ? "length" : "range",
1697 expr - range_p->arg, range_p->arg);
1698 goto cleanup;
1699 }
1700 expr += 3;
1701
1702 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1703 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, 0, basetype, 1, length_restr, NULL), cleanup);
1704 part->max_64 = part->min_64;
1705 } else if (*expr == '|') {
1706 if (!parts || range_expected) {
1707 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1708 "Invalid %s restriction - unexpected beginning of the expression (%s).", length_restr ? "length" : "range", expr);
1709 goto cleanup;
1710 }
1711 expr++;
1712 parts_done++;
1713 /* process next part of the expression */
Radek Krejci4f28eda2018-11-12 11:46:16 +01001714 } else if (!strncmp(expr, "..", 2)) {
1715 expr += 2;
1716 while (isspace(*expr)) {
1717 expr++;
1718 }
Radek Krejcib31c8992018-11-12 16:29:16 +01001719 if (!parts || LY_ARRAY_SIZE(parts) == parts_done) {
Radek Krejci4f28eda2018-11-12 11:46:16 +01001720 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1721 "Invalid %s restriction - unexpected \"..\" without a lower bound.", length_restr ? "length" : "range");
1722 goto cleanup;
1723 }
1724 /* continue expecting the upper boundary */
1725 range_expected = 1;
1726 } else if (isdigit(*expr) || (*expr == '-') || (*expr == '+')) {
1727 /* number */
1728 if (range_expected) {
1729 part = &parts[LY_ARRAY_SIZE(parts) - 1];
1730 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, &expr), cleanup);
Radek Krejcib31c8992018-11-12 16:29:16 +01001731 range_expected = 0;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001732 } else {
1733 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1734 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
1735 basetype, parts_done ? 0 : 1, length_restr, &expr), cleanup);
1736 part->max_64 = part->min_64;
1737 }
1738
1739 /* continue with possible another expression part */
Radek Krejci4f28eda2018-11-12 11:46:16 +01001740 } else if (!strncmp(expr, "max", 3)) {
1741 expr += 3;
1742 while (isspace(*expr)) {
1743 expr++;
1744 }
1745 if (*expr != '\0') {
1746 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data after max keyword (%s).",
1747 length_restr ? "length" : "range", expr);
1748 goto cleanup;
1749 }
1750 if (range_expected) {
1751 part = &parts[LY_ARRAY_SIZE(parts) - 1];
1752 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, NULL), cleanup);
Radek Krejcib31c8992018-11-12 16:29:16 +01001753 range_expected = 0;
Radek Krejci4f28eda2018-11-12 11:46:16 +01001754 } else {
1755 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1756 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
1757 basetype, parts_done ? 0 : 1, length_restr, NULL), cleanup);
1758 part->min_64 = part->max_64;
1759 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01001760 } else {
1761 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data (%s).",
1762 length_restr ? "length" : "range", expr);
1763 goto cleanup;
1764 }
1765 }
1766
Radek Krejcib31c8992018-11-12 16:29:16 +01001767 /* check with the previous range/length restriction */
1768 if (base_range) {
1769 switch (basetype) {
1770 case LY_TYPE_BINARY:
1771 case LY_TYPE_UINT8:
1772 case LY_TYPE_UINT16:
1773 case LY_TYPE_UINT32:
1774 case LY_TYPE_UINT64:
1775 case LY_TYPE_STRING:
1776 uns = 1;
1777 break;
1778 case LY_TYPE_DEC64:
1779 case LY_TYPE_INT8:
1780 case LY_TYPE_INT16:
1781 case LY_TYPE_INT32:
1782 case LY_TYPE_INT64:
1783 uns = 0;
1784 break;
1785 default:
1786 LOGINT(ctx->ctx);
1787 ret = LY_EINT;
1788 goto cleanup;
1789 }
1790 for (u = v = 0; u < parts_done && v < LY_ARRAY_SIZE(base_range->parts); ++u) {
1791 if ((uns && parts[u].min_u64 < base_range->parts[v].min_u64) || (!uns && parts[u].min_64 < base_range->parts[v].min_64)) {
1792 goto baseerror;
1793 }
1794 /* current lower bound is not lower than the base */
1795 if (base_range->parts[v].min_64 == base_range->parts[v].max_64) {
1796 /* base has single value */
1797 if (base_range->parts[v].min_64 == parts[u].min_64) {
1798 /* both lower bounds are the same */
1799 if (parts[u].min_64 != parts[u].max_64) {
1800 /* current continues with a range */
1801 goto baseerror;
1802 } else {
1803 /* equal single values, move both forward */
1804 ++v;
1805 continue;
1806 }
1807 } else {
1808 /* base is single value lower than current range, so the
1809 * value from base range is removed in the current,
1810 * move only base and repeat checking */
1811 ++v;
1812 --u;
1813 continue;
1814 }
1815 } else {
1816 /* base is the range */
1817 if (parts[u].min_64 == parts[u].max_64) {
1818 /* current is a single value */
1819 if ((uns && parts[u].max_u64 > base_range->parts[v].max_u64) || (!uns && parts[u].max_64 > base_range->parts[v].max_64)) {
1820 /* current is behind the base range, so base range is omitted,
1821 * move the base and keep the current for further check */
1822 ++v;
1823 --u;
1824 } /* else it is within the base range, so move the current, but keep the base */
1825 continue;
1826 } else {
1827 /* both are ranges - check the higher bound, the lower was already checked */
1828 if ((uns && parts[u].max_u64 > base_range->parts[v].max_u64) || (!uns && parts[u].max_64 > base_range->parts[v].max_64)) {
1829 /* higher bound is higher than the current higher bound */
1830 if ((uns && parts[u].min_u64 > base_range->parts[v].max_u64) || (!uns && parts[u].min_64 > base_range->parts[v].max_64)) {
1831 /* but the current lower bound is also higher, so the base range is omitted,
1832 * continue with the same current, but move the base */
1833 --u;
1834 ++v;
1835 continue;
1836 }
1837 /* current range starts within the base range but end behind it */
1838 goto baseerror;
1839 } else {
1840 /* current range is smaller than the base,
1841 * move current, but stay with the base */
1842 continue;
1843 }
1844 }
1845 }
1846 }
1847 if (u != parts_done) {
1848baseerror:
1849 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1850 "Invalid %s restriction - the derived restriction (%s) is not equally or more limiting.",
1851 length_restr ? "length" : "range", range_p->arg);
1852 goto cleanup;
1853 }
1854 }
1855
1856 if (!(*range)) {
1857 *range = calloc(1, sizeof **range);
1858 LY_CHECK_ERR_RET(!(*range), LOGMEM(ctx->ctx), LY_EMEM);
1859 }
1860
1861 if (range_p->eapptag) {
1862 lydict_remove(ctx->ctx, (*range)->eapptag);
1863 (*range)->eapptag = lydict_insert(ctx->ctx, range_p->eapptag, 0);
1864 }
1865 if (range_p->emsg) {
1866 lydict_remove(ctx->ctx, (*range)->emsg);
1867 (*range)->emsg = lydict_insert(ctx->ctx, range_p->emsg, 0);
1868 }
1869 /* extensions are taken only from the last range by the caller */
1870
Radek Krejci4f28eda2018-11-12 11:46:16 +01001871 (*range)->parts = parts;
1872 parts = NULL;
1873 ret = LY_SUCCESS;
1874cleanup:
1875 /* TODO clean up */
1876 LY_ARRAY_FREE(parts);
1877
1878 return ret;
1879}
1880
Radek Krejci4586a022018-11-13 11:29:26 +01001881/**
1882 * @brief Checks pattern syntax.
1883 *
1884 * @param[in] pattern Pattern to check.
1885 * @param[out] pcre_precomp Precompiled PCRE pattern. Can be NULL.
1886 * @return EXIT_SUCCESS on success, EXIT_FAILURE otherwise.
1887 */
1888static LY_ERR
1889lys_compile_type_pattern_check(struct lysc_ctx *ctx, const char *pattern, pcre **pcre_precomp)
1890{
1891 int idx, idx2, start, end, err_offset, count;
1892 char *perl_regex, *ptr;
1893 const char *err_msg, *orig_ptr;
1894 pcre *precomp;
1895#define URANGE_LEN 19
1896 char *ublock2urange[][2] = {
1897 {"BasicLatin", "[\\x{0000}-\\x{007F}]"},
1898 {"Latin-1Supplement", "[\\x{0080}-\\x{00FF}]"},
1899 {"LatinExtended-A", "[\\x{0100}-\\x{017F}]"},
1900 {"LatinExtended-B", "[\\x{0180}-\\x{024F}]"},
1901 {"IPAExtensions", "[\\x{0250}-\\x{02AF}]"},
1902 {"SpacingModifierLetters", "[\\x{02B0}-\\x{02FF}]"},
1903 {"CombiningDiacriticalMarks", "[\\x{0300}-\\x{036F}]"},
1904 {"Greek", "[\\x{0370}-\\x{03FF}]"},
1905 {"Cyrillic", "[\\x{0400}-\\x{04FF}]"},
1906 {"Armenian", "[\\x{0530}-\\x{058F}]"},
1907 {"Hebrew", "[\\x{0590}-\\x{05FF}]"},
1908 {"Arabic", "[\\x{0600}-\\x{06FF}]"},
1909 {"Syriac", "[\\x{0700}-\\x{074F}]"},
1910 {"Thaana", "[\\x{0780}-\\x{07BF}]"},
1911 {"Devanagari", "[\\x{0900}-\\x{097F}]"},
1912 {"Bengali", "[\\x{0980}-\\x{09FF}]"},
1913 {"Gurmukhi", "[\\x{0A00}-\\x{0A7F}]"},
1914 {"Gujarati", "[\\x{0A80}-\\x{0AFF}]"},
1915 {"Oriya", "[\\x{0B00}-\\x{0B7F}]"},
1916 {"Tamil", "[\\x{0B80}-\\x{0BFF}]"},
1917 {"Telugu", "[\\x{0C00}-\\x{0C7F}]"},
1918 {"Kannada", "[\\x{0C80}-\\x{0CFF}]"},
1919 {"Malayalam", "[\\x{0D00}-\\x{0D7F}]"},
1920 {"Sinhala", "[\\x{0D80}-\\x{0DFF}]"},
1921 {"Thai", "[\\x{0E00}-\\x{0E7F}]"},
1922 {"Lao", "[\\x{0E80}-\\x{0EFF}]"},
1923 {"Tibetan", "[\\x{0F00}-\\x{0FFF}]"},
1924 {"Myanmar", "[\\x{1000}-\\x{109F}]"},
1925 {"Georgian", "[\\x{10A0}-\\x{10FF}]"},
1926 {"HangulJamo", "[\\x{1100}-\\x{11FF}]"},
1927 {"Ethiopic", "[\\x{1200}-\\x{137F}]"},
1928 {"Cherokee", "[\\x{13A0}-\\x{13FF}]"},
1929 {"UnifiedCanadianAboriginalSyllabics", "[\\x{1400}-\\x{167F}]"},
1930 {"Ogham", "[\\x{1680}-\\x{169F}]"},
1931 {"Runic", "[\\x{16A0}-\\x{16FF}]"},
1932 {"Khmer", "[\\x{1780}-\\x{17FF}]"},
1933 {"Mongolian", "[\\x{1800}-\\x{18AF}]"},
1934 {"LatinExtendedAdditional", "[\\x{1E00}-\\x{1EFF}]"},
1935 {"GreekExtended", "[\\x{1F00}-\\x{1FFF}]"},
1936 {"GeneralPunctuation", "[\\x{2000}-\\x{206F}]"},
1937 {"SuperscriptsandSubscripts", "[\\x{2070}-\\x{209F}]"},
1938 {"CurrencySymbols", "[\\x{20A0}-\\x{20CF}]"},
1939 {"CombiningMarksforSymbols", "[\\x{20D0}-\\x{20FF}]"},
1940 {"LetterlikeSymbols", "[\\x{2100}-\\x{214F}]"},
1941 {"NumberForms", "[\\x{2150}-\\x{218F}]"},
1942 {"Arrows", "[\\x{2190}-\\x{21FF}]"},
1943 {"MathematicalOperators", "[\\x{2200}-\\x{22FF}]"},
1944 {"MiscellaneousTechnical", "[\\x{2300}-\\x{23FF}]"},
1945 {"ControlPictures", "[\\x{2400}-\\x{243F}]"},
1946 {"OpticalCharacterRecognition", "[\\x{2440}-\\x{245F}]"},
1947 {"EnclosedAlphanumerics", "[\\x{2460}-\\x{24FF}]"},
1948 {"BoxDrawing", "[\\x{2500}-\\x{257F}]"},
1949 {"BlockElements", "[\\x{2580}-\\x{259F}]"},
1950 {"GeometricShapes", "[\\x{25A0}-\\x{25FF}]"},
1951 {"MiscellaneousSymbols", "[\\x{2600}-\\x{26FF}]"},
1952 {"Dingbats", "[\\x{2700}-\\x{27BF}]"},
1953 {"BraillePatterns", "[\\x{2800}-\\x{28FF}]"},
1954 {"CJKRadicalsSupplement", "[\\x{2E80}-\\x{2EFF}]"},
1955 {"KangxiRadicals", "[\\x{2F00}-\\x{2FDF}]"},
1956 {"IdeographicDescriptionCharacters", "[\\x{2FF0}-\\x{2FFF}]"},
1957 {"CJKSymbolsandPunctuation", "[\\x{3000}-\\x{303F}]"},
1958 {"Hiragana", "[\\x{3040}-\\x{309F}]"},
1959 {"Katakana", "[\\x{30A0}-\\x{30FF}]"},
1960 {"Bopomofo", "[\\x{3100}-\\x{312F}]"},
1961 {"HangulCompatibilityJamo", "[\\x{3130}-\\x{318F}]"},
1962 {"Kanbun", "[\\x{3190}-\\x{319F}]"},
1963 {"BopomofoExtended", "[\\x{31A0}-\\x{31BF}]"},
1964 {"EnclosedCJKLettersandMonths", "[\\x{3200}-\\x{32FF}]"},
1965 {"CJKCompatibility", "[\\x{3300}-\\x{33FF}]"},
1966 {"CJKUnifiedIdeographsExtensionA", "[\\x{3400}-\\x{4DB5}]"},
1967 {"CJKUnifiedIdeographs", "[\\x{4E00}-\\x{9FFF}]"},
1968 {"YiSyllables", "[\\x{A000}-\\x{A48F}]"},
1969 {"YiRadicals", "[\\x{A490}-\\x{A4CF}]"},
1970 {"HangulSyllables", "[\\x{AC00}-\\x{D7A3}]"},
1971 {"PrivateUse", "[\\x{E000}-\\x{F8FF}]"},
1972 {"CJKCompatibilityIdeographs", "[\\x{F900}-\\x{FAFF}]"},
1973 {"AlphabeticPresentationForms", "[\\x{FB00}-\\x{FB4F}]"},
1974 {"ArabicPresentationForms-A", "[\\x{FB50}-\\x{FDFF}]"},
1975 {"CombiningHalfMarks", "[\\x{FE20}-\\x{FE2F}]"},
1976 {"CJKCompatibilityForms", "[\\x{FE30}-\\x{FE4F}]"},
1977 {"SmallFormVariants", "[\\x{FE50}-\\x{FE6F}]"},
1978 {"ArabicPresentationForms-B", "[\\x{FE70}-\\x{FEFE}]"},
1979 {"HalfwidthandFullwidthForms", "[\\x{FF00}-\\x{FFEF}]"},
1980 {NULL, NULL}
1981 };
1982
1983 /* adjust the expression to a Perl equivalent
1984 * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs */
1985
1986 /* we need to replace all "$" with "\$", count them now */
Radek Krejcicda74152018-11-13 15:27:32 +01001987 for (count = 0, ptr = strpbrk(pattern, "^$"); ptr; ++count, ptr = strpbrk(ptr + 1, "^$"));
Radek Krejci4586a022018-11-13 11:29:26 +01001988
1989 perl_regex = malloc((strlen(pattern) + 4 + count) * sizeof(char));
1990 LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx->ctx), LY_EMEM);
1991 perl_regex[0] = '\0';
1992
1993 ptr = perl_regex;
1994
1995 if (strncmp(pattern + strlen(pattern) - 2, ".*", 2)) {
Radek Krejcicda74152018-11-13 15:27:32 +01001996 /* we will add line-end anchoring */
Radek Krejci4586a022018-11-13 11:29:26 +01001997 ptr[0] = '(';
1998 ++ptr;
1999 }
2000
2001 for (orig_ptr = pattern; orig_ptr[0]; ++orig_ptr) {
2002 if (orig_ptr[0] == '$') {
2003 ptr += sprintf(ptr, "\\$");
Radek Krejcicda74152018-11-13 15:27:32 +01002004 } else if (orig_ptr[0] == '^') {
2005 ptr += sprintf(ptr, "\\^");
Radek Krejci4586a022018-11-13 11:29:26 +01002006 } else {
2007 ptr[0] = orig_ptr[0];
2008 ++ptr;
2009 }
2010 }
2011
2012 if (strncmp(pattern + strlen(pattern) - 2, ".*", 2)) {
2013 ptr += sprintf(ptr, ")$");
2014 } else {
2015 ptr[0] = '\0';
2016 ++ptr;
2017 }
2018
2019 /* substitute Unicode Character Blocks with exact Character Ranges */
2020 while ((ptr = strstr(perl_regex, "\\p{Is"))) {
2021 start = ptr - perl_regex;
2022
2023 ptr = strchr(ptr, '}');
2024 if (!ptr) {
2025 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_INREGEXP,
2026 pattern, perl_regex + start + 2, "unterminated character property");
2027 free(perl_regex);
2028 return LY_EVALID;
2029 }
2030 end = (ptr - perl_regex) + 1;
2031
2032 /* need more space */
2033 if (end - start < URANGE_LEN) {
2034 perl_regex = ly_realloc(perl_regex, strlen(perl_regex) + (URANGE_LEN - (end - start)) + 1);
2035 LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx->ctx); free(perl_regex), LY_EMEM);
2036 }
2037
2038 /* find our range */
2039 for (idx = 0; ublock2urange[idx][0]; ++idx) {
2040 if (!strncmp(perl_regex + start + 5, ublock2urange[idx][0], strlen(ublock2urange[idx][0]))) {
2041 break;
2042 }
2043 }
2044 if (!ublock2urange[idx][0]) {
2045 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_INREGEXP,
2046 pattern, perl_regex + start + 5, "unknown block name");
2047 free(perl_regex);
2048 return LY_EVALID;
2049 }
2050
2051 /* make the space in the string and replace the block (but we cannot include brackets if it was already enclosed in them) */
2052 for (idx2 = 0, count = 0; idx2 < start; ++idx2) {
2053 if ((perl_regex[idx2] == '[') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
2054 ++count;
2055 }
2056 if ((perl_regex[idx2] == ']') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
2057 --count;
2058 }
2059 }
2060 if (count) {
2061 /* skip brackets */
2062 memmove(perl_regex + start + (URANGE_LEN - 2), perl_regex + end, strlen(perl_regex + end) + 1);
2063 memcpy(perl_regex + start, ublock2urange[idx][1] + 1, URANGE_LEN - 2);
2064 } else {
2065 memmove(perl_regex + start + URANGE_LEN, perl_regex + end, strlen(perl_regex + end) + 1);
2066 memcpy(perl_regex + start, ublock2urange[idx][1], URANGE_LEN);
2067 }
2068 }
2069
2070 /* must return 0, already checked during parsing */
Radek Krejcicda74152018-11-13 15:27:32 +01002071 precomp = pcre_compile(perl_regex, PCRE_UTF8 | PCRE_ANCHORED | PCRE_DOLLAR_ENDONLY | PCRE_NO_AUTO_CAPTURE,
Radek Krejci4586a022018-11-13 11:29:26 +01002072 &err_msg, &err_offset, NULL);
2073 if (!precomp) {
2074 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_INREGEXP, pattern, perl_regex + err_offset, err_msg);
2075 free(perl_regex);
2076 return LY_EVALID;
2077 }
2078 free(perl_regex);
2079
2080 if (pcre_precomp) {
2081 *pcre_precomp = precomp;
2082 } else {
2083 free(precomp);
2084 }
2085
2086 return LY_SUCCESS;
2087
2088#undef URANGE_LEN
2089}
2090
2091static LY_ERR
2092lys_compile_type_patterns(struct lysc_ctx *ctx, struct lysp_restr *patterns_p, int options,
2093 struct lysc_pattern **base_patterns, struct lysc_pattern ***patterns)
2094{
Radek Krejci56aa27c2018-11-13 14:21:59 +01002095 struct lysc_pattern **result = NULL, **pattern;
Radek Krejci4586a022018-11-13 11:29:26 +01002096 unsigned int u, v;
2097 const char *err_msg;
2098 LY_ERR ret;
2099
2100 /* first, copy the patterns from the base type */
2101 if (base_patterns) {
2102 result = lysc_patterns_dup(ctx->ctx, base_patterns);
2103 LY_CHECK_ERR_RET(!result, LOGMEM(ctx->ctx), LY_EMEM);
2104 }
2105
2106 LY_ARRAY_FOR(patterns_p, u) {
2107 LY_ARRAY_NEW_GOTO(ctx->ctx, result, pattern, ret, cleanup);
2108 *pattern = calloc(1, sizeof **pattern);
2109 ++(*pattern)->refcount;
2110
2111 ret = lys_compile_type_pattern_check(ctx, &patterns_p[u].arg[1], &(*pattern)->expr);
2112 LY_CHECK_GOTO(ret, cleanup);
2113 (*pattern)->expr_extra = pcre_study((*pattern)->expr, 0, &err_msg);
2114 if (err_msg) {
2115 LOGWRN(ctx->ctx, "Studying pattern \"%s\" failed (%s).", pattern, err_msg);
2116 }
2117
2118 if (patterns_p[u].arg[0] == 0x15) {
2119 (*pattern)->inverted = 1;
2120 }
Radek Krejci0f07bed2018-11-13 14:01:40 +01002121 DUP_STRING(ctx->ctx, (*pattern)->eapptag, patterns_p[u].eapptag);
2122 DUP_STRING(ctx->ctx, (*pattern)->emsg, patterns_p[u].emsg);
Radek Krejci4586a022018-11-13 11:29:26 +01002123 COMPILE_ARRAY_GOTO(ctx, patterns_p[u].exts, (*pattern)->exts,
2124 options, v, lys_compile_ext, ret, cleanup);
2125 }
2126
2127 (*patterns) = result;
2128 result = NULL;
2129 ret = LY_SUCCESS;
2130
2131cleanup:
2132 FREE_ARRAY(ctx->ctx, result, lysc_pattern_free);
2133
2134 return ret;
2135}
2136
Radek Krejcid505e3d2018-11-13 09:04:17 +01002137static uint16_t type_substmt_map[LY_DATA_TYPE_COUNT] = {
2138 0 /* LY_TYPE_UNKNOWN */,
2139 LYS_SET_LENGTH /* LY_TYPE_BINARY */,
2140 LYS_SET_BIT /* LY_TYPE_BITS */,
2141 0 /* LY_TYPE_BOOL */,
2142 LYS_SET_FRDIGITS | LYS_SET_RANGE /* LY_TYPE_DEC64 */,
2143 0 /* LY_TYPE_EMPTY */,
2144 LYS_SET_ENUM /* LY_TYPE_ENUM */,
2145 LYS_SET_BASE /* LY_TYPE_IDENT */,
2146 LYS_SET_REQINST /* LY_TYPE_INST */,
2147 LYS_SET_REQINST | LYS_SET_PATH /* LY_TYPE_LEAFREF */,
2148 LYS_SET_LENGTH | LYS_SET_PATTERN /* LY_TYPE_STRING */,
2149 LYS_SET_TYPE /* LY_TYPE_UNION */,
2150 LYS_SET_RANGE /* LY_TYPE_INT8 */,
2151 LYS_SET_RANGE /* LY_TYPE_UINT8 */,
2152 LYS_SET_RANGE /* LY_TYPE_INT16 */,
2153 LYS_SET_RANGE /* LY_TYPE_UINT16 */,
2154 LYS_SET_RANGE /* LY_TYPE_INT32 */,
2155 LYS_SET_RANGE /* LY_TYPE_UINT32 */,
2156 LYS_SET_RANGE /* LY_TYPE_INT64 */,
2157 LYS_SET_RANGE /* LY_TYPE_UINT64 */
2158};
2159
Radek Krejci4f28eda2018-11-12 11:46:16 +01002160static LY_ERR
Radek Krejci8b764662018-11-14 14:15:13 +01002161lys_compile_type_enums(struct lysc_ctx *ctx, struct lysp_type_enum *enums_p, LY_DATA_TYPE basetype, int options,
2162 struct lysc_type_enum_item *base_enums, struct lysc_type_enum_item **enums)
2163{
2164 LY_ERR ret = LY_SUCCESS;
2165 unsigned int u, v, match;
2166 int32_t value = 0;
2167 uint32_t position = 0;
2168 struct lysc_type_enum_item *e;
2169
2170 LY_ARRAY_FOR(enums_p, u) {
2171 LY_ARRAY_NEW_RET(ctx->ctx, *enums, e, LY_EMEM);
2172 DUP_STRING(ctx->ctx, e->name, enums_p[u].name);
2173 if (base_enums) {
2174 /* check the enum/bit presence in the base type - the set of enums/bits in the derived type must be a subset */
2175 LY_ARRAY_FOR(base_enums, v) {
2176 if (!strcmp(e->name, base_enums[v].name)) {
2177 break;
2178 }
2179 }
2180 if (v == LY_ARRAY_SIZE(base_enums)) {
2181 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2182 "Invalid %s - derived type adds new item \"%s\".",
2183 basetype == LY_TYPE_ENUM ? "enumeration" : "bits", e->name);
2184 return LY_EVALID;
2185 }
2186 match = v;
2187 }
2188
2189 if (basetype == LY_TYPE_ENUM) {
2190 if (enums_p[u].flags & LYS_SET_VALUE) {
2191 e->value = (int32_t)enums_p[u].value;
2192 if (!u || e->value >= value) {
2193 value = e->value + 1;
2194 }
2195 /* check collision with other values */
2196 for (v = 0; v < LY_ARRAY_SIZE(*enums) - 1; ++v) {
2197 if (e->value == (*enums)[v].value) {
2198 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2199 "Invalid enumeration - value %d collide in items \"%s\" and \"%s\".",
2200 e->value, e->name, (*enums)[v].name);
2201 return LY_EVALID;
2202 }
2203 }
2204 } else if (base_enums) {
2205 /* inherit the assigned value */
2206 e->value = base_enums[match].value;
2207 if (!u || e->value >= value) {
2208 value = e->value + 1;
2209 }
2210 } else {
2211 /* assign value automatically */
2212 if (u && value == INT32_MIN) {
2213 /* counter overflow */
2214 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2215 "Invalid enumeration - it is not possible to auto-assign enum value for "
2216 "\"%s\" since the highest value is already 2147483647.", e->name);
2217 return LY_EVALID;
2218 }
2219 e->value = value++;
2220 }
2221 } else { /* LY_TYPE_BITS */
2222 if (enums_p[u].flags & LYS_SET_VALUE) {
2223 e->value = (int32_t)enums_p[u].value;
2224 if (!u || (uint32_t)e->value >= position) {
2225 position = (uint32_t)e->value + 1;
2226 }
2227 /* check collision with other values */
2228 for (v = 0; v < LY_ARRAY_SIZE(*enums) - 1; ++v) {
2229 if (e->value == (*enums)[v].value) {
2230 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2231 "Invalid bits - position %u collide in items \"%s\" and \"%s\".",
2232 (uint32_t)e->value, e->name, (*enums)[v].name);
2233 return LY_EVALID;
2234 }
2235 }
2236 } else if (base_enums) {
2237 /* inherit the assigned value */
2238 e->value = base_enums[match].value;
2239 if (!u || (uint32_t)e->value >= position) {
2240 position = (uint32_t)e->value + 1;
2241 }
2242 } else {
2243 /* assign value automatically */
2244 if (u && position == 0) {
2245 /* counter overflow */
2246 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2247 "Invalid bits - it is not possible to auto-assign bit position for "
2248 "\"%s\" since the highest value is already 4294967295.", e->name);
2249 return LY_EVALID;
2250 }
2251 e->value = position++;
2252 }
2253 }
2254
2255 if (base_enums) {
2256 /* the assigned values must not change from the derived type */
2257 if (e->value != base_enums[match].value) {
2258 if (basetype == LY_TYPE_ENUM) {
2259 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2260 "Invalid enumeration - value of the item \"%s\" has changed from %d to %d in the derived type.",
2261 e->name, base_enums[match].value, e->value);
2262 } else {
2263 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2264 "Invalid bits - position of the item \"%s\" has changed from %u to %u in the derived type.",
2265 e->name, (uint32_t)base_enums[match].value, (uint32_t)e->value);
2266 }
2267 return LY_EVALID;
2268 }
2269 }
2270
2271 COMPILE_ARRAY_GOTO(ctx, enums_p[u].iffeatures, e->iffeatures, options, v, lys_compile_iffeature, ret, done);
2272 COMPILE_ARRAY_GOTO(ctx, enums_p[u].exts, e->exts, options, u, lys_compile_ext, ret, done);
2273 }
2274
2275done:
2276 return ret;
2277}
2278
2279static LY_ERR
Radek Krejci4f28eda2018-11-12 11:46:16 +01002280lys_compile_type(struct lysc_ctx *ctx, struct lysp_node_leaf *leaf_p, int options, struct lysc_type **type)
2281{
2282 LY_ERR ret = LY_SUCCESS;
2283 unsigned int u;
2284 struct lysp_type *type_p = &leaf_p->type;
2285 struct type_context {
2286 const struct lysp_tpdf *tpdf;
2287 struct lysp_node *node;
2288 struct lysp_module *mod;
2289 } *tctx, *tctx_prev = NULL;
2290 LY_DATA_TYPE basetype = LY_TYPE_UNKNOWN;
Radek Krejcib31c8992018-11-12 16:29:16 +01002291 struct lysc_type *base = NULL;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002292 struct ly_set tpdf_chain = {0};
Radek Krejci8b764662018-11-14 14:15:13 +01002293 struct lysc_type_bin *bin;
2294 struct lysc_type_num *num;
2295 struct lysc_type_str *str;
2296 struct lysc_type_bits *bits;
2297 struct lysc_type_enum *enumeration;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002298
Radek Krejci9a191e62018-11-13 13:19:56 +01002299 (*type) = NULL;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002300
2301 tctx = calloc(1, sizeof *tctx);
2302 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
2303 for (ret = lysp_type_find(type_p->name, (struct lysp_node*)leaf_p, ctx->mod->parsed,
2304 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod);
Radek Krejcib31c8992018-11-12 16:29:16 +01002305 ret == LY_SUCCESS;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002306 ret = lysp_type_find(tctx_prev->tpdf->type.name, tctx_prev->node, tctx_prev->mod,
2307 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod)) {
2308 if (basetype) {
2309 break;
2310 }
2311
2312 /* check status */
Radek Krejci4586a022018-11-13 11:29:26 +01002313 ret = lysc_check_status(ctx, leaf_p->flags, ctx->mod->parsed, leaf_p->name,
2314 tctx->tpdf->flags, tctx->mod, tctx->node ? tctx->node->name : tctx->mod->name);
2315 LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
Radek Krejci4f28eda2018-11-12 11:46:16 +01002316
Radek Krejcib31c8992018-11-12 16:29:16 +01002317 if (tctx->tpdf->type.compiled) {
2318 /* it is not necessary to continue, the rest of the chain was already compiled */
2319 basetype = tctx->tpdf->type.compiled->basetype;
2320 ly_set_add(&tpdf_chain, tctx, LY_SET_OPT_USEASLIST);
2321 tctx = NULL;
2322 break;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002323 }
2324
2325 /* store information for the following processing */
2326 ly_set_add(&tpdf_chain, tctx, LY_SET_OPT_USEASLIST);
2327
2328 /* prepare next loop */
Radek Krejcib31c8992018-11-12 16:29:16 +01002329 tctx_prev = tctx;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002330 tctx = calloc(1, sizeof *tctx);
2331 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
2332 }
2333 free(tctx);
2334
2335 /* allocate type according to the basetype */
2336 switch (basetype) {
2337 case LY_TYPE_BINARY:
2338 *type = calloc(1, sizeof(struct lysc_type_bin));
2339 bin = (struct lysc_type_bin*)(*type);
2340 break;
2341 case LY_TYPE_BITS:
2342 *type = calloc(1, sizeof(struct lysc_type_bits));
Radek Krejci8b764662018-11-14 14:15:13 +01002343 bits = (struct lysc_type_bits*)(*type);
Radek Krejci4f28eda2018-11-12 11:46:16 +01002344 break;
2345 case LY_TYPE_BOOL:
2346 case LY_TYPE_EMPTY:
2347 *type = calloc(1, sizeof(struct lysc_type));
2348 break;
2349 case LY_TYPE_DEC64:
2350 *type = calloc(1, sizeof(struct lysc_type_dec));
2351 break;
2352 case LY_TYPE_ENUM:
2353 *type = calloc(1, sizeof(struct lysc_type_enum));
Radek Krejci8b764662018-11-14 14:15:13 +01002354 enumeration = (struct lysc_type_enum*)(*type);
Radek Krejci4f28eda2018-11-12 11:46:16 +01002355 break;
2356 case LY_TYPE_IDENT:
2357 *type = calloc(1, sizeof(struct lysc_type_identityref));
2358 break;
2359 case LY_TYPE_INST:
2360 *type = calloc(1, sizeof(struct lysc_type_instanceid));
2361 break;
2362 case LY_TYPE_LEAFREF:
2363 *type = calloc(1, sizeof(struct lysc_type_leafref));
2364 break;
2365 case LY_TYPE_STRING:
2366 *type = calloc(1, sizeof(struct lysc_type_str));
Radek Krejci4586a022018-11-13 11:29:26 +01002367 str = (struct lysc_type_str*)(*type);
Radek Krejci4f28eda2018-11-12 11:46:16 +01002368 break;
2369 case LY_TYPE_UNION:
2370 *type = calloc(1, sizeof(struct lysc_type_union));
2371 break;
2372 case LY_TYPE_INT8:
2373 case LY_TYPE_UINT8:
2374 case LY_TYPE_INT16:
2375 case LY_TYPE_UINT16:
2376 case LY_TYPE_INT32:
2377 case LY_TYPE_UINT32:
2378 case LY_TYPE_INT64:
2379 case LY_TYPE_UINT64:
2380 *type = calloc(1, sizeof(struct lysc_type_num));
Radek Krejci4586a022018-11-13 11:29:26 +01002381 num = (struct lysc_type_num*)(*type);
Radek Krejci4f28eda2018-11-12 11:46:16 +01002382 break;
Radek Krejcib31c8992018-11-12 16:29:16 +01002383 case LY_TYPE_UNKNOWN:
Radek Krejci4586a022018-11-13 11:29:26 +01002384 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Radek Krejcib31c8992018-11-12 16:29:16 +01002385 "Referenced type \"%s\" not found.", tctx_prev ? tctx_prev->tpdf->type.name : type_p->name);
Radek Krejci4586a022018-11-13 11:29:26 +01002386 ret = LY_EVALID;
Radek Krejcib31c8992018-11-12 16:29:16 +01002387 goto cleanup;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002388 }
2389 LY_CHECK_ERR_GOTO(!(*type), LOGMEM(ctx->ctx), cleanup);
Radek Krejci4586a022018-11-13 11:29:26 +01002390 if (~type_substmt_map[basetype] & leaf_p->type.flags) {
2391 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid type restrictions for %s type.",
2392 ly_data_type2str[basetype]);
Radek Krejci9a191e62018-11-13 13:19:56 +01002393 free(*type);
2394 (*type) = NULL;
Radek Krejci4586a022018-11-13 11:29:26 +01002395 ret = LY_EVALID;
2396 goto cleanup;
2397 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01002398
2399 /* get restrictions from the referred typedefs */
2400 for (u = tpdf_chain.count - 1; u + 1 > 0; --u) {
2401 tctx = (struct type_context*)tpdf_chain.objs[u];
Radek Krejcid505e3d2018-11-13 09:04:17 +01002402 if (~type_substmt_map[basetype] & tctx->tpdf->type.flags) {
2403 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid type \"%s\" restriction(s) for %s type.",
Radek Krejci4586a022018-11-13 11:29:26 +01002404 tctx->tpdf->name, ly_data_type2str[basetype]);
2405 ret = LY_EVALID;
Radek Krejcid505e3d2018-11-13 09:04:17 +01002406 goto cleanup;
2407 } else if (tctx->tpdf->type.compiled) {
Radek Krejcib31c8992018-11-12 16:29:16 +01002408 base = tctx->tpdf->type.compiled;
2409 continue;
Radek Krejci9a191e62018-11-13 13:19:56 +01002410 } else if ((u != tpdf_chain.count - 1) && !(tctx->tpdf->type.flags)) {
2411 /* no change, just use the type information from the base */
Radek Krejcib31c8992018-11-12 16:29:16 +01002412 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = ((struct type_context*)tpdf_chain.objs[u + 1])->tpdf->type.compiled;
2413 ++base->refcount;
2414 continue;
2415 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01002416
Radek Krejcib31c8992018-11-12 16:29:16 +01002417 ++(*type)->refcount;
2418 (*type)->basetype = basetype;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002419 switch (basetype) {
2420 case LY_TYPE_BINARY:
2421 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
2422 if (tctx->tpdf->type.length) {
Radek Krejcib31c8992018-11-12 16:29:16 +01002423 ret = lys_compile_type_range(ctx, tctx->tpdf->type.length, basetype, 1,
2424 base ? ((struct lysc_type_bin*)base)->length : NULL, &bin->length);
Radek Krejci4f28eda2018-11-12 11:46:16 +01002425 LY_CHECK_GOTO(ret, cleanup);
2426 }
Radek Krejcib31c8992018-11-12 16:29:16 +01002427
2428 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = *type;
2429 *type = calloc(1, sizeof(struct lysc_type_bin));
2430 bin = (struct lysc_type_bin*)(*type);
Radek Krejci4f28eda2018-11-12 11:46:16 +01002431 break;
Radek Krejci8b764662018-11-14 14:15:13 +01002432 case LY_TYPE_BITS:
2433 /* RFC 6020 9.6 - enum */
2434 if (tctx->tpdf->type.bits) {
2435 ret = lys_compile_type_enums(ctx, tctx->tpdf->type.bits, basetype, options,
2436 base ? (struct lysc_type_enum_item*)((struct lysc_type_bits*)base)->bits : NULL,
2437 (struct lysc_type_enum_item**)&bits->bits);
2438 LY_CHECK_GOTO(ret, cleanup);
2439 }
2440
2441 if ((u == tpdf_chain.count - 1) && !(tctx->tpdf->type.flags)) {
2442 /* type derived from bits built-in type must contain at least one bit */
2443 if (!bits->bits) {
2444 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2445 "Missing bit substatement for bits type \"%s\".", tctx->tpdf->name);
2446 ret = LY_EVALID;
2447 goto cleanup;
2448 }
2449 }
2450
2451 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = *type;
2452 *type = calloc(1, sizeof(struct lysc_type_bits));
2453 bits = (struct lysc_type_bits*)(*type);
2454 break;
Radek Krejci4586a022018-11-13 11:29:26 +01002455 case LY_TYPE_STRING:
2456 /* RFC 6020 9.4.4 - length */
2457 if (tctx->tpdf->type.length) {
2458 ret = lys_compile_type_range(ctx, tctx->tpdf->type.length, basetype, 1,
2459 base ? ((struct lysc_type_str*)base)->length : NULL, &str->length);
2460 LY_CHECK_GOTO(ret, cleanup);
2461 } else if (base && ((struct lysc_type_str*)base)->length) {
2462 str->length = lysc_range_dup(ctx->ctx, ((struct lysc_type_str*)base)->length);
2463 }
2464
2465 /* RFC 6020 9.4.6 - pattern */
2466 if (tctx->tpdf->type.patterns) {
2467 ret = lys_compile_type_patterns(ctx, tctx->tpdf->type.patterns, options,
2468 base ? ((struct lysc_type_str*)base)->patterns : NULL, &str->patterns);
2469 LY_CHECK_GOTO(ret, cleanup);
2470 } else if (base && ((struct lysc_type_str*)base)->patterns) {
2471 str->patterns = lysc_patterns_dup(ctx->ctx, ((struct lysc_type_str*)base)->patterns);
2472 }
2473
2474 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = *type;
2475 *type = calloc(1, sizeof(struct lysc_type_str));
2476 str = (struct lysc_type_str*)(*type);
2477 break;
Radek Krejci8b764662018-11-14 14:15:13 +01002478 case LY_TYPE_ENUM:
2479 /* RFC 6020 9.6 - enum */
2480 if (tctx->tpdf->type.enums) {
2481 ret = lys_compile_type_enums(ctx, tctx->tpdf->type.enums, basetype, options,
2482 base ? ((struct lysc_type_enum*)base)->enums : NULL, &enumeration->enums);
2483 LY_CHECK_GOTO(ret, cleanup);
2484 }
2485
2486 if ((u == tpdf_chain.count - 1) && !(tctx->tpdf->type.flags)) {
2487 /* type derived from enumerations built-in type must contain at least one enum */
2488 if (!enumeration->enums) {
2489 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2490 "Missing enum substatement for enumeration type \"%s\".", tctx->tpdf->name);
2491 ret = LY_EVALID;
2492 goto cleanup;
2493 }
2494 }
2495
2496 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = *type;
2497 *type = calloc(1, sizeof(struct lysc_type_enum));
2498 enumeration = (struct lysc_type_enum*)(*type);
2499 break;
Radek Krejci4586a022018-11-13 11:29:26 +01002500 case LY_TYPE_INT8:
2501 case LY_TYPE_UINT8:
2502 case LY_TYPE_INT16:
2503 case LY_TYPE_UINT16:
2504 case LY_TYPE_INT32:
2505 case LY_TYPE_UINT32:
2506 case LY_TYPE_INT64:
2507 case LY_TYPE_UINT64:
2508 /* RFC 6020 9.2.4 - range */
2509 if (tctx->tpdf->type.range) {
2510 ret = lys_compile_type_range(ctx, tctx->tpdf->type.range, basetype, 1,
2511 base ? ((struct lysc_type_num*)base)->range : NULL, &num->range);
2512 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci4586a022018-11-13 11:29:26 +01002513 }
2514
2515 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = *type;
2516 *type = calloc(1, sizeof(struct lysc_type_num));
2517 num = (struct lysc_type_num*)(*type);
2518 break;
2519 case LY_TYPE_BOOL:
2520 case LY_TYPE_EMPTY:
2521 case LY_TYPE_UNKNOWN: /* just to complete switch */
2522 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = *type;
2523 *type = calloc(1, sizeof(struct lysc_type));
2524 break;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002525 }
Radek Krejci4586a022018-11-13 11:29:26 +01002526 LY_CHECK_ERR_GOTO(!(*type), LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
Radek Krejcib31c8992018-11-12 16:29:16 +01002527
Radek Krejci4f28eda2018-11-12 11:46:16 +01002528 }
2529
Radek Krejci9a191e62018-11-13 13:19:56 +01002530 if (leaf_p->type.flags) {
2531 /* get restrictions from the node itself, finalize the type structure */
2532 (*type)->basetype = basetype;
2533 ++(*type)->refcount;
2534 switch (basetype) {
2535 case LY_TYPE_BINARY:
2536 if (leaf_p->type.length) {
2537 ret = lys_compile_type_range(ctx, leaf_p->type.length, basetype, 1,
2538 base ? ((struct lysc_type_bin*)base)->length : NULL, &bin->length);
2539 LY_CHECK_GOTO(ret, cleanup);
2540 COMPILE_ARRAY_GOTO(ctx, leaf_p->type.length->exts, bin->length->exts,
2541 options, u, lys_compile_ext, ret, cleanup);
Radek Krejci9a191e62018-11-13 13:19:56 +01002542 }
2543 break;
Radek Krejci8b764662018-11-14 14:15:13 +01002544 case LY_TYPE_BITS:
2545 if (leaf_p->type.bits) {
2546 ret = lys_compile_type_enums(ctx, leaf_p->type.bits, basetype, options,
2547 base ? (struct lysc_type_enum_item*)((struct lysc_type_bits*)base)->bits : NULL,
2548 (struct lysc_type_enum_item**)&bits->bits);
2549 LY_CHECK_GOTO(ret, cleanup);
2550 }
2551 break;
Radek Krejci9a191e62018-11-13 13:19:56 +01002552 case LY_TYPE_STRING:
2553 if (leaf_p->type.length) {
2554 ret = lys_compile_type_range(ctx, leaf_p->type.length, basetype, 1,
2555 base ? ((struct lysc_type_str*)base)->length : NULL, &str->length);
2556 LY_CHECK_GOTO(ret, cleanup);
2557 COMPILE_ARRAY_GOTO(ctx, leaf_p->type.length->exts, str->length->exts,
2558 options, u, lys_compile_ext, ret, cleanup);
2559 } else if (base && ((struct lysc_type_str*)base)->length) {
2560 str->length = lysc_range_dup(ctx->ctx, ((struct lysc_type_str*)base)->length);
2561 }
Radek Krejci4586a022018-11-13 11:29:26 +01002562
Radek Krejci9a191e62018-11-13 13:19:56 +01002563 if (leaf_p->type.patterns) {
2564 ret = lys_compile_type_patterns(ctx, leaf_p->type.patterns, options,
2565 base ? ((struct lysc_type_str*)base)->patterns : NULL, &str->patterns);
2566 LY_CHECK_GOTO(ret, cleanup);
2567 } else if (base && ((struct lysc_type_str*)base)->patterns) {
2568 str->patterns = lysc_patterns_dup(ctx->ctx, ((struct lysc_type_str*)base)->patterns);
2569 }
2570 break;
Radek Krejci8b764662018-11-14 14:15:13 +01002571 case LY_TYPE_ENUM:
2572 if (leaf_p->type.enums) {
2573 ret = lys_compile_type_enums(ctx, leaf_p->type.enums, basetype, options,
2574 base ? ((struct lysc_type_enum*)base)->enums : NULL, &enumeration->enums);
2575 LY_CHECK_GOTO(ret, cleanup);
2576 }
2577 break;
Radek Krejci9a191e62018-11-13 13:19:56 +01002578 case LY_TYPE_INT8:
2579 case LY_TYPE_UINT8:
2580 case LY_TYPE_INT16:
2581 case LY_TYPE_UINT16:
2582 case LY_TYPE_INT32:
2583 case LY_TYPE_UINT32:
2584 case LY_TYPE_INT64:
2585 case LY_TYPE_UINT64:
2586 if (leaf_p->type.range) {
2587 ret = lys_compile_type_range(ctx, leaf_p->type.range, basetype, 0,
2588 base ? ((struct lysc_type_num*)base)->range : NULL, &num->range);
2589 LY_CHECK_GOTO(ret, cleanup);
2590 COMPILE_ARRAY_GOTO(ctx, leaf_p->type.range->exts, num->range->exts,
2591 options, u, lys_compile_ext, ret, cleanup);
Radek Krejci9a191e62018-11-13 13:19:56 +01002592 }
2593 break;
2594 case LY_TYPE_BOOL:
2595 case LY_TYPE_EMPTY:
2596 case LY_TYPE_UNKNOWN: /* just to complete switch */
2597 /* nothing to do */
2598 break;
Radek Krejci4586a022018-11-13 11:29:26 +01002599 }
Radek Krejci9a191e62018-11-13 13:19:56 +01002600 } else if (base) {
2601 /* no specific restriction in leaf's type definition, copy from the base */
2602 free(*type);
2603 (*type) = base;
2604 ++(*type)->refcount;
Radek Krejci8b764662018-11-14 14:15:13 +01002605 } else {
2606 /* there are some limitations on types derived directly from built-in types */
2607 if (basetype == LY_TYPE_BITS) {
2608 if (!bits->bits) {
2609 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2610 "Missing bit substatement for bits type.");
2611 free(*type);
2612 *type = NULL;
2613 ret = LY_EVALID;
2614 goto cleanup;
2615 }
2616 } else if (basetype == LY_TYPE_ENUM) {
2617 if (!enumeration->enums) {
2618 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2619 "Missing enum substatement for enumeration type.");
2620 free(*type);
2621 *type = NULL;
2622 ret = LY_EVALID;
2623 goto cleanup;
2624 }
2625 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01002626 }
2627
Radek Krejcib31c8992018-11-12 16:29:16 +01002628 COMPILE_ARRAY_GOTO(ctx, type_p->exts, (*type)->exts, options, u, lys_compile_ext, ret, cleanup);
2629
Radek Krejci4f28eda2018-11-12 11:46:16 +01002630cleanup:
2631 ly_set_erase(&tpdf_chain, free);
Radek Krejci4f28eda2018-11-12 11:46:16 +01002632 return ret;
2633}
2634
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002635static LY_ERR lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent);
2636
2637static LY_ERR
2638lys_compile_node_container(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
2639{
2640 struct lysp_node_container *cont_p = (struct lysp_node_container*)node_p;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002641 struct lysc_node_container *cont = (struct lysc_node_container*)node;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002642 struct lysp_node *child_p;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002643 unsigned int u;
2644 LY_ERR ret = LY_SUCCESS;
2645
2646 COMPILE_MEMBER_GOTO(ctx, cont_p->when, cont->when, options, lys_compile_when, ret, done);
2647 COMPILE_ARRAY_GOTO(ctx, cont_p->iffeatures, cont->iffeatures, options, u, lys_compile_iffeature, ret, done);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002648
2649 LY_LIST_FOR(cont_p->child, child_p) {
2650 LY_CHECK_RET(lys_compile_node(ctx, child_p, options, node));
2651 }
2652
Radek Krejci4f28eda2018-11-12 11:46:16 +01002653 COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, options, u, lys_compile_must, ret, done);
2654 //COMPILE_ARRAY_GOTO(ctx, cont_p->actions, cont->actions, options, u, lys_compile_action, ret, done);
2655 //COMPILE_ARRAY_GOTO(ctx, cont_p->notifs, cont->notifs, options, u, lys_compile_notif, ret, done);
2656
2657done:
2658 return ret;
2659}
2660
2661static LY_ERR
2662lys_compile_node_leaf(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
2663{
2664 struct lysp_node_leaf *leaf_p = (struct lysp_node_leaf*)node_p;
2665 struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)node;
2666 unsigned int u;
2667 LY_ERR ret = LY_SUCCESS;
2668
2669 COMPILE_MEMBER_GOTO(ctx, leaf_p->when, leaf->when, options, lys_compile_when, ret, done);
2670 COMPILE_ARRAY_GOTO(ctx, leaf_p->iffeatures, leaf->iffeatures, options, u, lys_compile_iffeature, ret, done);
2671
2672 COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, options, u, lys_compile_must, ret, done);
2673 ret = lys_compile_type(ctx, leaf_p, options, &leaf->type);
2674 LY_CHECK_GOTO(ret, done);
2675
Radek Krejci0f07bed2018-11-13 14:01:40 +01002676 DUP_STRING(ctx->ctx, leaf->units, leaf_p->units);
2677 DUP_STRING(ctx->ctx, leaf->dflt, leaf_p->dflt);
Radek Krejci4f28eda2018-11-12 11:46:16 +01002678done:
2679 return ret;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002680}
2681
2682static LY_ERR
2683lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent)
2684{
2685 LY_ERR ret = LY_EVALID;
Radek Krejci4f28eda2018-11-12 11:46:16 +01002686 struct lysc_node *node, **children;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002687 unsigned int u;
2688 LY_ERR (*node_compile_spec)(struct lysc_ctx*, struct lysp_node*, int, struct lysc_node*);
2689
2690 switch (node_p->nodetype) {
2691 case LYS_CONTAINER:
2692 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_container));
2693 node_compile_spec = lys_compile_node_container;
2694 break;
2695 case LYS_LEAF:
2696 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaf));
Radek Krejci4f28eda2018-11-12 11:46:16 +01002697 node_compile_spec = lys_compile_node_leaf;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002698 break;
2699 case LYS_LIST:
2700 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_list));
2701 break;
2702 case LYS_LEAFLIST:
2703 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaflist));
2704 break;
2705 case LYS_CASE:
2706 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_case));
2707 break;
2708 case LYS_CHOICE:
2709 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_choice));
2710 break;
2711 case LYS_USES:
2712 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_uses));
2713 break;
2714 case LYS_ANYXML:
2715 case LYS_ANYDATA:
2716 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_anydata));
2717 break;
2718 default:
2719 LOGINT(ctx->ctx);
2720 return LY_EINT;
2721 }
2722 LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
2723 node->nodetype = node_p->nodetype;
2724 node->module = ctx->mod;
2725 node->prev = node;
2726 node->flags = node_p->flags;
2727
2728 /* config */
2729 if (!(node->flags & LYS_CONFIG_MASK)) {
2730 /* config not explicitely set, inherit it from parent */
2731 if (parent) {
2732 node->flags |= parent->flags & LYS_CONFIG_MASK;
2733 } else {
2734 /* default is config true */
2735 node->flags |= LYS_CONFIG_W;
2736 }
2737 }
2738
2739 /* status - it is not inherited by specification, but it does not make sense to have
2740 * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
2741 if (!(node->flags & LYS_STATUS_MASK)) {
2742 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
Radek Krejci98094b32018-11-02 16:21:47 +01002743 LOGWRN(ctx->ctx, "Missing explicit \"%s\" status that was already specified in parent, inheriting.",
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002744 (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
2745 node->flags |= parent->flags & LYS_STATUS_MASK;
2746 } else {
2747 node->flags |= LYS_STATUS_CURR;
2748 }
2749 } else if (parent) {
2750 /* check status compatibility with the parent */
2751 if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
2752 if (node->flags & LYS_STATUS_CURR) {
2753 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
2754 "A \"current\" status is in conflict with the parent's \"%s\" status.",
2755 (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
2756 } else { /* LYS_STATUS_DEPRC */
2757 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
2758 "A \"deprecated\" status is in conflict with the parent's \"obsolete\" status.");
2759 }
2760 goto error;
2761 }
2762 }
2763
Radek Krejci4f28eda2018-11-12 11:46:16 +01002764 if (!(options & LYSC_OPT_FREE_SP)) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002765 node->sp = node_p;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002766 }
Radek Krejci0f07bed2018-11-13 14:01:40 +01002767 DUP_STRING(ctx->ctx, node->name, node_p->name);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002768 COMPILE_ARRAY_GOTO(ctx, node_p->exts, node->exts, options, u, lys_compile_ext, ret, error);
2769
2770 /* nodetype-specific part */
2771 LY_CHECK_GOTO(node_compile_spec(ctx, node_p, options, node), error);
2772
2773 /* insert into parent's children */
Radek Krejci4f28eda2018-11-12 11:46:16 +01002774 if (parent && (children = lysc_node_children(parent))) {
2775 if (!(*children)) {
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002776 /* first child */
Radek Krejci4f28eda2018-11-12 11:46:16 +01002777 *children = node;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002778 } else {
2779 /* insert at the end of the parent's children list */
Radek Krejci4f28eda2018-11-12 11:46:16 +01002780 (*children)->prev->next = node;
2781 node->prev = (*children)->prev;
2782 (*children)->prev = node;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002783 }
2784 } else {
2785 /* top-level element */
2786 if (!ctx->mod->compiled->data) {
2787 ctx->mod->compiled->data = node;
2788 } else {
2789 /* insert at the end of the module's top-level nodes list */
2790 ctx->mod->compiled->data->prev->next = node;
2791 node->prev = ctx->mod->compiled->data->prev;
2792 ctx->mod->compiled->data->prev = node;
2793 }
2794 }
2795
2796 return LY_SUCCESS;
2797
2798error:
Radek Krejci4f28eda2018-11-12 11:46:16 +01002799 lysc_node_free(ctx->ctx, node);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002800 return ret;
2801}
2802
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002803LY_ERR
Radek Krejcid14e9692018-11-01 11:00:37 +01002804lys_compile(struct lys_module *mod, int options)
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002805{
Radek Krejci86d106e2018-10-18 09:53:19 +02002806 struct lysc_ctx ctx = {0};
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002807 struct lysc_module *mod_c;
Radek Krejcif8f882a2018-10-31 14:51:15 +01002808 struct lysp_module *sp;
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002809 struct lysp_node *node_p;
Radek Krejci151a5b72018-10-19 14:21:44 +02002810 unsigned int u;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002811 LY_ERR ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002812
Radek Krejcif8f882a2018-10-31 14:51:15 +01002813 LY_CHECK_ARG_RET(NULL, mod, mod->parsed, mod->parsed->ctx, LY_EINVAL);
2814 sp = mod->parsed;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002815
2816 if (sp->submodule) {
Radek Krejci86d106e2018-10-18 09:53:19 +02002817 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 +02002818 return LY_EINVAL;
2819 }
2820
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002821 ctx.ctx = sp->ctx;
2822 ctx.mod = mod;
2823
2824 mod->compiled = mod_c = calloc(1, sizeof *mod_c);
Radek Krejci86d106e2018-10-18 09:53:19 +02002825 LY_CHECK_ERR_RET(!mod_c, LOGMEM(sp->ctx), LY_EMEM);
2826 mod_c->ctx = sp->ctx;
Radek Krejcid14e9692018-11-01 11:00:37 +01002827 mod_c->implemented = sp->implemented;
2828 mod_c->latest_revision = sp->latest_revision;
Radek Krejci86d106e2018-10-18 09:53:19 +02002829 mod_c->version = sp->version;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002830
Radek Krejci0f07bed2018-11-13 14:01:40 +01002831 DUP_STRING(sp->ctx, mod_c->name, sp->name);
2832 DUP_STRING(sp->ctx, mod_c->ns, sp->ns);
2833 DUP_STRING(sp->ctx, mod_c->prefix, sp->prefix);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002834 if (sp->revs) {
Radek Krejci0f07bed2018-11-13 14:01:40 +01002835 DUP_STRING(sp->ctx, mod_c->revision, sp->revs[0].date);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002836 }
Radek Krejcice8c1592018-10-29 15:35:51 +01002837 COMPILE_ARRAY_GOTO(&ctx, sp->imports, mod_c->imports, options, u, lys_compile_import, ret, error);
2838 COMPILE_ARRAY_GOTO(&ctx, sp->features, mod_c->features, options, u, lys_compile_feature, ret, error);
Radek Krejci2a408df2018-10-29 16:32:26 +01002839 COMPILE_ARRAY_GOTO(&ctx, sp->identities, mod_c->identities, options, u, lys_compile_identity, ret, error);
2840 if (sp->identities) {
2841 LY_CHECK_RET(lys_compile_identities_derived(&ctx, sp->identities, mod_c->identities));
2842 }
Radek Krejcice8c1592018-10-29 15:35:51 +01002843
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002844 LY_LIST_FOR(sp->data, node_p) {
2845 ret = lys_compile_node(&ctx, node_p, options, NULL);
2846 LY_CHECK_GOTO(ret, error);
2847 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01002848 //COMPILE_ARRAY_GOTO(ctx, sp->rpcs, mod_c->rpcs, options, u, lys_compile_action, ret, error);
2849 //COMPILE_ARRAY_GOTO(ctx, sp->notifs, mod_c->notifs, options, u, lys_compile_notif, ret, error);
2850
2851 COMPILE_ARRAY_GOTO(&ctx, sp->exts, mod_c->exts, options, u, lys_compile_ext, ret, error);
Radek Krejcibd8d9ba2018-11-02 16:06:26 +01002852
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002853 if (options & LYSC_OPT_FREE_SP) {
Radek Krejci4f28eda2018-11-12 11:46:16 +01002854 lysp_module_free(mod->parsed);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002855 ((struct lys_module*)mod)->parsed = NULL;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002856 }
2857
Radek Krejcif8f882a2018-10-31 14:51:15 +01002858 ((struct lys_module*)mod)->compiled = mod_c;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002859 return LY_SUCCESS;
2860
2861error:
Radek Krejci4f28eda2018-11-12 11:46:16 +01002862 lysc_module_free(mod_c, NULL);
Radek Krejcif8f882a2018-10-31 14:51:15 +01002863 ((struct lys_module*)mod)->compiled = NULL;
Radek Krejcidd4e8d42018-10-16 14:55:43 +02002864 return ret;
2865}
Radek Krejci86d106e2018-10-18 09:53:19 +02002866
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002867static void
Radek Krejci086c7132018-10-26 15:29:04 +02002868lys_latest_switch(struct lys_module *old, struct lysp_module *new)
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002869{
Radek Krejci086c7132018-10-26 15:29:04 +02002870 if (old->parsed) {
2871 new->latest_revision = old->parsed->latest_revision;
2872 old->parsed->latest_revision = 0;
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002873 }
Radek Krejci086c7132018-10-26 15:29:04 +02002874 if (old->compiled) {
2875 new->latest_revision = old->parsed->latest_revision;
2876 old->compiled->latest_revision = 0;
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002877 }
2878}
2879
Radek Krejcid33273d2018-10-25 14:55:52 +02002880struct lys_module *
Radek Krejci3b1f9292018-11-08 10:58:35 +01002881lys_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 +01002882 LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
Radek Krejci86d106e2018-10-18 09:53:19 +02002883{
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002884 struct lys_module *mod = NULL, *latest, *mod_dup;
Radek Krejcid33273d2018-10-25 14:55:52 +02002885 struct lysp_module *latest_p;
Radek Krejci086c7132018-10-26 15:29:04 +02002886 struct lysp_import *imp;
2887 struct lysp_include *inc;
Radek Krejci9ed7a192018-10-31 16:23:51 +01002888 LY_ERR ret = LY_EINVAL;
Radek Krejci086c7132018-10-26 15:29:04 +02002889 unsigned int u, i;
Radek Krejcibbe09a92018-11-08 09:36:54 +01002890 struct ly_parser_ctx context = {0};
Radek Krejci86d106e2018-10-18 09:53:19 +02002891
2892 LY_CHECK_ARG_RET(ctx, ctx, data, NULL);
2893
Radek Krejcibbe09a92018-11-08 09:36:54 +01002894 context.ctx = ctx;
2895 context.line = 1;
2896
Radek Krejci3b1f9292018-11-08 10:58:35 +01002897 if (main_ctx) {
2898 /* map the typedefs and groupings list from main context to the submodule's context */
2899 memcpy(&context.tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
2900 memcpy(&context.grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
2901 }
2902
Radek Krejci86d106e2018-10-18 09:53:19 +02002903 mod = calloc(1, sizeof *mod);
2904 LY_CHECK_ERR_RET(!mod, LOGMEM(ctx), NULL);
2905
2906 switch (format) {
2907 case LYS_IN_YIN:
2908 /* TODO not yet supported
2909 mod = yin_read_module(ctx, data, revision, implement);
2910 */
2911 break;
2912 case LYS_IN_YANG:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002913 ret = yang_parse(&context, data, &mod->parsed);
Radek Krejci86d106e2018-10-18 09:53:19 +02002914 break;
2915 default:
2916 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
2917 break;
2918 }
Radek Krejcifaa1eac2018-10-30 14:34:55 +01002919 LY_CHECK_ERR_RET(ret, free(mod), NULL);
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002920
2921 /* make sure that the newest revision is at position 0 */
2922 lysp_sort_revisions(mod->parsed->revs);
Radek Krejci86d106e2018-10-18 09:53:19 +02002923
2924 if (implement) {
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002925 /* mark the loaded module implemented */
Radek Krejcib7db73a2018-10-24 14:18:40 +02002926 if (ly_ctx_get_module_implemented(ctx, mod->parsed->name)) {
2927 LOGERR(ctx, LY_EDENIED, "Module \"%s\" is already implemented in the context.", mod->parsed->name);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002928 goto error;
Radek Krejcib7db73a2018-10-24 14:18:40 +02002929 }
Radek Krejci86d106e2018-10-18 09:53:19 +02002930 mod->parsed->implemented = 1;
2931 }
2932
Radek Krejci9ed7a192018-10-31 16:23:51 +01002933 if (custom_check) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002934 LY_CHECK_GOTO(custom_check(ctx, mod->parsed, check_data), error);
Radek Krejci86d106e2018-10-18 09:53:19 +02002935 }
2936
Radek Krejcid33273d2018-10-25 14:55:52 +02002937 if (mod->parsed->submodule) { /* submodule */
Radek Krejci3b1f9292018-11-08 10:58:35 +01002938 if (!main_ctx) {
2939 LOGERR(ctx, LY_EDENIED, "Input data contains submodule \"%s\" which cannot be parsed directly without its main module.",
2940 mod->parsed->name);
2941 goto error;
2942 }
Radek Krejcid33273d2018-10-25 14:55:52 +02002943 /* decide the latest revision */
2944 latest_p = ly_ctx_get_submodule(ctx, mod->parsed->belongsto, mod->parsed->name, NULL);
2945 if (latest_p) {
2946 if (mod->parsed->revs) {
2947 if (!latest_p->revs) {
2948 /* latest has no revision, so mod is anyway newer */
Radek Krejci9ed7a192018-10-31 16:23:51 +01002949 mod->parsed->latest_revision = latest_p->latest_revision;
Radek Krejcid33273d2018-10-25 14:55:52 +02002950 latest_p->latest_revision = 0;
2951 } else {
2952 if (strcmp(mod->parsed->revs[0].date, latest_p->revs[0].date) > 0) {
Radek Krejci9ed7a192018-10-31 16:23:51 +01002953 mod->parsed->latest_revision = latest_p->latest_revision;
Radek Krejcid33273d2018-10-25 14:55:52 +02002954 latest_p->latest_revision = 0;
2955 }
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002956 }
2957 }
Radek Krejcid33273d2018-10-25 14:55:52 +02002958 } else {
Radek Krejci9ed7a192018-10-31 16:23:51 +01002959 mod->parsed->latest_revision = 1;
Radek Krejci9f5e6fb2018-10-25 09:26:12 +02002960 }
Radek Krejci3b1f9292018-11-08 10:58:35 +01002961 /* remap possibly changed and reallocated typedefs and groupings list back to the main context */
2962 memcpy(&main_ctx->tpdfs_nodes, &context.tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
2963 memcpy(&main_ctx->grps_nodes, &context.grps_nodes, sizeof main_ctx->grps_nodes);
Radek Krejcid33273d2018-10-25 14:55:52 +02002964 } else { /* module */
2965 /* check for duplicity in the context */
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002966 mod_dup = (struct lys_module*)ly_ctx_get_module(ctx, mod->parsed->name, mod->parsed->revs ? mod->parsed->revs[0].date : NULL);
2967 if (mod_dup) {
2968 if (mod_dup->parsed) {
2969 /* error */
2970 if (mod->parsed->revs) {
2971 LOGERR(ctx, LY_EEXIST, "Module \"%s\" of revision \"%s\" is already present in the context.",
2972 mod->parsed->name, mod->parsed->revs[0].date);
2973 } else {
2974 LOGERR(ctx, LY_EEXIST, "Module \"%s\" with no revision is already present in the context.",
2975 mod->parsed->name);
2976 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01002977 goto error;
Radek Krejcid33273d2018-10-25 14:55:52 +02002978 } else {
Radek Krejci6d6e4e42018-10-29 13:28:19 +01002979 /* add the parsed data to the currently compiled-only module in the context */
2980 mod_dup->parsed = mod->parsed;
2981 free(mod);
2982 mod = mod_dup;
2983 goto finish_parsing;
Radek Krejcid33273d2018-10-25 14:55:52 +02002984 }
Radek Krejcid33273d2018-10-25 14:55:52 +02002985 }
Radek Krejci86d106e2018-10-18 09:53:19 +02002986
2987#if 0
2988 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
2989 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
2990 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
2991 * the anotation definitions available in the internal schema structure. There is another hack in schema
2992 * printers to do not print this internally added annotation. */
2993 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
2994 if (lyp_add_ietf_netconf_annotations(mod)) {
2995 lys_free(mod, NULL, 1, 1);
2996 return NULL;
2997 }
2998 }
2999#endif
3000
Radek Krejcid33273d2018-10-25 14:55:52 +02003001 /* decide the latest revision */
3002 latest = (struct lys_module*)ly_ctx_get_module_latest(ctx, mod->parsed->name);
3003 if (latest) {
3004 if (mod->parsed->revs) {
Radek Krejcif8f882a2018-10-31 14:51:15 +01003005 if ((latest->parsed && !latest->parsed->revs) || (!latest->parsed && !latest->compiled->revision)) {
Radek Krejcid33273d2018-10-25 14:55:52 +02003006 /* latest has no revision, so mod is anyway newer */
Radek Krejci086c7132018-10-26 15:29:04 +02003007 lys_latest_switch(latest, mod->parsed);
Radek Krejcid33273d2018-10-25 14:55:52 +02003008 } else {
Radek Krejcif8f882a2018-10-31 14:51:15 +01003009 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 +02003010 lys_latest_switch(latest, mod->parsed);
Radek Krejcid33273d2018-10-25 14:55:52 +02003011 }
3012 }
3013 }
3014 } else {
3015 mod->parsed->latest_revision = 1;
3016 }
3017
3018 /* add into context */
3019 ly_set_add(&ctx->list, mod, LY_SET_OPT_USEASLIST);
3020
Radek Krejci6d6e4e42018-10-29 13:28:19 +01003021finish_parsing:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003022 /* resolve imports */
Radek Krejci086c7132018-10-26 15:29:04 +02003023 mod->parsed->parsing = 1;
3024 LY_ARRAY_FOR(mod->parsed->imports, u) {
3025 imp = &mod->parsed->imports[u];
Radek Krejci6d6e4e42018-10-29 13:28:19 +01003026 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 +01003027 goto error_ctx;
Radek Krejci086c7132018-10-26 15:29:04 +02003028 }
3029 /* check for importing the same module twice */
3030 for (i = 0; i < u; ++i) {
3031 if (imp->module == mod->parsed->imports[i].module) {
3032 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 +01003033 goto error_ctx;
Radek Krejci086c7132018-10-26 15:29:04 +02003034 }
3035 }
3036 }
3037 LY_ARRAY_FOR(mod->parsed->includes, u) {
3038 inc = &mod->parsed->includes[u];
Radek Krejci3b1f9292018-11-08 10:58:35 +01003039 if (!inc->submodule && lysp_load_submodule(&context, mod->parsed, inc)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01003040 goto error_ctx;
Radek Krejci086c7132018-10-26 15:29:04 +02003041 }
3042 }
3043 mod->parsed->parsing = 0;
Radek Krejcibbe09a92018-11-08 09:36:54 +01003044
3045 /* check name collisions - typedefs and groupings */
3046 LY_CHECK_GOTO(lysp_check_typedefs(&context), error_ctx);
Radek Krejcid33273d2018-10-25 14:55:52 +02003047 }
3048
Radek Krejci86d106e2018-10-18 09:53:19 +02003049 return mod;
Radek Krejcibbe09a92018-11-08 09:36:54 +01003050
3051error_ctx:
3052 ly_set_rm(&ctx->list, mod, NULL);
3053error:
3054 lys_module_free(mod, NULL);
3055 ly_set_erase(&context.tpdfs_nodes, NULL);
3056 return NULL;
Radek Krejci86d106e2018-10-18 09:53:19 +02003057}
3058
Radek Krejcid14e9692018-11-01 11:00:37 +01003059API struct lys_module *
Radek Krejci86d106e2018-10-18 09:53:19 +02003060lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
3061{
Radek Krejci3b1f9292018-11-08 10:58:35 +01003062 return lys_parse_mem_(ctx, data, format, 1, NULL, NULL, NULL);
Radek Krejci86d106e2018-10-18 09:53:19 +02003063}
3064
3065static void
3066lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
3067{
3068#ifdef __APPLE__
3069 char path[MAXPATHLEN];
3070#else
3071 int len;
3072 char path[PATH_MAX], proc_path[32];
3073#endif
3074
3075#ifdef __APPLE__
3076 if (fcntl(fd, F_GETPATH, path) != -1) {
3077 *filename = lydict_insert(ctx, path, 0);
3078 }
3079#else
3080 /* get URI if there is /proc */
3081 sprintf(proc_path, "/proc/self/fd/%d", fd);
3082 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
3083 *filename = lydict_insert(ctx, path, len);
3084 }
3085#endif
3086}
3087
Radek Krejcid33273d2018-10-25 14:55:52 +02003088struct lys_module *
Radek Krejci3b1f9292018-11-08 10:58:35 +01003089lys_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 +01003090 LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
Radek Krejci86d106e2018-10-18 09:53:19 +02003091{
Radek Krejcid33273d2018-10-25 14:55:52 +02003092 struct lys_module *mod;
Radek Krejci86d106e2018-10-18 09:53:19 +02003093 size_t length;
3094 char *addr;
3095
3096 LY_CHECK_ARG_RET(ctx, ctx, NULL);
3097 if (fd < 0) {
3098 LOGARG(ctx, fd);
3099 return NULL;
3100 }
3101
3102 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
3103 if (!addr) {
3104 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
3105 return NULL;
3106 }
3107
Radek Krejci3b1f9292018-11-08 10:58:35 +01003108 mod = lys_parse_mem_(ctx, addr, format, implement, main_ctx, custom_check, check_data);
Radek Krejci86d106e2018-10-18 09:53:19 +02003109 ly_munmap(addr, length);
3110
3111 if (mod && !mod->parsed->filepath) {
3112 lys_parse_set_filename(ctx, &mod->parsed->filepath, fd);
3113 }
3114
3115 return mod;
3116}
3117
Radek Krejcid14e9692018-11-01 11:00:37 +01003118API struct lys_module *
Radek Krejci86d106e2018-10-18 09:53:19 +02003119lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
3120{
Radek Krejci3b1f9292018-11-08 10:58:35 +01003121 return lys_parse_fd_(ctx, fd, format, 1, NULL, NULL, NULL);
Radek Krejci86d106e2018-10-18 09:53:19 +02003122}
3123
Radek Krejcid33273d2018-10-25 14:55:52 +02003124struct lys_module *
Radek Krejci3b1f9292018-11-08 10:58:35 +01003125lys_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 +01003126 LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
Radek Krejci86d106e2018-10-18 09:53:19 +02003127{
3128 int fd;
Radek Krejcid33273d2018-10-25 14:55:52 +02003129 struct lys_module *mod;
Radek Krejci86d106e2018-10-18 09:53:19 +02003130 const char *rev, *dot, *filename;
3131 size_t len;
3132
3133 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
3134
3135 fd = open(path, O_RDONLY);
3136 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
3137
Radek Krejci3b1f9292018-11-08 10:58:35 +01003138 mod = lys_parse_fd_(ctx, fd, format, implement, main_ctx, custom_check, check_data);
Radek Krejci86d106e2018-10-18 09:53:19 +02003139 close(fd);
3140 LY_CHECK_RET(!mod, NULL);
3141
3142 /* check that name and revision match filename */
3143 filename = strrchr(path, '/');
3144 if (!filename) {
3145 filename = path;
3146 } else {
3147 filename++;
3148 }
3149 rev = strchr(filename, '@');
3150 dot = strrchr(filename, '.');
3151
3152 /* name */
3153 len = strlen(mod->parsed->name);
3154 if (strncmp(filename, mod->parsed->name, len) ||
3155 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
3156 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, mod->parsed->name);
3157 }
3158 if (rev) {
3159 len = dot - ++rev;
Radek Krejcib7db73a2018-10-24 14:18:40 +02003160 if (!mod->parsed->revs || len != 10 || strncmp(mod->parsed->revs[0].date, rev, len)) {
Radek Krejci86d106e2018-10-18 09:53:19 +02003161 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
Radek Krejcib7db73a2018-10-24 14:18:40 +02003162 mod->parsed->revs ? mod->parsed->revs[0].date : "none");
Radek Krejci86d106e2018-10-18 09:53:19 +02003163 }
3164 }
3165
3166 if (!mod->parsed->filepath) {
3167 /* store URI */
3168 char rpath[PATH_MAX];
3169 if (realpath(path, rpath) != NULL) {
3170 mod->parsed->filepath = lydict_insert(ctx, rpath, 0);
3171 } else {
3172 mod->parsed->filepath = lydict_insert(ctx, path, 0);
3173 }
3174 }
3175
3176 return mod;
3177}
3178
Radek Krejcid14e9692018-11-01 11:00:37 +01003179API struct lys_module *
Radek Krejcid33273d2018-10-25 14:55:52 +02003180lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
3181{
Radek Krejci3b1f9292018-11-08 10:58:35 +01003182 return lys_parse_path_(ctx, path, format, 1, NULL, NULL, NULL);
Radek Krejcid33273d2018-10-25 14:55:52 +02003183}
3184
3185API LY_ERR
3186lys_search_localfile(const char * const *searchpaths, int cwd, const char *name, const char *revision,
3187 char **localfile, LYS_INFORMAT *format)
3188{
3189 size_t len, flen, match_len = 0, dir_len;
3190 int i, implicit_cwd = 0, ret = EXIT_FAILURE;
3191 char *wd, *wn = NULL;
3192 DIR *dir = NULL;
3193 struct dirent *file;
3194 char *match_name = NULL;
3195 LYS_INFORMAT format_aux, match_format = 0;
3196 struct ly_set *dirs;
3197 struct stat st;
3198
3199 LY_CHECK_ARG_RET(NULL, localfile, LY_EINVAL);
3200
3201 /* start to fill the dir fifo with the context's search path (if set)
3202 * and the current working directory */
3203 dirs = ly_set_new();
3204 if (!dirs) {
3205 LOGMEM(NULL);
3206 return EXIT_FAILURE;
3207 }
3208
3209 len = strlen(name);
3210 if (cwd) {
3211 wd = get_current_dir_name();
3212 if (!wd) {
3213 LOGMEM(NULL);
3214 goto cleanup;
3215 } else {
3216 /* add implicit current working directory (./) to be searched,
3217 * this directory is not searched recursively */
3218 if (ly_set_add(dirs, wd, 0) == -1) {
3219 goto cleanup;
3220 }
3221 implicit_cwd = 1;
3222 }
3223 }
3224 if (searchpaths) {
3225 for (i = 0; searchpaths[i]; i++) {
3226 /* check for duplicities with the implicit current working directory */
3227 if (implicit_cwd && !strcmp(dirs->objs[0], searchpaths[i])) {
3228 implicit_cwd = 0;
3229 continue;
3230 }
3231 wd = strdup(searchpaths[i]);
3232 if (!wd) {
3233 LOGMEM(NULL);
3234 goto cleanup;
3235 } else if (ly_set_add(dirs, wd, 0) == -1) {
3236 goto cleanup;
3237 }
3238 }
3239 }
3240 wd = NULL;
3241
3242 /* start searching */
3243 while (dirs->count) {
3244 free(wd);
3245 free(wn); wn = NULL;
3246
3247 dirs->count--;
3248 wd = (char *)dirs->objs[dirs->count];
3249 dirs->objs[dirs->count] = NULL;
3250 LOGVRB("Searching for \"%s\" in %s.", name, wd);
3251
3252 if (dir) {
3253 closedir(dir);
3254 }
3255 dir = opendir(wd);
3256 dir_len = strlen(wd);
3257 if (!dir) {
3258 LOGWRN(NULL, "Unable to open directory \"%s\" for searching (sub)modules (%s).", wd, strerror(errno));
3259 } else {
3260 while ((file = readdir(dir))) {
3261 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
3262 /* skip . and .. */
3263 continue;
3264 }
3265 free(wn);
3266 if (asprintf(&wn, "%s/%s", wd, file->d_name) == -1) {
3267 LOGMEM(NULL);
3268 goto cleanup;
3269 }
3270 if (stat(wn, &st) == -1) {
3271 LOGWRN(NULL, "Unable to get information about \"%s\" file in \"%s\" when searching for (sub)modules (%s)",
3272 file->d_name, wd, strerror(errno));
3273 continue;
3274 }
3275 if (S_ISDIR(st.st_mode) && (dirs->count || !implicit_cwd)) {
3276 /* we have another subdirectory in searchpath to explore,
3277 * subdirectories are not taken into account in current working dir (dirs->set.g[0]) */
3278 if (ly_set_add(dirs, wn, 0) == -1) {
3279 goto cleanup;
3280 }
3281 /* continue with the next item in current directory */
3282 wn = NULL;
3283 continue;
3284 } else if (!S_ISREG(st.st_mode)) {
3285 /* not a regular file (note that we see the target of symlinks instead of symlinks */
3286 continue;
3287 }
3288
3289 /* here we know that the item is a file which can contain a module */
3290 if (strncmp(name, file->d_name, len) ||
3291 (file->d_name[len] != '.' && file->d_name[len] != '@')) {
3292 /* different filename than the module we search for */
3293 continue;
3294 }
3295
3296 /* get type according to filename suffix */
3297 flen = strlen(file->d_name);
3298 if (!strcmp(&file->d_name[flen - 4], ".yin")) {
3299 format_aux = LYS_IN_YIN;
3300 } else if (!strcmp(&file->d_name[flen - 5], ".yang")) {
3301 format_aux = LYS_IN_YANG;
3302 } else {
3303 /* not supportde suffix/file format */
3304 continue;
3305 }
3306
3307 if (revision) {
3308 /* we look for the specific revision, try to get it from the filename */
3309 if (file->d_name[len] == '@') {
3310 /* check revision from the filename */
3311 if (strncmp(revision, &file->d_name[len + 1], strlen(revision))) {
3312 /* another revision */
3313 continue;
3314 } else {
3315 /* exact revision */
3316 free(match_name);
3317 match_name = wn;
3318 wn = NULL;
3319 match_len = dir_len + 1 + len;
3320 match_format = format_aux;
3321 goto success;
3322 }
3323 } else {
3324 /* continue trying to find exact revision match, use this only if not found */
3325 free(match_name);
3326 match_name = wn;
3327 wn = NULL;
3328 match_len = dir_len + 1 +len;
3329 match_format = format_aux;
3330 continue;
3331 }
3332 } else {
3333 /* remember the revision and try to find the newest one */
3334 if (match_name) {
3335 if (file->d_name[len] != '@' ||
3336 lysp_check_date(NULL, &file->d_name[len + 1], flen - (format_aux == LYS_IN_YANG ? 5 : 4) - len - 1, NULL)) {
3337 continue;
3338 } else if (match_name[match_len] == '@' &&
3339 (strncmp(&match_name[match_len + 1], &file->d_name[len + 1], LY_REV_SIZE - 1) >= 0)) {
3340 continue;
3341 }
3342 free(match_name);
3343 }
3344
3345 match_name = wn;
3346 wn = NULL;
3347 match_len = dir_len + 1 + len;
3348 match_format = format_aux;
3349 continue;
3350 }
3351 }
3352 }
3353 }
3354
3355success:
3356 (*localfile) = match_name;
3357 match_name = NULL;
3358 if (format) {
3359 (*format) = match_format;
3360 }
3361 ret = EXIT_SUCCESS;
3362
3363cleanup:
3364 free(wn);
3365 free(wd);
3366 if (dir) {
3367 closedir(dir);
3368 }
3369 free(match_name);
3370 ly_set_free(dirs, free);
3371
3372 return ret;
3373}
3374