#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); }