]> git.proxmox.com Git - mirror_frr.git/blame - lib/grammar_sandbox.c
lib: Code cleanup, formatting, & headers
[mirror_frr.git] / lib / grammar_sandbox.c
CommitLineData
1ab84bf3
QY
1/*
2 * Testing shim and API examples for the new CLI backend.
3 *
4 * This unit defines a number of commands in the old engine that can
5 * be used to test and interact with the new engine.
6 *
7 * This shim should be removed upon integration. It is currently hooked in
8 * vtysh/vtysh.c. It has no header, vtysh.c merely includes this entire unit
9 * since it clutters up the makefiles less and this is only a temporary shim.
10 *
11 * --
12 * Copyright (C) 2016 Cumulus Networks, Inc.
13 *
14 * This file is part of GNU Zebra.
15 *
16 * GNU Zebra is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2, or (at your option) any
19 * later version.
20 *
21 * GNU Zebra is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with GNU Zebra; see the file COPYING. If not, write to the Free
28 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
29 * 02111-1307, USA.
30 */
31
51e156b3 32#include "command.h"
9d0662e0 33#include "command_graph.h"
478bdaeb 34#include "command_parse.h"
9d0662e0 35#include "command_match.h"
51e156b3
QY
36
37#define GRAMMAR_STR "CLI grammar sandbox\n"
38
1ab84bf3
QY
39void
40grammar_sandbox_init(void);
41void
42pretty_print_graph (struct graph_node *start, int level);
43
44/*
45 * Start node for testing command graph.
46 *
47 * Each cmd_node will have one of these that replaces the `cmdvector` member.
48 * The examples below show how to install a command to the graph, calculate
49 * completions for a given input line, and match input against the graph.
50 */
340a2b4a
QY
51struct graph_node * nodegraph;
52
1ab84bf3
QY
53/**
54 * Reference use of parsing / command installation API
55 */
9d0662e0
QY
56DEFUN (grammar_test,
57 grammar_test_cmd,
58 "grammar parse .COMMAND",
59 GRAMMAR_STR
60 "command to pass to new parser\n")
61{
1ab84bf3
QY
62 char *command = argv_concat(argv, argc, 0);
63
64 // initialize a pretend cmd_element
65 struct cmd_element *cmd = XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct cmd_element));
eceb1066 66 cmd->string = command;
e648e61a
QY
67 cmd->doc = NULL;
68 cmd->func = NULL;
e1cbb2ff 69 cmd->tokens = vector_init(VECTOR_MIN_SIZE);
51e156b3 70
1ab84bf3
QY
71 // parse the command and install it into the command graph
72 parse_command_format (nodegraph, cmd);
73
74 // free resources
75 free (command);
0aa2c2ff 76
9d0662e0
QY
77 return CMD_SUCCESS;
78}
79
1ab84bf3
QY
80
81/**
82 * Reference use of completions API
83 */
eceb1066
QY
84DEFUN (grammar_test_complete,
85 grammar_test_complete_cmd,
86 "grammar complete .COMMAND",
9d0662e0 87 GRAMMAR_STR
eceb1066
QY
88 "attempt to complete input on DFA\n"
89 "command to complete")
9d0662e0 90{
1ab84bf3
QY
91 char *cmdstr = argv_concat (argv, argc, 0);
92 vector command = cmd_make_strvec (cmdstr);
93
94 struct list *completions;
95 enum matcher_rv result = match_command_complete (nodegraph, command, &completions);
18be0e59 96
1ab84bf3
QY
97 // print completions or relevant error message
98 if (completions)
99 {
100 struct listnode *ln;
101 struct graph_node *gn;
102 for (ALL_LIST_ELEMENTS_RO(completions,ln,gn))
103 {
104 if (gn->type == END_GN)
105 zlog_info ("<cr> (%p)", gn->element->func);
106 else
107 zlog_info ("%-30s%s", gn->text, gn->doc);
108 }
109 list_delete (completions);
110 }
18be0e59 111 else
1ab84bf3
QY
112 {
113 assert(MATCHER_ERROR(result));
114 zlog_info ("%% No match for \"%s\"", cmdstr);
880e24a1 115 }
1ab84bf3
QY
116
117 // free resources
118 cmd_free_strvec (command);
119 free (cmdstr);
18be0e59 120
9d0662e0 121 return CMD_SUCCESS;
340a2b4a
QY
122}
123
1ab84bf3
QY
124/**
125 * Reference use of matching API
126 */
eceb1066
QY
127DEFUN (grammar_test_match,
128 grammar_test_match_cmd,
129 "grammar match .COMMAND",
130 GRAMMAR_STR
131 "attempt to match input on DFA\n"
132 "command to match")
133{
1ab84bf3
QY
134 char *cmdstr = argv_concat(argv, argc, 0);
135 vector command = cmd_make_strvec (cmdstr);
6ce82b63 136
de9d7e4f 137 struct list *argvv = NULL;
6ce82b63 138 struct cmd_element *element = NULL;
1ab84bf3
QY
139 enum matcher_rv result = match_command (nodegraph, command, &argvv, &element);
140
141 // print completions or relevant error message
142 if (element)
143 {
144 zlog_info ("Matched: %s", element->string);
145 struct listnode *ln;
146 struct graph_node *gn;
147 for (ALL_LIST_ELEMENTS_RO(argvv,ln,gn))
148 if (gn->type != END_GN)
149 zlog_info ("func: %p", gn->element->func);
150 else
151 zlog_info ("%s -- %s", gn->text, gn->arg);
152
153 list_delete (argvv);
154 }
de9d7e4f 155 else {
1ab84bf3 156 assert(MATCHER_ERROR(result));
6ce82b63
QY
157 switch (result) {
158 case MATCHER_NO_MATCH:
1ab84bf3 159 zlog_info ("%% Unknown command");
6ce82b63
QY
160 break;
161 case MATCHER_INCOMPLETE:
1ab84bf3 162 zlog_info ("%% Incomplete command");
6ce82b63
QY
163 break;
164 case MATCHER_AMBIGUOUS:
1ab84bf3 165 zlog_info ("%% Ambiguous command");
6ce82b63
QY
166 break;
167 default:
1ab84bf3 168 zlog_info ("%% Unknown error");
6ce82b63
QY
169 break;
170 }
de9d7e4f
QY
171 }
172
1ab84bf3
QY
173 // free resources
174 cmd_free_strvec(command);
175 free(cmdstr);
176
eceb1066
QY
177 return CMD_SUCCESS;
178}
179
1ab84bf3
QY
180/**
181 * Testing shim to test docstrings
182 */
183DEFUN (grammar_test_doc,
184 grammar_test_doc_cmd,
185 "grammar test docstring",
186 GRAMMAR_STR
187 "Test function for docstring\n"
188 "Command end\n")
189{
190 // create cmd_element with docstring
191 struct cmd_element *cmd = XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct cmd_element));
192 cmd->string = "test docstring <example|selector follow> (1-255) end VARIABLE [OPTION|set lol] . VARARG";
193 cmd->doc = "Test stuff\n"
194 "docstring thing\n"
195 "first example\n"
196 "second example\n"
197 "follow\n"
198 "random range\n"
199 "end thingy\n"
200 "variable\n"
201 "optional variable\n"
202 "optional set\n"
203 "optional lol\n"
204 "vararg!\n";
205 cmd->func = NULL;
206 cmd->tokens = vector_init (VECTOR_MIN_SIZE);
207
208 // parse element
209 parse_command_format (nodegraph, cmd);
210
211 return CMD_SUCCESS;
212}
213
214/**
215 * Debugging command to print command graph
216 */
217DEFUN (grammar_test_show,
218 grammar_test_show_cmd,
219 "grammar show graph",
220 GRAMMAR_STR
221 "print current accumulated DFA\n")
222{
223 if (!nodegraph)
224 zlog_info("nodegraph uninitialized");
225 else
226 pretty_print_graph (nodegraph, 0);
227 return CMD_SUCCESS;
228}
51e156b3 229
1ab84bf3 230/* this is called in vtysh.c to set up the testing shim */
51e156b3 231void grammar_sandbox_init() {
1ab84bf3 232 zlog_info ("Initializing grammar testing shim");
5a5d576b 233 nodegraph = new_node(START_GN);
478bdaeb 234 install_element (ENABLE_NODE, &grammar_test_cmd);
340a2b4a 235 install_element (ENABLE_NODE, &grammar_test_show_cmd);
9d0662e0 236 install_element (ENABLE_NODE, &grammar_test_match_cmd);
eceb1066 237 install_element (ENABLE_NODE, &grammar_test_complete_cmd);
0aa2c2ff 238 install_element (ENABLE_NODE, &grammar_test_doc_cmd);
51e156b3 239}
1ab84bf3
QY
240
241/* recursive pretty-print for command graph */
242void
243pretty_print_graph (struct graph_node *start, int level)
244{
245 // print this node
246 fprintf (stdout, "%s[%d] ", start->text, vector_active (start->children));
247
248 if (vector_active (start->children))
249 {
250 if (vector_active (start->children) == 1)
251 pretty_print_graph (vector_slot (start->children, 0), level);
252 else
253 {
254 fprintf(stdout, "\n");
255 for (unsigned int i = 0; i < vector_active (start->children); i++)
256 {
257 struct graph_node *r = vector_slot (start->children, i);
258 for (int j = 0; j < level+1; j++)
259 fprintf (stdout, " ");
260 pretty_print_graph (r, level+1);
261 }
262 }
263 }
264 else
265 fprintf(stdout, "\n");
266}