From 4b69ab87c6bc7dd4af853855a09679d6d4682910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind?= Date: Sun, 13 Feb 2022 17:43:10 +0100 Subject: [PATCH] Added recursive free of nodes --- exercises/02/vslc/src/tree.c | 96 ++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 exercises/02/vslc/src/tree.c diff --git a/exercises/02/vslc/src/tree.c b/exercises/02/vslc/src/tree.c new file mode 100644 index 0000000..108c644 --- /dev/null +++ b/exercises/02/vslc/src/tree.c @@ -0,0 +1,96 @@ +#include + +static void node_print ( node_t *root, int nesting ); +static void node_finalize ( node_t *discard ); +static void destroy_subtree ( node_t *discard ); + + +/* External interface */ +void +destroy_syntax_tree ( void ) +{ + destroy_subtree ( root ); +} + + +void +print_syntax_tree ( void ) +{ + node_print ( root, 0 ); +} + + +void +node_init (node_t *nd, node_index_t type, void *data, uint64_t n_children, ...) +{ + // Copy the type + nd->type = type; + // Copy n_children + nd->n_children = n_children; + + /* + The memory for this data needs to be + allocated somewhere not here, since this + function does not know the type. + */ + nd->data = data; + + // Prepeare the VA list + va_list list_children; + va_start(list_children, n_children); + + // Create memory region for the children pointers + nd->children = malloc(n_children * sizeof(node_t*)); + + // Populate the memory with pointers to children + for (int i = 0; i < n_children; i++) + nd->children[i] = va_arg(list_children, node_t*); +} + + +static void +node_print ( node_t *root, int nesting ) +{ + if ( root != NULL ) + { + printf ( "%*c%s", nesting, ' ', node_string[root->type] ); + if ( root->type == IDENTIFIER_DATA || + root->type == STRING_DATA || + root->type == EXPRESSION ) + printf ( "(%s)", (char *) root->data ); + else if ( root->type == NUMBER_DATA ) + printf ( "(%ld)", *((int64_t *)root->data) ); + putchar ( '\n' ); + for ( int64_t i=0; in_children; i++ ) + node_print ( root->children[i], nesting+1 ); + } + else + printf ( "%*c%p\n", nesting, ' ', root ); +} + +// The discard should have zero children here. If not -> MEMORY LEAK +static void +node_finalize ( node_t *discard ) +{ + // Free the data and the children lists. + free(discard->data); + free(discard->children); + free(discard); +} + + +static void +destroy_subtree ( node_t *discard ) +{ + // Don't do anything if discard is nullptr + if (discard == NULL) + return; + + // This will not run if n_children is zero + // If non-zero, destroy all child recursivly + while (discard->n_children--) + destroy_subtree(discard->children[discard->n_children]); + + // Finally, destroy yourself + node_finalize(discard); +}