summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.header17
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.trailer11
-rw-r--r--src/interfaces/ecpg/preproc/type.c15
-rw-r--r--src/interfaces/ecpg/preproc/type.h5
-rw-r--r--src/interfaces/ecpg/preproc/variable.c7
5 files changed, 42 insertions, 13 deletions
diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header
index a415780faff..e79b6b0de8c 100644
--- a/src/interfaces/ecpg/preproc/ecpg.header
+++ b/src/interfaces/ecpg/preproc/ecpg.header
@@ -44,7 +44,19 @@ static char *actual_startline[STRUCT_DEPTH];
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 */
@@ -507,11 +519,12 @@ add_typedef(const char *name, const char *dimension, const char *length,
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;
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer
index 424903f76e0..321bcbccac7 100644
--- a/src/interfaces/ecpg/preproc/ecpg.trailer
+++ b/src/interfaces/ecpg/preproc/ecpg.trailer
@@ -755,6 +755,7 @@ var_type: simple_type
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);
}
}
@@ -882,6 +883,7 @@ var_type: simple_type
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);
}
}
@@ -904,6 +906,7 @@ var_type: simple_type
$$.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
@@ -913,6 +916,7 @@ var_type: simple_type
$$.type_dimension = "-1";
$$.type_index = "-1";
$$.type_sizeof = "";
+ ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = NULL;
}
}
@@ -928,6 +932,7 @@ enum_definition: '{' c_list '}'
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");
@@ -969,12 +974,13 @@ struct_union_type_with_symbol: s_struct_union_symbol
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, "}");
@@ -984,6 +990,7 @@ struct_union_type_with_symbol: s_struct_union_symbol
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");
diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c
index 7f52521dbf1..9f6dacd2aea 100644
--- a/src/interfaces/ecpg/preproc/type.c
+++ b/src/interfaces/ecpg/preproc/type.c
@@ -94,13 +94,14 @@ 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)
+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;
}
@@ -622,7 +623,7 @@ ECPGfree_struct_member(struct ECPGstruct_member *rm)
rm = rm->next;
free(p->name);
- free(p->type);
+ ECPGfree_type(p->type);
free(p);
}
}
@@ -643,14 +644,13 @@ ECPGfree_type(struct ECPGtype *type)
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:
@@ -662,6 +662,9 @@ ECPGfree_type(struct ECPGtype *type)
break;
}
}
+ free(type->type_name);
+ free(type->size);
+ free(type->struct_sizeof);
free(type);
}
diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h
index 90126551d19..3d99e1703de 100644
--- a/src/interfaces/ecpg/preproc/type.h
+++ b/src/interfaces/ecpg/preproc/type.h
@@ -38,8 +38,9 @@ void ECPGmake_struct_member(const char *name, struct ECPGtype *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. */
diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c
index ac80d2c0209..e9bdfe56456 100644
--- a/src/interfaces/ecpg/preproc/variable.c
+++ b/src/interfaces/ecpg/preproc/variable.c
@@ -277,7 +277,12 @@ remove_typedefs(int brace_level)
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);