/*-------------------------------------------------------------------------*/ void count_struct_type_ref (struct_type_t * pSType) /* Count all references held by struct typeobject <pSType> */ { unsigned short num; pSType->ref++; if (test_memory_reference(pSType)) { note_malloced_block_ref(pSType); if (pSType->member) note_malloced_block_ref(pSType->member); count_struct_name_ref(pSType->name); /* If we're a newer definition, remember us in the name. */ if (!pSType->name->current || pSType->name->current->prog_id < pSType->prog_id) pSType->name->current = pSType; if (pSType->unique_name) count_ref_from_string(pSType->unique_name); if (pSType->base) count_struct_type_ref(pSType->base); for (num = struct_t_size(pSType); num-- > 0; ) { count_ref_from_string(pSType->member[num].name); count_lpctype_ref(pSType->member[num].type); } } } /* count_struct_type_ref() */
/*-------------------------------------------------------------------------*/ void count_struct_name_ref (struct_name_t * pSName) /* Count all references held by struct name object <pSName> */ { pSName->ref++; if (test_memory_reference(pSName)) { note_malloced_block_ref(pSName); count_ref_from_string(pSName->name); count_ref_from_string(pSName->prog_name); } } /* count_struct_name_ref() */
/*-------------------------------------------------------------------------*/ void count_struct_ref (struct_t * pStruct) /* Count all references held by struct <pStruct> */ { pStruct->ref++; if (test_memory_reference(pStruct)) { note_malloced_block_ref(pStruct); count_struct_type_ref(pStruct->type); if (struct_size(pStruct)) { count_ref_in_vector(pStruct->member, struct_size(pStruct)); } } } /* count_struct_ref() */
/*-------------------------------------------------------------------------*/ void count_lpctype_ref (lpctype_t *t) /* Count all references by <t>. */ { bool repair = false; if (!t) return; if (t->t_static) { /* Just repair not-refcounted references. */ repair = true; } else { t->ref++; if (test_memory_reference(t)) { note_malloced_block_ref(t); repair = true; switch(t->t_class) { case TCLASS_PRIMARY: break; /* Can't happen. See above. */ case TCLASS_STRUCT: if (t->t_struct) { count_struct_type_ref(t->t_struct); t->t_struct->lpctype = t; } break; case TCLASS_ARRAY: count_lpctype_ref(t->t_array.element); break; case TCLASS_UNION: count_lpctype_ref(t->t_union.head); count_lpctype_ref(t->t_union.member); break; } } } if (repair) { switch(t->t_class) { case TCLASS_PRIMARY: case TCLASS_STRUCT: break; /* Nothing to do. */ case TCLASS_ARRAY: t->t_array.element->array_of = t; break; case TCLASS_UNION: /* Did we already set the pointers back? */ if (t->t_union.next == NULL) { t->t_union.next = t->t_union.head->unions_of; t->t_union.head->unions_of = t; } break; } } } /* count_lpctype_ref() */
/*-------------------------------------------------------------------------*/ void remove_unreferenced_structs (void) /* Free all structs in the table which are not marked as referenced. * This function must be called before freeing all unreferenced strings! */ { size_t num; if (!table || !table_size) return; for (num = 0; num < table_size; num++) { struct_name_t * this, * prev; for (prev = NULL, this = table[num]; this != NULL; ) { if (!test_memory_reference(this)) { prev = this; this = this->next; } else { struct_name_t * next = this->next; if (prev) prev->next = next; else table[num] = next; num_types--; /* Now we deallocate the memory for the struct name * structure. */ size_struct_type -= STRUCT_NAME_MEMSIZE; dprintf2(gcollect_outfd, "struct name %x '%s' was left " "unreferenced, freeing now.\n" , (p_int) this , (p_int) get_txt(this->name) ); /* Reference all strings and free them, to avoid unnecessary * 'string unreferenced' diagnostics. */ count_ref_from_string(this->name); free_mstring(this->name); count_ref_from_string(this->prog_name); free_mstring(this->prog_name); /* Reference the memory (to update its flags) and free it */ note_malloced_block_ref(this); xfree(this); this = next; } } } /* for (num) */ } /* remove_unreferenced_structs() */