diff options
-rw-r--r-- | src/nvim/ex_docmd.c | 21 | ||||
-rw-r--r-- | src/nvim/garray.h | 18 | ||||
-rw-r--r-- | src/nvim/spell.c | 48 |
3 files changed, 47 insertions, 40 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index e180be4421..e6242ff94d 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -97,6 +97,8 @@ typedef struct { linenr_T lnum; /* sourcing_lnum of the line */ } wcmd_T; +#define FREE_WCMD(wcmd) free((wcmd)->line) + /* * Structure used to store info for line position in a while or for loop. * This is required, because do_one_cmd() may invoke ex_function(), which @@ -708,9 +710,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, */ if (cstack.cs_looplevel == 0) { if (!GA_EMPTY(&lines_ga)) { - sourcing_lnum = - ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum; - free_cmdlines(&lines_ga); + sourcing_lnum = ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum; + GA_DEEP_CLEAR(&lines_ga, wcmd_T, FREE_WCMD); } current_line = 0; } @@ -777,8 +778,7 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, free(cmdline_copy); did_emsg_syntax = FALSE; - free_cmdlines(&lines_ga); - ga_clear(&lines_ga); + GA_DEEP_CLEAR(&lines_ga, wcmd_T, FREE_WCMD); if (cstack.cs_idx >= 0) { /* @@ -1018,17 +1018,6 @@ static void store_loop_line(garray_T *gap, char_u *line) } /* - * Free the lines stored for a ":while" or ":for" loop. - */ -static void free_cmdlines(garray_T *gap) -{ - while (!GA_EMPTY(gap)) { - free(((wcmd_T *)(gap->ga_data))[gap->ga_len - 1].line); - --gap->ga_len; - } -} - -/* * If "fgetline" is get_loop_line(), return TRUE if the getline it uses equals * "func". * Otherwise return TRUE when "fgetline" equals "func". */ diff --git a/src/nvim/garray.h b/src/nvim/garray.h index b32bab52f7..52493d6391 100644 --- a/src/nvim/garray.h +++ b/src/nvim/garray.h @@ -43,4 +43,22 @@ static inline void *ga_append_via_ptr(garray_T *gap, size_t item_size) return ((char *)gap->ga_data) + (item_size * (size_t)gap->ga_len++); } +/// Deep free a garray of specific type using a custom free function. +/// Items in the array as well as the array itself are freed. +/// +/// @param gap the garray to be freed +/// @param item_type type of the item in the garray +/// @param free_item_fn free function that takes (*item_type) as parameter +#define GA_DEEP_CLEAR(gap, item_type, free_item_fn) \ + do { \ + garray_T *_gap = (gap); \ + if (_gap->ga_data != NULL) { \ + for (int i = 0; i < _gap->ga_len; i++) { \ + item_type *_item = &(((item_type *)_gap->ga_data)[i]); \ + free_item_fn(_item); \ + } \ + } \ + ga_clear(_gap); \ + } while (false) + #endif // NVIM_GARRAY_H diff --git a/src/nvim/spell.c b/src/nvim/spell.c index fa786fdd74..fbdd58f4d3 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -2379,13 +2379,26 @@ static void slang_free(slang_T *lp) free(lp); } +/// Frees a salitem_T +static void free_salitem(salitem_T *smp) { + free(smp->sm_lead); + // Don't free sm_oneof and sm_rules, they point into sm_lead. + free(smp->sm_to); + free(smp->sm_lead_w); + free(smp->sm_oneof_w); + free(smp->sm_to_w); +} + +/// Frees a fromto_T +static void free_fromto(fromto_T *ftp) { + free(ftp->ft_from); + free(ftp->ft_to); +} + // Clear an slang_T so that the file can be reloaded. static void slang_clear(slang_T *lp) { garray_T *gap; - fromto_T *ftp; - salitem_T *smp; - int round; free(lp->sl_fbyts); lp->sl_fbyts = NULL; @@ -2401,36 +2414,23 @@ static void slang_clear(slang_T *lp) free(lp->sl_pidxs); lp->sl_pidxs = NULL; - for (round = 1; round <= 2; ++round) { - gap = round == 1 ? &lp->sl_rep : &lp->sl_repsal; - while (!GA_EMPTY(gap)) { - ftp = &((fromto_T *)gap->ga_data)[--gap->ga_len]; - free(ftp->ft_from); - free(ftp->ft_to); - } - ga_clear(gap); - } + GA_DEEP_CLEAR(&lp->sl_rep, fromto_T, free_fromto); + GA_DEEP_CLEAR(&lp->sl_repsal, fromto_T, free_fromto); gap = &lp->sl_sal; if (lp->sl_sofo) { // "ga_len" is set to 1 without adding an item for latin1 - if (gap->ga_data != NULL) + if (gap->ga_data != NULL) { // SOFOFROM and SOFOTO items: free lists of wide characters. for (int i = 0; i < gap->ga_len; ++i) { free(((int **)gap->ga_data)[i]); } - } else - // SAL items: free salitem_T items - while (!GA_EMPTY(gap)) { - smp = &((salitem_T *)gap->ga_data)[--gap->ga_len]; - free(smp->sm_lead); - // Don't free sm_oneof and sm_rules, they point into sm_lead. - free(smp->sm_to); - free(smp->sm_lead_w); - free(smp->sm_oneof_w); - free(smp->sm_to_w); } - ga_clear(gap); + ga_clear(gap); + } else { + // SAL items: free salitem_T items + GA_DEEP_CLEAR(gap, salitem_T, free_salitem); + } for (int i = 0; i < lp->sl_prefixcnt; ++i) { vim_regfree(lp->sl_prefprog[i]); |