diff options
| -rw-r--r-- | Lua/lbp.c | 40 | ||||
| -rw-r--r-- | bp.c | 2 | ||||
| -rw-r--r-- | match.c | 6 | ||||
| -rw-r--r-- | pattern.c | 62 | ||||
| -rw-r--r-- | pattern.h | 7 |
5 files changed, 56 insertions, 61 deletions
@@ -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; } @@ -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); @@ -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 { @@ -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 @@ -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 |
