Merge branch 'queue/osr/vtysh-generic'

WARNING: Merge contains nontrivial fixups in vrf_cmd handling.

Conflicts:
	lib/if.c
	zebra/interface.c
This commit is contained in:
David Lamparter 2016-12-05 20:04:08 +01:00
commit 7ddcfca4fb
25 changed files with 255 additions and 367 deletions

View File

@ -1418,12 +1418,7 @@ isis_circuit_init ()
/* Install interface node */
install_node (&interface_node, isis_interface_config_write);
install_element (CONFIG_NODE, &interface_cmd);
install_element (CONFIG_NODE, &no_interface_cmd);
install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
if_cmd_init ();
isis_vty_init ();
}

View File

@ -1618,14 +1618,7 @@ ldp_vty_if_init(void)
{
/* Install interface node. */
install_node (&interface_node, interface_config_write);
install_element(CONFIG_NODE, &interface_cmd);
install_element(CONFIG_NODE, &no_interface_cmd);
install_default(INTERFACE_NODE);
/* "description" commands. */
install_element(INTERFACE_NODE, &interface_desc_cmd);
install_element(INTERFACE_NODE, &no_interface_desc_cmd);
if_cmd_init ();
}
struct iface *

View File

@ -39,7 +39,6 @@
#include "workqueue.h"
#include "vrf.h"
#include "command_match.h"
#include "command_parse.h"
#include "qobj.h"
DEFINE_MTYPE( LIB, HOST, "Host config")
@ -1050,6 +1049,13 @@ DEFUN (config_exit,
config_exit_cmd,
"exit",
"Exit current mode and down to previous mode\n")
{
cmd_exit (vty);
return CMD_SUCCESS;
}
void
cmd_exit (struct vty *vty)
{
switch (vty->node)
{
@ -1118,7 +1124,6 @@ DEFUN (config_exit,
default:
break;
}
return CMD_SUCCESS;
}
/* ALIAS_FIXME */
@ -1264,17 +1269,12 @@ permute (struct graph_node *start, struct vty *vty)
list_delete_node (position, listtail(position));
}
/* Help display function for all node. */
DEFUN (config_list,
config_list_cmd,
"list [permutations]",
"Print command list\n"
"Print all possible command permutations\n")
int
cmd_list_cmds (struct vty *vty, int do_permute)
{
struct cmd_node *node = vector_slot (cmdvec, vty->node);
if ((strmatch (argv[0]->text, "list") && argc == 2) ||
(strmatch (argv[0]->text, "show") && argc == 3))
if (do_permute)
permute (vector_slot (node->cmdgraph->nodes, 0), vty);
else
{
@ -1289,13 +1289,23 @@ DEFUN (config_list,
return CMD_SUCCESS;
}
/* Help display function for all node. */
DEFUN (config_list,
config_list_cmd,
"list [permutations]",
"Print command list\n"
"Print all possible command permutations\n")
{
return cmd_list_cmds (vty, argc == 2);
}
DEFUN (show_commandtree,
show_commandtree_cmd,
"show commandtree [permutations]",
SHOW_STR
"Show command tree\n")
{
return config_list (self, vty, argc, argv);
return cmd_list_cmds (vty, argc == 3);
}
/* Write current configuration into file. */
@ -2352,10 +2362,8 @@ cmd_init (int terminal)
install_element (ENABLE_NODE, &config_logmsg_cmd);
install_default (CONFIG_NODE);
install_element (VIEW_NODE, &show_thread_cpu_cmd);
install_element (ENABLE_NODE, &clear_thread_cpu_cmd);
install_element (VIEW_NODE, &show_work_queues_cmd);
thread_cmd_init ();
workqueue_cmd_init ();
}
install_element (CONFIG_NODE, &hostname_cmd);
@ -2437,27 +2445,6 @@ copy_cmd_token (struct cmd_token *token)
return copy;
}
void
del_cmd_element(struct cmd_element *cmd)
{
if (!cmd) return;
free ((char *) cmd->string);
free ((char *) cmd->doc);
free (cmd);
}
struct cmd_element *
copy_cmd_element(const struct cmd_element *cmd)
{
struct cmd_element *el = XMALLOC(MTYPE_CMD_TOKENS, sizeof (struct cmd_element));
el->string = cmd->string ? XSTRDUP(MTYPE_CMD_TOKENS, cmd->string) : NULL;
el->func = cmd->func;
el->doc = cmd->doc ? XSTRDUP(MTYPE_CMD_TOKENS, cmd->doc) : NULL;
el->daemon = cmd->daemon;
el->attr = cmd->attr;
return el;
}
void
cmd_terminate ()
{

View File

@ -237,7 +237,7 @@ struct cmd_element
/* helper defines for end-user DEFUN* macros */
#define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
struct cmd_element cmdname = \
static struct cmd_element cmdname = \
{ \
.string = cmdstr, \
.func = funcname, \
@ -414,12 +414,8 @@ extern int cmd_execute_command (vector, struct vty *, const struct cmd_element *
extern int cmd_execute_command_strict (vector, struct vty *, const struct cmd_element **);
extern void cmd_init (int);
extern void cmd_terminate (void);
/* memory management for cmd_element */
void
del_cmd_element(struct cmd_element *);
struct cmd_element *
copy_cmd_element(const struct cmd_element *cmd);
extern void cmd_exit (struct vty *vty);
extern int cmd_list_cmds (struct vty *vty, int do_permute);
/* memory management for cmd_token */
struct cmd_token *
@ -429,12 +425,9 @@ del_cmd_token (struct cmd_token *);
struct cmd_token *
copy_cmd_token (struct cmd_token *);
extern void command_parse_format (struct graph *graph, struct cmd_element *cmd);
/* Export typical functions. */
extern struct cmd_element config_end_cmd;
extern struct cmd_element config_exit_cmd;
extern struct cmd_element config_quit_cmd;
extern struct cmd_element config_help_cmd;
extern struct cmd_element config_list_cmd;
extern const char *host_config_get (void);
extern void host_config_set (const char *);

View File

@ -24,10 +24,7 @@
%{
#include "command_parse.h"
extern void set_lexer_string (const char *);
extern void cleanup_lexer (void);
YY_BUFFER_STATE buffer;
#define YYSTYPE CMD_YYSTYPE
%}
WORD (\-|\+)?[a-z\*][-+_a-zA-Z0-9\*]*
@ -45,27 +42,34 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\)
%option nounput
%option noinput
%option outfile="command_lex.c"
%option header-file="command_lex.h"
%option prefix="cmd_yy"
%option reentrant
%option bison-bridge
%%
[ /t] /* ignore whitespace */;
{WORD} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return WORD;}
{IPV4} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return IPV4;}
{IPV4_PREFIX} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return IPV4_PREFIX;}
{IPV6} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return IPV6;}
{IPV6_PREFIX} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return IPV6_PREFIX;}
{VARIABLE} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return VARIABLE;}
{RANGE} {yylval.string = XSTRDUP(MTYPE_TMP, yytext); return RANGE;}
{WORD} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return WORD;}
{IPV4} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return IPV4;}
{IPV4_PREFIX} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return IPV4_PREFIX;}
{IPV6} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return IPV6;}
{IPV6_PREFIX} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return IPV6_PREFIX;}
{VARIABLE} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return VARIABLE;}
{RANGE} {yylval->string = XSTRDUP(MTYPE_TMP, yytext); return RANGE;}
. {return yytext[0];}
%%
void
set_lexer_string (const char *string)
YY_BUFFER_STATE buffer;
void set_lexer_string (yyscan_t *scn, const char *string)
{
buffer = yy_scan_string (string);
*scn = NULL;
yylex_init(scn);
buffer = yy_scan_string (string, *scn);
}
void
cleanup_lexer ()
void cleanup_lexer (yyscan_t *scn)
{
yy_delete_buffer (buffer);
// yy_delete_buffer (buffer, *scn);
yylex_destroy(*scn);
}

View File

@ -25,9 +25,17 @@
#include <zebra.h>
#include "command_match.h"
#include "command_parse.h"
#include "memory.h"
#ifdef TRACE_MATCHER
#define TM 1
#else
#define TM 0
#endif
#define trace_matcher(...) \
do { if (TM) fprintf (stderr, __VA_ARGS__); } while (0);
DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens")
/* matcher helper prototypes */
@ -116,12 +124,12 @@ command_match (struct graph *cmdgraph,
assert (*el);
}
#ifdef TRACE_MATCHER
if (!*el)
fprintf (stdout, "No match\n");
else
fprintf (stdout, "Matched command\n->string %s\n->desc %s\n", (*el)->string, (*el)->doc);
#endif
if (!*el) {
trace_matcher ("No match");
}
else {
trace_matcher ("Matched command\n->string %s\n->desc %s\n", (*el)->string, (*el)->doc);
}
// free the leader token we alloc'd
XFREE (MTYPE_TMP, vector_slot (vvline, 0));
@ -194,28 +202,26 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n)
// get the current operating input token
char *input_token = vector_slot (vline, n);
#ifdef TRACE_MATCHER
fprintf (stdout, "\"%-20s\" matches \"%-30s\" ? ", input_token, token->text);
trace_matcher ("\"%-20s\" matches \"%-30s\" ? ", input_token, token->text);
enum match_type mt = match_token (token, input_token);
fprintf (stdout, "min: %d - ", minmatch);
trace_matcher ("min: %d - ", minmatch);
switch (mt)
{
case trivial_match:
fprintf (stdout, "trivial_match ");
trace_matcher ("trivial_match ");
break;
case no_match:
fprintf (stdout, "no_match ");
trace_matcher ("no_match ");
break;
case partly_match:
fprintf (stdout, "partly_match ");
trace_matcher ("partly_match ");
break;
case exact_match:
fprintf (stdout, "exact_match ");
trace_matcher ("exact_match ");
break;
}
if (mt >= minmatch) fprintf (stdout, " MATCH");
fprintf (stdout, "\n");
#endif
if (mt >= minmatch) { trace_matcher (" MATCH") };
trace_matcher ("\n");
// if we don't match this node, die
if (match_token (token, input_token) < minmatch)
@ -345,37 +351,35 @@ command_complete (struct graph *graph,
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);
#endif
trace_matcher ("\"%s\" matches \"%s\" (%d) ? ", input_token, token->text, token->type);
switch (match_token (token, input_token))
{
case trivial_match:
#ifdef TRACE_MATCHER
fprintf (stdout, "trivial_match\n");
#endif
trace_matcher ("trivial_match\n");
assert(idx == vector_active (vline) - 1);
listnode_add (next, gn);
break;
case partly_match:
#ifdef TRACE_MATCHER
fprintf (stdout, "partly_match\n");
#endif
trace_matcher ("partly_match\n");
// last token on line is partial and
// not a space
if (idx == vector_active (vline) - 1)
{
listnode_add (next, gn);
break;
}
if (minmatch > partly_match)
break;
if (minmatch <= partly_match)
add_nexthops (next, gn);
break;
case exact_match:
#ifdef TRACE_MATCHER
fprintf (stdout, "exact_match\n");
#endif
trace_matcher ("exact_match\n");
add_nexthops (next, gn);
listnode_add (next, gn);
break;
default:
#ifdef TRACE_MATCHER
fprintf (stdout, "no_match\n");
#endif
trace_matcher ("no_match\n");
break;
}
}
@ -855,14 +859,9 @@ match_word (struct cmd_token *token, const char *word)
return no_match;
}
#define VARIABLE_ALPHABET \
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890:/._-"
static enum match_type
match_variable (struct cmd_token *token, const char *word)
{
assert (token->type == VARIABLE_TKN);
return strlen (word) == strspn(word, VARIABLE_ALPHABET) ?
exact_match : no_match;
return exact_match;
}

View File

@ -23,10 +23,18 @@
*/
%{
typedef union CMD_YYSTYPE CMD_YYSTYPE;
#define YYSTYPE CMD_YYSTYPE
#include "command_lex.h"
// compile with debugging facilities
#define YYDEBUG 1
%}
%define api.pure full
%define api.prefix {cmd_yy}
/* names for generated header and parser files */
%defines "command_parse.h"
%output "command_parse.c"
@ -39,21 +47,24 @@
#include "log.h"
#include "graph.h"
extern int
yylex (void);
struct parser_ctx {
yyscan_t scanner;
extern void
set_lexer_string (const char *);
struct cmd_element *el;
extern void
cleanup_lexer (void);
struct graph *graph;
struct graph_node *currnode, *startnode;
/* pointers to copy of command docstring */
char *docstr_start, *docstr;
};
extern void set_lexer_string (yyscan_t *scn, const char *string);
extern void cleanup_lexer (yyscan_t *scn);
}
/* functionality this unit exports */
%code provides {
void
command_parse_format (struct graph *, struct cmd_element *);
/* maximum length of a number, lexer will not match anything longer */
#define DECIMAL_STRLEN_MAX 20
}
@ -91,23 +102,19 @@
%type <subgraph> compound_token
%code {
/* bison declarations */
void
yyerror (struct graph *, struct cmd_element *el, char const *msg);
cmd_yyerror (struct parser_ctx *ctx, char const *msg);
/* subgraph semantic value */
struct subgraph {
struct graph_node *start, *end;
};
struct graph_node *currnode, *startnode;
/* pointers to copy of command docstring */
char *docstr_start, *docstr;
/* helper functions for parser */
static char *
doc_next (struct cmd_element *);
doc_next (struct parser_ctx *ctx);
static struct graph_node *
node_adjacent (struct graph_node *, struct graph_node *);
@ -119,47 +126,45 @@
cmp_token (struct cmd_token *, struct cmd_token *);
static struct graph_node *
new_token_node (struct graph *,
new_token_node (struct parser_ctx *,
enum cmd_token_type type,
u_char attr, char *text,
char *text,
char *doc);
static void
terminate_graph (struct graph *,
struct graph_node *,
struct cmd_element *);
terminate_graph (struct parser_ctx *ctx,
struct graph_node *);
static void
cleanup (void);
cleanup (struct parser_ctx *ctx);
#define scanner ctx->scanner
}
/* yyparse parameters */
%parse-param { struct graph *graph }
%parse-param { struct cmd_element *el }
%lex-param {yyscan_t scanner}
%parse-param {struct parser_ctx *ctx}
/* called automatically before yyparse */
%initial-action {
/* clear state pointers */
currnode = startnode = NULL;
ctx->currnode = ctx->startnode = NULL;
startnode = vector_slot (graph->nodes, 0);
/* set string to parse */
set_lexer_string (el->string);
ctx->startnode = vector_slot (ctx->graph->nodes, 0);
/* copy docstring and keep a pointer to the copy */
if (el->doc)
if (ctx->el->doc)
{
// allocate a new buffer, making room for a flag
size_t length = (size_t) strlen (el->doc) + 2;
docstr = malloc (length);
memcpy (docstr, el->doc, strlen (el->doc));
size_t length = (size_t) strlen (ctx->el->doc) + 2;
ctx->docstr = malloc (length);
memcpy (ctx->docstr, ctx->el->doc, strlen (ctx->el->doc));
// set the flag so doc_next knows when to print a warning
docstr[length - 2] = 0x03;
ctx->docstr[length - 2] = 0x03;
// null terminate
docstr[length - 1] = 0x00;
ctx->docstr[length - 1] = 0x00;
}
docstr_start = docstr;
ctx->docstr_start = ctx->docstr;
}
%%
@ -168,32 +173,32 @@ start:
sentence_root cmd_token_seq
{
// tack on the command element
terminate_graph (graph, currnode, el);
terminate_graph (ctx, ctx->currnode);
}
| sentence_root cmd_token_seq placeholder_token '.' '.' '.'
{
if ((currnode = add_edge_dedup (currnode, $3)) != $3)
graph_delete_node (graph, $3);
if ((ctx->currnode = add_edge_dedup (ctx->currnode, $3)) != $3)
graph_delete_node (ctx->graph, $3);
// adding a node as a child of itself accepts any number
// of the same token, which is what we want for variadics
add_edge_dedup (currnode, currnode);
add_edge_dedup (ctx->currnode, ctx->currnode);
// tack on the command element
terminate_graph (graph, currnode, el);
terminate_graph (ctx, ctx->currnode);
}
;
sentence_root: WORD
{
struct graph_node *root =
new_token_node (graph, WORD_TKN, el->attr, strdup ($1), doc_next(el));
new_token_node (ctx, WORD_TKN, strdup ($1), doc_next(ctx));
if ((currnode = add_edge_dedup (startnode, root)) != root)
graph_delete_node (graph, root);
if ((ctx->currnode = add_edge_dedup (ctx->startnode, root)) != root)
graph_delete_node (ctx->graph, root);
free ($1);
$$ = currnode;
$$ = ctx->currnode;
}
;
@ -205,13 +210,13 @@ cmd_token_seq:
cmd_token:
simple_token
{
if ((currnode = add_edge_dedup (currnode, $1)) != $1)
graph_delete_node (graph, $1);
if ((ctx->currnode = add_edge_dedup (ctx->currnode, $1)) != $1)
graph_delete_node (ctx->graph, $1);
}
| compound_token
{
graph_add_edge (currnode, $1->start);
currnode = $1->end;
graph_add_edge (ctx->currnode, $1->start);
ctx->currnode = $1->end;
free ($1);
}
;
@ -228,7 +233,7 @@ compound_token:
literal_token: WORD
{
$$ = new_token_node (graph, WORD_TKN, el->attr, strdup($1), doc_next(el));
$$ = new_token_node (ctx, WORD_TKN, strdup($1), doc_next(ctx));
free ($1);
}
;
@ -236,32 +241,32 @@ literal_token: WORD
placeholder_token:
IPV4
{
$$ = new_token_node (graph, IPV4_TKN, el->attr, strdup($1), doc_next(el));
$$ = new_token_node (ctx, IPV4_TKN, strdup($1), doc_next(ctx));
free ($1);
}
| IPV4_PREFIX
{
$$ = new_token_node (graph, IPV4_PREFIX_TKN, el->attr, strdup($1), doc_next(el));
$$ = new_token_node (ctx, IPV4_PREFIX_TKN, strdup($1), doc_next(ctx));
free ($1);
}
| IPV6
{
$$ = new_token_node (graph, IPV6_TKN, el->attr, strdup($1), doc_next(el));
$$ = new_token_node (ctx, IPV6_TKN, strdup($1), doc_next(ctx));
free ($1);
}
| IPV6_PREFIX
{
$$ = new_token_node (graph, IPV6_PREFIX_TKN, el->attr, strdup($1), doc_next(el));
$$ = new_token_node (ctx, IPV6_PREFIX_TKN, strdup($1), doc_next(ctx));
free ($1);
}
| VARIABLE
{
$$ = new_token_node (graph, VARIABLE_TKN, el->attr, strdup($1), doc_next(el));
$$ = new_token_node (ctx, VARIABLE_TKN, strdup($1), doc_next(ctx));
free ($1);
}
| RANGE
{
$$ = new_token_node (graph, RANGE_TKN, el->attr, strdup($1), doc_next(el));
$$ = new_token_node (ctx, RANGE_TKN, strdup($1), doc_next(ctx));
struct cmd_token *token = $$->data;
// get the numbers out
@ -271,7 +276,7 @@ placeholder_token:
token->max = strtoll (yylval.string, &yylval.string, 10);
// validate range
if (token->min > token->max) yyerror (graph, el, "Invalid range.");
if (token->min > token->max) cmd_yyerror (ctx, "Invalid range.");
free ($1);
}
@ -280,8 +285,8 @@ placeholder_token:
selector: '<' selector_seq_seq '>'
{
$$ = malloc (sizeof (struct subgraph));
$$->start = new_token_node (graph, SELECTOR_TKN, el->attr, NULL, NULL);
$$->end = new_token_node (graph, NUL_TKN, el->attr, NULL, NULL);
$$->start = new_token_node (ctx, SELECTOR_TKN, NULL, NULL);
$$->end = new_token_node (ctx, NUL_TKN, NULL, NULL);
for (unsigned int i = 0; i < vector_active ($2->start->to); i++)
{
struct graph_node *sn = vector_slot ($2->start->to, i),
@ -289,8 +294,8 @@ selector: '<' selector_seq_seq '>'
graph_add_edge ($$->start, sn);
graph_add_edge (en, $$->end);
}
graph_delete_node (graph, $2->start);
graph_delete_node (graph, $2->end);
graph_delete_node (ctx->graph, $2->start);
graph_delete_node (ctx->graph, $2->end);
free ($2);
};
@ -298,8 +303,8 @@ selector_seq_seq:
selector_seq_seq '|' selector_token_seq
{
$$ = malloc (sizeof (struct subgraph));
$$->start = graph_new_node (graph, NULL, NULL);
$$->end = graph_new_node (graph, NULL, NULL);
$$->start = graph_new_node (ctx->graph, NULL, NULL);
$$->end = graph_new_node (ctx->graph, NULL, NULL);
// link in last sequence
graph_add_edge ($$->start, $3->start);
@ -312,16 +317,16 @@ selector_seq_seq:
graph_add_edge ($$->start, sn);
graph_add_edge (en, $$->end);
}
graph_delete_node (graph, $1->start);
graph_delete_node (graph, $1->end);
graph_delete_node (ctx->graph, $1->start);
graph_delete_node (ctx->graph, $1->end);
free ($1);
free ($3);
}
| selector_token_seq '|' selector_token_seq
{
$$ = malloc (sizeof (struct subgraph));
$$->start = graph_new_node (graph, NULL, NULL);
$$->end = graph_new_node (graph, NULL, NULL);
$$->start = graph_new_node (ctx->graph, NULL, NULL);
$$->end = graph_new_node (ctx->graph, NULL, NULL);
graph_add_edge ($$->start, $1->start);
graph_add_edge ($1->end, $$->end);
graph_add_edge ($$->start, $3->start);
@ -363,8 +368,8 @@ option: '[' option_token_seq ']'
{
// make a new option
$$ = malloc (sizeof (struct subgraph));
$$->start = new_token_node (graph, OPTION_TKN, el->attr, NULL, NULL);
$$->end = new_token_node (graph, NUL_TKN, el->attr, NULL, NULL);
$$->start = new_token_node (ctx, OPTION_TKN, NULL, NULL);
$$->end = new_token_node (ctx, NUL_TKN, NULL, NULL);
// add a path through the sequence to the end
graph_add_edge ($$->start, $2->start);
graph_add_edge ($2->end, $$->end);
@ -398,72 +403,77 @@ option_token:
%%
#undef scanner
void
command_parse_format (struct graph *graph, struct cmd_element *cmd)
{
struct parser_ctx ctx = { .graph = graph, .el = cmd };
// set to 1 to enable parser traces
yydebug = 0;
set_lexer_string (&ctx.scanner, cmd->string);
// parse command into DFA
yyparse (graph, cmd);
cmd_yyparse (&ctx);
/* cleanup lexer */
cleanup_lexer (&ctx.scanner);
// cleanup
cleanup ();
cleanup (&ctx);
}
/* parser helper functions */
void
yyerror (struct graph *graph, struct cmd_element *el, char const *msg)
yyerror (struct parser_ctx *ctx, char const *msg)
{
zlog_err ("%s: FATAL parse error: %s", __func__, msg);
zlog_err ("while parsing this command definition: \n\t%s\n", el->string);
zlog_err ("while parsing this command definition: \n\t%s\n", ctx->el->string);
//exit(EXIT_FAILURE);
}
static void
cleanup()
cleanup (struct parser_ctx *ctx)
{
/* free resources */
free (docstr_start);
/* cleanup lexer */
cleanup_lexer ();
free (ctx->docstr_start);
/* clear state pointers */
currnode = NULL;
docstr_start = docstr = NULL;
ctx->currnode = NULL;
ctx->docstr_start = ctx->docstr = NULL;
}
static void
terminate_graph (struct graph *graph, struct graph_node *finalnode,
struct cmd_element *element)
terminate_graph (struct parser_ctx *ctx, struct graph_node *finalnode)
{
// end of graph should look like this
// * -> finalnode -> END_TKN -> cmd_element
struct cmd_element *element = ctx->el;
struct graph_node *end_token_node =
new_token_node (graph,
new_token_node (ctx,
END_TKN,
element->attr,
strdup (CMD_CR_TEXT),
strdup (""));
struct graph_node *end_element_node =
graph_new_node (graph, element, (void (*)(void *)) &del_cmd_element);
graph_new_node (ctx->graph, element, NULL);
if (node_adjacent (finalnode, end_token_node))
yyerror (graph, element, "Duplicate command.");
cmd_yyerror (ctx, "Duplicate command.");
graph_add_edge (finalnode, end_token_node);
graph_add_edge (end_token_node, end_element_node);
}
static char *
doc_next (struct cmd_element *el)
doc_next (struct parser_ctx *ctx)
{
const char *piece = docstr ? strsep (&docstr, "\n") : "";
const char *piece = ctx->docstr ? strsep (&ctx->docstr, "\n") : "";
if (*piece == 0x03)
{
zlog_debug ("Ran out of docstring while parsing '%s'", el->string);
zlog_debug ("Ran out of docstring while parsing '%s'", ctx->el->string);
piece = "";
}
@ -471,11 +481,11 @@ doc_next (struct cmd_element *el)
}
static struct graph_node *
new_token_node (struct graph *graph, enum cmd_token_type type,
u_char attr, char *text, char *doc)
new_token_node (struct parser_ctx *ctx, enum cmd_token_type type,
char *text, char *doc)
{
struct cmd_token *token = new_cmd_token (type, attr, text, doc);
return graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token);
struct cmd_token *token = new_cmd_token (type, ctx->el->attr, text, doc);
return graph_new_node (ctx->graph, token, (void (*)(void *)) &del_cmd_token);
}
/**

View File

@ -827,6 +827,17 @@ DEFUN_NOSH (no_interface,
return CMD_SUCCESS;
}
void
if_cmd_init (void)
{
install_element (CONFIG_NODE, &interface_cmd);
install_element (CONFIG_NODE, &no_interface_cmd);
install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
}
/* For debug purpose. */
DEFUN (show_address,
show_address_cmd,

View File

@ -447,6 +447,7 @@ extern int if_is_pointopoint (struct interface *);
extern int if_is_multicast (struct interface *);
extern void if_add_hook (int, int (*)(struct interface *));
extern void if_init (struct list **);
extern void if_cmd_init (void);
extern void if_terminate (struct list **);
extern void if_dump_all (void);
extern const char *if_flag_dump(unsigned long);
@ -485,19 +486,4 @@ struct nbr_connected *nbr_connected_check (struct interface *, struct prefix *);
struct if_link_params *if_link_params_get (struct interface *);
void if_link_params_free (struct interface *);
/* Exported variables. */
extern struct cmd_element interface_desc_cmd;
extern struct cmd_element no_interface_desc_cmd;
extern struct cmd_element interface_cmd;
extern struct cmd_element no_interface_cmd;
extern struct cmd_element interface_vrf_cmd;
extern struct cmd_element no_interface_vrf_cmd;
extern struct cmd_element interface_pseudo_cmd;
extern struct cmd_element no_interface_pseudo_cmd;
extern struct cmd_element show_address_cmd;
extern struct cmd_element show_address_vrf_cmd;
extern struct cmd_element show_address_vrf_all_cmd;
extern struct cmd_element vrf_cmd;
extern struct cmd_element no_vrf_cmd;
#endif /* _ZEBRA_IF_H */

View File

@ -423,6 +423,13 @@ DEFUN (clear_thread_cpu,
return CMD_SUCCESS;
}
void
thread_cmd_init (void)
{
install_element (VIEW_NODE, &show_thread_cpu_cmd);
install_element (ENABLE_NODE, &clear_thread_cpu_cmd);
}
static int
thread_timer_cmp(void *a, void *b)
{

View File

@ -244,8 +244,7 @@ extern void thread_set_yield_time (struct thread *, unsigned long);
/* Internal libzebra exports */
extern void thread_getrusage (RUSAGE_T *);
extern struct cmd_element show_thread_cpu_cmd;
extern struct cmd_element clear_thread_cpu_cmd;
extern void thread_cmd_init (void);
/* replacements for the system gettimeofday(), clock_gettime() and
* time() functions, providing support for non-decrementing clock on

View File

@ -531,6 +531,13 @@ DEFUN_NOSH (no_vrf,
}
struct cmd_node vrf_node =
{
VRF_NODE,
"%s(config-vrf)# ",
1
};
/*
* Debug CLI for vrf's
*/
@ -582,7 +589,13 @@ vrf_install_commands (void)
install_element (ENABLE_NODE, &vrf_debug_cmd);
install_element (CONFIG_NODE, &no_vrf_debug_cmd);
install_element (ENABLE_NODE, &no_vrf_debug_cmd);
}
void
vrf_cmd_init (int (*writefunc)(struct vty *vty))
{
install_element (CONFIG_NODE, &vrf_cmd);
install_element (CONFIG_NODE, &no_vrf_cmd);
install_node (&vrf_node, writefunc);
install_default (VRF_NODE);
}

View File

@ -26,6 +26,7 @@
#include "openbsd-tree.h"
#include "linklist.h"
#include "qobj.h"
#include "vty.h"
/* The default NS ID */
#define NS_DEFAULT 0
@ -171,6 +172,8 @@ extern int vrf_bitmap_check (vrf_bitmap_t, vrf_id_t);
extern void vrf_init (void);
extern void vrf_terminate (void);
extern void vrf_cmd_init (int (*writefunc)(struct vty *vty));
/*
* VRF utilities
*/

View File

@ -715,7 +715,7 @@ static void
vty_down_level (struct vty *vty)
{
vty_out (vty, "%s", VTY_NEWLINE);
(*config_exit_cmd.func)(NULL, vty, 0, NULL);
cmd_exit (vty);
vty_prompt (vty);
vty->cp = 0;
}

View File

@ -222,6 +222,12 @@ DEFUN (show_work_queues,
return CMD_SUCCESS;
}
void
workqueue_cmd_init (void)
{
install_element (VIEW_NODE, &show_work_queues_cmd);
}
/* 'plug' a queue: Stop it from being scheduled,
* ie: prevent the queue from draining.
*/

View File

@ -129,5 +129,7 @@ bool work_queue_is_scheduled (struct work_queue *);
/* Helpers, exported for thread.c and command.c */
extern int work_queue_run (struct thread *);
extern struct cmd_element show_work_queues_cmd;
extern void workqueue_cmd_init (void);
#endif /* _QUAGGA_WORK_QUEUE_H */

View File

@ -1845,15 +1845,12 @@ ospf6_interface_init (void)
{
/* Install interface node. */
install_node (&interface_node, config_write_ospf6_interface);
if_cmd_init ();
install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_cmd);
install_element (CONFIG_NODE, &interface_cmd);
install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
install_element (INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
install_element (INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);
install_element (INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);

View File

@ -9255,14 +9255,7 @@ ospf_vty_if_init (void)
{
/* Install interface node. */
install_node (&interface_node, config_write_interface);
install_element (CONFIG_NODE, &interface_cmd);
install_element (CONFIG_NODE, &no_interface_cmd);
install_default (INTERFACE_NODE);
/* "description" commands. */
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
if_cmd_init ();
/* "ip ospf authentication" commands. */
install_element (INTERFACE_NODE, &ip_ospf_authentication_args_addr_cmd);

View File

@ -1527,47 +1527,6 @@ static void clear_interfaces()
clear_pim_interfaces();
}
DEFUN (pim_interface,
pim_interface_cmd,
"interface IFNAME",
"Select an interface to configure\n"
"Interface's name\n")
{
int idx_ifname = 1;
struct interface *ifp;
const char *ifname = argv[idx_ifname]->arg;
size_t sl;
sl = strlen(ifname);
if (sl > INTERFACE_NAMSIZ) {
vty_out(vty, "%% Interface name %s is invalid: length exceeds "
"%d characters%s",
ifname, INTERFACE_NAMSIZ, VTY_NEWLINE);
return CMD_WARNING;
}
ifp = if_lookup_by_name_len(ifname, sl);
if (!ifp) {
vty_out(vty, "%% Interface %s does not exist%s", ifname, VTY_NEWLINE);
/* Returning here would prevent pimd from booting when there are
interface commands in pimd.conf, since all interfaces are
unknown at pimd boot time (the zebra daemon has not been
contacted for interface discovery). */
ifp = if_get_by_name_len(ifname, sl);
if (!ifp) {
vty_out(vty, "%% Could not create interface %s%s", ifname, VTY_NEWLINE);
return CMD_WARNING;
}
}
vty->index = ifp;
vty->node = INTERFACE_NODE;
return CMD_SUCCESS;
}
DEFUN (clear_ip_interfaces,
clear_ip_interfaces_cmd,
"clear ip interfaces",
@ -4832,6 +4791,7 @@ void pim_cmd_init()
{
install_node (&pim_global_node, pim_global_config_write); /* PIM_NODE */
install_node (&interface_node, pim_interface_config_write); /* INTERFACE_NODE */
if_cmd_init ();
install_element (CONFIG_NODE, &ip_multicast_routing_cmd);
install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd);
@ -4839,14 +4799,7 @@ void pim_cmd_init()
install_element (CONFIG_NODE, &no_ip_pim_rp_cmd);
install_element (CONFIG_NODE, &ip_ssmpingd_cmd);
install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd);
#if 0
install_element (CONFIG_NODE, &interface_cmd); /* from if.h */
#else
install_element (CONFIG_NODE, &pim_interface_cmd);
#endif
install_element (CONFIG_NODE, &no_interface_cmd); /* from if.h */
install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_ip_igmp_cmd);
install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd);
install_element (INTERFACE_NODE, &interface_ip_igmp_join_cmd);

View File

@ -2051,13 +2051,9 @@ rip_if_init (void)
/* Install interface node. */
install_node (&interface_node, rip_interface_config_write);
if_cmd_init ();
/* Install commands. */
install_element (CONFIG_NODE, &interface_cmd);
install_element (CONFIG_NODE, &no_interface_cmd);
install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
install_element (RIP_NODE, &rip_network_cmd);
install_element (RIP_NODE, &no_rip_network_cmd);
install_element (RIP_NODE, &rip_neighbor_cmd);

View File

@ -1190,13 +1190,7 @@ ripng_if_init ()
/* Install interface node. */
install_node (&interface_node, interface_config_write);
/* Install commands. */
install_element (CONFIG_NODE, &interface_cmd);
install_element (CONFIG_NODE, &no_interface_cmd);
install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
if_cmd_init ();
install_element (RIPNG_NODE, &ripng_network_cmd);
install_element (RIPNG_NODE, &no_ripng_network_cmd);

View File

@ -23,7 +23,6 @@
#include "command.h"
#include "graph.h"
#include "command_parse.h"
#include "vector.h"
#define USAGE "usage: permutations <cmdstr>"

View File

@ -2796,6 +2796,15 @@ DEFUN (vtysh_start_zsh,
}
#endif
DEFUN (config_list,
config_list_cmd,
"list [permutations]",
"Print command list\n"
"Print all possible command permutations\n")
{
return cmd_list_cmds (vty, argc == 2);
}
static void
vtysh_install_default (enum node_type node)
{

View File

@ -1237,32 +1237,6 @@ if_dump_vty (struct vty *vty, struct interface *ifp)
#endif /* HAVE_NET_RT_IFLIST */
}
/* Wrapper hook point for zebra daemon so that ifindex can be set
* DEFUN macro not used as extract.pl HAS to ignore this
* See also interface_cmd in lib/if.c
*/
DEFUN_NOSH (zebra_interface,
zebra_interface_cmd,
"interface IFNAME",
"Select an interface to configure\n"
"Interface's name\n")
{
int ret;
/* Call lib interface() */
if ((ret = interface_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
return ret;
VTY_DECLVAR_CONTEXT (interface, ifp);
if (ifp->ifindex == IFINDEX_INTERNAL)
/* Is this really necessary? Shouldn't status be initialized to 0
in that case? */
UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
return ret;
}
static void
interface_update_stats (void)
{
@ -2903,6 +2877,7 @@ zebra_if_init (void)
/* Install configuration write function. */
install_node (&interface_node, if_config_write);
install_node (&link_params_node, NULL);
if_cmd_init ();
install_element (VIEW_NODE, &show_interface_cmd);
install_element (VIEW_NODE, &show_interface_vrf_all_cmd);
@ -2911,11 +2886,6 @@ zebra_if_init (void)
install_element (ENABLE_NODE, &show_interface_desc_cmd);
install_element (ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
install_element (CONFIG_NODE, &zebra_interface_cmd);
install_element (CONFIG_NODE, &no_interface_cmd);
install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
install_element (INTERFACE_NODE, &multicast_cmd);
install_element (INTERFACE_NODE, &no_multicast_cmd);
install_element (INTERFACE_NODE, &linkdetect_cmd);

View File

@ -520,26 +520,6 @@ zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id)
return zvrf->table[afi][SAFI_UNICAST];
}
/* Wrapper hook point for zebra daemon so that ifindex can be set
* DEFUN macro not used as extract.pl HAS to ignore this
* See also interface_cmd in lib/if.c
*/
DEFUN_NOSH (zebra_vrf,
zebra_vrf_cmd,
"vrf NAME",
"Select a VRF to configure\n"
"VRF's name\n")
{
// VTY_DECLVAR_CONTEXT (vrf, vrfp);
int ret;
/* Call lib vrf() */
if ((ret = vrf_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
return ret;
return ret;
}
static int
vrf_config_write (struct vty *vty)
{
@ -558,13 +538,6 @@ vrf_config_write (struct vty *vty)
return 0;
}
struct cmd_node vrf_node =
{
VRF_NODE,
"%s(config-vrf)# ",
1
};
/* Zebra VRF initialization. */
void
zebra_vrf_init (void)
@ -575,9 +548,5 @@ zebra_vrf_init (void)
vrf_add_hook (VRF_DELETE_HOOK, zebra_vrf_delete);
vrf_init ();
install_node (&vrf_node, vrf_config_write);
install_default (VRF_NODE);
install_element (CONFIG_NODE, &zebra_vrf_cmd);
install_element (CONFIG_NODE, &no_vrf_cmd);
vrf_cmd_init (vrf_config_write);
}