From 2c3b392a9ad550ca87f6e5172072cd0b70b15f1d Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Wed, 21 Dec 2005 15:45:17 +0000 Subject: [PATCH] * tests/cxx-type.at: Construct a tree, count the parents of shared nodes, and free each node once and only once. Previously, the memory for semantic values was leaked instead. --- ChangeLog | 6 +++ tests/cxx-type.at | 135 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 119 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index a2032398..4bcf0a31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-12-21 Joel E. Denny + + * tests/cxx-type.at: Construct a tree, count the parents of shared + nodes, and free each node once and only once. Previously, the memory + for semantic values was leaked instead. + 2005-12-21 Joel E. Denny * data/glr.c (struct yyGLRStack): If pure, add yyval and yyloc members. diff --git a/tests/cxx-type.at b/tests/cxx-type.at index 818c8f82..dcc0810c 100644 --- a/tests/cxx-type.at +++ b/tests/cxx-type.at @@ -34,12 +34,33 @@ $1 %{ #include - #define YYSTYPE char * + union Node { + struct { + int type; + int parents; + } node_info; + struct { + int type; /* 1 */ + int parents; + char const *form; + union Node *children[3]; + } nterm; + struct { + int type; /* 0 */ + int parents; + char *text; + } term; + }; + typedef union Node Node; + static Node *new_nterm (char const *, Node *, Node *, Node *); + static Node *new_term (char *); + static void free_node (Node *); + static char *node_to_string (Node *); + #define YYSTYPE Node * ]m4_bmatch([$2], [stmtMerge], [ static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);])[ #define YYINITDEPTH 10 #define YYSTACKEXPANDABLE 1 - static char *format (char const *, ...); struct YYLTYPE; #if YYPURE # if YYLSP_NEEDED @@ -66,36 +87,41 @@ $1 %glr-parser -%destructor { free ($$); } TYPENAME ID +%destructor { free_node ($$); } stmt expr decl declarator TYPENAME ID %% prog : | prog stmt { -]AT_LOCATION_IF([ + char *output;]AT_LOCATION_IF([ printf ("%d.%d-%d.%d: ", @2.first_line, @2.first_column, @2.last_line, @2.last_column);])[ - printf ("%s\n", ]$[2); + output = node_to_string (]$[2); + printf ("%s\n", output); + free (output); + free_node (]$[2); } ; stmt : expr ';' $2 { $$ = ]$[1; } | decl $3 - | error ';' { static char error_msg[] = ""; $$ = error_msg; } + | error ';' { $$ = new_nterm ("", 0, 0, 0); } | '@' { YYACCEPT; } ; expr : ID - | TYPENAME '(' expr ')' { $$ = format ("(%s,%s)", ]$[3, ]$[1); } - | expr '+' expr { $$ = format ("+(%s,%s)", ]$[1, ]$[3); } - | expr '=' expr { $$ = format ("=(%s,%s)", ]$[1, ]$[3); } + | TYPENAME '(' expr ')' + { $$ = new_nterm ("(%s,%s)", ]$[3, ]$[1, 0); } + | expr '+' expr { $$ = new_nterm ("+(%s,%s)", ]$[1, ]$[3, 0); } + | expr '=' expr { $$ = new_nterm ("=(%s,%s)", ]$[1, ]$[3, 0); } ; decl : TYPENAME declarator ';' - { $$ = format ("(%s,%s)", ]$[1, ]$[2); } + { $$ = new_nterm ("(%s,%s)", ]$[1, ]$[2, 0); } | TYPENAME declarator '=' expr ';' - { $$ = format ("(%s,%s,%s)", ]$[1, ]$[2, ]$[4); } + { $$ = new_nterm ("(%s,%s,%s)", ]$[1, + ]$[2, ]$[4); } ; declarator : ID @@ -174,14 +200,13 @@ yylex (LEX_PARAMETERS) ungetc (c, stdin); buffer[i++] = 0; tok = isupper ((unsigned char) buffer[0]) ? TYPENAME : ID; - yylval = strcpy ((char *) malloc (i), buffer); + yylval = new_term (strcpy ((char *) malloc (i), buffer)); } else { - static char empty_string[] = ""; colNum += 1; tok = c; - yylval = empty_string; + yylval = 0; } #if YYLSP_NEEDED yylloc.last_column = colNum-1; @@ -203,16 +228,82 @@ yyerror (ERROR_PARAMETERS) fprintf (stderr, "%s\n", s); } +static Node * +new_nterm (char const *form, Node *child0, Node *child1, Node *child2) +{ + Node *node = malloc (sizeof (Node)); + node->nterm.type = 1; + node->nterm.parents = 0; + node->nterm.form = form; + node->nterm.children[0] = child0; + if (child0) + child0->node_info.parents += 1; + node->nterm.children[1] = child1; + if (child1) + child1->node_info.parents += 1; + node->nterm.children[2] = child2; + if (child2) + child2->node_info.parents += 1; + return node; +} + +static Node * +new_term (char *text) +{ + Node *node = malloc (sizeof (Node)); + node->term.type = 0; + node->term.parents = 0; + node->term.text = text; + return node; +} + +static void +free_node (Node *node) +{ + if (!node) + return; + node->node_info.parents -= 1; + /* Free only if 0 (last parent) or -1 (no parents). */ + if (node->node_info.parents > 0) + return; + if (node->node_info.type == 1) + { + free_node (node->nterm.children[0]); + free_node (node->nterm.children[1]); + free_node (node->nterm.children[2]); + } + else + free (node->term.text); + free (node); +} static char * -format (char const *form, ...) +node_to_string (Node *node) { - char buffer[1024]; - va_list args; - va_start (args, form); - vsprintf (buffer, form, args); - va_end (args); - return strcpy ((char *) malloc (strlen (buffer) + 1), buffer); + char *child0; + char *child1; + char *child2; + char *buffer; + if (!node) + { + buffer = malloc (1); + buffer[0] = 0; + } + else if (node->node_info.type == 1) + { + child0 = node_to_string (node->nterm.children[0]); + child1 = node_to_string (node->nterm.children[1]); + child2 = node_to_string (node->nterm.children[2]); + buffer = malloc (strlen (node->nterm.form) + strlen (child0) + + strlen (child1) + strlen (child2) + 1); + sprintf (buffer, node->nterm.form, child0, child1, child2); + free (child0); + free (child1); + free (child2); + } + else + buffer = strdup (node->term.text); + return buffer; } ]] @@ -220,7 +311,7 @@ m4_bmatch([$2], [stmtMerge], [[static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1) { - return format ("(%s,%s)", x0, x1); + return new_nterm ("(%s,%s)", x0, x1, 0); } ]]) ) -- 2.45.2