diff options
| author | Mattias Andrée <maandree@kth.se> | 2024-07-19 01:29:42 +0200 |
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2024-07-19 01:29:42 +0200 |
| commit | 4294ec0ed06ee34920c9edaeebaeb8b65c720791 (patch) | |
| tree | e0cded59452597c04fb38f403745a384675cb5f9 /libnormalform_free.c | |
| download | libnormalform-4294ec0ed06ee34920c9edaeebaeb8b65c720791.tar.gz libnormalform-4294ec0ed06ee34920c9edaeebaeb8b65c720791.tar.bz2 libnormalform-4294ec0ed06ee34920c9edaeebaeb8b65c720791.tar.xz | |
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
| -rw-r--r-- | libnormalform_free.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/libnormalform_free.c b/libnormalform_free.c new file mode 100644 index 0000000..3bce4df --- /dev/null +++ b/libnormalform_free.c @@ -0,0 +1,123 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +/** + * Recursively deallocate a `LIBNORMALFORM_SENTENCE *` + * according to `libnormalform_free` + * + * @param this The object to deallocate + */ +NONNULL_INPUT static void +free_sentence(LIBNORMALFORM_SENTENCE *this) +{ + LIBNORMALFORM_SENTENCE *head = NULL, *a, *b; + + if (--this->refcount) + return; + + do { + if (this->atom && !--this->atom->refcount) + free(this->atom); + + if (IS_BRANCH(this)) { + a = LEFT(this); + b = RIGHT(this); + if (b && !--b->refcount) + PUSH(&head, b); + push_a: + if (a && !--a->refcount) + PUSH(&head, a); + } else if (this->type == TYPE_TRANS) { + a = this->data.trans.input; + goto push_a; + } + + free(this); + } while (POP(&head, &this)); +} + + +/** + * Recursively deallocate a `LIBNORMALFORM_SENTENCE *` + * according to `libnormalform_free`, but do not + * deallocate the pointer itself + * + * @param this The object to deallocate + */ +NONNULL_INPUT static void +destroy_term(struct libnormalform_term *this) +{ + switch (this->type) { + case LIBNORMALFORM_DISJUNCTION: + case LIBNORMALFORM_CONJUNCTION: + case LIBNORMALFORM_EXCLUSIVE_DISJUNCTION: + while (this->term.clause.nterms) + destroy_term(&this->term.clause.terms[--this->term.clause.nterms]); + free(this->term.clause.terms); + free(this); + break; + + case LIBNORMALFORM_TRANSFORMATION: + free(this->term.transformation.sentence); + free(this); + return; + + case LIBNORMALFORM_FOR_ALL: + case LIBNORMALFORM_NEGATED_FOR_ALL: + case LIBNORMALFORM_FOR_ANY: + case LIBNORMALFORM_NEGATED_FOR_ANY: + case LIBNORMALFORM_FOR_ONE: + case LIBNORMALFORM_NEGATED_FOR_ONE: + destroy_term(this->term.qualification.antecedent); + destroy_term(this->term.qualification.predicate); + free(this->term.qualification.antecedent); + free(this->term.qualification.predicate); + /* fall through */ + + case LIBNORMALFORM_VARIABLE: + case LIBNORMALFORM_NEGATED_VARIABLE: + case LIBNORMALFORM_FUNCTION: + case LIBNORMALFORM_NEGATED_FUNCTION: + free(this); + break; + + default: + abort(); + } +} + + +void +(libnormalform_free)(void *this) +{ + if (!this) + return; + + if (*(enum libnormalform_term_type *)this >= SENTENCE_TYPE_OFFSET) { + free_sentence(this); + } else { + destroy_term(this); + free(this); + } +} + + +#else + + +int +main(void) +{ + TEST_BEGIN; + + libnormalform_free(NULL); + + /* Tested in other tests */ + + TEST_END; +} + + +#endif |
