From: Quentin Young Date: Thu, 10 Nov 2016 23:17:07 +0000 (+0000) Subject: lib: Implement hidden and deprecated commands X-Git-Tag: frr-3.0-branchpoint~129^2~42 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=ce882f81683f6b3547d4bad17aeee8ce7b5bdda1;p=matthieu%2Ffrr.git lib: Implement hidden and deprecated commands Each token now knows whether it is part of a hidden or deprecated command. Command completion logic hides such tokens when generating completions. Command matching logic works as before and will still match on hidden and deprecated commands. Signed-off-by: Quentin Young --- diff --git a/lib/command.c b/lib/command.c index 8eee923144..c0b9ee4e10 100644 --- a/lib/command.c +++ b/lib/command.c @@ -235,7 +235,7 @@ install_node (struct cmd_node *node, node->cmdgraph = graph_new (); node->cmd_vector = vector_init (VECTOR_MIN_SIZE); // add start node - struct cmd_token *token = new_cmd_token (START_TKN, NULL, NULL); + struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); graph_new_node (node->cmdgraph, token, (void (*)(void *)) &del_cmd_token); node->cmd_hash = hash_create (cmd_hash_key, cmd_hash_cmp); } @@ -2383,10 +2383,11 @@ cmd_init (int terminal) } struct cmd_token * -new_cmd_token (enum cmd_token_type type, char *text, char *desc) +new_cmd_token (enum cmd_token_type type, u_char attr, char *text, char *desc) { struct cmd_token *token = XMALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token)); token->type = type; + token->attr = attr; token->text = text; token->desc = desc; token->arg = NULL; @@ -2412,7 +2413,7 @@ del_cmd_token (struct cmd_token *token) struct cmd_token * copy_cmd_token (struct cmd_token *token) { - struct cmd_token *copy = new_cmd_token (token->type, NULL, NULL); + struct cmd_token *copy = new_cmd_token (token->type, token->attr, NULL, NULL); copy->max = token->max; copy->min = token->min; copy->text = token->text ? XSTRDUP (MTYPE_CMD_TOKENS, token->text) : NULL; diff --git a/lib/command.h b/lib/command.h index 7b1f7d9fb5..51f7f78085 100644 --- a/lib/command.h +++ b/lib/command.h @@ -182,24 +182,25 @@ enum cmd_token_type END_TKN, // last token in line }; -/** - * Token struct. - */ +/* Command attributes */ +enum +{ + CMD_ATTR_NORMAL, + CMD_ATTR_DEPRECATED, + CMD_ATTR_HIDDEN, +}; + +/* Comamand token struct. */ struct cmd_token { enum cmd_token_type type; // token type + u_char attr; // token attributes char *text; // token text char *desc; // token description long long min, max; // for ranges char *arg; // user input that matches this token }; -enum -{ - CMD_ATTR_DEPRECATED = 1, - CMD_ATTR_HIDDEN, -}; - /* Structure of command element. */ struct cmd_element { @@ -425,7 +426,7 @@ copy_cmd_element(struct cmd_element *cmd); /* memory management for cmd_token */ struct cmd_token * -new_cmd_token (enum cmd_token_type, char *, char *); +new_cmd_token (enum cmd_token_type, u_char attr, char *, char *); void del_cmd_token (struct cmd_token *); struct cmd_token * diff --git a/lib/command_match.c b/lib/command_match.c index 42788ecb01..8fa8da6b10 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -331,6 +331,10 @@ command_complete (struct graph *graph, for (ALL_LIST_ELEMENTS_RO (current,node,gn)) { struct cmd_token *token = gn->data; + + if (token->attr == CMD_ATTR_HIDDEN || token->attr == CMD_ATTR_DEPRECATED) + continue; + enum match_type minmatch = min_match_level (token->type); #ifdef TRACE_MATCHER fprintf (stdout, "\"%s\" matches \"%s\" (%d) ? ", input_token, token->text, token->type); diff --git a/lib/command_parse.y b/lib/command_parse.y index 680a74ccd2..3ef0b42ebe 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -121,7 +121,8 @@ static struct graph_node * new_token_node (struct graph *, enum cmd_token_type type, - char *text, char *doc); + u_char attr, char *text, + char *doc); static void terminate_graph (struct graph *, @@ -134,7 +135,7 @@ /* yyparse parameters */ %parse-param { struct graph *graph } -%parse-param { struct cmd_element *element } +%parse-param { struct cmd_element *el } /* called automatically before yyparse */ %initial-action { @@ -144,15 +145,15 @@ startnode = vector_slot (graph->nodes, 0); /* set string to parse */ - set_lexer_string (element->string); + set_lexer_string (el->string); /* copy docstring and keep a pointer to the copy */ - if (element->doc) + if (el->doc) { // allocate a new buffer, making room for a flag - size_t length = (size_t) strlen (element->doc) + 2; + size_t length = (size_t) strlen (el->doc) + 2; docstr = malloc (length); - memcpy (docstr, element->doc, strlen (element->doc)); + memcpy (docstr, el->doc, strlen (el->doc)); // set the flag so doc_next knows when to print a warning docstr[length - 2] = 0x03; // null terminate @@ -167,7 +168,7 @@ start: sentence_root cmd_token_seq { // tack on the command element - terminate_graph (graph, currnode, element); + terminate_graph (graph, currnode, el); } | sentence_root cmd_token_seq placeholder_token '.' '.' '.' { @@ -179,14 +180,14 @@ start: add_edge_dedup (currnode, currnode); // tack on the command element - terminate_graph (graph, currnode, element); + terminate_graph (graph, currnode, el); } ; sentence_root: WORD { struct graph_node *root = - new_token_node (graph, WORD_TKN, strdup ($1), doc_next(element)); + new_token_node (graph, WORD_TKN, el->attr, strdup ($1), doc_next(el)); if ((currnode = add_edge_dedup (startnode, root)) != root) graph_delete_node (graph, root); @@ -227,7 +228,7 @@ compound_token: literal_token: WORD { - $$ = new_token_node (graph, WORD_TKN, strdup($1), doc_next(element)); + $$ = new_token_node (graph, WORD_TKN, el->attr, strdup($1), doc_next(el)); free ($1); } ; @@ -235,32 +236,32 @@ literal_token: WORD placeholder_token: IPV4 { - $$ = new_token_node (graph, IPV4_TKN, strdup($1), doc_next(element)); + $$ = new_token_node (graph, IPV4_TKN, el->attr, strdup($1), doc_next(el)); free ($1); } | IPV4_PREFIX { - $$ = new_token_node (graph, IPV4_PREFIX_TKN, strdup($1), doc_next(element)); + $$ = new_token_node (graph, IPV4_PREFIX_TKN, el->attr, strdup($1), doc_next(el)); free ($1); } | IPV6 { - $$ = new_token_node (graph, IPV6_TKN, strdup($1), doc_next(element)); + $$ = new_token_node (graph, IPV6_TKN, el->attr, strdup($1), doc_next(el)); free ($1); } | IPV6_PREFIX { - $$ = new_token_node (graph, IPV6_PREFIX_TKN, strdup($1), doc_next(element)); + $$ = new_token_node (graph, IPV6_PREFIX_TKN, el->attr, strdup($1), doc_next(el)); free ($1); } | VARIABLE { - $$ = new_token_node (graph, VARIABLE_TKN, strdup($1), doc_next(element)); + $$ = new_token_node (graph, VARIABLE_TKN, el->attr, strdup($1), doc_next(el)); free ($1); } | RANGE { - $$ = new_token_node (graph, RANGE_TKN, strdup($1), doc_next(element)); + $$ = new_token_node (graph, RANGE_TKN, el->attr, strdup($1), doc_next(el)); struct cmd_token *token = $$->data; // get the numbers out @@ -270,7 +271,7 @@ placeholder_token: token->max = strtoll (yylval.string, &yylval.string, 10); // validate range - if (token->min > token->max) yyerror (graph, element, "Invalid range."); + if (token->min > token->max) yyerror (graph, el, "Invalid range."); free ($1); } @@ -279,8 +280,8 @@ placeholder_token: selector: '<' selector_seq_seq '>' { $$ = malloc (sizeof (struct subgraph)); - $$->start = new_token_node (graph, SELECTOR_TKN, NULL, NULL); - $$->end = new_token_node (graph, NUL_TKN, NULL, NULL); + $$->start = new_token_node (graph, SELECTOR_TKN, el->attr, NULL, NULL); + $$->end = new_token_node (graph, NUL_TKN, el->attr, NULL, NULL); for (unsigned int i = 0; i < vector_active ($2->start->to); i++) { struct graph_node *sn = vector_slot ($2->start->to, i), @@ -362,8 +363,8 @@ option: '[' option_token_seq ']' { // make a new option $$ = malloc (sizeof (struct subgraph)); - $$->start = new_token_node (graph, OPTION_TKN, NULL, NULL); - $$->end = new_token_node (graph, NUL_TKN, NULL, NULL); + $$->start = new_token_node (graph, OPTION_TKN, el->attr, NULL, NULL); + $$->end = new_token_node (graph, NUL_TKN, el->attr, NULL, NULL); // add a path through the sequence to the end graph_add_edge ($$->start, $2->start); graph_add_edge ($2->end, $$->end); @@ -434,13 +435,15 @@ cleanup() } static void -terminate_graph (struct graph *graph, struct graph_node *finalnode, struct cmd_element *element) +terminate_graph (struct graph *graph, struct graph_node *finalnode, + struct cmd_element *element) { // end of graph should look like this // * -> finalnode -> END_TKN -> cmd_element struct graph_node *end_token_node = new_token_node (graph, END_TKN, + element->attr, strdup (CMD_CR_TEXT), strdup ("")); struct graph_node *end_element_node = @@ -467,9 +470,10 @@ doc_next (struct cmd_element *el) } static struct graph_node * -new_token_node (struct graph *graph, enum cmd_token_type type, char *text, char *doc) +new_token_node (struct graph *graph, enum cmd_token_type type, + u_char attr, char *text, char *doc) { - struct cmd_token *token = new_cmd_token (type, text, doc); + struct cmd_token *token = new_cmd_token (type, attr, text, doc); return graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token); } @@ -507,7 +511,16 @@ static struct graph_node * add_edge_dedup (struct graph_node *from, struct graph_node *to) { struct graph_node *existing = node_adjacent (from, to); - return existing ? existing : graph_add_edge (from, to); + if (existing) + { + struct cmd_token *ex_tok = existing->data; + struct cmd_token *to_tok = to->data; + // NORMAL takes precedence over DEPRECATED takes precedence over HIDDEN + ex_tok->attr = (ex_tok->attr < to_tok->attr) ? ex_tok->attr : to_tok->attr; + return existing; + } + else + return graph_add_edge (from, to); } /**