From 0aa2c2ff01c78e6c194c16ce1d9925af918e7e4f Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 5 Aug 2016 16:41:42 +0000 Subject: [PATCH] lib: Add docstring support Signed-off-by: Quentin Young --- lib/command_graph.h | 3 ++- lib/command_parse.y | 30 +++++++++++++++++++++++++++++- lib/grammar_sandbox.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/lib/command_graph.h b/lib/command_graph.h index e1feb9f77f..c987213633 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -27,7 +27,8 @@ struct graph_node vector children; // this node's children struct graph_node * end; // pointer to end for SELECTOR_GN & OPTION_GN - char* text; // for WORD_GN and VARIABLE_GN + char *text; // original format text + char *doc; // docstring for this node long long value; // for NUMBER_GN long long min, max; // for RANGE_GN diff --git a/lib/command_parse.y b/lib/command_parse.y index ac075e67a3..35fac1b7d5 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -15,6 +15,8 @@ struct graph_node * node_exists(struct graph_node *, struct graph_node *); struct graph_node * node_replace(struct graph_node *, struct graph_node *); +char * +doc_next(void); #define DECIMAL_STRLEN_MAX 20 @@ -55,6 +57,7 @@ struct graph_node *selnode_start, // start node for selector set *selnode_end; // end node for selector set struct cmd_element *command; // command we're parsing +char *docstring; %} %token WORD @@ -128,6 +131,7 @@ sentence_root: WORD { struct graph_node *root = new_node(WORD_GN); root->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + root->doc = doc_next(); if ((currnode = node_replace(startnode, root)) != root) free (root); @@ -173,36 +177,42 @@ placeholder_token: { $$ = new_node(IPV4_GN); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + $$->doc = doc_next(); free ($1); } | IPV4_PREFIX { $$ = new_node(IPV4_PREFIX_GN); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + $$->doc = doc_next(); free ($1); } | IPV6 { $$ = new_node(IPV6_GN); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + $$->doc = doc_next(); free ($1); } | IPV6_PREFIX { $$ = new_node(IPV6_PREFIX_GN); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + $$->doc = doc_next(); free ($1); } | VARIABLE { $$ = new_node(VARIABLE_GN); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + $$->doc = doc_next(); free ($1); } | RANGE { $$ = new_node(RANGE_GN); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + $$->doc = doc_next(); // get the numbers out yylval.string++; @@ -222,12 +232,16 @@ literal_token: { $$ = new_node(WORD_GN); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + $$->doc = doc_next(); free ($1); } | NUMBER { $$ = new_node(NUMBER_GN); $$->value = yylval.integer; + $$->text = XCALLOC(MTYPE_CMD_TOKENS, DECIMAL_STRLEN_MAX+1); + snprintf($$->text, DECIMAL_STRLEN_MAX, "%lld", $$->value); + $$->doc = doc_next(); } ; @@ -354,12 +368,17 @@ parse_command_format(struct graph_node *start, struct cmd_element *cmd) // trace parser yydebug = 0; - // command string + // command element command = cmd; + // copy docstring and keep a pointer to the copy + char *doc = docstring = cmd->doc ? XSTRDUP(MTYPE_TMP, cmd->doc) : NULL; // make flex read from a string set_buffer_string(command->string); // parse command into DFA yyparse(); + // cleanup + free (doc); + doc = NULL; // startnode points to command DFA return startnode; } @@ -386,3 +405,12 @@ node_replace(struct graph_node *parent, struct graph_node *child) return existing; } + +char * +doc_next() +{ + char *piece = NULL; + if (!docstring || !(piece = strsep(&docstring, "\n"))) + return NULL; + return XSTRDUP(MTYPE_CMD_TOKENS, piece); +} diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index a2177c1767..d1779a9b6e 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -24,6 +24,33 @@ DEFUN (grammar_test, return CMD_SUCCESS; } +DEFUN (grammar_test_doc, + grammar_test_doc_cmd, + "grammar test docstring", + GRAMMAR_STR + "Test function for docstring\n" + "Command end\n") +{ + struct cmd_element *cmd = malloc(sizeof(struct cmd_element)); + cmd->string = "test docstring (1-255) end VARIABLE [OPTION|set lol] . VARARG"; + cmd->doc = "Test stuff\n" + "docstring thing\n" + "first example\n" + "second example\n" + "follow\n" + "random range\n" + "end thingy\n" + "variable\n" + "optional variable\n" + "optional set\n" + "optional lol\n" + "vararg!\n"; + cmd->func = NULL; + cmd->tokens = vector_init(VECTOR_MIN_SIZE); + parse_command_format(nodegraph, cmd); + return CMD_SUCCESS; +} + DEFUN (grammar_test_show, grammar_test_show_cmd, "grammar tree", @@ -52,7 +79,7 @@ DEFUN (grammar_test_complete, else { fprintf(stderr, "%% Matched full input, possible completions:\n"); - char* desc = malloc(50); + char* desc = malloc(30); struct listnode *node; struct graph_node *cnode; // print possible next hops, if any @@ -60,7 +87,7 @@ DEFUN (grammar_test_complete, if (cnode->type == END_GN) fprintf(stderr, " %p\n", cnode->element->func); else - fprintf(stderr, "%s\n", describe_node(cnode, desc, 50)); + fprintf(stderr, "%-30s%s\n", describe_node(cnode, desc, 30), cnode->doc); } free(desc); } @@ -118,4 +145,5 @@ void grammar_sandbox_init() { install_element (ENABLE_NODE, &grammar_test_show_cmd); install_element (ENABLE_NODE, &grammar_test_match_cmd); install_element (ENABLE_NODE, &grammar_test_complete_cmd); + install_element (ENABLE_NODE, &grammar_test_doc_cmd); } -- 2.39.5