From 4daf2527a0b8ed7df296ce770bf9c65da0a872ad Mon Sep 17 00:00:00 2001 From: Daniel Holden Date: Fri, 20 Sep 2013 12:51:04 +0100 Subject: [PATCH] Fixed memory leaks etc --- .gitignore | 1 + mpc.c | 271 ++++++++++++++++++++++++++++++-------------------- mpc.h | 5 +- tests/ident.c | 1 + tests/math.c | 5 + 5 files changed, 171 insertions(+), 112 deletions(-) diff --git a/.gitignore b/.gitignore index 9bb4877..06a9a1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *~ *.exe +test diff --git a/mpc.c b/mpc.c index dea16dd..7b0bd9a 100644 --- a/mpc.c +++ b/mpc.c @@ -36,6 +36,17 @@ static mpc_err_t* mpc_err_new(mpc_state_t s, char* expected) { return x; } +void mpc_err_delete(mpc_err_t* x) { + + int i; + for (i = 0; i < x->expected_num; i++) { + free(x->expected[i]); + } + + free(x->expected); + free(x); +} + static bool mpc_err_contains_expected(mpc_err_t* x, char* expected) { int i; @@ -56,17 +67,6 @@ static void mpc_err_add_expected(mpc_err_t* x, char* expected) { } -void mpc_err_delete(mpc_err_t* x) { - - int i; - for (i = 0; i < x->expected_num; i++) { - free(x->expected[i]); - } - - free(x->expected); - free(x); -} - void mpc_err_print(mpc_err_t* x) { mpc_err_print_to(x, stdout); } @@ -132,6 +132,17 @@ static mpc_err_t* mpc_err_either(mpc_err_t* x, mpc_err_t* y) { } +static mpc_err_t* mpc_err_or(mpc_err_t** x, int n) { + mpc_err_t* e = x[0]; + + int i; + for (i = 1; i < n; i++) { + e = mpc_err_either(e, x[i]); + } + + return e; +} + static mpc_err_t* mpc_err_many1(mpc_err_t* x) { /* TODO: Collapse expected list and add `one or more` prefix */ return x; @@ -325,30 +336,31 @@ bool mpc_input_string(mpc_input_t* i, const char* c, char** o) { */ enum { - MPC_TYPE_PASS = 0, - MPC_TYPE_FAIL = 1, - MPC_TYPE_LIFT = 2, - MPC_TYPE_EXPECT = 3, + MPC_TYPE_UNDEFINED = 0, + MPC_TYPE_PASS = 1, + MPC_TYPE_FAIL = 2, + MPC_TYPE_LIFT = 3, + MPC_TYPE_EXPECT = 4, - MPC_TYPE_ANY = 4, - MPC_TYPE_SINGLE = 5, - MPC_TYPE_ONEOF = 6, - MPC_TYPE_NONEOF = 7, - MPC_TYPE_RANGE = 8, - MPC_TYPE_SATISFY = 9, - MPC_TYPE_STRING = 10, + MPC_TYPE_ANY = 5, + MPC_TYPE_SINGLE = 6, + MPC_TYPE_ONEOF = 7, + MPC_TYPE_NONEOF = 8, + MPC_TYPE_RANGE = 9, + MPC_TYPE_SATISFY = 10, + MPC_TYPE_STRING = 11, - MPC_TYPE_APPLY = 11, + MPC_TYPE_APPLY = 12, - MPC_TYPE_MAYBE = 12, - MPC_TYPE_MANY = 13, - MPC_TYPE_MANY1 = 14, - MPC_TYPE_COUNT = 15, + MPC_TYPE_MAYBE = 13, + MPC_TYPE_MANY = 14, + MPC_TYPE_MANY1 = 15, + MPC_TYPE_COUNT = 16, - MPC_TYPE_EITHER = 16, - MPC_TYPE_ALSO = 17, - MPC_TYPE_OR = 18, - MPC_TYPE_AND = 19, + MPC_TYPE_EITHER = 17, + MPC_TYPE_ALSO = 18, + MPC_TYPE_OR = 19, + MPC_TYPE_AND = 20, }; typedef struct { void* x; } mpc_pdata_lift_t; @@ -405,6 +417,8 @@ bool mpc_parse_input(mpc_input_t* i, mpc_parser_t* p, mpc_result_t* r) { memset(r, 0, sizeof(mpc_result_t)); + if (p->type == MPC_TYPE_UNDEFINED) { fprintf(stderr, "Error: Parser Undefined!\n"); abort(); } + /* Trivial Parsers */ if (p->type == MPC_TYPE_PASS) { MPC_SUCCESS(NULL); } @@ -524,8 +538,15 @@ bool mpc_parse_input(mpc_input_t* i, mpc_parser_t* p, mpc_result_t* r) { } } - /* TODO: Implement */ - r->error = rs[0].error; + mpc_err_t** vals = malloc(sizeof(mpc_err_t*) * p->data.or.n); + + for (ri = 0; ri < p->data.and.n; ri++) { + vals[ri] = rs[ri].error; + } + + r->error = mpc_err_or(vals, p->data.or.n); + + free(vals); free(rs); return false; @@ -606,30 +627,30 @@ bool mpc_parse_filename(const char* filename, mpc_parser_t* p, mpc_result_t* r) ** Building a Parser */ -static void mpc_delete_unretained(mpc_parser_t* p, bool force); +static void mpc_undefine_unretained(mpc_parser_t* p, bool force); -static void mpc_delete_or(mpc_parser_t* p) { +static void mpc_undefine_or(mpc_parser_t* p) { int i; for (i = 0; i < p->data.or.n; i++) { - mpc_delete_unretained(p->data.or.xs[i], false); + mpc_undefine_unretained(p->data.or.xs[i], false); } free(p->data.or.xs); } -static void mpc_delete_and(mpc_parser_t* p) { +static void mpc_undefine_and(mpc_parser_t* p) { int i; for (i = 0; i < p->data.and.n; i++) { - mpc_delete_unretained(p->data.and.xs[i], false); - } + mpc_undefine_unretained(p->data.and.xs[i], false); + } free(p->data.and.xs); free(p->data.and.dxs); } -static void mpc_delete_unretained(mpc_parser_t* p, bool force) { +static void mpc_undefine_unretained(mpc_parser_t* p, bool force) { if (p->retained && !force) { return; } @@ -642,11 +663,11 @@ static void mpc_delete_unretained(mpc_parser_t* p, bool force) { break; case MPC_TYPE_APPLY: - mpc_delete_unretained(p->data.apply.x, false); + mpc_undefine_unretained(p->data.apply.x, false); break; case MPC_TYPE_EXPECT: - mpc_delete_unretained(p->data.expect.x, false); + mpc_undefine_unretained(p->data.expect.x, false); free(p->data.expect.m); break; @@ -654,72 +675,94 @@ static void mpc_delete_unretained(mpc_parser_t* p, bool force) { case MPC_TYPE_MANY: case MPC_TYPE_MANY1: case MPC_TYPE_COUNT: - mpc_delete_unretained(p->data.repeat.x, false); + mpc_undefine_unretained(p->data.repeat.x, false); break; case MPC_TYPE_EITHER: - mpc_delete_unretained(p->data.either.x, false); - mpc_delete_unretained(p->data.either.y, false); + mpc_undefine_unretained(p->data.either.x, false); + mpc_undefine_unretained(p->data.either.y, false); break; case MPC_TYPE_ALSO: - mpc_delete_unretained(p->data.also.x, false); - mpc_delete_unretained(p->data.also.y, false); + mpc_undefine_unretained(p->data.also.x, false); + mpc_undefine_unretained(p->data.also.y, false); break; case MPC_TYPE_OR: - mpc_delete_or(p); + mpc_undefine_or(p); break; case MPC_TYPE_AND: - mpc_delete_and(p); + mpc_undefine_and(p); break; default: break; } - free(p); + if (!force) { free(p); } } void mpc_delete(mpc_parser_t* p) { - mpc_delete_unretained(p, true); + + if (p->retained) { + + if (p->type != MPC_TYPE_UNDEFINED) { + fprintf(stderr, "Error: Parser still Defined! Use `mpc_undefine` before delete!\n"); + abort(); + } else { + free(p); + } + + } else { + + mpc_undefine_unretained(p, false); + + } + + } -mpc_parser_t* mpc_new(void) { - return mpc_pass(); -} - -mpc_parser_t* mpc_assign(mpc_parser_t* p, mpc_parser_t* a) { - memcpy(p, a, sizeof(mpc_parser_t)); - free(a); +static mpc_parser_t* mpc_undefined(void) { + mpc_parser_t* p = calloc(1, sizeof(mpc_parser_t)); + p->retained = false; + p->type = MPC_TYPE_UNDEFINED; return p; } -mpc_parser_t* mpc_define(mpc_parser_t* p, mpc_parser_t* a) { - return mpc_retain(mpc_assign(p, a)); -} - -mpc_parser_t* mpc_retain(mpc_parser_t* p) { +mpc_parser_t* mpc_new(void) { + mpc_parser_t* p = mpc_undefined(); p->retained = true; return p; } +mpc_parser_t* mpc_undefine(mpc_parser_t* p) { + mpc_undefine_unretained(p, true); + p->type = MPC_TYPE_UNDEFINED; + return p; +} + +mpc_parser_t* mpc_define(mpc_parser_t* p, mpc_parser_t* a) { + p->type = a->type; + p->data = a->data; + free(a); + return p; +} + mpc_parser_t* mpc_pass(void) { - mpc_parser_t* p = calloc(1, sizeof(mpc_parser_t)); - p->retained = false; + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_PASS; return p; } mpc_parser_t* mpc_fail(void) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_FAIL; return p; } mpc_parser_t* mpc_lift(mpc_val_t* x) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_LIFT; p->data.lift.x = x; return p; @@ -727,7 +770,7 @@ mpc_parser_t* mpc_lift(mpc_val_t* x) { mpc_parser_t* mpc_expect(mpc_parser_t* a, const char* expected) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_EXPECT; p->data.expect.x = a; p->data.expect.m = malloc(strlen(expected) + 1); @@ -740,13 +783,13 @@ mpc_parser_t* mpc_expect(mpc_parser_t* a, const char* expected) { */ mpc_parser_t* mpc_any(void) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_ANY; return mpc_expect(p, "any character"); } mpc_parser_t* mpc_char(char c) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_SINGLE; p->data.single.x = c; return mpc_expect(p, (char[]){ '\'', c, '\'', '\0' } ); @@ -754,7 +797,7 @@ mpc_parser_t* mpc_char(char c) { mpc_parser_t* mpc_range(char s, char e) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_RANGE; p->data.range.x = s; p->data.range.y = e; @@ -771,7 +814,7 @@ mpc_parser_t* mpc_range(char s, char e) { mpc_parser_t* mpc_oneof(const char* s) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_ONEOF; p->data.string.x = malloc(strlen(s) + 1); strcpy(p->data.string.x, s); @@ -790,7 +833,7 @@ mpc_parser_t* mpc_oneof(const char* s) { mpc_parser_t* mpc_noneof(const char* s) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_NONEOF; p->data.string.x = malloc(strlen(s) + 1); strcpy(p->data.string.x, s); @@ -809,7 +852,7 @@ mpc_parser_t* mpc_noneof(const char* s) { } mpc_parser_t* mpc_satisfy(bool(*f)(char)) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_SATISFY; p->data.satisfy.f = f; @@ -818,7 +861,7 @@ mpc_parser_t* mpc_satisfy(bool(*f)(char)) { mpc_parser_t* mpc_string(const char* s) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_STRING; p->data.string.x = malloc(strlen(s) + 1); strcpy(p->data.string.x, s); @@ -843,7 +886,7 @@ void mpc_dtor_null(mpc_val_t* x) { return; } */ mpc_parser_t* mpc_apply(mpc_parser_t* a, mpc_apply_t f) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_APPLY; p->data.apply.x = a; p->data.apply.f = f; @@ -851,14 +894,14 @@ mpc_parser_t* mpc_apply(mpc_parser_t* a, mpc_apply_t f) { } mpc_parser_t* mpc_maybe(mpc_parser_t* a) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_MAYBE; p->data.repeat.x = a; return p; } mpc_parser_t* mpc_many(mpc_parser_t* a, mpc_fold_t f) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_MANY; p->data.repeat.x = a; p->data.repeat.f = f; @@ -866,7 +909,7 @@ mpc_parser_t* mpc_many(mpc_parser_t* a, mpc_fold_t f) { } mpc_parser_t* mpc_many1(mpc_parser_t* a, mpc_fold_t f) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_MANY1; p->data.repeat.x = a; p->data.repeat.f = f; @@ -874,7 +917,7 @@ mpc_parser_t* mpc_many1(mpc_parser_t* a, mpc_fold_t f) { } mpc_parser_t* mpc_count(mpc_parser_t* a, mpc_dtor_t da, mpc_fold_t f, int n) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_COUNT; p->data.repeat.x = a; p->data.repeat.dx = da; @@ -884,7 +927,7 @@ mpc_parser_t* mpc_count(mpc_parser_t* a, mpc_dtor_t da, mpc_fold_t f, int n) { } mpc_parser_t* mpc_either(mpc_parser_t* a, mpc_parser_t* b) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_EITHER; p->data.either.x = a; p->data.either.y = b; @@ -892,7 +935,7 @@ mpc_parser_t* mpc_either(mpc_parser_t* a, mpc_parser_t* b) { } mpc_parser_t* mpc_also(mpc_parser_t* a, mpc_parser_t* b, mpc_dtor_t da, mpc_fold_t f) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_ALSO; p->data.also.x = a; p->data.also.y = b; @@ -907,7 +950,7 @@ mpc_parser_t* mpc_bind(mpc_parser_t* a, mpc_parser_t* b, mpc_dtor_t da, mpc_fold mpc_parser_t* mpc_or(int n, ...) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_OR; p->data.or.n = n; @@ -926,7 +969,7 @@ mpc_parser_t* mpc_or(int n, ...) { mpc_parser_t* mpc_and(int n, mpc_afold_t f, ...) { - mpc_parser_t* p = mpc_pass(); + mpc_parser_t* p = mpc_undefined(); p->type = MPC_TYPE_AND; p->data.and.n = n; @@ -1143,12 +1186,13 @@ mpc_parser_t* mpc_re(const char* re) { )); mpc_result_t r; - if (mpc_parse(re, Regex, &r)) { - return r.output; - } else { - /* TODO: Proper Error Reporting */ - return NULL; - } + bool res = mpc_parse(re, Regex, &r); + + mpc_undefine(Regex); + mpc_undefine(Term); + mpc_undefine(Factor); + mpc_undefine(Base); + mpc_undefine(Range); mpc_delete(Regex); mpc_delete(Term); @@ -1156,6 +1200,13 @@ mpc_parser_t* mpc_re(const char* re) { mpc_delete(Base); mpc_delete(Range); + if (res) { + return r.output; + } else { + mpc_err_delete(r.error); + return NULL; + } + } /* @@ -1215,7 +1266,7 @@ static mpc_val_t* mpcf_escape_new(mpc_val_t* x) { } if (!found) { - y = realloc(y, strlen(y) + 1); + y = realloc(y, strlen(y) + 2); strcat(y, (char[]){*s, '\0'}); } @@ -1257,7 +1308,7 @@ mpc_val_t* mpcf_freefold(mpc_val_t* t, mpc_val_t* x) { mpc_val_t* mpcf_strfold(mpc_val_t* t, mpc_val_t* x) { - if (t == NULL) { t = calloc(1, 1); } + if (t == NULL) { return x; } t = realloc(t, strlen(t) + strlen(x) + 1); strcat(t, x); @@ -1291,16 +1342,15 @@ mpc_val_t* mpcf_maths(int n, mpc_val_t** xs) { ** Printing */ - - -static void mpc_print_rt(mpc_parser_t* p, bool force) { +static void mpc_print_unretained(mpc_parser_t* p, bool force) { if (p->retained && !force) { printf(""); return; } + if (p->type == MPC_TYPE_UNDEFINED) { printf(""); } if (p->type == MPC_TYPE_PASS) { printf(""); } if (p->type == MPC_TYPE_FAIL) { printf(""); } if (p->type == MPC_TYPE_LIFT) { printf(""); } - if (p->type == MPC_TYPE_EXPECT) { mpc_print_rt(p->data.expect.x, false); } + if (p->type == MPC_TYPE_EXPECT) { mpc_print_unretained(p->data.expect.x, false); } if (p->type == MPC_TYPE_ANY) { printf(""); } if (p->type == MPC_TYPE_SATISFY) { printf("", p->data.satisfy.f); } @@ -1337,50 +1387,50 @@ static void mpc_print_rt(mpc_parser_t* p, bool force) { free(s); } - if (p->type == MPC_TYPE_APPLY) { mpc_print_rt(p->data.apply.x, false); } - if (p->type == MPC_TYPE_MAYBE) { printf("("); mpc_print_rt(p->data.repeat.x, false); printf(")?"); } - if (p->type == MPC_TYPE_MANY) { printf("("); mpc_print_rt(p->data.repeat.x, false); printf(")*"); } - if (p->type == MPC_TYPE_MANY1) { printf("("); mpc_print_rt(p->data.repeat.x, false); printf(")+"); } - if (p->type == MPC_TYPE_COUNT) { printf("("); mpc_print_rt(p->data.repeat.x, false); printf("){%i}", p->data.repeat.n); } + if (p->type == MPC_TYPE_APPLY) { mpc_print_unretained(p->data.apply.x, false); } + if (p->type == MPC_TYPE_MAYBE) { printf("("); mpc_print_unretained(p->data.repeat.x, false); printf(")?"); } + if (p->type == MPC_TYPE_MANY) { printf("("); mpc_print_unretained(p->data.repeat.x, false); printf(")*"); } + if (p->type == MPC_TYPE_MANY1) { printf("("); mpc_print_unretained(p->data.repeat.x, false); printf(")+"); } + if (p->type == MPC_TYPE_COUNT) { printf("("); mpc_print_unretained(p->data.repeat.x, false); printf("){%i}", p->data.repeat.n); } if (p->type == MPC_TYPE_EITHER) { printf("("); - mpc_print_rt(p->data.either.x, false); + mpc_print_unretained(p->data.either.x, false); printf(" | "); - mpc_print_rt(p->data.either.y, false); + mpc_print_unretained(p->data.either.y, false); printf(")"); } if (p->type == MPC_TYPE_ALSO) { - mpc_print_rt(p->data.also.x, false); + mpc_print_unretained(p->data.also.x, false); printf(" "); - mpc_print_rt(p->data.also.y, false); + mpc_print_unretained(p->data.also.y, false); } if (p->type == MPC_TYPE_OR) { printf("("); int i; for(i = 0; i < p->data.or.n-1; i++) { - mpc_print_rt(p->data.or.xs[i], false); + mpc_print_unretained(p->data.or.xs[i], false); printf(" | "); } - mpc_print_rt(p->data.or.xs[p->data.or.n-1], false); + mpc_print_unretained(p->data.or.xs[p->data.or.n-1], false); printf(")"); } if (p->type == MPC_TYPE_AND) { int i; for(i = 0; i < p->data.and.n-1; i++) { - mpc_print_rt(p->data.and.xs[i], false); + mpc_print_unretained(p->data.and.xs[i], false); printf(" "); } - mpc_print_rt(p->data.and.xs[p->data.and.n-1], false); + mpc_print_unretained(p->data.and.xs[p->data.and.n-1], false); } } void mpc_print(mpc_parser_t* p) { - mpc_print_rt(p, true); + mpc_print_unretained(p, true); printf("\n"); } @@ -1406,6 +1456,7 @@ bool mpc_test(mpc_parser_t* p, const char* s, void* data, printf("Failed!\n"); printf("Got "); printer(r.output); printf("\n"); printf("Expected "); printer(data); printf("\n"); + destructor(r.output); return false; } diff --git a/mpc.h b/mpc.h index bee8225..a37b6a6 100644 --- a/mpc.h +++ b/mpc.h @@ -52,9 +52,10 @@ bool mpc_parse_filename(const char* filename, mpc_parser_t* p, mpc_result_t* r); void mpc_delete(mpc_parser_t* p); mpc_parser_t* mpc_new(void); -mpc_parser_t* mpc_assign(mpc_parser_t* p, mpc_parser_t* a); + mpc_parser_t* mpc_define(mpc_parser_t* p, mpc_parser_t* a); -mpc_parser_t* mpc_retain(mpc_parser_t* p); +mpc_parser_t* mpc_undefine(mpc_parser_t* p); + mpc_parser_t* mpc_expect(mpc_parser_t* a, const char* expected); mpc_parser_t* mpc_pass(void); diff --git a/tests/ident.c b/tests/ident.c index 3b4677e..d5ca8bb 100644 --- a/tests/ident.c +++ b/tests/ident.c @@ -31,6 +31,7 @@ bool suite_ident(void) { mpc_test(Ident, "", "", string_eq, free, string_print); mpc_test(Ident, "18nums", "", string_eq, free, string_print); + mpc_undefine(Ident); mpc_delete(Ident); return true; diff --git a/tests/math.c b/tests/math.c index d13194e..0cc067f 100644 --- a/tests/math.c +++ b/tests/math.c @@ -46,6 +46,11 @@ bool suite_math(void) { mpc_test(Maths, "a", (int[]){ 0 }, int_eq, free, int_print); mpc_test(Maths, "2b+4", (int[]){ 2 }, int_eq, free, int_print); + mpc_undefine(Expr); + mpc_undefine(Factor); + mpc_undefine(Term); + mpc_undefine(Maths); + mpc_delete(Expr); mpc_delete(Factor); mpc_delete(Term);