blob: f8cd55938f5ad547e202a44bd321b3d401825f56 [file] [log] [blame]
Radek Krejcid6b76452019-09-03 17:03:03 +02001/**
2 * @file plugins_exts_nacm.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief libyang extension plugin - Metadata (RFC 7952)
5 *
6 * Copyright (c) 2019 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 Krejcid6b76452019-09-03 17:03:03 +020014
15#include <stdlib.h>
16
17#include "plugins_exts.h"
Radek Krejcid6b76452019-09-03 17:03:03 +020018#include "plugins_exts_metadata.h"
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020019#include "schema_compile.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010020#include "tree_edit.h"
Michal Vasko69730152020-10-09 16:30:07 +020021#include "tree_schema.h"
Radek Krejcid6b76452019-09-03 17:03:03 +020022
23/**
24 * @brief Storage for ID used to check plugin API version compatibility.
25 * Ignored here in the internal plugin.
26LYEXT_VERSION_CHECK
27 */
28
Radek Krejci1b2eef82021-02-17 11:17:27 +010029/**
30 * @brief Representation of the compiled metadata substatements - simplify storage for the items available via
31 * ::lysc_ext_substmt.
32 */
33struct lyext_metadata {
34 struct lysc_type *type; /**< type of the metadata (mandatory) */
35 const char *units; /**< units of the leaf's type */
36 struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
37 const char *dsc; /**< description */
38 const char *ref; /**< reference */
39 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
40};
Radek Krejci38d85362019-09-05 16:26:38 +020041
Radek Krejcid6b76452019-09-03 17:03:03 +020042/**
43 * @brief Compile annotation extension instances.
44 *
45 * Implementation of lyext_clb_compile callback set as lyext_plugin::compile.
46 */
47LY_ERR
48annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext)
49{
Radek Krejci859a15a2021-03-05 20:56:59 +010050 LY_ERR ret;
Radek Krejcid6b76452019-09-03 17:03:03 +020051 struct lyext_metadata *annotation;
52 struct lysc_module *mod_c;
Michal Vaskofd69e1d2020-07-03 11:57:17 +020053 LY_ARRAY_COUNT_TYPE u;
Radek Krejcid6b76452019-09-03 17:03:03 +020054
55 /* annotations can appear only at the top level of a YANG module or submodule */
Radek Krejciab430862021-03-02 20:13:40 +010056 if ((c_ext->parent_stmt != LY_STMT_MODULE) && (c_ext->parent_stmt != LY_STMT_SUBMODULE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020057 lyext_log(c_ext, LY_LLERR, LY_EVALID, cctx->path, "Extension %s is allowed only at the top level of a YANG module or submodule, but it is placed in \"%s\" statement.",
Radek Krejciab430862021-03-02 20:13:40 +010058 p_ext->name, ly_stmt2str(c_ext->parent_stmt));
Radek Krejcid6b76452019-09-03 17:03:03 +020059 return LY_EVALID;
60 }
Radek Krejci335332a2019-09-05 13:03:35 +020061 /* check mandatory argument */
62 if (!c_ext->argument) {
63 lyext_log(c_ext, LY_LLERR, LY_EVALID, cctx->path, "Extension %s is instantiated without mandatory argument representing metadata name.",
Michal Vasko69730152020-10-09 16:30:07 +020064 p_ext->name);
Radek Krejci335332a2019-09-05 13:03:35 +020065 return LY_EVALID;
66 }
Radek Krejcid6b76452019-09-03 17:03:03 +020067
68 mod_c = (struct lysc_module *)c_ext->parent;
69
70 /* check for duplication */
71 LY_ARRAY_FOR(mod_c->exts, u) {
Michal Vasko69730152020-10-09 16:30:07 +020072 if ((&mod_c->exts[u] != c_ext) && (mod_c->exts[u].def == c_ext->def) && !strcmp(mod_c->exts[u].argument, c_ext->argument)) {
Radek Krejci335332a2019-09-05 13:03:35 +020073 /* duplication of the same annotation extension in a single module */
Radek Krejcid6b76452019-09-03 17:03:03 +020074 lyext_log(c_ext, LY_LLERR, LY_EVALID, cctx->path, "Extension %s is instantiated multiple times.", p_ext->name);
75 return LY_EVALID;
76 }
77 }
78
79 /* compile annotation substatements */
80 c_ext->data = annotation = calloc(1, sizeof *annotation);
Radek Krejci1b2eef82021-02-17 11:17:27 +010081 if (!annotation) {
Radek Krejci859a15a2021-03-05 20:56:59 +010082 goto emem;
Radek Krejci1b2eef82021-02-17 11:17:27 +010083 }
Radek Krejci859a15a2021-03-05 20:56:59 +010084 LY_ARRAY_CREATE_GOTO(cctx->ctx, c_ext->substmts, 6, ret, emem);
Radek Krejcid6b76452019-09-03 17:03:03 +020085
Radek Krejci1b2eef82021-02-17 11:17:27 +010086 LY_ARRAY_INCREMENT(c_ext->substmts);
87 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].stmt = LY_STMT_IF_FEATURE;
88 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].cardinality = LY_STMT_CARD_ANY;
89 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].storage = &annotation->iffeatures;
90
91 LY_ARRAY_INCREMENT(c_ext->substmts);
92 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].stmt = LY_STMT_UNITS;
93 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].cardinality = LY_STMT_CARD_OPT;
94 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].storage = &annotation->units;
95
96 LY_ARRAY_INCREMENT(c_ext->substmts);
97 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].stmt = LY_STMT_STATUS;
98 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].cardinality = LY_STMT_CARD_OPT;
99 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].storage = &annotation->flags;
100
101 LY_ARRAY_INCREMENT(c_ext->substmts);
102 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].stmt = LY_STMT_TYPE;
103 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].cardinality = LY_STMT_CARD_MAND;
104 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].storage = &annotation->type;
105
106 LY_ARRAY_INCREMENT(c_ext->substmts);
107 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].stmt = LY_STMT_DESCRIPTION;
108 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].cardinality = LY_STMT_CARD_OPT;
109 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].storage = &annotation->dsc;
110
111 LY_ARRAY_INCREMENT(c_ext->substmts);
112 c_ext->substmts[ANNOTATION_SUBSTMT_REF].stmt = LY_STMT_REFERENCE;
113 c_ext->substmts[ANNOTATION_SUBSTMT_REF].cardinality = LY_STMT_CARD_OPT;
114 c_ext->substmts[ANNOTATION_SUBSTMT_REF].storage = &annotation->ref;
115
Radek Krejci859a15a2021-03-05 20:56:59 +0100116 ret = lys_compile_extension_instance(cctx, p_ext, c_ext);
117 return ret;
Radek Krejcid6b76452019-09-03 17:03:03 +0200118
Radek Krejci859a15a2021-03-05 20:56:59 +0100119emem:
120 lyext_log(c_ext, LY_LLERR, LY_EMEM, cctx->path, "Memory allocation failed (%s()).", __func__);
121 return LY_EMEM;
Radek Krejcid6b76452019-09-03 17:03:03 +0200122}
123
Radek Krejci38d85362019-09-05 16:26:38 +0200124/**
Radek Krejciadcf63d2021-02-09 10:21:18 +0100125 * @brief INFO printer
126 *
127 * Implementation of lyext_clb_schema_printer set as ::lyext_plugin::sprinter
128 */
129LY_ERR
130annotation_schema_printer(struct lys_ypr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
131{
132 lysc_print_extension_instance(ctx, ext, flag);
133
134 return LY_SUCCESS;
135}
136
137/**
Radek Krejci38d85362019-09-05 16:26:38 +0200138 * @brief Free annotation extension instances' data.
139 *
Radek Krejciadcf63d2021-02-09 10:21:18 +0100140 * Implementation of lyext_clb_free callback set as ::lyext_plugin::free.
Radek Krejci38d85362019-09-05 16:26:38 +0200141 */
142void
143annotation_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
144{
Radek Krejci1b2eef82021-02-17 11:17:27 +0100145 if (!ext->substmts) {
Radek Krejciad5963b2019-09-06 16:03:05 +0200146 return;
147 }
148
Radek Krejci1b2eef82021-02-17 11:17:27 +0100149 lysc_extension_instance_substatements_free(ctx, ext->substmts);
Radek Krejci0f969882020-08-21 16:56:47 +0200150 free(ext->data);
Radek Krejci38d85362019-09-05 16:26:38 +0200151}
Radek Krejcid6b76452019-09-03 17:03:03 +0200152
153/**
154 * @brief Plugin for the Metadata's annotation extension
155 */
156struct lyext_plugin metadata_plugin = {
157 .id = "libyang 2 - metadata, version 1",
158 .compile = &annotation_compile,
159 .validate = NULL,
Radek Krejciadcf63d2021-02-09 10:21:18 +0100160 .sprinter = &annotation_schema_printer,
Radek Krejci38d85362019-09-05 16:26:38 +0200161 .free = annotation_free
Radek Krejcid6b76452019-09-03 17:03:03 +0200162};