]>
git.proxmox.com Git - mirror_frr.git/blob - tools/gen_northbound_callbacks.c
2 * Copyright (C) 2018 NetDEF, Inc.
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)
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
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
20 #define REALLY_NEED_PLAIN_GETOPT 1
27 #include "northbound.h"
29 static bool static_cbs
;
31 static void __attribute__((noreturn
)) usage(int status
)
33 extern const char *__progname
;
34 fprintf(stderr
, "usage: %s [-h] [-s] [-p path] MODULE\n", __progname
);
38 static struct nb_callback_info
{
42 char return_value
[32];
46 .operation
= NB_OP_CREATE
,
47 .return_type
= "int ",
48 .return_value
= "NB_OK",
50 "enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource",
53 .operation
= NB_OP_MODIFY
,
54 .return_type
= "int ",
55 .return_value
= "NB_OK",
57 "enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource",
60 .operation
= NB_OP_DESTROY
,
61 .return_type
= "int ",
62 .return_value
= "NB_OK",
64 "enum nb_event event, const struct lyd_node *dnode",
67 .operation
= NB_OP_MOVE
,
68 .return_type
= "int ",
69 .return_value
= "NB_OK",
71 "enum nb_event event, const struct lyd_node *dnode",
74 .operation
= NB_OP_APPLY_FINISH
,
76 .return_type
= "void ",
78 .arguments
= "const struct lyd_node *dnode",
81 .operation
= NB_OP_GET_ELEM
,
82 .return_type
= "struct yang_data *",
83 .return_value
= "NULL",
84 .arguments
= "const char *xpath, const void *list_entry",
87 .operation
= NB_OP_GET_NEXT
,
88 .return_type
= "const void *",
89 .return_value
= "NULL",
91 "const void *parent_list_entry, const void *list_entry",
94 .operation
= NB_OP_GET_KEYS
,
95 .return_type
= "int ",
96 .return_value
= "NB_OK",
98 "const void *list_entry, struct yang_list_keys *keys",
101 .operation
= NB_OP_LOOKUP_ENTRY
,
102 .return_type
= "const void *",
103 .return_value
= "NULL",
105 "const void *parent_list_entry, const struct yang_list_keys *keys",
108 .operation
= NB_OP_RPC
,
109 .return_type
= "int ",
110 .return_value
= "NB_OK",
112 "const char *xpath, const struct list *input, struct list *output",
120 static void replace_hyphens_by_underscores(char *str
)
125 while ((p
= strchr(p
, '-')) != NULL
)
129 static void generate_callback_name(struct lys_node
*snode
,
130 enum nb_operation operation
, char *buffer
,
137 for (; snode
; snode
= lys_parent(snode
)) {
138 /* Skip schema-only snodes. */
139 if (CHECK_FLAG(snode
->nodetype
, LYS_USES
| LYS_CHOICE
| LYS_CASE
144 listnode_add_head(snodes
, snode
);
147 memset(buffer
, 0, size
);
148 for (ALL_LIST_ELEMENTS_RO(snodes
, ln
, snode
)) {
149 strlcat(buffer
, snode
->name
, size
);
150 strlcat(buffer
, "_", size
);
152 strlcat(buffer
, nb_operation_name(operation
), size
);
153 list_delete(&snodes
);
155 replace_hyphens_by_underscores(buffer
);
158 static void generate_prototype(const struct nb_callback_info
*ncinfo
,
161 printf("%s%s(%s);\n", ncinfo
->return_type
, cb_name
, ncinfo
->arguments
);
164 static int generate_prototypes(const struct lys_node
*snode
, void *arg
)
166 switch (snode
->nodetype
) {
175 return YANG_ITER_CONTINUE
;
178 for (struct nb_callback_info
*cb
= &nb_callbacks
[0];
179 cb
->operation
!= -1; cb
++) {
180 char cb_name
[BUFSIZ
];
183 || !nb_operation_is_valid(cb
->operation
, snode
))
186 generate_callback_name((struct lys_node
*)snode
, cb
->operation
,
187 cb_name
, sizeof(cb_name
));
188 generate_prototype(cb
, cb_name
);
191 return YANG_ITER_CONTINUE
;
194 static void generate_callback(const struct nb_callback_info
*ncinfo
,
197 printf("%s%s%s(%s)\n{\n", static_cbs
? "static " : "",
198 ncinfo
->return_type
, cb_name
, ncinfo
->arguments
);
200 switch (ncinfo
->operation
) {
205 printf("\tswitch (event) {\n"
206 "\tcase NB_EV_VALIDATE:\n"
207 "\tcase NB_EV_PREPARE:\n"
208 "\tcase NB_EV_ABORT:\n"
209 "\tcase NB_EV_APPLY:\n"
210 "\t\t/* TODO: implement me. */\n"
217 printf("\t/* TODO: implement me. */\n");
221 printf("\treturn %s;\n}\n\n", ncinfo
->return_value
);
224 static int generate_callbacks(const struct lys_node
*snode
, void *arg
)
228 switch (snode
->nodetype
) {
237 return YANG_ITER_CONTINUE
;
240 for (struct nb_callback_info
*cb
= &nb_callbacks
[0];
241 cb
->operation
!= -1; cb
++) {
242 char cb_name
[BUFSIZ
];
245 || !nb_operation_is_valid(cb
->operation
, snode
))
249 char xpath
[XPATH_MAXLEN
];
251 yang_snode_get_path(snode
, YANG_PATH_DATA
, xpath
,
261 generate_callback_name((struct lys_node
*)snode
, cb
->operation
,
262 cb_name
, sizeof(cb_name
));
263 generate_callback(cb
, cb_name
);
266 return YANG_ITER_CONTINUE
;
269 static int generate_nb_nodes(const struct lys_node
*snode
, void *arg
)
273 switch (snode
->nodetype
) {
282 return YANG_ITER_CONTINUE
;
285 for (struct nb_callback_info
*cb
= &nb_callbacks
[0];
286 cb
->operation
!= -1; cb
++) {
287 char cb_name
[BUFSIZ
];
290 || !nb_operation_is_valid(cb
->operation
, snode
))
294 char xpath
[XPATH_MAXLEN
];
296 yang_snode_get_path(snode
, YANG_PATH_DATA
, xpath
,
300 "\t\t\t.xpath = \"%s\",\n",
302 printf("\t\t\t.cbs = {\n");
306 generate_callback_name((struct lys_node
*)snode
, cb
->operation
,
307 cb_name
, sizeof(cb_name
));
308 printf("\t\t\t\t.%s = %s,\n", nb_operation_name(cb
->operation
),
317 return YANG_ITER_CONTINUE
;
320 int main(int argc
, char *argv
[])
322 const char *search_path
= NULL
;
323 struct yang_module
*module
;
324 char module_name_underscores
[64];
328 while ((opt
= getopt(argc
, argv
, "hp:s")) != -1) {
334 if (stat(optarg
, &st
) == -1) {
336 "error: invalid search path '%s': %s\n",
337 optarg
, strerror(errno
));
340 if (S_ISDIR(st
.st_mode
) == 0) {
342 "error: search path is not directory");
346 search_path
= optarg
;
364 ly_ctx_set_searchdir(ly_native_ctx
, search_path
);
366 /* Load all FRR native models to ensure all augmentations are loaded. */
367 yang_module_load_all();
368 module
= yang_module_find(argv
[0]);
370 /* Non-native FRR module (e.g. modules from unit tests). */
371 module
= yang_module_load(argv
[0]);
373 /* Create a nb_node for all YANG schema nodes. */
376 /* Generate callback prototypes. */
378 printf("/* prototypes */\n");
379 yang_snodes_iterate_module(module
->info
, generate_prototypes
, 0,
384 /* Generate callback functions. */
385 yang_snodes_iterate_module(module
->info
, generate_callbacks
, 0, NULL
);
387 strlcpy(module_name_underscores
, module
->name
,
388 sizeof(module_name_underscores
));
389 replace_hyphens_by_underscores(module_name_underscores
);
391 /* Generate frr_yang_module_info array. */
392 printf("/* clang-format off */\n"
393 "const struct frr_yang_module_info %s_info = {\n"
394 "\t.name = \"%s\",\n"
396 module_name_underscores
, module
->name
);
397 yang_snodes_iterate_module(module
->info
, generate_nb_nodes
, 0, NULL
);
399 "\t\t\t.xpath = NULL,\n"
404 /* Cleanup and exit. */