]>
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",
49 .arguments
= "struct nb_cb_create_args *args",
52 .operation
= NB_OP_MODIFY
,
53 .return_type
= "int ",
54 .return_value
= "NB_OK",
55 .arguments
= "struct nb_cb_modify_args *args",
58 .operation
= NB_OP_DESTROY
,
59 .return_type
= "int ",
60 .return_value
= "NB_OK",
61 .arguments
= "struct nb_cb_destroy_args *args",
64 .operation
= NB_OP_MOVE
,
65 .return_type
= "int ",
66 .return_value
= "NB_OK",
67 .arguments
= "struct nb_cb_move_args *args",
70 .operation
= NB_OP_APPLY_FINISH
,
72 .return_type
= "void ",
74 .arguments
= "struct nb_cb_apply_finish_args *args",
77 .operation
= NB_OP_GET_ELEM
,
78 .return_type
= "struct yang_data *",
79 .return_value
= "NULL",
80 .arguments
= "struct nb_cb_get_elem_args *args",
83 .operation
= NB_OP_GET_NEXT
,
84 .return_type
= "const void *",
85 .return_value
= "NULL",
86 .arguments
= "struct nb_cb_get_next_args *args",
89 .operation
= NB_OP_GET_KEYS
,
90 .return_type
= "int ",
91 .return_value
= "NB_OK",
92 .arguments
= "struct nb_cb_get_keys_args *args",
95 .operation
= NB_OP_LOOKUP_ENTRY
,
96 .return_type
= "const void *",
97 .return_value
= "NULL",
98 .arguments
= "struct nb_cb_lookup_entry_args *args",
101 .operation
= NB_OP_RPC
,
102 .return_type
= "int ",
103 .return_value
= "NB_OK",
104 .arguments
= "struct nb_cb_rpc_args *args",
112 static void replace_hyphens_by_underscores(char *str
)
117 while ((p
= strchr(p
, '-')) != NULL
)
121 static void generate_callback_name(struct lys_node
*snode
,
122 enum nb_operation operation
, char *buffer
,
129 for (; snode
; snode
= lys_parent(snode
)) {
130 /* Skip schema-only snodes. */
131 if (CHECK_FLAG(snode
->nodetype
, LYS_USES
| LYS_CHOICE
| LYS_CASE
136 listnode_add_head(snodes
, snode
);
139 memset(buffer
, 0, size
);
140 for (ALL_LIST_ELEMENTS_RO(snodes
, ln
, snode
)) {
141 strlcat(buffer
, snode
->name
, size
);
142 strlcat(buffer
, "_", size
);
144 strlcat(buffer
, nb_operation_name(operation
), size
);
145 list_delete(&snodes
);
147 replace_hyphens_by_underscores(buffer
);
150 static void generate_prototype(const struct nb_callback_info
*ncinfo
,
153 printf("%s%s(%s);\n", ncinfo
->return_type
, cb_name
, ncinfo
->arguments
);
156 static int generate_prototypes(const struct lys_node
*snode
, void *arg
)
158 switch (snode
->nodetype
) {
167 return YANG_ITER_CONTINUE
;
170 for (struct nb_callback_info
*cb
= &nb_callbacks
[0];
171 cb
->operation
!= -1; cb
++) {
172 char cb_name
[BUFSIZ
];
175 || !nb_operation_is_valid(cb
->operation
, snode
))
178 generate_callback_name((struct lys_node
*)snode
, cb
->operation
,
179 cb_name
, sizeof(cb_name
));
180 generate_prototype(cb
, cb_name
);
183 return YANG_ITER_CONTINUE
;
186 static void generate_callback(const struct nb_callback_info
*ncinfo
,
189 printf("%s%s%s(%s)\n{\n", static_cbs
? "static " : "",
190 ncinfo
->return_type
, cb_name
, ncinfo
->arguments
);
192 switch (ncinfo
->operation
) {
197 printf("\tswitch (args->event) {\n"
198 "\tcase NB_EV_VALIDATE:\n"
199 "\tcase NB_EV_PREPARE:\n"
200 "\tcase NB_EV_ABORT:\n"
201 "\tcase NB_EV_APPLY:\n"
202 "\t\t/* TODO: implement me. */\n"
209 printf("\t/* TODO: implement me. */\n");
213 printf("\treturn %s;\n}\n\n", ncinfo
->return_value
);
216 static int generate_callbacks(const struct lys_node
*snode
, void *arg
)
220 switch (snode
->nodetype
) {
229 return YANG_ITER_CONTINUE
;
232 for (struct nb_callback_info
*cb
= &nb_callbacks
[0];
233 cb
->operation
!= -1; cb
++) {
234 char cb_name
[BUFSIZ
];
237 || !nb_operation_is_valid(cb
->operation
, snode
))
241 char xpath
[XPATH_MAXLEN
];
243 yang_snode_get_path(snode
, YANG_PATH_DATA
, xpath
,
253 generate_callback_name((struct lys_node
*)snode
, cb
->operation
,
254 cb_name
, sizeof(cb_name
));
255 generate_callback(cb
, cb_name
);
258 return YANG_ITER_CONTINUE
;
261 static int generate_nb_nodes(const struct lys_node
*snode
, void *arg
)
265 switch (snode
->nodetype
) {
274 return YANG_ITER_CONTINUE
;
277 for (struct nb_callback_info
*cb
= &nb_callbacks
[0];
278 cb
->operation
!= -1; cb
++) {
279 char cb_name
[BUFSIZ
];
282 || !nb_operation_is_valid(cb
->operation
, snode
))
286 char xpath
[XPATH_MAXLEN
];
288 yang_snode_get_path(snode
, YANG_PATH_DATA
, xpath
,
292 "\t\t\t.xpath = \"%s\",\n",
294 printf("\t\t\t.cbs = {\n");
298 generate_callback_name((struct lys_node
*)snode
, cb
->operation
,
299 cb_name
, sizeof(cb_name
));
300 printf("\t\t\t\t.%s = %s,\n", nb_operation_name(cb
->operation
),
309 return YANG_ITER_CONTINUE
;
312 int main(int argc
, char *argv
[])
314 const char *search_path
= NULL
;
315 struct yang_module
*module
;
316 char module_name_underscores
[64];
320 while ((opt
= getopt(argc
, argv
, "hp:s")) != -1) {
326 if (stat(optarg
, &st
) == -1) {
328 "error: invalid search path '%s': %s\n",
329 optarg
, strerror(errno
));
332 if (S_ISDIR(st
.st_mode
) == 0) {
334 "error: search path is not directory");
338 search_path
= optarg
;
356 ly_ctx_set_searchdir(ly_native_ctx
, search_path
);
358 /* Load all FRR native models to ensure all augmentations are loaded. */
359 yang_module_load_all();
360 module
= yang_module_find(argv
[0]);
362 /* Non-native FRR module (e.g. modules from unit tests). */
363 module
= yang_module_load(argv
[0]);
365 /* Create a nb_node for all YANG schema nodes. */
368 /* Generate callback prototypes. */
370 printf("/* prototypes */\n");
371 yang_snodes_iterate(module
->info
, generate_prototypes
, 0, NULL
);
375 /* Generate callback functions. */
376 yang_snodes_iterate(module
->info
, generate_callbacks
, 0, NULL
);
378 strlcpy(module_name_underscores
, module
->name
,
379 sizeof(module_name_underscores
));
380 replace_hyphens_by_underscores(module_name_underscores
);
382 /* Generate frr_yang_module_info array. */
383 printf("/* clang-format off */\n"
384 "const struct frr_yang_module_info %s_info = {\n"
385 "\t.name = \"%s\",\n"
387 module_name_underscores
, module
->name
);
388 yang_snodes_iterate(module
->info
, generate_nb_nodes
, 0, NULL
);
390 "\t\t\t.xpath = NULL,\n"
395 /* Cleanup and exit. */