* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "command.h"
#include "memory_vty.h"
#include "graph.h"
DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc")
-#define MAXDEPTH 64
-
/** headers **/
void grammar_sandbox_init(void);
void pretty_print_graph(struct vty *vty, struct graph_node *, int, int,
struct graph_node **, size_t);
-static void pretty_print_dot(FILE *ofd, unsigned opts, struct graph_node *start,
- struct graph_node **stack, size_t stackpos,
- struct graph_node **visited, size_t *visitpos);
void init_cmdgraph(struct vty *, struct graph **);
/** shim interface commands **/
vty_out(vty, "%% No match\n");
// free resources
- list_delete(completions);
+ list_delete(&completions);
cmd_free_strvec(command);
XFREE(MTYPE_TMP, cmdstr);
vty_out(vty, "func: %p\n", element->func);
- list_delete(argvv);
+ list_delete(&argvv);
} else {
assert(MATCHER_ERROR(result));
switch (result) {
{
check_nodegraph();
- struct graph_node *stack[MAXDEPTH];
+ struct graph_node *stack[CMD_ARGC_MAX];
pretty_print_graph(vty, vector_slot(nodegraph->nodes, 0), 0, argc >= 3,
stack, 0);
return CMD_SUCCESS;
".dot filename\n")
{
check_nodegraph();
-
- struct graph_node *stack[MAXDEPTH];
- struct graph_node *visited[MAXDEPTH * MAXDEPTH];
- size_t vpos = 0;
-
FILE *ofd = fopen(argv[2]->arg, "w");
+
if (!ofd) {
vty_out(vty, "%s: %s\r\n", argv[2]->arg, strerror(errno));
return CMD_SUCCESS;
}
- fprintf(ofd,
- "digraph {\n graph [ rankdir = LR ];\n node [ fontname = \"Fira Mono\", fontsize = 9 ];\n\n");
- pretty_print_dot(ofd, 0, vector_slot(nodegraph->nodes, 0), stack, 0,
- visited, &vpos);
- fprintf(ofd, "}\n");
+ char *dot = cmd_graph_dump_dot(nodegraph);
+
+ fprintf(ofd, "%s", dot);
fclose(ofd);
+ XFREE(MTYPE_TMP, dot);
+
return CMD_SUCCESS;
}
struct graph_node *gn = stack[stackpos];
struct cmd_token *tok = gn->data;
char *appendp = cmd + strlen(cmd);
- size_t i, j;
+ size_t j;
if (tok->type < SPECIAL_TKN) {
sprintf(appendp, "%s ", tok->text);
return;
}
- if (++stackpos == MAXDEPTH)
+ if (++stackpos == CMD_ARGC_MAX)
return;
- for (i = 0; i < vector_active(gn->to); i++) {
+ for (size_t i = 0; i < vector_active(gn->to); i++) {
struct graph_node *gnext = vector_slot(gn->to, i);
for (j = 0; j < stackpos; j++)
if (stack[j] == gnext)
static struct list *cmd_graph_permutations(struct graph *graph)
{
char accumulate[2048] = "";
- struct graph_node *stack[MAXDEPTH];
+ struct graph_node *stack[CMD_ARGC_MAX];
struct list *rv = list_new();
rv->cmp = cmd_permute_cmp;
nodegraph = cnode->cmdgraph;
if (!nodegraph)
continue;
- vty_out(vty, "scanning node %d (%s)\n",
- scannode - 1, node_names[scannode - 1]);
+ vty_out(vty, "scanning node %d (%s)\n", scannode - 1,
+ node_names[scannode - 1]);
}
commands = cmd_graph_permutations(nodegraph);
}
prev = cur;
}
- list_delete(commands);
+ list_delete(&commands);
vty_out(vty, "\n");
} while (scan && scannode < LINK_PARAMS_NODE);
install_element(ENABLE_NODE, &grammar_access_cmd);
}
-#define item(x) { x, #x }
-struct message tokennames[] = {item(WORD_TKN), // words
- item(VARIABLE_TKN), // almost anything
- item(RANGE_TKN), // integer range
- item(IPV4_TKN), // IPV4 addresses
- item(IPV4_PREFIX_TKN), // IPV4 network prefixes
- item(IPV6_TKN), // IPV6 prefixes
- item(IPV6_PREFIX_TKN), // IPV6 network prefixes
- item(MAC_TKN), // MAC address
- item(MAC_PREFIX_TKN), // MAC address w/ mask
-
- /* plumbing types */
- item(FORK_TKN),
- item(JOIN_TKN),
- item(START_TKN), // first token in line
- item(END_TKN), // last token in line
- {0}};
-
/**
* Pretty-prints a graph, assuming it is a tree.
*
vty_out(vty, " ?'%s'", tok->desc);
vty_out(vty, " ");
- if (stackpos == MAXDEPTH) {
+ if (stackpos == CMD_ARGC_MAX) {
vty_out(vty, " -aborting! (depth limit)\n");
return;
}
vty_out(vty, "\n");
}
-static void pretty_print_dot(FILE *ofd, unsigned opts, struct graph_node *start,
- struct graph_node **stack, size_t stackpos,
- struct graph_node **visited, size_t *visitpos)
-{
- // print this node
- char tokennum[32];
- struct cmd_token *tok = start->data;
- const char *color;
-
- for (size_t i = 0; i < (*visitpos); i++)
- if (visited[i] == start)
- return;
- visited[(*visitpos)++] = start;
- if ((*visitpos) == MAXDEPTH * MAXDEPTH)
- return;
-
- snprintf(tokennum, sizeof(tokennum), "%d?", tok->type);
- fprintf(ofd, " n%p [ shape=box, label=<", start);
-
- fprintf(ofd, "<b>%s</b>", lookup_msg(tokennames, tok->type, NULL));
- if (tok->attr == CMD_ATTR_DEPRECATED)
- fprintf(ofd, " (d)");
- else if (tok->attr == CMD_ATTR_HIDDEN)
- fprintf(ofd, " (h)");
- if (tok->text) {
- if (tok->type == WORD_TKN)
- fprintf(ofd,
- "<br/>\"<font color=\"#0055ff\" point-size=\"11\"><b>%s</b></font>\"",
- tok->text);
- else
- fprintf(ofd, "<br/>%s", tok->text);
- }
- /* if (desc)
- fprintf(ofd, " ?'%s'", tok->desc); */
- switch (tok->type) {
- case START_TKN:
- color = "#ccffcc";
- break;
- case FORK_TKN:
- color = "#aaddff";
- break;
- case JOIN_TKN:
- color = "#ddaaff";
- break;
- case WORD_TKN:
- color = "#ffffff";
- break;
- default:
- color = "#ffffff";
- break;
- }
- fprintf(ofd, ">, style = filled, fillcolor = \"%s\" ];\n", color);
-
- if (stackpos == MAXDEPTH)
- return;
- stack[stackpos++] = start;
-
- for (unsigned int i = 0; i < vector_active(start->to); i++) {
- struct graph_node *adj = vector_slot(start->to, i);
- // if this node is a vararg, just print *
- if (adj == start) {
- fprintf(ofd, " n%p -> n%p;\n", start, start);
- } else if (((struct cmd_token *)adj->data)->type == END_TKN) {
- // struct cmd_token *et = adj->data;
- fprintf(ofd, " n%p -> end%p;\n", start, adj);
- fprintf(ofd,
- " end%p [ shape=box, label=<end>, style = filled, fillcolor = \"#ffddaa\" ];\n",
- adj);
- } else {
- fprintf(ofd, " n%p -> n%p;\n", start, adj);
- size_t k;
- for (k = 0; k < stackpos; k++)
- if (stack[k] == adj)
- break;
- if (k == stackpos) {
- pretty_print_dot(ofd, opts, adj, stack,
- stackpos, visited, visitpos);
- }
- }
- }
-}
-
-
/** stuff that should go in command.c + command.h */
void init_cmdgraph(struct vty *vty, struct graph **graph)
{