ECPGfree_type() and related functions were quite incomplete
about removing subsidiary data structures. Possibly this is
because ecpg wasn't careful to make sure said data structures
always had their own storage. Previous es in this series
cleaned up a lot of that, and I had to add a couple more
mm_strdup's here.
Also, ecpg.trailer tended to overwrite struct_member_list[struct_level]
without bothering to free up its previous contents, thus potentially
ing a lot of struct-member-related storage. Add
ECPGfree_struct_member() calls at appropriate points.
Discussion: https://postgr.es/m/
2011420.
1713493114@sss.pgh.pa.us
static int varchar_counter = 1;
static int bytea_counter = 1;
-/* temporarily store struct members while creating the data structure */
+/*
+ * We temporarily store struct members here while parsing struct declarations.
+ * The struct_member_list (at a given nesting depth) is constructed while
+ * scanning the fields within "struct { .... }", but we can't remove it upon
+ * seeing the right brace. It's kept around and copied into the variables
+ * or typedefs that follow, in order to handle cases like
+ * "struct foo { ... } foovar1, foovar2;". We recycle the storage only
+ * upon closing the current nesting level or starting the next struct
+ * declaration within the same nesting level.
+ * For cases like "struct foo foovar1, foovar2;", we copy the saved struct
+ * field list for the typedef or struct tag into the struct_member_list
+ * global variable, and then copy it again to the newly-declared variables.
+ */
struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = {NULL};
/* also store struct type so we can do a sizeof() later */
this->name = mm_strdup(name);
this->brace_level = braces_open;
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
+ this->type->type_storage = NULL;
this->type->type_enum = type_enum;
this->type->type_str = mm_strdup(name);
this->type->type_dimension = mm_strdup(dimension); /* dimension of array */
this->type->type_index = mm_strdup(length); /* length of string */
- this->type->type_sizeof = ECPGstruct_sizeof;
+ this->type->type_sizeof = ECPGstruct_sizeof ? mm_strdup(ECPGstruct_sizeof) : NULL;
this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
else
$$.type_sizeof = cat_str(3, "sizeof(", this->name, ")");
+ ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
}
}
else
$$.type_sizeof = cat_str(3, "sizeof(", this->name, ")");
+ ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
}
}
$$.type_dimension = this->type->type_dimension;
$$.type_index = this->type->type_index;
$$.type_sizeof = this->type->type_sizeof;
+ ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
}
else
$$.type_dimension = "-1";
$$.type_index = "-1";
$$.type_sizeof = "";
+ ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = NULL;
}
}
struct_union_type_with_symbol: s_struct_union_symbol
{
+ ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
this->name = mm_strdup(su_type.type_str);
this->brace_level = braces_open;
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
+ this->type->type_storage = NULL;
this->type->type_enum = su_type.type_enum;
this->type->type_str = mm_strdup(su_type.type_str);
this->type->type_dimension = mm_strdup("-1"); /* dimension of array */
this->type->type_index = mm_strdup("-1"); /* length of string */
- this->type->type_sizeof = ECPGstruct_sizeof;
- this->struct_member_list = struct_member_list[struct_level];
+ this->type->type_sizeof = ECPGstruct_sizeof ? mm_strdup(ECPGstruct_sizeof) : NULL;
+ this->struct_member_list = ECPGstruct_member_dup(struct_member_list[struct_level]);
types = this;
@$ = cat_str(4, su_type.type_str, "{", @4, "}");
struct_union_type: struct_union_type_with_symbol
| s_struct_union
{
+ ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
}
struct ECPGtype *
-ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type, char *type_name, char *struct_sizeof)
+ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type,
+ const char *type_name, const char *struct_sizeof)
{
struct ECPGtype *ne = ECPGmake_simple_type(type, "1", 0);
ne->type_name = mm_strdup(type_name);
ne->u.members = ECPGstruct_member_dup(rm);
- ne->struct_sizeof = struct_sizeof;
+ ne->struct_sizeof = mm_strdup(struct_sizeof);
return ne;
}
rm = rm->next;
free(p->name);
- free(p->type);
+ ECPGfree_type(p->type);
free(p);
}
}
case ECPGt_struct:
case ECPGt_union:
/* Array of structs. */
- ECPGfree_struct_member(type->u.element->u.members);
- free(type->u.element);
+ ECPGfree_type(type->u.element);
break;
default:
if (!IS_SIMPLE_TYPE(type->u.element->type))
base_yyerror("internal error: unknown datatype, please report this to <" PACKAGE_BUGREPORT ">");
- free(type->u.element);
+ ECPGfree_type(type->u.element);
}
break;
case ECPGt_struct:
break;
}
}
+ free(type->type_name);
+ free(type->size);
+ free(type->struct_sizeof);
free(type);
}
struct ECPGtype *ECPGmake_simple_type(enum ECPGttype type, const char *size, int counter);
struct ECPGtype *ECPGmake_array_type(struct ECPGtype *type, const char *size);
struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *rm,
- enum ECPGttype type, char *type_name,
- char *struct_sizeof);
+ enum ECPGttype type,
+ const char *type_name,
+ const char *struct_sizeof);
struct ECPGstruct_member *ECPGstruct_member_dup(struct ECPGstruct_member *rm);
/* Frees a type. */
prev->next = p->next;
if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
- free(p->struct_member_list);
+ ECPGfree_struct_member(p->struct_member_list);
+ free(p->type->type_storage);
+ free(p->type->type_str);
+ free(p->type->type_dimension);
+ free(p->type->type_index);
+ free(p->type->type_sizeof);
free(p->type);
free(p->name);
free(p);