From: Quentin Young Date: Wed, 27 Jul 2016 04:17:51 +0000 (+0000) Subject: lib: Cleanup parser memory management X-Git-Tag: frr-3.0-branchpoint~129^2~279 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=5a5d576b346b03888636bcb0af31efb8a1e43cc2;p=matthieu%2Ffrr.git lib: Cleanup parser memory management Free as appropriate. Additionally add new type of node to demark graph head (START_GN). Signed-off-by: Quentin Young --- diff --git a/lib/command_graph.c b/lib/command_graph.c index 38baa802c3..a5880f34a6 100644 --- a/lib/command_graph.c +++ b/lib/command_graph.c @@ -32,18 +32,18 @@ cmp_node(struct graph_node *first, struct graph_node *second) if (first->type != second->type) return 0; switch (first->type) { - case WORD_GN: // words and variables are equal if their - case VARIABLE_GN: // text value is equal + case WORD_GN: + case VARIABLE_GN: if (first->text && second->text) { if (strcmp(first->text, second->text)) return 0; } else if (first->text != second->text) return 0; break; - case RANGE_GN: // ranges are equal if their bounds are equal + case RANGE_GN: if (first->min != second->min || first->max != second->max) return 0; break; - case NUMBER_GN: // numbers are equal if their values are equal + case NUMBER_GN: if (first->value != second->value) return 0; break; /* selectors and options should be equal if all paths are equal, @@ -53,8 +53,10 @@ cmp_node(struct graph_node *first, struct graph_node *second) case SELECTOR_GN: case OPTION_GN: return 0; - // end nodes are always considered equal, since each node may only - // have one at a time + /* end nodes are always considered equal, since each node may only + * have one at a time + */ + case START_GN: case END_GN: default: break; @@ -66,20 +68,34 @@ cmp_node(struct graph_node *first, struct graph_node *second) struct graph_node * new_node(enum graph_node_type type) { - struct graph_node *node = malloc(sizeof(struct graph_node)); + struct graph_node *node = + XMALLOC(MTYPE_CMD_TOKENS, sizeof(struct graph_node)); + node->type = type; node->children = vector_init(VECTOR_MIN_SIZE); - node->is_root = 0; - node->end = NULL; - node->text = NULL; - node->value = 0; - node->min = 0; - node->max = 0; - node->element = NULL; + node->is_start = 0; + node->end = NULL; + node->text = NULL; + node->value = 0; + node->min = 0; + node->max = 0; + node->element = NULL; return node; } +void +free_node (struct graph_node *node) +{ + if (!node) return; + free_node (node->end); + vector_free (node->children); + free (node->text); + free (node->arg); + free (node->element); + free (node); +} + char * describe_node(struct graph_node *node, char* buffer, unsigned int bufsize) { @@ -114,6 +130,9 @@ describe_node(struct graph_node *node, char* buffer, unsigned int bufsize) case END_GN: snprintf(buffer, bufsize, "END"); break; + case START_GN: + snprintf(buffer, bufsize, "START"); + break; default: snprintf(buffer, bufsize, "ERROR"); } @@ -146,3 +165,4 @@ walk_graph(struct graph_node *start, int level) else fprintf(stderr, "\n"); } + diff --git a/lib/command_graph.h b/lib/command_graph.h index f0ded21262..f82bbd052b 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -16,6 +16,7 @@ enum graph_node_type SELECTOR_GN, OPTION_GN, NUL_GN, + START_GN, END_GN }; @@ -26,9 +27,9 @@ 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 - long value; // for NUMBER_GN - long min, max; // for RANGE_GN + char* text; // for WORD_GN and VARIABLE_GN + long value; // for NUMBER_GN + long min, max; // for RANGE_GN /* cmd_element struct pointer, only valid for END_GN */ struct cmd_element *element; @@ -37,14 +38,14 @@ struct graph_node }; /* - * Adds a child to a node. - * If the node already has the exact same child, nothing is done. This is - * decided with cmp_node. + * Adds a node as a child of another node. + * If the new parent has a child that is equal to the prospective child, as + * determined by cmp_node, then a pointer to the existing node is returned and + * the prospective child is not added. Otherwise the return value is NULL. * * @param[in] parent node * @param[in] child node - * @return the new child, or the existing child if the parent already has the - * new child + * @return pointer to child if it is added, pointer to existing child otherwise */ extern struct graph_node * add_node(struct graph_node *, struct graph_node *); diff --git a/lib/command_parse.y b/lib/command_parse.y index 7b56aec952..8c0584facd 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -18,6 +18,7 @@ extern void yyerror(const char *); %code requires { #include "command.h" #include "command_graph.h" + #include "memory.h" } %code provides { extern void @@ -50,14 +51,14 @@ struct graph_node *selnode_start, // start node for selector set struct cmd_element *command; // command we're parsing %} -%token WORD -%token IPV4 -%token IPV4_PREFIX -%token IPV6 -%token IPV6_PREFIX -%token VARIABLE -%token RANGE -%token NUMBER +%token WORD +%token IPV4 +%token IPV4_PREFIX +%token IPV6 +%token IPV6_PREFIX +%token VARIABLE +%token RANGE +%token NUMBER %type start %type sentence_root @@ -80,44 +81,45 @@ struct cmd_element *command; // command we're parsing start: sentence_root cmd_token_seq { - // this should never happen... - if (currnode->type == END_GN) - yyerror("Unexpected leaf"); - - // create function pointer node + // create leaf node struct graph_node *end = new_node(END_GN); end->element = command; - // ensure there are no END_GN children - for (unsigned int i = 0; i < vector_active(currnode->children); i++) + // add node + if (add_node(currnode, end) != end) { - struct graph_node *child = vector_slot(currnode->children, i); - if (child->type == END_GN) - yyerror("Duplicate command."); + yyerror("Duplicate command."); + YYABORT; } - - // add node - end = add_node(currnode, end); } sentence_root: WORD { - $$ = new_node(WORD_GN); - $$->text = strdup(yylval.string); - fprintf(stderr, ">>>>>>>> YYLVAL.STRING: %s\n", yylval.string); - fprintf(stderr, ">>>>>>>> TEXT: %s\n", $$->text); + struct graph_node *root = new_node(WORD_GN); + root->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + + currnode = add_node(startnode, root); + if (currnode != root) + free (root); - currnode = $$; - currnode->is_root = 1; - currnode = add_node(startnode, currnode); + free ($1); + $$ = currnode; }; /* valid top level tokens */ cmd_token: placeholder_token -{ currnode = add_node(currnode, $1); } +{ + currnode = add_node(currnode, $1); + if (currnode != $1) + free_node ($1); +} | literal_token -{ currnode = add_node(currnode, $1); } +{ + currnode = add_node(currnode, $1); + if (currnode != $1) + free_node ($1); +} /* selectors and options are subgraphs with start and end nodes */ | selector { @@ -142,37 +144,44 @@ placeholder_token: IPV4 { $$ = new_node(IPV4_GN); - $$->text = strdup(yylval.string); + $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + free ($1); } | IPV4_PREFIX { $$ = new_node(IPV4_PREFIX_GN); - $$->text = strdup(yylval.string); + $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + free ($1); } | IPV6 { $$ = new_node(IPV6_GN); - $$->text = strdup(yylval.string); + $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + free ($1); } | IPV6_PREFIX { $$ = new_node(IPV6_PREFIX_GN); - $$->text = strdup(yylval.string); + $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + free ($1); } | VARIABLE { $$ = new_node(VARIABLE_GN); - $$->text = strdup(yylval.string); + $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + free ($1); } | RANGE { $$ = new_node(RANGE_GN); - $$->text = strdup(yylval.string); + $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); // get the numbers out strsep(&yylval.string, "(-)"); $$->min = atoi( strsep(&yylval.string, "(-)") ); $$->max = atoi( strsep(&yylval.string, "(-)") ); + + free ($1); } ; @@ -180,9 +189,8 @@ literal_token: WORD { $$ = new_node(WORD_GN); - $$->text = strdup(yylval.string); - fprintf(stderr, ">>>>>>>> YYLVAL.STRING: %s\n", yylval.string); - fprintf(stderr, ">>>>>>>> TEXT: %s\n", $$->text); + $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); + free ($1); } | NUMBER { @@ -300,8 +308,7 @@ option_token: void yyerror(char const *message) { // fail on bad parse - printf("Grammar error: %s\n", message); - exit(EXIT_FAILURE); + fprintf(stderr, "Grammar error: %s\n", message); } struct graph_node * @@ -310,7 +317,8 @@ parse_command_format(struct graph_node *start, struct cmd_element *cmd) fprintf(stderr, "parsing: %s\n", cmd->string); /* clear state pointers */ - startnode = currnode = seqhead = NULL; + startnode = start; + currnode = seqhead = NULL; selnode_start = selnode_end = NULL; optnode_start = optnode_end = NULL; @@ -320,8 +328,6 @@ parse_command_format(struct graph_node *start, struct cmd_element *cmd) command = cmd; // make flex read from a string set_buffer_string(command->string); - // initialize the start node of this command dfa - startnode = start; // parse command into DFA yyparse(); // startnode points to command DFA diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 6eee9c8b65..f78ba060a6 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -101,7 +101,7 @@ DEFUN (grammar_test_match, void grammar_sandbox_init(void); void grammar_sandbox_init() { fprintf(stderr, "reinitializing graph\n"); - nodegraph = new_node(NUL_GN); + nodegraph = new_node(START_GN); install_element (ENABLE_NODE, &grammar_test_cmd); install_element (ENABLE_NODE, &grammar_test_show_cmd); install_element (ENABLE_NODE, &grammar_test_match_cmd);