diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-06-28 15:48:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-28 15:48:33 +0200 |
commit | 1e84e9a697729e8e3847346c8046181f948f4350 (patch) | |
tree | 57240610b4008c7604912f8c913dc981da968737 /doc | |
parent | Merge pull request #757 from donaldsharp/extract_sort (diff) | |
parent | redhat: On CentOS/RedHat 6, use python27-devel from iuscommunity.org (diff) | |
download | frr-1e84e9a697729e8e3847346c8046181f948f4350.tar.xz frr-1e84e9a697729e8e3847346c8046181f948f4350.zip |
Merge pull request #714 from opensourcerouting/cli_magic_defpy
CLI magic: part 1 (DEFPY)
Diffstat (limited to 'doc')
-rw-r--r-- | doc/Building_FRR_on_CentOS6.md | 3 | ||||
-rw-r--r-- | doc/cli.md | 121 |
2 files changed, 122 insertions, 2 deletions
diff --git a/doc/Building_FRR_on_CentOS6.md b/doc/Building_FRR_on_CentOS6.md index 9f40418ff..d88f8144a 100644 --- a/doc/Building_FRR_on_CentOS6.md +++ b/doc/Building_FRR_on_CentOS6.md @@ -46,8 +46,7 @@ Install newer version of autoconf and automake (Package versions are too old) sudo make install cd .. -Install `Python 2.7` in parallel to default 2.6 (needed for `make check` to -run unittests). +Install `Python 2.7` in parallel to default 2.6 Make sure you've install EPEL (`epel-release` as above). Then install current `python2.7` and `pytest` diff --git a/doc/cli.md b/doc/cli.md index ffd34dd30..cfb4d629f 100644 --- a/doc/cli.md +++ b/doc/cli.md @@ -107,6 +107,127 @@ Automatic assignment of variable names works by applying the following rules: These rules should make it possible to avoid manual varname assignment in 90% of the cases. +DEFPY +----- + +`DEFPY(...)` is an enhanced version of `DEFUN()` which is preprocessed by +` python/clidef.py`. The python script parses the command definition string, +extracts variable names and types, and generates a C wrapper function that +parses the variables and passes them on. This means that in the CLI function +body, you will receive additional parameters with appropriate types. + +This is best explained by an example: + +``` +DEFPY(func, func_cmd, "[no] foo bar A.B.C.D (0-99)$num", "...help...") + +=> + +func(self, vty, argc, argv, /* standard CLI arguments */ + + const char *no, /* unparsed "no" */ + struct in_addr bar, /* parsed IP address */ + const char *bar_str, /* unparsed IP address */ + long num, /* parsed num */ + const char *num_str) /* unparsed num */ +``` + +Note that as documented in the previous section, "bar" is automatically +applied as variable name for "A.B.C.D". The python code then detects this +is an IP address argument and generates code to parse it into a +`struct in_addr`, passing it in `bar`. The raw value is passed in `bar_str`. +The range/number argument works in the same way with the explicitly given +variable name. + +### Type rules + +| Token(s) | Type | Value if omitted by user | +|--------------------------|-------------|--------------------------| +| `A.B.C.D` | `struct in_addr` | 0.0.0.0 | +| `X:X::X:X` | `struct in6_addr` | :: | +| `A.B.C.D + X:X::X:X` | `const union sockunion *` | NULL | +| `A.B.C.D/M` | `const struct prefix_ipv4 *` | NULL | +| `X:X::X:X/M` | `const struct prefix_ipv6 *` | NULL | +| `A.B.C.D/M + X:X::X:X/M` | `const struct prefix *` | NULL | +| `(0-9)` | `long` | 0 | +| `VARIABLE` | `const char *` | NULL | +| `word` | `const char *` | NULL | +| _all other_ | `const char *` | NULL | + +Note the following details: + +* not all parameters are pointers, some are passed as values. +* when the type is not `const char *`, there will be an extra `_str` argument + with type `const char *`. +* you can give a variable name not only to `VARIABLE` tokens but also to + `word` tokens (e.g. constant words). This is useful if some parts of a + command are optional. The type will be `const char *`. +* `[no]` will be passed as `const char *no`. +* pointers will be NULL when the argument is optional and the user did not + use it. +* if a parameter is not a pointer, but is optional and the user didn't use it, + the default value will be passed. Check the `_str` argument if you need to + determine whether the parameter was omitted. +* if the definition contains multiple parameters with the same variable name, + they will be collapsed into a single function parameter. The python code + will detect if the types are compatible (i.e. IPv4 + IPv6 variantes) and + choose a corresponding C type. +* the standard DEFUN parameters (self, vty, argc, argv) are still present and + can be used. A DEFUN can simply be **edited into a DEFPY without further + changes and it will still work**; this allows easy forward migration. +* a file may contain both DEFUN and DEFPY statements. + +### Getting a parameter dump + +The clidef.py script can be called to get a list of DEFUNs/DEFPYs with +the parameter name/type list: + +``` +lib/clippy python/clidef.py --all-defun --show lib/plist.c > /dev/null +``` + +The generated code is printed to stdout, the info dump to stderr. The +`--all-defun` argument will make it process DEFUN blocks as well as DEFPYs, +which is useful prior to converting some DEFUNs. **The dump does not list +the `_str` arguments** to keep the output shorter. + +Note that the clidef.py script cannot be run with python directly, it needs +to be run with _clippy_ since the latter makes the CLI parser available. + +### Include & Makefile requirements + +A source file that uses DEFPY needs to include the `_clippy.c` file **before +all DEFPY statements**: + +``` +/* GPL header */ +#include ... + +... + +#include "filename_clippy.c" + +DEFPY(...) +DEFPY(...) + +install_element(...) +``` + +This dependency needs to be marked in Makefile.am: (there is no ordering +requirement) + +``` +include ../common.am + +# ... + +# if linked into a LTLIBRARY (.la/.so): +filename.lo: filename_clippy.c + +# if linked into an executable or static library (.a): +filename.o: filename_clippy.c +``` + Doc Strings ----------- Each token in a command definition should be documented with a brief doc |