aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lua/lbp.c40
-rw-r--r--bp.c2
-rw-r--r--match.c6
-rw-r--r--pattern.c62
-rw-r--r--pattern.h7
5 files changed, 56 insertions, 61 deletions
diff --git a/Lua/lbp.c b/Lua/lbp.c
index 51ba9d2..37d3bb3 100644
--- a/Lua/lbp.c
+++ b/Lua/lbp.c
@@ -112,41 +112,6 @@ static void push_match(lua_State *L, match_t *m, const char *start)
lua_setfield(L, -2, "after");
}
-static void recursively_free_pat(pat_t *pat)
-{
- // Do a depth-first traversal, freeing everyting along the way:
- if (!pat) return;
- switch (pat->type) {
- case BP_DEFINITION:
- recursively_free_pat(pat->args.def.def);
- recursively_free_pat(pat->args.def.pat);
- break;
- case BP_REPEAT:
- recursively_free_pat(pat->args.repetitions.sep);
- recursively_free_pat(pat->args.repetitions.repeat_pat);
- break;
- case BP_CHAIN: case BP_UPTO: case BP_UPTO_STRICT:
- case BP_OTHERWISE: case BP_NOT_MATCH: case BP_MATCH:
- recursively_free_pat(pat->args.multiple.first);
- recursively_free_pat(pat->args.multiple.second);
- break;
- case BP_REPLACE:
- recursively_free_pat(pat->args.replace.pat);
- break;
- case BP_CAPTURE:
- recursively_free_pat(pat->args.capture.capture_pat);
- break;
- case BP_NOT: case BP_AFTER: case BP_BEFORE:
- recursively_free_pat(pat->args.pat);
- break;
- case BP_LEFTRECURSION:
- recursively_free_pat(pat->args.leftrec.fallback);
- break;
- default: break;
- }
- free_pat(pat);
-}
-
static int Lmatch(lua_State *L)
{
if (lua_isstring(L, 1)) {
@@ -226,7 +191,7 @@ static int Lreplace(lua_State *L)
lua_pushinteger(L, replacements);
fclose(out);
- free_pat(maybe_replacement.value.pat);
+ delete_pat(&maybe_replacement.value.pat, false);
return 2;
}
@@ -281,8 +246,7 @@ static int Lpat_tostring(lua_State *L)
static int Lpat_gc(lua_State *L)
{
pat_t *pat = lua_touserdata(L, 1);
- if (pat)
- recursively_free_pat(pat);
+ if (pat) delete_pat(&pat, true);
return 0;
}
diff --git a/bp.c b/bp.c
index f9d1512..73b0469 100644
--- a/bp.c
+++ b/bp.c
@@ -682,7 +682,7 @@ int main(int argc, char *argv[])
// tracking down memory leaks.
free_all_matches();
defs = free_defs(defs, NULL);
- free_pat(NULL);
+ free_all_pats();
while (loaded_files) {
file_t *next = loaded_files->next;
destroy_file(&loaded_files);
diff --git a/match.c b/match.c
index 874f60a..5ae9f0f 100644
--- a/match.c
+++ b/match.c
@@ -531,10 +531,8 @@ static match_t *match(match_ctx_t *ctx, const char *str, pat_t *pat)
ctx2.defs = with_def(ctx->defs, m1->pat->args.capture.namelen, m1->pat->args.capture.name, backref);
++m1->refcount; {
m2 = match(&ctx2, m1->end, pat->args.multiple.second);
- if (!m2) { // No need to keep the backref in memory if it didn't match
- free_pat(backref);
- backref = NULL;
- }
+ if (!m2) // No need to keep the backref in memory if it didn't match
+ delete_pat(&backref, false);
free_defs(ctx2.defs, ctx->defs);
} --m1->refcount;
} else {
diff --git a/pattern.c b/pattern.c
index eef1413..9865c0f 100644
--- a/pattern.c
+++ b/pattern.c
@@ -52,6 +52,7 @@ static pat_t *new_pat(enum pattype_e type, const char *start, const char *end, s
static size_t next_pat_id = 1;
pat_t *pat = new(pat_t);
*pat = (pat_t){
+ .home = &allocated_pats,
.next = allocated_pats,
.type = type,
.start = start,
@@ -60,6 +61,7 @@ static pat_t *new_pat(enum pattype_e type, const char *start, const char *end, s
.max_matchlen = maxlen,
.id = next_pat_id++,
};
+ if (allocated_pats) allocated_pats->home = &pat->next;
allocated_pats = pat;
return pat;
}
@@ -635,24 +637,54 @@ maybe_pat_t bp_pattern(const char *str, const char *end)
return (maybe_pat_t){.success = false, .value.error.start = str, .value.error.end = end, .value.error.msg = "Failed to parse this pattern"};
}
-void free_pat(pat_t *target)
+void free_all_pats(void)
{
- if (target) {
- for (pat_t **rem = &allocated_pats; *rem; rem = &(*rem)->next) {
- if ((*rem) == target) {
- pat_t *tmp = *rem;
- *rem = (*rem)->next;
- delete(&tmp);
- break;
- }
- }
- } else {
- while (allocated_pats) {
- pat_t *tofree = allocated_pats;
- allocated_pats = tofree->next;
- delete(&tofree);
+ while (allocated_pats) {
+ pat_t *tofree = allocated_pats;
+ allocated_pats = tofree->next;
+ delete(&tofree);
+ }
+}
+
+void delete_pat(pat_t **at_pat, bool recursive)
+{
+ pat_t *pat = *at_pat;
+ if (!pat) return;
+
+ if (recursive) {
+ switch (pat->type) {
+ case BP_DEFINITION:
+ delete_pat(&pat->args.def.def, true);
+ delete_pat(&pat->args.def.pat, true);
+ break;
+ case BP_REPEAT:
+ delete_pat(&pat->args.repetitions.sep, true);
+ delete_pat(&pat->args.repetitions.repeat_pat, true);
+ break;
+ case BP_CHAIN: case BP_UPTO: case BP_UPTO_STRICT:
+ case BP_OTHERWISE: case BP_NOT_MATCH: case BP_MATCH:
+ delete_pat(&pat->args.multiple.first, true);
+ delete_pat(&pat->args.multiple.second, true);
+ break;
+ case BP_REPLACE:
+ delete_pat(&pat->args.replace.pat, true);
+ break;
+ case BP_CAPTURE:
+ delete_pat(&pat->args.capture.capture_pat, true);
+ break;
+ case BP_NOT: case BP_AFTER: case BP_BEFORE:
+ delete_pat(&pat->args.pat, true);
+ break;
+ case BP_LEFTRECURSION:
+ delete_pat(&pat->args.leftrec.fallback, true);
+ break;
+ default: break;
}
}
+
+ if (pat->home) *(pat->home) = pat->next;
+ if (pat->next) pat->next->home = pat->home;
+ delete(at_pat);
}
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/pattern.h b/pattern.h
index ef08441..3a78f13 100644
--- a/pattern.h
+++ b/pattern.h
@@ -42,7 +42,7 @@ enum pattype_e {
// A struct reperesenting a BP virtual machine operation
//
typedef struct pat_s {
- struct pat_s *next;
+ struct pat_s *next, **home;
enum pattype_e type;
const char *start, *end;
// The bounds of the match length (used for backtracking)
@@ -115,8 +115,9 @@ pat_t *chain_together(pat_t *first, pat_t *second);
pat_t *either_pat(pat_t *first, pat_t *second);
__attribute__((nonnull))
maybe_pat_t bp_pattern(const char *str, const char *end);
-
-void free_pat(pat_t *pat);
+void free_all_pats(void);
+__attribute__((nonnull))
+void delete_pat(pat_t **at_pat, bool recursive);
#endif