summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2016-11-18 12:06:57 +0100
committerQuentin Young <qlyoung@users.noreply.github.com>2017-05-15 16:27:43 +0200
commit16705ecc653dd657c5b8149934d8734e89c27c07 (patch)
tree382236b56dcc7542e95d302d031c686ae6618eb7
parentMerge pull request #520 from opensourcerouting/bgpd-fixes-master (diff)
downloadfrr-16705ecc653dd657c5b8149934d8734e89c27c07.tar.xz
frr-16705ecc653dd657c5b8149934d8734e89c27c07.zip
lib: parser: add named variables in CLI
struct cmd_token now has a "varname" field which is derived from the DEFUN's string definition. It can be manually specified with "$name" after some token, e.g. "foo WORD$var". A later commit adds code to automatically fill the value if nothing is specified. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
-rw-r--r--lib/command.c9
-rw-r--r--lib/command.h2
-rw-r--r--lib/command_parse.y42
-rw-r--r--lib/grammar_sandbox.c2
4 files changed, 50 insertions, 5 deletions
diff --git a/lib/command.c b/lib/command.c
index 2b8eee8de..06d9422f7 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -2772,6 +2772,7 @@ new_cmd_token (enum cmd_token_type type, u_char attr,
token->refcnt = 1;
token->arg = NULL;
token->allowrepeat = false;
+ token->varname = NULL;
return token;
}
@@ -2800,11 +2801,19 @@ copy_cmd_token (struct cmd_token *token)
copy->text = token->text ? XSTRDUP (MTYPE_CMD_TEXT, token->text) : NULL;
copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_DESC, token->desc) : NULL;
copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_ARG, token->arg) : NULL;
+ copy->varname = token->varname ? XSTRDUP (MTYPE_CMD_ARG, token->varname) : NULL;
return copy;
}
void
+cmd_set_varname (struct cmd_token *token, const char *varname)
+{
+ XFREE (MTYPE_CMD_VAR, token->varname);
+ token->varname = varname ? XSTRDUP (MTYPE_CMD_VAR, varname) : NULL;
+}
+
+void
cmd_terminate ()
{
struct cmd_node *cmd_node;
diff --git a/lib/command.h b/lib/command.h
index 8f6abc85b..9b2af5799 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -210,6 +210,7 @@ struct cmd_token
char *desc; // token description
long long min, max; // for ranges
char *arg; // user input that matches this token
+ char *varname;
struct graph_node *forkjoin; // paired FORK/JOIN for JOIN/FORK
};
@@ -446,6 +447,7 @@ extern struct cmd_token *new_cmd_token (enum cmd_token_type, u_char attr,
const char *text, const char *desc);
extern void del_cmd_token (struct cmd_token *);
extern struct cmd_token *copy_cmd_token (struct cmd_token *);
+extern void cmd_set_varname(struct cmd_token *token, const char *varname);
extern vector completions_to_vec (struct list *completions);
extern void cmd_merge_graphs (struct graph *old, struct graph *new, int direction);
diff --git a/lib/command_parse.y b/lib/command_parse.y
index 0c415af3a..7e7a68ffd 100644
--- a/lib/command_parse.y
+++ b/lib/command_parse.y
@@ -104,12 +104,15 @@
%type <node> start
%type <node> literal_token
%type <node> placeholder_token
+%type <node> placeholder_token_real
%type <node> simple_token
%type <subgraph> selector
%type <subgraph> selector_token
%type <subgraph> selector_token_seq
%type <subgraph> selector_seq_seq
+%type <string> varname_token
+
%code {
/* bison declarations */
@@ -184,6 +187,16 @@ start:
}
;
+varname_token: '$' WORD
+{
+ $$ = XSTRDUP (MTYPE_LEX, $2);
+}
+| /* empty */
+{
+ $$ = NULL;
+}
+;
+
cmd_token_seq:
/* empty */
| cmd_token_seq cmd_token
@@ -207,14 +220,16 @@ simple_token:
| placeholder_token
;
-literal_token: WORD
+literal_token: WORD varname_token
{
$$ = new_token_node (ctx, WORD_TKN, $1, doc_next(ctx));
+ cmd_set_varname ($$->data, $2);
+ XFREE (MTYPE_LEX, $2);
XFREE (MTYPE_LEX, $1);
}
;
-placeholder_token:
+placeholder_token_real:
IPV4
{
$$ = new_token_node (ctx, IPV4_TKN, $1, doc_next(ctx));
@@ -257,10 +272,22 @@ placeholder_token:
XFREE (MTYPE_LEX, $1);
}
+placeholder_token:
+ placeholder_token_real varname_token
+{
+ struct cmd_token *token = $$->data;
+ $$ = $1;
+ cmd_set_varname (token, $2);
+ XFREE (MTYPE_LEX, $2);
+};
+
+
/* <selector|set> productions */
-selector: '<' selector_seq_seq '>'
+selector: '<' selector_seq_seq '>' varname_token
{
$$ = $2;
+ cmd_set_varname ($2.end->data, $4);
+ XFREE (MTYPE_LEX, $4);
};
selector_seq_seq:
@@ -283,7 +310,7 @@ selector_seq_seq:
;
/* {keyword} productions */
-selector: '{' selector_seq_seq '}'
+selector: '{' selector_seq_seq '}' varname_token
{
$$ = $2;
graph_add_edge ($$.end, $$.start);
@@ -293,6 +320,9 @@ selector: '{' selector_seq_seq '}'
* loop-avoidal fails to handle
* just use [{a|b}] if neccessary, that will work perfectly fine, and reason
* #1 is good enough to keep it this way. */
+
+ cmd_set_varname ($2.end->data, $4);
+ XFREE (MTYPE_LEX, $4);
};
@@ -315,10 +345,12 @@ selector_token_seq:
;
/* [option] productions */
-selector: '[' selector_seq_seq ']'
+selector: '[' selector_seq_seq ']' varname_token
{
$$ = $2;
graph_add_edge ($$.start, $$.end);
+ cmd_set_varname ($2.end->data, $4);
+ XFREE (MTYPE_LEX, $4);
}
;
diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c
index 0da7981fc..f35b8beff 100644
--- a/lib/grammar_sandbox.c
+++ b/lib/grammar_sandbox.c
@@ -526,6 +526,8 @@ pretty_print_graph (struct vty *vty, struct graph_node *start, int level,
vty_out(vty, "%s", LOOKUP_DEF(tokennames, tok->type, tokennum));
if (tok->text)
vty_out(vty, ":\"%s\"", tok->text);
+ if (tok->varname)
+ vty_out(vty, " => %s", tok->varname);
if (desc)
vty_out(vty, " ?'%s'", tok->desc);
vty_out(vty, " ");