diff options
-rw-r--r-- | src/nvim/eval.c | 12 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 4 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 8 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 42 | ||||
-rw-r--r-- | src/nvim/fold.c | 5 | ||||
-rw-r--r-- | src/nvim/garray.c | 5 | ||||
-rw-r--r-- | src/nvim/garray.h | 26 | ||||
-rw-r--r-- | src/nvim/menu.c | 15 | ||||
-rw-r--r-- | src/nvim/spell.c | 61 | ||||
-rw-r--r-- | src/nvim/syntax.c | 16 |
10 files changed, 86 insertions, 108 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c58e6ee996..45ab901398 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5420,20 +5420,12 @@ static int list_join(garray_T *gap, list_T *l, char_u *sep, int echo_style, int { garray_T join_ga; int retval; - join_T *p; ga_init(&join_ga, (int)sizeof(join_T), l->lv_len); retval = list_join_inner(gap, l, sep, echo_style, copyID, &join_ga); - /* Dispose each item in join_ga. */ - if (join_ga.ga_data != NULL) { - p = (join_T *)join_ga.ga_data; - for (int i = 0; i < join_ga.ga_len; ++i) { - free(p->tofree); - ++p; - } - ga_clear(&join_ga); - } +# define FREE_JOIN_TOFREE(join) free((join)->tofree) + GA_DEEP_CLEAR(&join_ga, join_T, FREE_JOIN_TOFREE); return retval; } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 5ae03c6be3..701e969393 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -5625,9 +5625,7 @@ helptags_one ( if (mix) got_int = FALSE; /* continue with other languages */ - for (int i = 0; i < ga.ga_len; ++i) - free(((char_u **)ga.ga_data)[i]); - ga_clear(&ga); + GA_DEEP_CLEAR_PTR(&ga); fclose(fd_tags); /* there is no check for an error... */ } diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 794e9930b9..fa78047a46 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -2580,13 +2580,11 @@ char_u *get_scriptname(scid_T id) } # if defined(EXITFREE) || defined(PROTO) -void free_scriptnames(void) +void free_scriptnames() { - for (int i = script_items.ga_len; i > 0; --i) - free(SCRIPT_ITEM(i).sn_name); - ga_clear(&script_items); +# define FREE_SCRIPTNAME(item) free((item)->sn_name) + GA_DEEP_CLEAR(&script_items, scriptitem_T, FREE_SCRIPTNAME); } - # endif diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index e180be4421..6bca1ff34d 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". */ @@ -4546,20 +4535,18 @@ void ex_comclear(exarg_T *eap) uc_clear(&curbuf->b_ucmds); } +static void free_ucmd(ucmd_T* cmd) { + free(cmd->uc_name); + free(cmd->uc_rep); + free(cmd->uc_compl_arg); +} + /* * Clear all user commands for "gap". */ void uc_clear(garray_T *gap) { - ucmd_T *cmd; - - for (int i = 0; i < gap->ga_len; ++i) { - cmd = USER_CMD_GA(gap, i); - free(cmd->uc_name); - free(cmd->uc_rep); - free(cmd->uc_compl_arg); - } - ga_clear(gap); + GA_DEEP_CLEAR(gap, ucmd_T, free_ucmd); } static void ex_delcommand(exarg_T *eap) @@ -5488,9 +5475,8 @@ static void ex_goto(exarg_T *eap) */ void alist_clear(alist_T *al) { - while (--al->al_ga.ga_len >= 0) - free(AARGLIST(al)[al->al_ga.ga_len].ae_fname); - ga_clear(&al->al_ga); +# define FREE_AENTRY_FNAME(arg) free(arg->ae_fname) + GA_DEEP_CLEAR(&al->al_ga, aentry_T, FREE_AENTRY_FNAME); } /* diff --git a/src/nvim/fold.c b/src/nvim/fold.c index e76aacbadc..505ac8da0d 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -1336,9 +1336,8 @@ static void deleteFoldEntry(garray_T *gap, int idx, int recursive) */ void deleteFoldRecurse(garray_T *gap) { - for (int i = 0; i < gap->ga_len; ++i) - deleteFoldRecurse(&(((fold_T *)(gap->ga_data))[i].fd_nested)); - ga_clear(gap); +# define DELETE_FOLD_NESTED(fd) deleteFoldRecurse(&((fd)->fd_nested)) + GA_DEEP_CLEAR(gap, fold_T, DELETE_FOLD_NESTED); } /* foldMarkAdjust() {{{2 */ diff --git a/src/nvim/garray.c b/src/nvim/garray.c index 08a38493bf..c4f8f66bfe 100644 --- a/src/nvim/garray.c +++ b/src/nvim/garray.c @@ -37,10 +37,7 @@ void ga_clear(garray_T *gap) /// @param gap void ga_clear_strings(garray_T *gap) { - for (int i = 0; i < gap->ga_len; ++i) { - free(((char_u **)(gap->ga_data))[i]); - } - ga_clear(gap); + GA_DEEP_CLEAR_PTR(gap); } /// Initialize a growing array. diff --git a/src/nvim/garray.h b/src/nvim/garray.h index b32bab52f7..b758fce5da 100644 --- a/src/nvim/garray.h +++ b/src/nvim/garray.h @@ -43,4 +43,30 @@ 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) + +#define FREE_PTR_PTR(ptr) free(*(ptr)) + +/// Call `free` for every pointer stored in the garray and then frees the +/// garray. +/// +/// @param gap the garray to be freed +#define GA_DEEP_CLEAR_PTR(gap) GA_DEEP_CLEAR(gap, void*, FREE_PTR_PTR) + #endif // NVIM_GARRAY_H diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 1573aaae84..b31b6c1cec 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -1424,6 +1424,12 @@ typedef struct { static garray_T menutrans_ga = GA_EMPTY_INIT_VALUE; +#define FREE_MENUTRANS(mt) \ + menutrans_T* _mt = (mt); \ + free(_mt->from); \ + free(_mt->from_noamp); \ + free(_mt->to) + /* * ":menutrans". * This function is also defined without the +multi_lang feature, in which @@ -1441,13 +1447,8 @@ void ex_menutranslate(exarg_T *eap) * ":menutrans clear": clear all translations. */ if (STRNCMP(arg, "clear", 5) == 0 && ends_excmd(*skipwhite(arg + 5))) { - menutrans_T *tp = (menutrans_T *)menutrans_ga.ga_data; - for (int i = 0; i < menutrans_ga.ga_len; ++i) { - free(tp[i].from); - free(tp[i].from_noamp); - free(tp[i].to); - } - ga_clear(&menutrans_ga); + GA_DEEP_CLEAR(&menutrans_ga, menutrans_T, FREE_MENUTRANS); + /* Delete all "menutrans_" global variables. */ del_menutrans_vars(); } else { diff --git a/src/nvim/spell.c b/src/nvim/spell.c index fa786fdd74..83dcddecd6 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,17 @@ 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) - // 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 + GA_DEEP_CLEAR_PTR(gap); + } 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_DEEP_CLEAR(gap, salitem_T, free_salitem); + } for (int i = 0; i < lp->sl_prefixcnt; ++i) { vim_regfree(lp->sl_prefprog[i]); @@ -9206,15 +9200,10 @@ static void tree_count_words(char_u *byts, idx_T *idxs) // Free the info put in "*su" by spell_find_suggest(). static void spell_find_cleanup(suginfo_T *su) { +# define FREE_SUG_WORD(sug) free(sug->st_word) // Free the suggestions. - for (int i = 0; i < su->su_ga.ga_len; ++i) { - free(SUG(su->su_ga, i).st_word); - } - ga_clear(&su->su_ga); - for (int i = 0; i < su->su_sga.ga_len; ++i) { - free(SUG(su->su_sga, i).st_word); - } - ga_clear(&su->su_sga); + GA_DEEP_CLEAR(&su->su_ga, suggest_T, FREE_SUG_WORD); + GA_DEEP_CLEAR(&su->su_sga, suggest_T, FREE_SUG_WORD); // Free the banned words. hash_clear_all(&su->su_banned, 0); diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 45b42730bc..896f27f9e4 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -550,14 +550,9 @@ void syntax_start(win_T *wp, linenr_T lnum) */ static void clear_syn_state(synstate_T *p) { - garray_T *gap; - if (p->sst_stacksize > SST_FIX_STATES) { - gap = &(p->sst_union.sst_ga); - for (int i = 0; i < gap->ga_len; i++) { - unref_extmatch(SYN_STATE_P(gap)[i].bs_extmatch); - } - ga_clear(gap); +# define UNREF_BUFSTATE_EXTMATCH(bs) unref_extmatch((bs)->bs_extmatch) + GA_DEEP_CLEAR(&(p->sst_union.sst_ga), bufstate_T, UNREF_BUFSTATE_EXTMATCH); } else { for (int i = 0; i < p->sst_stacksize; i++) { unref_extmatch(p->sst_union.sst_stack[i].bs_extmatch); @@ -570,11 +565,8 @@ static void clear_syn_state(synstate_T *p) */ static void clear_current_state(void) { - stateitem_T *sip = (stateitem_T *)(current_state.ga_data); - for (int i = 0; i < current_state.ga_len; i++) { - unref_extmatch(sip[i].si_extmatch); - } - ga_clear(¤t_state); +# define UNREF_STATEITEM_EXTMATCH(si) unref_extmatch((si)->si_extmatch) + GA_DEEP_CLEAR(¤t_state, stateitem_T, UNREF_STATEITEM_EXTMATCH); } /* |