]> git.proxmox.com Git - mirror_frr.git/blame - tools/gen_northbound_callbacks.c
staticd: Do not ready prefix for printing till it's decoded
[mirror_frr.git] / tools / gen_northbound_callbacks.c
CommitLineData
1c2facd1
RW
1/*
2 * Copyright (C) 2018 NetDEF, Inc.
3 * Renato Westphal
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#define REALLY_NEED_PLAIN_GETOPT 1
21
22#include <zebra.h>
23
24#include <unistd.h>
25
26#include "yang.h"
27#include "northbound.h"
28
29static void __attribute__((noreturn)) usage(int status)
30{
31 fprintf(stderr, "usage: gen_northbound_callbacks [-h] MODULE\n");
32 exit(status);
33}
34
35static struct nb_callback_info {
36 int operation;
37 bool optional;
38 char return_type[32];
39 char return_value[32];
40 char arguments[128];
41} nb_callbacks[] = {
42 {
43 .operation = NB_OP_CREATE,
44 .return_type = "int ",
45 .return_value = "NB_OK",
46 .arguments =
47 "enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource",
48 },
49 {
50 .operation = NB_OP_MODIFY,
51 .return_type = "int ",
52 .return_value = "NB_OK",
53 .arguments =
54 "enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource",
55 },
56 {
57 .operation = NB_OP_DELETE,
58 .return_type = "int ",
59 .return_value = "NB_OK",
60 .arguments =
61 "enum nb_event event, const struct lyd_node *dnode",
62 },
63 {
64 .operation = NB_OP_MOVE,
65 .return_type = "int ",
66 .return_value = "NB_OK",
67 .arguments =
68 "enum nb_event event, const struct lyd_node *dnode",
69 },
70 {
71 .operation = NB_OP_APPLY_FINISH,
72 .optional = true,
73 .return_type = "void ",
74 .return_value = "",
75 .arguments = "const struct lyd_node *dnode",
76 },
77 {
78 .operation = NB_OP_GET_ELEM,
79 .return_type = "struct yang_data *",
80 .return_value = "NULL",
81 .arguments = "const char *xpath, const void *list_entry",
82 },
83 {
84 .operation = NB_OP_GET_NEXT,
85 .return_type = "const void *",
86 .return_value = "NULL",
1a4bc045
RW
87 .arguments =
88 "const void *parent_list_entry, const void *list_entry",
1c2facd1
RW
89 },
90 {
91 .operation = NB_OP_GET_KEYS,
92 .return_type = "int ",
93 .return_value = "NB_OK",
1a4bc045
RW
94 .arguments =
95 "const void *list_entry, struct yang_list_keys *keys",
1c2facd1
RW
96 },
97 {
98 .operation = NB_OP_LOOKUP_ENTRY,
99 .return_type = "const void *",
100 .return_value = "NULL",
1a4bc045
RW
101 .arguments =
102 "const void *parent_list_entry, const struct yang_list_keys *keys",
1c2facd1
RW
103 },
104 {
105 .operation = NB_OP_RPC,
106 .return_type = "int ",
107 .return_value = "NB_OK",
108 .arguments =
109 "const char *xpath, const struct list *input, struct list *output",
110 },
111 {
112 /* sentinel */
113 .operation = -1,
114 },
115};
116
117static void replace_hyphens_by_underscores(char *str)
118{
119 char *p;
120
121 p = str;
122 while ((p = strchr(p, '-')) != NULL)
123 *p++ = '_';
124}
125
126static void generate_callback_name(struct lys_node *snode,
127 enum nb_operation operation, char *buffer,
128 size_t size)
129{
130 struct list *snodes;
131 struct listnode *ln;
132
133 snodes = list_new();
134 for (; snode; snode = lys_parent(snode)) {
135 /* Skip schema-only snodes. */
db452508
RW
136 if (CHECK_FLAG(snode->nodetype, LYS_USES | LYS_CHOICE | LYS_CASE
137 | LYS_INPUT
138 | LYS_OUTPUT))
1c2facd1
RW
139 continue;
140
141 listnode_add_head(snodes, snode);
142 }
143
144 memset(buffer, 0, size);
145 for (ALL_LIST_ELEMENTS_RO(snodes, ln, snode)) {
146 strlcat(buffer, snode->name, size);
147 strlcat(buffer, "_", size);
148 }
149 strlcat(buffer, nb_operation_name(operation), size);
150 list_delete(&snodes);
151
152 replace_hyphens_by_underscores(buffer);
153}
154
e0ccfad2 155static int generate_callbacks(const struct lys_node *snode, void *arg)
1c2facd1
RW
156{
157 bool first = true;
158
159 switch (snode->nodetype) {
160 case LYS_CONTAINER:
161 case LYS_LEAF:
162 case LYS_LEAFLIST:
163 case LYS_LIST:
164 case LYS_NOTIF:
165 case LYS_RPC:
166 break;
167 default:
e0ccfad2 168 return YANG_ITER_CONTINUE;
1c2facd1
RW
169 }
170
171 for (struct nb_callback_info *cb = &nb_callbacks[0];
172 cb->operation != -1; cb++) {
173 char cb_name[BUFSIZ];
174
175 if (cb->optional
176 || !nb_operation_is_valid(cb->operation, snode))
177 continue;
178
179 if (first) {
180 char xpath[XPATH_MAXLEN];
181
182 yang_snode_get_path(snode, YANG_PATH_DATA, xpath,
183 sizeof(xpath));
184
185 printf("/*\n"
186 " * XPath: %s\n"
187 " */\n",
188 xpath);
189 first = false;
190 }
191
192 generate_callback_name((struct lys_node *)snode, cb->operation,
193 cb_name, sizeof(cb_name));
194 printf("static %s%s(%s)\n"
195 "{\n"
196 "\t/* TODO: implement me. */\n"
197 "\treturn %s;\n"
198 "}\n\n",
199 nb_callbacks[cb->operation].return_type, cb_name,
200 nb_callbacks[cb->operation].arguments,
201 nb_callbacks[cb->operation].return_value);
202 }
e0ccfad2
RW
203
204 return YANG_ITER_CONTINUE;
1c2facd1
RW
205}
206
e0ccfad2 207static int generate_nb_nodes(const struct lys_node *snode, void *arg)
1c2facd1
RW
208{
209 bool first = true;
210
211 switch (snode->nodetype) {
212 case LYS_CONTAINER:
213 case LYS_LEAF:
214 case LYS_LEAFLIST:
215 case LYS_LIST:
216 case LYS_NOTIF:
217 case LYS_RPC:
218 break;
219 default:
e0ccfad2 220 return YANG_ITER_CONTINUE;
1c2facd1
RW
221 }
222
223 for (struct nb_callback_info *cb = &nb_callbacks[0];
224 cb->operation != -1; cb++) {
225 char cb_name[BUFSIZ];
226
227 if (cb->optional
228 || !nb_operation_is_valid(cb->operation, snode))
229 continue;
230
231 if (first) {
232 char xpath[XPATH_MAXLEN];
233
234 yang_snode_get_path(snode, YANG_PATH_DATA, xpath,
235 sizeof(xpath));
236
237 printf("\t\t{\n"
238 "\t\t\t.xpath = \"%s\",\n",
239 xpath);
240 first = false;
241 }
242
243 generate_callback_name((struct lys_node *)snode, cb->operation,
244 cb_name, sizeof(cb_name));
245 printf("\t\t\t.cbs.%s = %s,\n",
246 nb_operation_name(cb->operation), cb_name);
247 }
248
249 if (!first)
250 printf("\t\t},\n");
e0ccfad2
RW
251
252 return YANG_ITER_CONTINUE;
1c2facd1
RW
253}
254
255int main(int argc, char *argv[])
256{
257 struct yang_module *module;
258 char module_name_underscores[64];
259 int opt;
260
261 while ((opt = getopt(argc, argv, "h")) != -1) {
262 switch (opt) {
263 case 'h':
264 usage(EXIT_SUCCESS);
265 /* NOTREACHED */
266 default:
267 usage(EXIT_FAILURE);
268 /* NOTREACHED */
269 }
270 }
271 argc -= optind;
272 argv += optind;
273 if (argc != 1)
274 usage(EXIT_FAILURE);
275
276 yang_init();
277
544ca69a
RW
278 /* Load all FRR native models to ensure all augmentations are loaded. */
279 yang_module_load_all();
280 module = yang_module_find(argv[0]);
281 if (!module)
282 /* Non-native FRR module (e.g. modules from unit tests). */
283 module = yang_module_load(argv[0]);
284
285 /* Create a nb_node for all YANG schema nodes. */
286 nb_nodes_create();
1c2facd1
RW
287
288 /* Generate callback functions. */
e0ccfad2 289 yang_snodes_iterate_module(module->info, generate_callbacks, 0, NULL);
1c2facd1
RW
290
291 strlcpy(module_name_underscores, module->name,
292 sizeof(module_name_underscores));
293 replace_hyphens_by_underscores(module_name_underscores);
294
295 /* Generate frr_yang_module_info array. */
296 printf("/* clang-format off */\n"
297 "const struct frr_yang_module_info %s_info = {\n"
298 "\t.name = \"%s\",\n"
299 "\t.nodes = {\n",
300 module_name_underscores, module->name);
e0ccfad2 301 yang_snodes_iterate_module(module->info, generate_nb_nodes, 0, NULL);
1c2facd1
RW
302 printf("\t\t{\n"
303 "\t\t\t.xpath = NULL,\n"
304 "\t\t},\n");
305 printf("\t}\n"
306 "};\n");
307
308 /* Cleanup and exit. */
544ca69a 309 nb_nodes_delete();
1c2facd1
RW
310 yang_terminate();
311
312 return 0;
313}