forked from Mirror/frr
lib: make cmd_element->attr a bitmask & clarify
It already "looks" like a bitmask, but we currently can't flag a command both YANG and HIDDEN at the same time. It really should be a bitmask. Also clarify DEPRECATED behaviour (or the absence thereof.) Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
53d8bf6d7a
commit
9eebf97e3d
|
@ -264,8 +264,7 @@ void install_node(struct cmd_node *node)
|
||||||
node->cmdgraph = graph_new();
|
node->cmdgraph = graph_new();
|
||||||
node->cmd_vector = vector_init(VECTOR_MIN_SIZE);
|
node->cmd_vector = vector_init(VECTOR_MIN_SIZE);
|
||||||
// add start node
|
// add start node
|
||||||
struct cmd_token *token =
|
struct cmd_token *token = cmd_token_new(START_TKN, 0, NULL, NULL);
|
||||||
cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
|
|
||||||
graph_new_node(node->cmdgraph, token,
|
graph_new_node(node->cmdgraph, token,
|
||||||
(void (*)(void *)) & cmd_token_del);
|
(void (*)(void *)) & cmd_token_del);
|
||||||
|
|
||||||
|
@ -325,7 +324,7 @@ void _install_element(enum node_type ntype, const struct cmd_element *cmd)
|
||||||
if (cnode->graph_built || !defer_cli_tree) {
|
if (cnode->graph_built || !defer_cli_tree) {
|
||||||
struct graph *graph = graph_new();
|
struct graph *graph = graph_new();
|
||||||
struct cmd_token *token =
|
struct cmd_token *token =
|
||||||
cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
|
cmd_token_new(START_TKN, 0, NULL, NULL);
|
||||||
graph_new_node(graph, token,
|
graph_new_node(graph, token,
|
||||||
(void (*)(void *)) & cmd_token_del);
|
(void (*)(void *)) & cmd_token_del);
|
||||||
|
|
||||||
|
@ -348,8 +347,7 @@ static void cmd_finalize_iter(struct hash_bucket *hb, void *arg)
|
||||||
struct cmd_node *cnode = arg;
|
struct cmd_node *cnode = arg;
|
||||||
const struct cmd_element *cmd = hb->data;
|
const struct cmd_element *cmd = hb->data;
|
||||||
struct graph *graph = graph_new();
|
struct graph *graph = graph_new();
|
||||||
struct cmd_token *token =
|
struct cmd_token *token = cmd_token_new(START_TKN, 0, NULL, NULL);
|
||||||
cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
|
|
||||||
|
|
||||||
graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del);
|
graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del);
|
||||||
|
|
||||||
|
@ -404,7 +402,7 @@ void uninstall_element(enum node_type ntype, const struct cmd_element *cmd)
|
||||||
if (cnode->graph_built) {
|
if (cnode->graph_built) {
|
||||||
struct graph *graph = graph_new();
|
struct graph *graph = graph_new();
|
||||||
struct cmd_token *token =
|
struct cmd_token *token =
|
||||||
cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
|
cmd_token_new(START_TKN, 0, NULL, NULL);
|
||||||
graph_new_node(graph, token,
|
graph_new_node(graph, token,
|
||||||
(void (*)(void *)) & cmd_token_del);
|
(void (*)(void *)) & cmd_token_del);
|
||||||
|
|
||||||
|
@ -990,7 +988,7 @@ static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
|
||||||
* Perform pending commit (if any) before executing
|
* Perform pending commit (if any) before executing
|
||||||
* non-YANG command.
|
* non-YANG command.
|
||||||
*/
|
*/
|
||||||
if (matched_element->attr != CMD_ATTR_YANG)
|
if (!(matched_element->attr & CMD_ATTR_YANG))
|
||||||
(void)nb_cli_pending_commit_check(vty);
|
(void)nb_cli_pending_commit_check(vty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1471,8 +1469,7 @@ static void permute(struct graph_node *start, struct vty *vty)
|
||||||
for (unsigned int i = 0; i < vector_active(start->to); i++) {
|
for (unsigned int i = 0; i < vector_active(start->to); i++) {
|
||||||
struct graph_node *gn = vector_slot(start->to, i);
|
struct graph_node *gn = vector_slot(start->to, i);
|
||||||
struct cmd_token *tok = gn->data;
|
struct cmd_token *tok = gn->data;
|
||||||
if (tok->attr == CMD_ATTR_HIDDEN
|
if (tok->attr & CMD_ATTR_HIDDEN)
|
||||||
|| tok->attr == CMD_ATTR_DEPRECATED)
|
|
||||||
continue;
|
continue;
|
||||||
else if (tok->type == END_TKN || gn == start) {
|
else if (tok->type == END_TKN || gn == start) {
|
||||||
vty_out(vty, " ");
|
vty_out(vty, " ");
|
||||||
|
@ -1561,9 +1558,8 @@ int cmd_list_cmds(struct vty *vty, int do_permute)
|
||||||
const struct cmd_element *element = NULL;
|
const struct cmd_element *element = NULL;
|
||||||
for (unsigned int i = 0; i < vector_active(node->cmd_vector);
|
for (unsigned int i = 0; i < vector_active(node->cmd_vector);
|
||||||
i++)
|
i++)
|
||||||
if ((element = vector_slot(node->cmd_vector, i))
|
if ((element = vector_slot(node->cmd_vector, i)) &&
|
||||||
&& element->attr != CMD_ATTR_DEPRECATED
|
!(element->attr & CMD_ATTR_HIDDEN)) {
|
||||||
&& element->attr != CMD_ATTR_HIDDEN) {
|
|
||||||
vty_out(vty, " ");
|
vty_out(vty, " ");
|
||||||
print_cmd(vty, element->string);
|
print_cmd(vty, element->string);
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,9 +358,13 @@ struct cmd_node {
|
||||||
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, \
|
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, \
|
||||||
0)
|
0)
|
||||||
|
|
||||||
|
/* note: DEPRECATED implies HIDDEN, and other than that there is currently no
|
||||||
|
* difference. It's purely for expressing intent in the source code - a
|
||||||
|
* DEPRECATED command is supposed to go away, a HIDDEN one is likely to stay.
|
||||||
|
*/
|
||||||
#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
|
#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
|
||||||
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, \
|
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, \
|
||||||
CMD_ATTR_DEPRECATED, 0)
|
CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN, 0)
|
||||||
|
|
||||||
#define ALIAS_YANG(funcname, cmdname, cmdstr, helpstr) \
|
#define ALIAS_YANG(funcname, cmdname, cmdstr, helpstr) \
|
||||||
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_YANG, 0)
|
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_YANG, 0)
|
||||||
|
|
|
@ -494,9 +494,10 @@ void cmd_graph_node_print_cb(struct graph_node *gn, struct buffer *buf)
|
||||||
snprintf(nbuf, sizeof(nbuf), "<b>%s</b>",
|
snprintf(nbuf, sizeof(nbuf), "<b>%s</b>",
|
||||||
lookup_msg(tokennames, tok->type, NULL));
|
lookup_msg(tokennames, tok->type, NULL));
|
||||||
buffer_putstr(buf, nbuf);
|
buffer_putstr(buf, nbuf);
|
||||||
if (tok->attr == CMD_ATTR_DEPRECATED)
|
if (tok->attr & CMD_ATTR_DEPRECATED)
|
||||||
buffer_putstr(buf, " (d)");
|
buffer_putstr(buf, " (d)");
|
||||||
else if (tok->attr == CMD_ATTR_HIDDEN)
|
/* DEPRECATED implies HIDDEN, don't print both */
|
||||||
|
else if (tok->attr & CMD_ATTR_HIDDEN)
|
||||||
buffer_putstr(buf, " (h)");
|
buffer_putstr(buf, " (h)");
|
||||||
if (tok->text) {
|
if (tok->text) {
|
||||||
if (tok->type == WORD_TKN)
|
if (tok->type == WORD_TKN)
|
||||||
|
|
|
@ -73,10 +73,10 @@ enum cmd_token_type {
|
||||||
#define IS_VARYING_TOKEN(x) ((x) >= VARIABLE_TKN && (x) < FORK_TKN)
|
#define IS_VARYING_TOKEN(x) ((x) >= VARIABLE_TKN && (x) < FORK_TKN)
|
||||||
|
|
||||||
/* Command attributes */
|
/* Command attributes */
|
||||||
enum { CMD_ATTR_NORMAL,
|
enum {
|
||||||
CMD_ATTR_DEPRECATED,
|
CMD_ATTR_YANG = (1 << 0),
|
||||||
CMD_ATTR_HIDDEN,
|
CMD_ATTR_HIDDEN = (1 << 1),
|
||||||
CMD_ATTR_YANG,
|
CMD_ATTR_DEPRECATED = (1 << 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum varname_src {
|
enum varname_src {
|
||||||
|
|
|
@ -395,8 +395,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
|
||||||
for (ALL_LIST_ELEMENTS_RO(current, node, gstack)) {
|
for (ALL_LIST_ELEMENTS_RO(current, node, gstack)) {
|
||||||
struct cmd_token *token = gstack[0]->data;
|
struct cmd_token *token = gstack[0]->data;
|
||||||
|
|
||||||
if (token->attr == CMD_ATTR_HIDDEN
|
if (token->attr & CMD_ATTR_HIDDEN)
|
||||||
|| token->attr == CMD_ATTR_DEPRECATED)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
enum match_type minmatch = min_match_level(token->type);
|
enum match_type minmatch = min_match_level(token->type);
|
||||||
|
|
|
@ -226,8 +226,8 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph,
|
||||||
wrap->type = "???";
|
wrap->type = "???";
|
||||||
}
|
}
|
||||||
|
|
||||||
wrap->deprecated = (tok->attr == CMD_ATTR_DEPRECATED);
|
wrap->deprecated = !!(tok->attr & CMD_ATTR_DEPRECATED);
|
||||||
wrap->hidden = (tok->attr == CMD_ATTR_HIDDEN);
|
wrap->hidden = !!(tok->attr & CMD_ATTR_HIDDEN);
|
||||||
wrap->text = tok->text;
|
wrap->text = tok->text;
|
||||||
wrap->desc = tok->desc;
|
wrap->desc = tok->desc;
|
||||||
wrap->varname = tok->varname;
|
wrap->varname = tok->varname;
|
||||||
|
@ -353,6 +353,11 @@ PyMODINIT_FUNC command_py_init(void)
|
||||||
if (!pymod)
|
if (!pymod)
|
||||||
initret(NULL);
|
initret(NULL);
|
||||||
|
|
||||||
|
if (PyModule_AddIntMacro(pymod, CMD_ATTR_YANG)
|
||||||
|
|| PyModule_AddIntMacro(pymod, CMD_ATTR_HIDDEN)
|
||||||
|
|| PyModule_AddIntMacro(pymod, CMD_ATTR_DEPRECATED))
|
||||||
|
initret(NULL);
|
||||||
|
|
||||||
Py_INCREF(&typeobj_graph_node);
|
Py_INCREF(&typeobj_graph_node);
|
||||||
PyModule_AddObject(pymod, "GraphNode", (PyObject *)&typeobj_graph_node);
|
PyModule_AddObject(pymod, "GraphNode", (PyObject *)&typeobj_graph_node);
|
||||||
Py_INCREF(&typeobj_graph);
|
Py_INCREF(&typeobj_graph);
|
||||||
|
|
|
@ -76,8 +76,7 @@ DEFUN (grammar_test,
|
||||||
|
|
||||||
// parse the command and install it into the command graph
|
// parse the command and install it into the command graph
|
||||||
struct graph *graph = graph_new();
|
struct graph *graph = graph_new();
|
||||||
struct cmd_token *token =
|
struct cmd_token *token = cmd_token_new(START_TKN, 0, NULL, NULL);
|
||||||
cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
|
|
||||||
graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del);
|
graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del);
|
||||||
|
|
||||||
cmd_graph_parse(graph, cmd);
|
cmd_graph_parse(graph, cmd);
|
||||||
|
|
|
@ -17,8 +17,22 @@
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
import os, stat
|
import os, stat
|
||||||
|
|
||||||
|
try:
|
||||||
|
from enum import IntFlag as _IntFlag
|
||||||
|
except ImportError:
|
||||||
|
# python <3.6
|
||||||
|
from enum import IntEnum as _IntFlag # type: ignore
|
||||||
|
|
||||||
import _clippy
|
import _clippy
|
||||||
from _clippy import parse, Graph, GraphNode
|
from _clippy import (
|
||||||
|
parse,
|
||||||
|
Graph,
|
||||||
|
GraphNode,
|
||||||
|
CMD_ATTR_YANG,
|
||||||
|
CMD_ATTR_HIDDEN,
|
||||||
|
CMD_ATTR_DEPRECATED,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
frr_top_src = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
frr_top_src = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
@ -78,3 +92,9 @@ def wrdiff(filename, buf, reffiles=[]):
|
||||||
with open(newname, "w") as out:
|
with open(newname, "w") as out:
|
||||||
out.write(buf)
|
out.write(buf)
|
||||||
os.rename(newname, filename)
|
os.rename(newname, filename)
|
||||||
|
|
||||||
|
|
||||||
|
class CmdAttr(_IntFlag):
|
||||||
|
YANG = CMD_ATTR_YANG
|
||||||
|
HIDDEN = CMD_ATTR_HIDDEN
|
||||||
|
DEPRECATED = CMD_ATTR_DEPRECATED
|
||||||
|
|
|
@ -26,7 +26,7 @@ import argparse
|
||||||
|
|
||||||
from clippy.uidhash import uidhash
|
from clippy.uidhash import uidhash
|
||||||
from clippy.elf import *
|
from clippy.elf import *
|
||||||
from clippy import frr_top_src
|
from clippy import frr_top_src, CmdAttr
|
||||||
from tiabwarfo import FieldApplicator
|
from tiabwarfo import FieldApplicator
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -196,8 +196,6 @@ Xref.containers[XREFT_LOGMSG] = XrefLogmsg
|
||||||
class CmdElement(ELFDissectStruct, XrelfoJson):
|
class CmdElement(ELFDissectStruct, XrelfoJson):
|
||||||
struct = 'cmd_element'
|
struct = 'cmd_element'
|
||||||
|
|
||||||
cmd_attrs = { 0: None, 1: 'deprecated', 2: 'hidden'}
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -207,10 +205,14 @@ class CmdElement(ELFDissectStruct, XrelfoJson):
|
||||||
jsobj.update({
|
jsobj.update({
|
||||||
'string': self.string,
|
'string': self.string,
|
||||||
'doc': self.doc,
|
'doc': self.doc,
|
||||||
'attr': self.cmd_attrs.get(self.attr, self.attr),
|
|
||||||
})
|
})
|
||||||
if jsobj['attr'] is None:
|
if self.attr:
|
||||||
del jsobj['attr']
|
jsobj['attr'] = attr = self.attr
|
||||||
|
for attrname in CmdAttr.__members__:
|
||||||
|
val = CmdAttr[attrname]
|
||||||
|
if attr & val:
|
||||||
|
jsobj.setdefault('attrs', []).append(attrname.lower())
|
||||||
|
attr &= ~val
|
||||||
|
|
||||||
jsobj['defun'] = dict([(i, getattr(self.xref, i)) for i in ['file', 'line', 'func']])
|
jsobj['defun'] = dict([(i, getattr(self.xref, i)) for i in ['file', 'line', 'func']])
|
||||||
|
|
||||||
|
|
|
@ -80,8 +80,7 @@ void permute(struct graph_node *start)
|
||||||
for (unsigned int i = 0; i < vector_active(start->to); i++) {
|
for (unsigned int i = 0; i < vector_active(start->to); i++) {
|
||||||
struct graph_node *gn = vector_slot(start->to, i);
|
struct graph_node *gn = vector_slot(start->to, i);
|
||||||
struct cmd_token *tok = gn->data;
|
struct cmd_token *tok = gn->data;
|
||||||
if (tok->attr == CMD_ATTR_HIDDEN
|
if (tok->attr & CMD_ATTR_HIDDEN)
|
||||||
|| tok->attr == CMD_ATTR_DEPRECATED)
|
|
||||||
continue;
|
continue;
|
||||||
else if (tok->type == END_TKN || gn == start) {
|
else if (tok->type == END_TKN || gn == start) {
|
||||||
fprintf(stdout, " ");
|
fprintf(stdout, " ");
|
||||||
|
|
Loading…
Reference in a new issue