]>
Commit | Line | Data |
---|---|---|
9b9cdb46 QY |
1 | FRR Command Line Interface |
2 | ========================== | |
3 | ||
4 | Definition Grammar | |
5 | ------------------ | |
6 | ||
7 | This is a reference for the syntax used when defining new CLI commands. An | |
8 | example definition is: | |
9 | ||
4e3e06d6 | 10 | ``` |
9b9cdb46 QY |
11 | DEFUN (command_name, |
12 | command_name_cmd, | |
13 | --> "example <command|line [interface]> DEFINITION...", | |
14 | <..doc strings..>) | |
4e3e06d6 | 15 | ``` |
9b9cdb46 QY |
16 | |
17 | The arrowed part is the definition string. | |
18 | ||
19 | Explicit syntax rules in Flex and Bison may be found in lib/command_lex.l and | |
20 | lib/command_parse.y, respectively. If you can read BNF and regex those will be | |
21 | more useful than this document. | |
22 | ||
23 | If the parser is throwing syntax or other errors and you can't figure out why, | |
24 | it's unlikely to be a bug in the parser. If the error message is not useful, | |
25 | please file a bug for a better error message. If all else fails, read the token | |
26 | definitions in the lexer source and the Bison BNF in the parser source. | |
27 | ||
28 | Characters allowed in each token type: | |
29 | ||
30 | Tokens | |
31 | ------ | |
4e3e06d6 | 32 | * `WORD` -- A token that begins with +, -, or a lowercase letter. It is |
9779e3f1 QY |
33 | an unchanging part of the command and will only match itself. |
34 | Example: "show ip bgp", every token is a WORD. | |
4e3e06d6 DL |
35 | * `IPV4` -- 'A.B.C.D', matches an IPv4 address. |
36 | * `IPV6` -- 'X:X::X:X', matches an IPv6 address. | |
37 | * `IPV4_PREFIX` -- 'A.B.C.D/M', matches an IPv4 prefix in CIDR notation. | |
38 | * `IPV6_PREFIX` -- 'X:X::X:X/M', matches an IPv6 prefix in CIDR notation. | |
9779e3f1 QY |
39 | * `MAC` -- 'M:A:C', matches a 48-bit mac address |
40 | * `MAC_PREFIX` -- 'M:A:C/M', matches a 48-bit mac address with a mask | |
4e3e06d6 DL |
41 | * `VARIABLE` -- Begins with a capital letter. Matches any input. |
42 | * `RANGE` -- Numeric range delimited by parentheses, e.g. (-100 - 100) or | |
9779e3f1 | 43 | (10-20). Will only match numbers in the range. |
9b9cdb46 QY |
44 | |
45 | Rules | |
46 | ----- | |
4e3e06d6 | 47 | * `<angle|brackets>` -- Contain sequences of tokens separated by pipes and |
9b9cdb46 | 48 | provide mutual exclusion. Sequences may contain |
4e3e06d6 DL |
49 | `<mutual|exclusion>` but not as the first token. |
50 | Disallowed: `"example <<a|b> c|d>"` | |
51 | Allowed: `"example <a c|b c|d>"` | |
52 | * `[square brackets]` -- Contains sequences of tokens that are optional (can be | |
53 | omitted). `[<a|b>]` can be shortened to `[a|b]`. | |
54 | * `{curly|braces}` -- similar to angle brackets, but instead of mutual | |
9b9cdb46 QY |
55 | exclusion, curly braces indicate that one or more of the |
56 | pipe-separated sequences may be provided in any order. | |
4e3e06d6 | 57 | * `VARIADICS...` -- Any token which accepts input (so anything except WORD) |
9b9cdb46 QY |
58 | and that occurs as the last token of a line may be |
59 | followed by an ellipsis, which indicates that input | |
60 | matching the token may be repeated an unlimited number | |
61 | of times. | |
4e3e06d6 DL |
62 | * `$name` -- Specify a variable name for the preceding token. See |
63 | "Variable Names" below. | |
9b9cdb46 QY |
64 | |
65 | Some general notes: | |
66 | ||
67 | * Options are allowed at the beginning of the command. The developer is | |
68 | entreated to use these extremely sparingly. They are most useful for | |
69 | implementing the 'no' form of configuration commands. Please think carefully | |
70 | before using them for anything else. There is usually a better solution, even | |
71 | if it is just separating out the command definition into separate ones. | |
72 | ||
73 | * The developer should judiciously apply separation of concerns when defining | |
74 | CLI. CLI definitions for two unrelated or vaguely related commands or | |
75 | configuration items should be defined in separate commands. Clarity is | |
76 | preferred over LOC (within reason). | |
77 | ||
bb74e5ac QY |
78 | * The maximum number of space-separated tokens that can be entered is presently |
79 | limited to 256. Please keep this limit in mind when implementing new CLI. | |
80 | ||
4e3e06d6 DL |
81 | Variable Names |
82 | -------------- | |
83 | The parser tries to fill the "varname" field on each token. This can happen | |
84 | either manually or automatically. Manual specifications work by appending | |
85 | `"$name"` after the input specifier: | |
86 | ||
87 | ``` | |
88 | foo bar$cmd WORD$name A.B.C.D$ip | |
89 | ``` | |
90 | ||
91 | Note that you can also assign variable names to fixed input tokens, this can | |
92 | be useful if multiple commands share code. You can also use "$name" after a | |
93 | multiple-choice option: | |
94 | ||
95 | ``` | |
96 | foo bar <A.B.C.D|X:X::X:X>$addr [optionA|optionB]$mode | |
97 | ``` | |
98 | ||
99 | The variable name is in this case assigned to the last token in each of the | |
100 | branches. | |
101 | ||
102 | Automatic assignment of variable names works by applying the following rules: | |
103 | ||
104 | - manual names always have priority | |
105 | - a "[no]" at the beginning receives "no" as varname on the "no" token | |
32a71fd8 | 106 | - VARIABLE tokens whose text is not "WORD" or "NAME" receive a cleaned lowercase |
4e3e06d6 DL |
107 | version of the token text as varname, e.g. "ROUTE-MAP" becomes "route_map". |
108 | - other variable tokens (i.e. everything except "fixed") receive the text of | |
109 | the preceding fixed token as varname, if one can be found. E.g.: | |
110 | "ip route A.B.C.D/M INTERFACE" assigns "route" to the "A.B.C.D/M" token. | |
111 | ||
112 | These rules should make it possible to avoid manual varname assignment in 90% | |
113 | of the cases. | |
114 | ||
ae56903c DL |
115 | DEFPY |
116 | ----- | |
117 | ||
118 | `DEFPY(...)` is an enhanced version of `DEFUN()` which is preprocessed by | |
119 | ` python/clidef.py`. The python script parses the command definition string, | |
120 | extracts variable names and types, and generates a C wrapper function that | |
121 | parses the variables and passes them on. This means that in the CLI function | |
122 | body, you will receive additional parameters with appropriate types. | |
123 | ||
124 | This is best explained by an example: | |
125 | ||
126 | ``` | |
127 | DEFPY(func, func_cmd, "[no] foo bar A.B.C.D (0-99)$num", "...help...") | |
128 | ||
129 | => | |
130 | ||
131 | func(self, vty, argc, argv, /* standard CLI arguments */ | |
132 | ||
133 | const char *no, /* unparsed "no" */ | |
134 | struct in_addr bar, /* parsed IP address */ | |
135 | const char *bar_str, /* unparsed IP address */ | |
136 | long num, /* parsed num */ | |
137 | const char *num_str) /* unparsed num */ | |
138 | ``` | |
139 | ||
140 | Note that as documented in the previous section, "bar" is automatically | |
141 | applied as variable name for "A.B.C.D". The python code then detects this | |
142 | is an IP address argument and generates code to parse it into a | |
143 | `struct in_addr`, passing it in `bar`. The raw value is passed in `bar_str`. | |
144 | The range/number argument works in the same way with the explicitly given | |
145 | variable name. | |
146 | ||
147 | ### Type rules | |
148 | ||
149 | | Token(s) | Type | Value if omitted by user | | |
150 | |--------------------------|-------------|--------------------------| | |
151 | | `A.B.C.D` | `struct in_addr` | 0.0.0.0 | | |
152 | | `X:X::X:X` | `struct in6_addr` | :: | | |
153 | | `A.B.C.D + X:X::X:X` | `const union sockunion *` | NULL | | |
154 | | `A.B.C.D/M` | `const struct prefix_ipv4 *` | NULL | | |
155 | | `X:X::X:X/M` | `const struct prefix_ipv6 *` | NULL | | |
156 | | `A.B.C.D/M + X:X::X:X/M` | `const struct prefix *` | NULL | | |
157 | | `(0-9)` | `long` | 0 | | |
158 | | `VARIABLE` | `const char *` | NULL | | |
159 | | `word` | `const char *` | NULL | | |
160 | | _all other_ | `const char *` | NULL | | |
161 | ||
162 | Note the following details: | |
163 | ||
164 | * not all parameters are pointers, some are passed as values. | |
165 | * when the type is not `const char *`, there will be an extra `_str` argument | |
166 | with type `const char *`. | |
167 | * you can give a variable name not only to `VARIABLE` tokens but also to | |
168 | `word` tokens (e.g. constant words). This is useful if some parts of a | |
169 | command are optional. The type will be `const char *`. | |
170 | * `[no]` will be passed as `const char *no`. | |
171 | * pointers will be NULL when the argument is optional and the user did not | |
172 | use it. | |
173 | * if a parameter is not a pointer, but is optional and the user didn't use it, | |
174 | the default value will be passed. Check the `_str` argument if you need to | |
175 | determine whether the parameter was omitted. | |
176 | * if the definition contains multiple parameters with the same variable name, | |
177 | they will be collapsed into a single function parameter. The python code | |
178 | will detect if the types are compatible (i.e. IPv4 + IPv6 variantes) and | |
179 | choose a corresponding C type. | |
180 | * the standard DEFUN parameters (self, vty, argc, argv) are still present and | |
181 | can be used. A DEFUN can simply be **edited into a DEFPY without further | |
182 | changes and it will still work**; this allows easy forward migration. | |
183 | * a file may contain both DEFUN and DEFPY statements. | |
184 | ||
185 | ### Getting a parameter dump | |
186 | ||
187 | The clidef.py script can be called to get a list of DEFUNs/DEFPYs with | |
188 | the parameter name/type list: | |
189 | ||
190 | ``` | |
191 | lib/clippy python/clidef.py --all-defun --show lib/plist.c > /dev/null | |
192 | ``` | |
193 | ||
194 | The generated code is printed to stdout, the info dump to stderr. The | |
195 | `--all-defun` argument will make it process DEFUN blocks as well as DEFPYs, | |
196 | which is useful prior to converting some DEFUNs. **The dump does not list | |
197 | the `_str` arguments** to keep the output shorter. | |
198 | ||
199 | Note that the clidef.py script cannot be run with python directly, it needs | |
200 | to be run with _clippy_ since the latter makes the CLI parser available. | |
201 | ||
202 | ### Include & Makefile requirements | |
203 | ||
204 | A source file that uses DEFPY needs to include the `_clippy.c` file **before | |
205 | all DEFPY statements**: | |
206 | ||
207 | ``` | |
208 | /* GPL header */ | |
209 | #include ... | |
210 | ||
211 | ... | |
212 | ||
2e4c2296 | 213 | #include "daemon/filename_clippy.c" |
ae56903c DL |
214 | |
215 | DEFPY(...) | |
216 | DEFPY(...) | |
217 | ||
218 | install_element(...) | |
219 | ``` | |
220 | ||
221 | This dependency needs to be marked in Makefile.am: (there is no ordering | |
222 | requirement) | |
223 | ||
224 | ``` | |
225 | include ../common.am | |
226 | ||
227 | # ... | |
228 | ||
229 | # if linked into a LTLIBRARY (.la/.so): | |
230 | filename.lo: filename_clippy.c | |
231 | ||
232 | # if linked into an executable or static library (.a): | |
233 | filename.o: filename_clippy.c | |
234 | ``` | |
235 | ||
9b9cdb46 QY |
236 | Doc Strings |
237 | ----------- | |
238 | Each token in a command definition should be documented with a brief doc | |
239 | string that informs a user of the meaning and/or purpose of the subsequent | |
240 | command tree. These strings are provided as the last parameter to DEFUN macros, | |
241 | concatenated together and separated by an escaped newline ('\n'). These are | |
242 | best explained by example. | |
243 | ||
4e3e06d6 | 244 | ``` |
9b9cdb46 QY |
245 | DEFUN (config_terminal, |
246 | config_terminal_cmd, | |
247 | "configure terminal", | |
248 | "Configuration from vty interface\n" | |
249 | "Configuration terminal\n") | |
4e3e06d6 | 250 | ``` |
9b9cdb46 QY |
251 | |
252 | The last parameter is split into two lines for readability. Two newline | |
253 | delimited doc strings are present, one for each token in the command. The | |
254 | second string documents the functionality of the 'terminal' command in the | |
255 | 'configure' tree. | |
256 | ||
257 | Note that the first string, for 'configure' does not contain documentation for | |
258 | 'terminal'. This is because the CLI is best envisioned as a tree, with tokens | |
259 | defining branches. An imaginary 'start' token is the root of every command in a | |
260 | CLI node. Each subsequent written token descends into a subtree, so the | |
261 | documentation for that token ideally summarizes all the functionality contained | |
262 | in the subtree. | |
263 | ||
264 | A consequence of this structure is that the developer must be careful to use | |
265 | the same doc strings when defining multiple commands that are part of the same | |
266 | tree. Commands which share prefixes must share the same doc strings for those | |
267 | prefixes. On startup the parser will generate warnings if it notices | |
268 | inconsistent doc strings. Behavior is undefined; the same token may show up | |
269 | twice in completions, with different doc strings, or it may show up once with a | |
270 | random doc string. Parser warnings should be heeded and fixed to avoid | |
271 | confusing users. | |
272 | ||
273 | The number of doc strings provided must be equal to the amount of tokens | |
274 | present in the command definition, read left to right, ignoring any special | |
275 | constructs. | |
276 | ||
277 | In the examples below, each arrowed token needs a doc string. | |
278 | ||
4e3e06d6 | 279 | ``` |
9b9cdb46 QY |
280 | "show ip bgp" |
281 | ^ ^ ^ | |
282 | ||
283 | "command <foo|bar> [example]" | |
284 | ^ ^ ^ ^ | |
4e3e06d6 | 285 | ``` |
9b9cdb46 QY |
286 | |
287 | Data Structures | |
288 | --------------- | |
289 | On startup, the CLI parser sequentially parses each command string definition | |
290 | and constructs a directed graph with each token forming a node. This graph is | |
291 | the basis of the entire CLI system. It is used to match user input in order to | |
292 | generate command completions and match commands to functions. | |
293 | ||
294 | There is one graph per CLI node (not the same as a graph node in the CLI | |
295 | graph). The CLI node struct keeps a reference to its graph (see lib/command.h). | |
296 | ||
297 | While most of the graph maintains the form of a tree, special constructs | |
298 | outlined in the Rules section introduce some quirks. <>, [] and {} form | |
299 | self-contained 'subgraphs'. Each subgraph is a tree except that all of the | |
300 | 'leaves' actually share a child node. This helps with minimizing graph size and | |
301 | debugging. | |
302 | ||
303 | As an example, the subgraph generated by <foo|bar> looks like this: | |
304 | ||
305 | . | |
306 | . | |
307 | | | |
308 | +----+---+ | |
309 | +--- -+ FORK +----+ | |
310 | | +--------+ | | |
311 | +--v---+ +--v---+ | |
312 | | foo | | bar | | |
313 | +--+---+ +--+---+ | |
314 | | +------+ | | |
315 | +------> JOIN <-----+ | |
316 | +---+--+ | |
317 | | | |
318 | . | |
319 | . | |
320 | ||
321 | FORK and JOIN nodes are plumbing nodes that don't correspond to user input. | |
322 | They're necessary in order to deduplicate these constructs where applicable. | |
323 | ||
324 | Options follow the same form, except that there is an edge from the FORK node | |
325 | to the JOIN node. | |
326 | ||
327 | Keywords follow the same form, except that there is an edge from JOIN to FORK. | |
328 | Because of this the CLI graph cannot be called acyclic. There is special logic | |
329 | in the input matching code that keeps a stack of paths already taken through | |
330 | the node in order to disallow following the same path more than once. | |
331 | ||
332 | Variadics are a bit special; they have an edge back to themselves, which allows | |
333 | repeating the same input indefinitely. | |
334 | ||
335 | The leaves of the graph are nodes that have no out edges. These nodes are | |
336 | special; their data section does not contain a token, as most nodes do, or | |
337 | NULL, as in FORK/JOIN nodes, but instead has a pointer to a cmd_element. All | |
338 | paths through the graph that terminate on a leaf are guaranteed to be defined | |
339 | by that command. When a user enters a complete command, the command matcher | |
340 | tokenizes the input and executes a DFS on the CLI graph. If it is | |
341 | simultaneously able to exhaust all input (one input token per graph node), and | |
342 | then find exactly one leaf connected to the last node it reaches, then the | |
343 | input has matched the corresponding command and the command is executed. If it | |
344 | finds more than one node, then the command is ambiguous (more on this in | |
345 | deduplication). If it cannot exhaust all input, the command is unknown. If it | |
346 | exhausts all input but does not find an edge node, the command is incomplete. | |
347 | ||
348 | The parser uses an incremental strategy to build the CLI graph for a node. Each | |
349 | command is parsed into its own graph, and then this graph is merged into the | |
350 | overall graph. During this merge step, the parser makes a best-effort attempt | |
351 | to remove duplicate nodes. If it finds a node in the overall graph that is | |
352 | equal to a node in the corresponding position in the command graph, it will | |
353 | intelligently merge the properties from the node in the command graph into the | |
354 | already-existing node. Subgraphs are also checked for isomorphism and merged | |
355 | where possible. The definition of whether two nodes are 'equal' is based on the | |
356 | equality of some set of token properties; read the parser source for the most | |
357 | up-to-date definition of equality. | |
358 | ||
359 | When the parser is unable to deduplicate some complicated constructs, this | |
360 | can result in two identical paths through separate parts of the graph. If | |
361 | this occurs and the user enters input that matches these paths, they will | |
362 | receive an 'ambiguous command' error and will be unable to execute the command. | |
363 | Most of the time the parser can detect and warn about duplicate commands, but | |
364 | it will not always be able to do this. Hence care should be taken before | |
365 | defining a new command to ensure it is not defined elsewhere. | |
366 | ||
367 | ||
368 | Command handlers | |
369 | ---------------- | |
370 | The block that follows a CLI definition is executed when a user enters input | |
371 | that matches the definition. Its function signature looks like this: | |
372 | ||
373 | int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]); | |
374 | ||
375 | The first argument is the command definition struct. The last argument is an | |
376 | ordered array of tokens that correspond to the path taken through the graph, | |
377 | and the argument just prior to that is the length of the array. | |
378 | ||
379 | The arrangement of the token array has changed from the prior incarnation of | |
380 | the CLI system. In the old system, missing arguments were padded with NULLs so | |
381 | that the same parts of a command would show up at the same indices regardless | |
382 | of what was entered. The new system does not perform such padding and therefore | |
383 | it is generally _incorrect_ to assume consistent indices in this array. As a | |
384 | simple example: | |
385 | ||
386 | Command definition: | |
4e3e06d6 | 387 | ``` |
9b9cdb46 | 388 | command [foo] <bar|baz> |
4e3e06d6 | 389 | ``` |
9b9cdb46 QY |
390 | |
391 | User enters: | |
4e3e06d6 | 392 | ``` |
9b9cdb46 | 393 | command foo bar |
4e3e06d6 | 394 | ``` |
9b9cdb46 QY |
395 | |
396 | Array: | |
4e3e06d6 | 397 | ``` |
9b9cdb46 QY |
398 | [0] -> command |
399 | [1] -> foo | |
400 | [2] -> bar | |
4e3e06d6 | 401 | ``` |
9b9cdb46 QY |
402 | |
403 | User enters: | |
4e3e06d6 | 404 | ``` |
9b9cdb46 | 405 | command baz |
4e3e06d6 | 406 | ``` |
9b9cdb46 QY |
407 | |
408 | Array: | |
4e3e06d6 | 409 | ``` |
9b9cdb46 QY |
410 | [0] -> command |
411 | [1] -> baz | |
4e3e06d6 | 412 | ``` |
9b9cdb46 QY |
413 | |
414 | ||
415 | ||
416 | Command abbreviation & matching priority | |
417 | ---------------------------------------- | |
418 | As in the prior implementation, it is possible for users to elide parts of | |
419 | tokens when the CLI matcher does not need them to make an unambiguous match. | |
420 | This is best explained by example. | |
421 | ||
422 | Command definitions: | |
4e3e06d6 | 423 | ``` |
9b9cdb46 QY |
424 | command dog cow |
425 | command dog crow | |
4e3e06d6 | 426 | ``` |
9b9cdb46 QY |
427 | |
428 | User input: | |
4e3e06d6 | 429 | ``` |
9b9cdb46 QY |
430 | c d c -> ambiguous command |
431 | c d co -> match "command dog cow" | |
4e3e06d6 | 432 | ``` |
9b9cdb46 QY |
433 | |
434 | In the new implementation, this functionality has improved. Where previously | |
435 | the parser would stop at the first ambiguous token, it will now look ahead and | |
436 | attempt to disambiguate based on tokens later on in the input string. | |
437 | ||
438 | Command definitions: | |
4e3e06d6 | 439 | ``` |
9b9cdb46 QY |
440 | show ip bgp A.B.C.D |
441 | show ipv6 bgp X:X::X:X | |
4e3e06d6 | 442 | ``` |
9b9cdb46 QY |
443 | |
444 | User enters: | |
4e3e06d6 | 445 | ``` |
9b9cdb46 QY |
446 | s i b 4.3.2.1 -> match "show ip bgp A.B.C.D" |
447 | s i b ::e0 -> match "show ipv6 bgp X:X::X:X" | |
4e3e06d6 | 448 | ``` |
9b9cdb46 QY |
449 | |
450 | Previously both of these commands would be ambiguous since 'i' does not | |
451 | explicitly select either 'ip' or 'ipv6'. However, since the user later provides | |
452 | a token that matches only one of the commands (an IPv4 or IPv6 address) the | |
453 | parser is able to look ahead and select the appropriate command. This has some | |
454 | implications for parsing the argv*[] that is passed to the command handler. | |
455 | ||
456 | Now consider a command definition such as: | |
4e3e06d6 | 457 | ``` |
9b9cdb46 | 458 | command <foo|VAR> |
4e3e06d6 | 459 | ``` |
9b9cdb46 QY |
460 | |
461 | 'foo' only matches the string 'foo', but 'VAR' matches any input, including | |
462 | 'foo'. Who wins? In situations like this the matcher will always choose the | |
463 | 'better' match, so 'foo' will win. | |
464 | ||
465 | Consider also: | |
4e3e06d6 | 466 | ``` |
9b9cdb46 | 467 | show <ip|ipv6> foo |
4e3e06d6 | 468 | ``` |
9b9cdb46 QY |
469 | |
470 | User input: | |
4e3e06d6 | 471 | ``` |
9b9cdb46 | 472 | show ip foo |
4e3e06d6 | 473 | ``` |
9b9cdb46 QY |
474 | |
475 | 'ip' partially matches 'ipv6' but exactly matches 'ip', so 'ip' will win. | |
476 | ||
477 | ||
478 | struct cmd_token | |
479 | ---------------- | |
480 | ||
4e3e06d6 | 481 | ``` |
9b9cdb46 QY |
482 | /* Command token struct. */ |
483 | struct cmd_token | |
484 | { | |
485 | enum cmd_token_type type; // token type | |
486 | u_char attr; // token attributes | |
487 | bool allowrepeat; // matcher allowed to match token repetitively? | |
488 | ||
489 | char *text; // token text | |
490 | char *desc; // token description | |
491 | long long min, max; // for ranges | |
492 | char *arg; // user input that matches this token | |
4e3e06d6 | 493 | char *varname; // variable name |
9b9cdb46 | 494 | }; |
4e3e06d6 | 495 | ``` |
9b9cdb46 QY |
496 | |
497 | This struct is used in the CLI graph to match input against. It is also used to | |
498 | pass user input to command handler functions, as it is frequently useful for | |
499 | handlers to have access to that information. When a command is matched, the | |
500 | sequence of cmd_tokens that form the matching path are duplicated and placed in | |
501 | order into argv*[]. Before this happens the ->arg field is set to point at the | |
502 | snippet of user input that matched it. | |
503 | ||
504 | For most nontrivial commands the handler function will need to determine which | |
505 | of the possible matching inputs was entered. Previously this was done by | |
506 | looking at the first few characters of input. This is now considered an | |
507 | anti-pattern and should be avoided. Instead, the ->type or ->text fields for | |
508 | this logic. The ->type field can be used when the possible inputs differ in | |
509 | type. When the possible types are the same, use the ->text field. This field | |
510 | has the full text of the corresponding token in the definition string and using | |
511 | it makes for much more readable code. An example is helpful. | |
512 | ||
513 | Command definition: | |
4e3e06d6 | 514 | ``` |
9b9cdb46 | 515 | command <(1-10)|foo|BAR> |
4e3e06d6 | 516 | ``` |
9b9cdb46 QY |
517 | |
518 | In this example, the user may enter any one of: | |
519 | * an integer between 1 and 10 | |
520 | * "foo" | |
521 | * anything at all | |
522 | ||
523 | If the user enters "command f", then: | |
524 | ||
4e3e06d6 | 525 | ``` |
9b9cdb46 QY |
526 | argv[1]->type == WORD_TKN |
527 | argv[1]->arg == "f" | |
528 | argv[1]->text == "foo" | |
4e3e06d6 | 529 | ``` |
9b9cdb46 QY |
530 | |
531 | Range tokens have some special treatment; a token with ->type == RANGE_TKN will | |
532 | have the ->min and ->max fields set to the bounding values of the range. | |
533 | ||
534 | ||
535 | Permutations | |
536 | ------------ | |
537 | Finally, it is sometimes useful to check all the possible combinations of input | |
538 | that would match an arbitrary definition string. There is a tool in tools/ | |
539 | called 'permutations' that reads CLI definition strings on stdin and prints out | |
540 | all matching input permutations. It also dumps a text representation of the | |
541 | graph, which is more useful for debugging than anything else. It looks like | |
542 | this: | |
543 | ||
4e3e06d6 | 544 | ``` |
9b9cdb46 QY |
545 | $ ./permutations "show [ip] bgp [<view|vrf> WORD]" |
546 | ||
547 | show ip bgp view WORD | |
548 | show ip bgp vrf WORD | |
549 | show ip bgp | |
550 | show bgp view WORD | |
551 | show bgp vrf WORD | |
552 | show bgp | |
4e3e06d6 | 553 | ``` |
9b9cdb46 QY |
554 | |
555 | This functionality is also built into VTY/VTYSH; the 'list permutations' | |
556 | command will list all possible matching input permutations in the current CLI | |
557 | node. |