diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-06 23:19:48 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-06 23:32:28 +0300 |
commit | 18d7db07b9f369901300bf664d07d4b39032ce64 (patch) | |
tree | a25c55b95491a507564b2f62a1c1abeebff636ad | |
parent | 352b268186931579ae8dcc6a19aaaa89547555f5 (diff) | |
download | grecs-18d7db07b9f369901300bf664d07d4b39032ce64.tar.gz grecs-18d7db07b9f369901300bf664d07d4b39032ce64.tar.bz2 |
Redo memory management (1).
* src/grecs-lex.l (grecs_lex_end): Free both lists.
Additional argument specifies if string data should be
freed as well (on error).
(grecs_value_dup): Don't append to string_list.
* src/grecs.h (grecs_value) <v.string>: Remove const qualifier.
<v.arg.v>: Array of struct grecs_value pointers.
(grecs_node)<value>: Move to the union v.
<v.texttab>: Text storage table (for grecs_node_root).
(grecs_lex_end): Fix prototype.
(grecs_value_list_create): New prototype.
(grecs_value_free: New prototype.
(grecs_value_dup): Rename to grecs_value_ptr_from_static.
* src/text.c (grecs_text_table): New function.
* src/tree.c (grecs_value_free): New function.
(grecs_node_free): Reimplement.
(grecs_tree_free): Rewrite using grecs_tree_recurse.
(grecs_string_convert): strdup string values.
(grecs_value_list_create): New function.
* tests/gcffmt.c: Call grecs_tree_free.
* tests/gcfpeek.c: Likewise.
* tests/gcfset.c: Likewise.
-rw-r--r-- | src/format.c | 8 | ||||
-rw-r--r-- | src/grecs-gram.y | 61 | ||||
-rw-r--r-- | src/grecs-lex.l | 9 | ||||
-rw-r--r-- | src/grecs.h | 18 | ||||
-rw-r--r-- | src/lookup.c | 29 | ||||
-rw-r--r-- | src/text.c | 9 | ||||
-rw-r--r-- | src/tree.c | 137 | ||||
-rw-r--r-- | tests/gcffmt.c | 1 | ||||
-rw-r--r-- | tests/gcfpeek.c | 1 | ||||
-rw-r--r-- | tests/gcfset.c | 1 |
10 files changed, 181 insertions, 93 deletions
diff --git a/src/format.c b/src/format.c index 4d4c126..41889b7 100644 --- a/src/format.c +++ b/src/format.c @@ -202,9 +202,9 @@ grecs_format_node_path(struct grecs_node *node, int flags, FILE *fp) fputc(delim ? delim : '.', fp); fprintf(fp, "%s", node->ident); if (node->type == grecs_node_block && - !GRECS_VALUE_EMPTY_P(&node->value)) { + !GRECS_VALUE_EMPTY_P(node->v.value)) { fputc('=', fp); - grecs_format_value(&node->value, flags|GRECS_NODE_FLAG_QUOTE, + grecs_format_value(node->v.value, flags|GRECS_NODE_FLAG_QUOTE, fp); } } @@ -253,7 +253,7 @@ grecs_format_value(struct grecs_value *val, int flags, FILE *fp) for (i = 0; i < val->v.arg.c; i++) { if (i) fputc(' ', fp); - grecs_format_value(&val->v.arg.v[i], flags, fp); + grecs_format_value(val->v.arg.v[i], flags, fp); } } } @@ -289,7 +289,7 @@ grecs_format_node(struct grecs_node *node, int flags, FILE *fp) if (flags & GRECS_NODE_FLAG_VALUE) { if (delim_str) fprintf(fp, "%s", delim_str); - grecs_format_value(&node->value, flags, fp); + grecs_format_value(node->v.value, flags, fp); } } } diff --git a/src/grecs-gram.y b/src/grecs-gram.y index f31305e..3d4cb2f 100644 --- a/src/grecs-gram.y +++ b/src/grecs-gram.y @@ -34,7 +34,7 @@ int grecs_default_port = 0; %union { char *string; - grecs_value_t value; + grecs_value_t svalue, *pvalue; struct grecs_list *list; struct grecs_node *node; struct { struct grecs_node *head, *tail; } node_list; @@ -43,7 +43,8 @@ int grecs_default_port = 0; %token <string> IDENT STRING QSTRING MSTRING %type <string> string slist %type <list> slist0 -%type <value> value tag vallist +%type <svalue> value tag +%type <pvalue> vallist %type <list> values list vlist %type <node> stmt simple block %type <node_list> stmtlist @@ -54,6 +55,7 @@ input : stmtlist { parse_tree = grecs_node_create(grecs_node_root, &grecs_current_locus); + parse_tree->v.texttab = grecs_text_table(); grecs_node_bind(parse_tree, $1.head, 1); } ; @@ -77,7 +79,7 @@ simple : IDENT vallist ';' $$ = grecs_node_create(grecs_node_stmt, &grecs_current_locus); $$->ident = $1; - $$->value = $2; + $$->v.value = $2; } ; @@ -86,7 +88,7 @@ block : IDENT tag '{' stmtlist '}' opt_sc $$ = grecs_node_create(grecs_node_block, &grecs_current_locus); $$->ident = $1; - $$->value = $2; + $$->v.value = grecs_value_ptr_from_static(&$2); grecs_node_bind($$, $4.head, 1); } ; @@ -104,30 +106,32 @@ vallist : vlist size_t n; if ((n = grecs_list_size($1)) == 1) { - $$ = *(grecs_value_t *)grecs_list_index($1, 0); + $$ = grecs_list_index($1, 0); } else { size_t i; struct grecs_list_entry *ep; - $$.type = GRECS_TYPE_ARRAY; - $$.v.arg.c = n; - $$.v.arg.v = grecs_malloc(n * - sizeof($$.v.arg.v[0])); + $$ = grecs_malloc(sizeof($$[0])); + $$->type = GRECS_TYPE_ARRAY; + $$->v.arg.c = n; + $$->v.arg.v = grecs_calloc(n, + sizeof($$->v.arg.v[0])); for (i = 0, ep = $1->head; ep; i++, ep = ep->next) - $$.v.arg.v[i] = *(grecs_value_t *)ep->data; + $$->v.arg.v[i] = ep->data; } + $1->free_entry = NULL; grecs_list_free($1); } ; vlist : value { - $$ = _grecs_simple_list_create(0); - grecs_list_append($$, grecs_value_dup(&$1)); + $$ = grecs_value_list_create(); + grecs_list_append($$, grecs_value_ptr_from_static(&$1)); } | vlist value { - grecs_list_append($1, grecs_value_dup(&$2)); + grecs_list_append($1, grecs_value_ptr_from_static(&$2)); } ; @@ -167,7 +171,7 @@ slist : slist0 slist0 : QSTRING { - $$ = _grecs_simple_list_create(0); + $$ = grecs_list_create(); grecs_list_append($$, $1); } | slist0 QSTRING @@ -193,12 +197,12 @@ list : '(' ')' values : value { - $$ = _grecs_simple_list_create(0); - grecs_list_append($$, grecs_value_dup(&$1)); + $$ = grecs_value_list_create(); + grecs_list_append($$, grecs_value_ptr_from_static(&$1)); } | values ',' value { - grecs_list_append($1, grecs_value_dup(&$3)); + grecs_list_append($1, grecs_value_ptr_from_static(&$3)); $$ = $1; } ; @@ -216,21 +220,6 @@ yyerror(char *s) return 0; } -static void -listel_dispose(void *el) -{ - free(el); -} - -struct grecs_list * -_grecs_simple_list_create(int dispose) -{ - struct grecs_list *lp = grecs_list_create(); - if (dispose) - lp->free_entry = listel_dispose; - return lp; -} - int grecs_vasprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap) { @@ -301,8 +290,10 @@ grecs_parse(const char *name) return NULL; parse_tree = NULL; rc = yyparse(); - grecs_lex_end(); - if (grecs_error_count) { + if (grecs_error_count) + rc = 1; + grecs_lex_end(rc); + if (rc) { grecs_tree_free(parse_tree); parse_tree = NULL; } @@ -315,7 +306,7 @@ grecs_gram_trace(int n) yydebug = n; } - + diff --git a/src/grecs-lex.l b/src/grecs-lex.l index 97571e6..32a8913 100644 --- a/src/grecs-lex.l +++ b/src/grecs-lex.l @@ -210,8 +210,12 @@ grecs_lex_begin(const char *name) } void -grecs_lex_end() +grecs_lex_end(int err) { + if (!err) + string_list->free_entry = NULL; + grecs_list_free(string_list); + grecs_list_clear(line_acc); } static int @@ -424,10 +428,9 @@ grecs_lex_trace(int n) } grecs_value_t * -grecs_value_dup(grecs_value_t *input) +grecs_value_ptr_from_static(grecs_value_t *input) { grecs_value_t *ptr = grecs_malloc(sizeof(*ptr)); - grecs_list_append(string_list, ptr); *ptr = *input; return ptr; } diff --git a/src/grecs.h b/src/grecs.h index 41f88d9..f6b88ab 100644 --- a/src/grecs.h +++ b/src/grecs.h @@ -105,10 +105,10 @@ typedef struct grecs_value { int type; union { struct grecs_list *list; - const char *string; + char *string; struct { size_t c; - struct grecs_value *v; + struct grecs_value **v; } arg; } v; } grecs_value_t; @@ -131,7 +131,10 @@ typedef struct grecs_node { struct grecs_node *next; struct grecs_node *prev; char *ident; - struct grecs_value value; + union { + struct grecs_value *value; + struct grecs_symtab *texttab; + } v; } grecs_node_t; typedef int (*grecs_callback_fn)( @@ -173,7 +176,7 @@ void *grecs_realloc(void *ptr, size_t size); void grecs_alloc_die(void); char *grecs_strdup(const char *str); -grecs_value_t *grecs_value_dup(grecs_value_t *input); +grecs_value_t *grecs_value_ptr_from_static(grecs_value_t *input); extern void (*grecs_print_diag_fun)(grecs_locus_t *, int, int, const char*); @@ -185,10 +188,11 @@ void grecs_gram_trace(int n); void grecs_lex_trace(int n); int grecs_lex_begin(const char*); -void grecs_lex_end(void); +void grecs_lex_end(int err); struct grecs_node *grecs_parse(const char *name); struct grecs_list *_grecs_simple_list_create(int dispose); +struct grecs_list *grecs_value_list_create(void); void grecs_line_begin(void); void grecs_line_add(const char *text, size_t len); @@ -227,6 +231,7 @@ void grecs_preproc_extrn_shutdown(pid_t pid); char *grecs_install_text(const char *str); void grecs_destroy_text(void); +struct grecs_symtab *grecs_text_table(void); void grecs_include_path_setup(const char *dir, ...); void grecs_include_path_setup_v(char **dirs); @@ -300,8 +305,9 @@ int grecs_symtab_enumerate(struct grecs_symtab *st, size_t grecs_symtab_count_entries(struct grecs_symtab *st); +void grecs_value_free(struct grecs_value *val); void grecs_node_free(struct grecs_node *node); -void grecs_tree_free(struct grecs_node *node); +int grecs_tree_free(struct grecs_node *node); enum grecs_tree_recurse_op { grecs_tree_recurse_set, diff --git a/src/lookup.c b/src/lookup.c index b2621da..32ba2df 100644 --- a/src/lookup.c +++ b/src/lookup.c @@ -52,7 +52,7 @@ _grecs_array_eq(struct grecs_value *a, struct grecs_value *b) return 0; for (i = 0; i < a->v.arg.c; i++) - if (!grecs_value_eq(&a->v.arg.v[i], &b->v.arg.v[i])) + if (!grecs_value_eq(a->v.arg.v[i], b->v.arg.v[i])) return 0; return 1; } @@ -138,7 +138,7 @@ free_value_mem(struct grecs_value *p) case GRECS_TYPE_ARRAY: { size_t i; for (i = 0; i < p->v.arg.c; i++) - free_value_mem(&p->v.arg.v[i]); + free_value_mem(p->v.arg.v[i]); } } } @@ -192,11 +192,11 @@ parse_label(const char *str) } else { val->type = GRECS_TYPE_ARRAY; val->v.arg.c = ws.ws_wordc; - val->v.arg.v = grecs_malloc(ws.ws_wordc * + val->v.arg.v = grecs_calloc(ws.ws_wordc, sizeof(val->v.arg.v[0])); for (i = 0; i < ws.ws_wordc; i++) { - val->v.arg.v[i].type = GRECS_TYPE_STRING; - val->v.arg.v[i].v.string = ws.ws_wordv[i]; + val->v.arg.v[i]->type = GRECS_TYPE_STRING; + val->v.arg.v[i]->v.string = ws.ws_wordv[i]; } } ws.ws_wordc = 0; @@ -235,7 +235,8 @@ node_finder(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data) return grecs_tree_recurse_ok; if (strcmp(fdptr->argv[fdptr->tag], node->ident) == 0 - && (!fdptr->label || grecs_value_eq(fdptr->label, &node->value))) { + && (!fdptr->label || + grecs_value_eq(fdptr->label, node->v.value))) { fdptr->tag++; if (fdptr->tag == fdptr->argc) { fdptr->node = node; @@ -287,12 +288,9 @@ grecs_node_from_path(const char *path, const char *value) dn->ident = argv[argc - 1]; if (value) { struct grecs_value *gval = parse_label(value); - dn->value = *gval; - free(gval); //FIXME - } else { - dn->value.type = GRECS_TYPE_STRING; - dn->value.v.string = NULL; - } + dn->v.value = gval; + } else + dn->v.value = NULL; for (i = argc - 2; i >= 0; i--) { struct grecs_value *label = NULL; @@ -313,10 +311,9 @@ grecs_node_from_path(const char *path, const char *value) node = grecs_node_create(grecs_node_block, NULL); node->ident = argv[i]; - if (label) { - node->value = *label; - free(label); //FIXME - } + if (label) + node->v.value = label; + node->down = dn; if (dn) dn->up = node; @@ -49,3 +49,12 @@ grecs_destroy_text() { grecs_symtab_free(text_table); } + +struct grecs_symtab * +grecs_text_table() +{ + struct grecs_symtab *tmp = text_table; + text_table = NULL; + return tmp; +} + @@ -25,8 +25,33 @@ #include <arpa/inet.h> #include <netdb.h> #include <stdlib.h> +#include <errno.h> #include "grecs.h" +void +grecs_value_free(struct grecs_value *val) +{ + int i; + + if (!val) + return; + switch (val->type) { + case GRECS_TYPE_STRING: + free(val->v.string); + break; + + case GRECS_TYPE_LIST: + grecs_list_free(val->v.list); + break; + + case GRECS_TYPE_ARRAY: + for (i = 0; i < val->v.arg.c; i++) + grecs_value_free(val->v.arg.v[i]); + free(val->v.arg.v); + } + free(val); +} + struct grecs_node * grecs_node_create(enum grecs_node_type type, grecs_locus_t *loc) { @@ -83,6 +108,23 @@ grecs_node_unlink(struct grecs_node *node) } +static void +listel_dispose(void *el) +{ + free(el); +} + +struct grecs_list * +_grecs_simple_list_create(int dispose) +{ + struct grecs_list *lp = grecs_list_create(); + if (dispose) + lp->free_entry = listel_dispose; + return lp; +} + + + static enum grecs_tree_recurse_res _tree_recurse(struct grecs_node *node, grecs_tree_recursor_t recfun, @@ -143,20 +185,44 @@ grecs_tree_recurse(struct grecs_node *node, grecs_tree_recursor_t recfun, void grecs_node_free(struct grecs_node *node) { - /*FIXME: value*/ + if (!node) + return; + switch (node->type) { + case grecs_node_root: + grecs_symtab_free(node->v.texttab); + break; + default: + grecs_value_free(node->v.value); + } free(node); } -void -grecs_tree_free(struct grecs_node *node) +static enum grecs_tree_recurse_res +freeproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data) { - while (node) { - struct grecs_node *next = node->next; - if (node->down) - grecs_tree_free(node->down); + switch (op) { + case grecs_tree_recurse_set: + case grecs_tree_recurse_post: + grecs_node_unlink(node); grecs_node_free(node); - node = next; + break; + case grecs_tree_recurse_pre: + /* descend into the subtree */ + break; + } + return grecs_tree_recurse_ok; +} + +int +grecs_tree_free(struct grecs_node *node) +{ + /* FIXME: Check if that's a node_type_root */ + if (node->type != grecs_node_root) { + errno = EINVAL; + return 1; } + grecs_tree_recurse(node, freeproc, NULL); + return 0; } @@ -449,7 +515,7 @@ grecs_string_convert(void *target, enum grecs_data_type type, abort(); case grecs_type_string: - *(const char**)target = string; + *(const char**)target = grecs_strdup(string); break; case grecs_type_short: @@ -622,10 +688,11 @@ grecs_process_ident(struct grecs_keyword *kwp, grecs_value_t *value, __FILE__, __LINE__, type); abort(); } - - list = grecs_list_create(); - list->cmp = grecs_prop_tab[type].cmp; + list = _grecs_simple_list_create( + type == grecs_type_string); + list->cmp = grecs_prop_tab[type].cmp; + for (ep = value->v.list->head; ep; ep = ep->next) { const grecs_value_t *vp = ep->data; @@ -635,7 +702,7 @@ grecs_process_ident(struct grecs_keyword *kwp, grecs_value_t *value, kwp->ident, num); else if (type == grecs_type_string) grecs_list_append(list, - (void*) vp->v.string); + grecs_strdup(vp->v.string)); else { void *ptr = grecs_malloc(size); if (grecs_string_convert(ptr, @@ -674,7 +741,8 @@ grecs_process_ident(struct grecs_keyword *kwp, grecs_value_t *value, grecs_list_append(list, value->v.string); else { ptr = grecs_malloc(size); - if (grecs_string_convert(ptr, type, value->v.string, locus)) { + if (grecs_string_convert(ptr, type, + value->v.string, locus)) { free(ptr); grecs_list_free(list); return; @@ -710,7 +778,7 @@ stmt_begin(struct nodeproc_closure *clos, if (kwp->callback(grecs_callback_section_begin, &node->locus, target, - &node->value, + node->v.value, &kwp->callback_data)) clos->cursect = &fake; } else @@ -758,7 +826,7 @@ nodeproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data) grecs_error(&node->locus, 0, _("Unknown keyword")); return grecs_tree_recurse_skip; } - grecs_process_ident(kwp, &node->value, CURRENT_BASE(clos), + grecs_process_ident(kwp, node->v.value, CURRENT_BASE(clos), &node->locus); break; @@ -806,12 +874,27 @@ grecs_node_eq(struct grecs_node *a, struct grecs_node *b) if (strcmp(a->ident, b->ident)) return 1; if (a->type == grecs_node_block && - !grecs_value_eq(&a->value, &b->value)) + !grecs_value_eq(a->v.value, b->v.value)) return 1; return 0; } static void +free_value_entry(void *ptr) +{ + struct grecs_value *v = ptr; + grecs_value_free(v); +} + +struct grecs_list * +grecs_value_list_create() +{ + struct grecs_list *list = grecs_list_create(); + list->free_entry = free_value_entry; + return list; +} + +static void value_to_list(struct grecs_value *val) { struct grecs_list *list; @@ -819,18 +902,15 @@ value_to_list(struct grecs_value *val) if (val->type != GRECS_TYPE_LIST) return; - list = _grecs_simple_list_create(0);/* FIXME: this relies on - grecs_value_dup registering its - return in string_list */ + list = grecs_value_list_create(); switch (val->type) { case GRECS_TYPE_STRING: - grecs_list_append(list, grecs_value_dup(val)); + grecs_list_append(list, val); break; case GRECS_TYPE_ARRAY: for (i = 0; i < val->v.arg.c; i++) - grecs_list_append(list, - grecs_value_dup(&val->v.arg.v[i])); + grecs_list_append(list, val->v.arg.v[i]); } val->type = GRECS_TYPE_LIST; val->v.list = list; @@ -839,9 +919,9 @@ value_to_list(struct grecs_value *val) static void node_aggregate_stmt(struct grecs_node *dst, struct grecs_node *src, int type) { - value_to_list(&dst->value); - value_to_list(&src->value); - grecs_list_add(dst->value.v.list, src->value.v.list); + value_to_list(dst->v.value); + value_to_list(src->v.value); + grecs_list_add(dst->v.value->v.list, src->v.value->v.list); } static void @@ -851,9 +931,8 @@ node_merge_stmt(struct grecs_node *to_node, struct grecs_node *from_node, if (kwp && GRECS_IS_LIST(kwp->type) && (kwp->type & GRECS_AGGR)) node_aggregate_stmt(to_node, from_node, kwp->type); else { - /*FIXME: grecs_value_free(from_node->value) */ - from_node->value.type = GRECS_TYPE_STRING; - from_node->value.v.string = NULL; + grecs_value_free(from_node->v.value); + from_node->v.value = NULL; } } diff --git a/tests/gcffmt.c b/tests/gcffmt.c index 29aa69a..64a4f63 100644 --- a/tests/gcffmt.c +++ b/tests/gcffmt.c @@ -80,5 +80,6 @@ main(int argc, char **argv) grecs_format_node(node, flags, stdout); fputc('\n', stdout); } + grecs_tree_free(tree); exit(0); } diff --git a/tests/gcfpeek.c b/tests/gcfpeek.c index 905f4ca..5ff8583 100644 --- a/tests/gcfpeek.c +++ b/tests/gcfpeek.c @@ -79,5 +79,6 @@ main(int argc, char **argv) grecs_format_node(node, flags, stdout); fputc('\n', stdout); } + grecs_tree_free(tree); exit(rc); } diff --git a/tests/gcfset.c b/tests/gcfset.c index 8d5b464..f41d67f 100644 --- a/tests/gcfset.c +++ b/tests/gcfset.c @@ -219,6 +219,7 @@ main(int argc, char **argv) if (grecs_tree_process(tree, main_kwtab)) exit(2); + grecs_tree_free(tree); printf("Global settings:\n"); printf("scalar = %s\n", S(scalar_string)); |