]> git.proxmox.com Git - mirror_frr.git/blob - lib/command_graph.c
0a866de330bf72f37ac4ac30a526c7f011bead16
[mirror_frr.git] / lib / command_graph.c
1 /*
2 * Command DFA module.
3 * Provides a DFA data structure and associated functions for manipulating it.
4 * Used to match user command line input.
5 *
6 * @author Quentin Young <qlyoung@cumulusnetworks.com>
7 */
8
9 #include "command_graph.h"
10 #include <zebra.h>
11 #include "memory.h"
12
13 struct graph_node *
14 add_node(struct graph_node *parent, struct graph_node *child)
15 {
16 vector_set(parent->children, child);
17 child->refs++;
18 return child;
19 }
20
21 struct graph_node *
22 new_node(enum graph_node_type type)
23 {
24 struct graph_node *node =
25 XMALLOC(MTYPE_CMD_TOKENS, sizeof(struct graph_node));
26
27 node->type = type;
28 node->children = vector_init(VECTOR_MIN_SIZE);
29 node->end = NULL;
30 node->text = NULL;
31 node->element = NULL;
32 node->arg = NULL;
33 node->is_start = 0;
34 node->value = 0;
35 node->min = 0;
36 node->max = 0;
37 node->refs = 0;
38
39 return node;
40 }
41
42 void
43 free_node (struct graph_node *node)
44 {
45 if (!node) return;
46 if (node->children) vector_free (node->children);
47 if (node->element) free_cmd_element (node->element);
48 free (node->text);
49 free (node->arg);
50 free (node);
51 }
52
53 void
54 free_graph (struct graph_node *start)
55 {
56 if (start && start->children && vector_active(start->children) > 0) {
57 for (unsigned int i = 0; i < vector_active(start->children); i++) {
58 free_graph (vector_slot(start->children, i));
59 vector_unset(start->children, i);
60 }
61 }
62
63 if (--(start->refs) == 0)
64 free_node (start);
65 }
66
67 char *
68 describe_node(struct graph_node *node, char* buffer, unsigned int bufsize)
69 {
70 if (node == NULL) {
71 snprintf(buffer, bufsize, "(null node)");
72 return buffer;
73 }
74
75 // print this node
76 switch (node->type) {
77 case WORD_GN:
78 case IPV4_GN:
79 case IPV4_PREFIX_GN:
80 case IPV6_GN:
81 case IPV6_PREFIX_GN:
82 case VARIABLE_GN:
83 case RANGE_GN:
84 snprintf(buffer, bufsize, node->text);
85 break;
86 case NUMBER_GN:
87 snprintf(buffer, bufsize, "%lld", node->value);
88 break;
89 case SELECTOR_GN:
90 snprintf(buffer, bufsize, "<>");
91 break;
92 case OPTION_GN:
93 snprintf(buffer, bufsize, "[]");
94 break;
95 case NUL_GN:
96 snprintf(buffer, bufsize, "NUL");
97 break;
98 case END_GN:
99 snprintf(buffer, bufsize, "END");
100 break;
101 case START_GN:
102 snprintf(buffer, bufsize, "START");
103 break;
104 default:
105 snprintf(buffer, bufsize, "ERROR");
106 }
107
108 return buffer;
109 }
110
111 void
112 walk_graph(struct graph_node *start, int level)
113 {
114 char* desc = malloc(50);
115 // print this node
116 fprintf(stderr, "%s[%d] ", describe_node(start, desc, 50), vector_active(start->children));
117 free(desc);
118
119 if (vector_active(start->children)) {
120 if (vector_active(start->children) == 1)
121 walk_graph(vector_slot(start->children, 0), level);
122 else {
123 fprintf(stderr, "\n");
124 for (unsigned int i = 0; i < vector_active(start->children); i++) {
125 struct graph_node *r = vector_slot(start->children, i);
126 for (int j = 0; j < level+1; j++)
127 fprintf(stderr, " ");
128 walk_graph(r, level+1);
129 }
130 }
131 }
132 else
133 fprintf(stderr, "\n");
134 }
135
136 void
137 dump_node (struct graph_node *node)
138 {
139 char buf[50];
140 describe_node(node, buf, 50);
141 fprintf(stderr, "%s[%d]\n", buf, node->type);
142 fprintf(stderr, "\t->text: %s\n", node->text);
143 fprintf(stderr, "\t->value: %lld\n", node->value);
144 fprintf(stderr, "\t->is_start: %d\n", node->is_start);
145 fprintf(stderr, "\t->element: %p\n", node->element);
146 fprintf(stderr, "\t->min: %lld\n->max: %lld\n", node->min, node->max);
147 fprintf(stderr, "\t->arg: %s\n", node->arg);
148 fprintf(stderr, "\t->refs: %d\n", node->refs);
149 fprintf(stderr, "\tnum children: %d\n", vector_active(node->children));
150 }