diff options
-rw-r--r-- | src/interfaces/ecpg/preproc/ecpg.header | 17 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/ecpg.trailer | 11 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/type.c | 15 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/type.h | 5 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/variable.c | 7 |
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); |