summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-06-28 15:48:33 +0200
committerGitHub <noreply@github.com>2017-06-28 15:48:33 +0200
commit1e84e9a697729e8e3847346c8046181f948f4350 (patch)
tree57240610b4008c7604912f8c913dc981da968737 /doc
parentMerge pull request #757 from donaldsharp/extract_sort (diff)
parentredhat: On CentOS/RedHat 6, use python27-devel from iuscommunity.org (diff)
downloadfrr-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.md3
-rw-r--r--doc/cli.md121
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