mirror of
https://github.com/neovim/neovim.git
synced 2025-09-18 17:28:23 +00:00
GA_DEEP_CLEAR macro for garray memory deallocation
Used to free garrays of `salitem_T` and `fromto_T` in spell.c, and garray `wcmd_T` in ex_docmd.c. Helped-by: Jiaqi Li
This commit is contained in:
@@ -97,6 +97,8 @@ typedef struct {
|
|||||||
linenr_T lnum; /* sourcing_lnum of the line */
|
linenr_T lnum; /* sourcing_lnum of the line */
|
||||||
} wcmd_T;
|
} wcmd_T;
|
||||||
|
|
||||||
|
#define FREE_WCMD(wcmd) free((wcmd)->line)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure used to store info for line position in a while or for loop.
|
* 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
|
* 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 (cstack.cs_looplevel == 0) {
|
||||||
if (!GA_EMPTY(&lines_ga)) {
|
if (!GA_EMPTY(&lines_ga)) {
|
||||||
sourcing_lnum =
|
sourcing_lnum = ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
|
||||||
((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
|
GA_DEEP_CLEAR(&lines_ga, wcmd_T, FREE_WCMD);
|
||||||
free_cmdlines(&lines_ga);
|
|
||||||
}
|
}
|
||||||
current_line = 0;
|
current_line = 0;
|
||||||
}
|
}
|
||||||
@@ -777,8 +778,7 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
|
|||||||
|
|
||||||
free(cmdline_copy);
|
free(cmdline_copy);
|
||||||
did_emsg_syntax = FALSE;
|
did_emsg_syntax = FALSE;
|
||||||
free_cmdlines(&lines_ga);
|
GA_DEEP_CLEAR(&lines_ga, wcmd_T, FREE_WCMD);
|
||||||
ga_clear(&lines_ga);
|
|
||||||
|
|
||||||
if (cstack.cs_idx >= 0) {
|
if (cstack.cs_idx >= 0) {
|
||||||
/*
|
/*
|
||||||
@@ -1017,17 +1017,6 @@ static void store_loop_line(garray_T *gap, char_u *line)
|
|||||||
p->lnum = sourcing_lnum;
|
p->lnum = sourcing_lnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
* If "fgetline" is get_loop_line(), return TRUE if the getline it uses equals
|
||||||
* "func". * Otherwise return TRUE when "fgetline" equals "func".
|
* "func". * Otherwise return TRUE when "fgetline" equals "func".
|
||||||
|
@@ -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++);
|
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
|
#endif // NVIM_GARRAY_H
|
||||||
|
@@ -2379,13 +2379,26 @@ static void slang_free(slang_T *lp)
|
|||||||
free(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.
|
// Clear an slang_T so that the file can be reloaded.
|
||||||
static void slang_clear(slang_T *lp)
|
static void slang_clear(slang_T *lp)
|
||||||
{
|
{
|
||||||
garray_T *gap;
|
garray_T *gap;
|
||||||
fromto_T *ftp;
|
|
||||||
salitem_T *smp;
|
|
||||||
int round;
|
|
||||||
|
|
||||||
free(lp->sl_fbyts);
|
free(lp->sl_fbyts);
|
||||||
lp->sl_fbyts = NULL;
|
lp->sl_fbyts = NULL;
|
||||||
@@ -2401,36 +2414,23 @@ static void slang_clear(slang_T *lp)
|
|||||||
free(lp->sl_pidxs);
|
free(lp->sl_pidxs);
|
||||||
lp->sl_pidxs = NULL;
|
lp->sl_pidxs = NULL;
|
||||||
|
|
||||||
for (round = 1; round <= 2; ++round) {
|
GA_DEEP_CLEAR(&lp->sl_rep, fromto_T, free_fromto);
|
||||||
gap = round == 1 ? &lp->sl_rep : &lp->sl_repsal;
|
GA_DEEP_CLEAR(&lp->sl_repsal, fromto_T, free_fromto);
|
||||||
while (!GA_EMPTY(gap)) {
|
|
||||||
ftp = &((fromto_T *)gap->ga_data)[--gap->ga_len];
|
|
||||||
free(ftp->ft_from);
|
|
||||||
free(ftp->ft_to);
|
|
||||||
}
|
|
||||||
ga_clear(gap);
|
|
||||||
}
|
|
||||||
|
|
||||||
gap = &lp->sl_sal;
|
gap = &lp->sl_sal;
|
||||||
if (lp->sl_sofo) {
|
if (lp->sl_sofo) {
|
||||||
// "ga_len" is set to 1 without adding an item for latin1
|
// "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.
|
// SOFOFROM and SOFOTO items: free lists of wide characters.
|
||||||
for (int i = 0; i < gap->ga_len; ++i) {
|
for (int i = 0; i < gap->ga_len; ++i) {
|
||||||
free(((int **)gap->ga_data)[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) {
|
for (int i = 0; i < lp->sl_prefixcnt; ++i) {
|
||||||
vim_regfree(lp->sl_prefprog[i]);
|
vim_regfree(lp->sl_prefprog[i]);
|
||||||
|
Reference in New Issue
Block a user