Refactor of pat_t memory management to use doubly linked lists, and
moving the recursive freeing code from Lua/lbp.c into pattern.c
This commit is contained in:
parent
ee0174001b
commit
77d9007a88
40
Lua/lbp.c
40
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");
|
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)
|
static int Lmatch(lua_State *L)
|
||||||
{
|
{
|
||||||
if (lua_isstring(L, 1)) {
|
if (lua_isstring(L, 1)) {
|
||||||
@ -226,7 +191,7 @@ static int Lreplace(lua_State *L)
|
|||||||
lua_pushinteger(L, replacements);
|
lua_pushinteger(L, replacements);
|
||||||
fclose(out);
|
fclose(out);
|
||||||
|
|
||||||
free_pat(maybe_replacement.value.pat);
|
delete_pat(&maybe_replacement.value.pat, false);
|
||||||
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
@ -281,8 +246,7 @@ static int Lpat_tostring(lua_State *L)
|
|||||||
static int Lpat_gc(lua_State *L)
|
static int Lpat_gc(lua_State *L)
|
||||||
{
|
{
|
||||||
pat_t *pat = lua_touserdata(L, 1);
|
pat_t *pat = lua_touserdata(L, 1);
|
||||||
if (pat)
|
if (pat) delete_pat(&pat, true);
|
||||||
recursively_free_pat(pat);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
bp.c
2
bp.c
@ -682,7 +682,7 @@ int main(int argc, char *argv[])
|
|||||||
// tracking down memory leaks.
|
// tracking down memory leaks.
|
||||||
free_all_matches();
|
free_all_matches();
|
||||||
defs = free_defs(defs, NULL);
|
defs = free_defs(defs, NULL);
|
||||||
free_pat(NULL);
|
free_all_pats();
|
||||||
while (loaded_files) {
|
while (loaded_files) {
|
||||||
file_t *next = loaded_files->next;
|
file_t *next = loaded_files->next;
|
||||||
destroy_file(&loaded_files);
|
destroy_file(&loaded_files);
|
||||||
|
6
match.c
6
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);
|
ctx2.defs = with_def(ctx->defs, m1->pat->args.capture.namelen, m1->pat->args.capture.name, backref);
|
||||||
++m1->refcount; {
|
++m1->refcount; {
|
||||||
m2 = match(&ctx2, m1->end, pat->args.multiple.second);
|
m2 = match(&ctx2, m1->end, pat->args.multiple.second);
|
||||||
if (!m2) { // No need to keep the backref in memory if it didn't match
|
if (!m2) // No need to keep the backref in memory if it didn't match
|
||||||
free_pat(backref);
|
delete_pat(&backref, false);
|
||||||
backref = NULL;
|
|
||||||
}
|
|
||||||
free_defs(ctx2.defs, ctx->defs);
|
free_defs(ctx2.defs, ctx->defs);
|
||||||
} --m1->refcount;
|
} --m1->refcount;
|
||||||
} else {
|
} else {
|
||||||
|
64
pattern.c
64
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;
|
static size_t next_pat_id = 1;
|
||||||
pat_t *pat = new(pat_t);
|
pat_t *pat = new(pat_t);
|
||||||
*pat = (pat_t){
|
*pat = (pat_t){
|
||||||
|
.home = &allocated_pats,
|
||||||
.next = allocated_pats,
|
.next = allocated_pats,
|
||||||
.type = type,
|
.type = type,
|
||||||
.start = start,
|
.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,
|
.max_matchlen = maxlen,
|
||||||
.id = next_pat_id++,
|
.id = next_pat_id++,
|
||||||
};
|
};
|
||||||
|
if (allocated_pats) allocated_pats->home = &pat->next;
|
||||||
allocated_pats = pat;
|
allocated_pats = pat;
|
||||||
return 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"};
|
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) {
|
while (allocated_pats) {
|
||||||
for (pat_t **rem = &allocated_pats; *rem; rem = &(*rem)->next) {
|
pat_t *tofree = allocated_pats;
|
||||||
if ((*rem) == target) {
|
allocated_pats = tofree->next;
|
||||||
pat_t *tmp = *rem;
|
delete(&tofree);
|
||||||
*rem = (*rem)->next;
|
|
||||||
delete(&tmp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
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
|
// 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
|
// A struct reperesenting a BP virtual machine operation
|
||||||
//
|
//
|
||||||
typedef struct pat_s {
|
typedef struct pat_s {
|
||||||
struct pat_s *next;
|
struct pat_s *next, **home;
|
||||||
enum pattype_e type;
|
enum pattype_e type;
|
||||||
const char *start, *end;
|
const char *start, *end;
|
||||||
// The bounds of the match length (used for backtracking)
|
// 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);
|
pat_t *either_pat(pat_t *first, pat_t *second);
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
maybe_pat_t bp_pattern(const char *str, const char *end);
|
maybe_pat_t bp_pattern(const char *str, const char *end);
|
||||||
|
void free_all_pats(void);
|
||||||
void free_pat(pat_t *pat);
|
__attribute__((nonnull))
|
||||||
|
void delete_pat(pat_t **at_pat, bool recursive);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user