]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: parser: add named variables in CLI
authorDavid Lamparter <equinox@opensourcerouting.org>
Fri, 18 Nov 2016 11:06:57 +0000 (12:06 +0100)
committerQuentin Young <qlyoung@users.noreply.github.com>
Mon, 15 May 2017 14:27:43 +0000 (10:27 -0400)
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>
lib/command.c
lib/command.h
lib/command_parse.y
lib/grammar_sandbox.c

index 2b8eee8de335e348e7dbb1528b91f918dd0abb8f..06d9422f70b7849b018492026702cde169626bd0 100644 (file)
@@ -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,10 +2801,18 @@ 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 ()
 {
index 8f6abc85baf519b57431111aa71e96f1356bbdb6..9b2af579913034b43e4b51c0c09328e468dd9dd4 100644 (file)
@@ -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);
index 0c415af3aaf0211e3b736b9bb1af871ccca02045..7e7a68ffdda71076b8fa593388c46a6d11151738 100644 (file)
 %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);
 }
 ;
 
index 0da7981fc166465350020eb6f02c9edd6f1e355f..f35b8beffd4fdd8fa52df4eb2fb249f14ac2be13 100644 (file)
@@ -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, " ");