From: Mehdi Abaakouk Date: Wed, 20 Sep 2017 09:05:35 +0000 (+0200) Subject: tags: Don't duplicate tags allocation X-Git-Tag: neomutt-20171006~8^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=58a1469ed575499b6df624c672eba304323028c6;p=neomutt tags: Don't duplicate tags allocation The HeaderTags and TagList structure can be replaced by a simple linked list. --- diff --git a/copy.c b/copy.c index f3ceaa70a..71014bd7d 100644 --- a/copy.c +++ b/copy.c @@ -465,13 +465,14 @@ int mutt_copy_header(FILE *in, struct Header *h, FILE *out, int flags, const cha fputs(buf, out); fputc('\n', out); } - const char *tags = driver_tags_get(h->tags); + char *tags = driver_tags_get(&h->tags); if (tags && !(option(OPT_WEED) && mutt_matches_ignore("tags"))) { fputs("Tags: ", out); fputs(tags, out); fputc('\n', out); } + FREE(&tags); } #endif diff --git a/curs_main.c b/curs_main.c index 85fdcc2a5..f480403c8 100644 --- a/curs_main.c +++ b/curs_main.c @@ -1865,8 +1865,11 @@ int mutt_index_menu(void) CHECK_MSGCOUNT; CHECK_VISIBLE; CHECK_READONLY; - - rc = mx_tags_editor(Context, tag ? NULL : driver_tags_get_with_hidden(CURHDR->tags), buf, sizeof(buf)); + char *tags = NULL; + if (!tag) + tags = driver_tags_get_with_hidden(&CURHDR->tags); + rc = mx_tags_editor(Context, tags, buf, sizeof(buf)); + FREE(&tags); if (rc < 0) break; else if (rc == 0) diff --git a/hcache/hcache.c b/hcache/hcache.c index 2e6c0c96c..6f210d306 100644 --- a/hcache/hcache.c +++ b/hcache/hcache.c @@ -60,6 +60,7 @@ #include "list.h" #include "mbyte.h" #include "mutt_regex.h" +#include "mutt_tags.h" #include "parameter.h" #include "protos.h" #include "rfc822.h" @@ -685,7 +686,7 @@ static void *hcache_dump(header_cache_t *h, struct Header *header, int *off, nh.path = NULL; nh.tree = NULL; nh.thread = NULL; - nh.tags = NULL; + STAILQ_INIT(&nh.tags); #ifdef MIXMASTER STAILQ_INIT(&nh.chain); #endif diff --git a/hdrline.c b/hdrline.c index 7b96913bf..b7c1bea69 100644 --- a/hdrline.c +++ b/hdrline.c @@ -510,7 +510,7 @@ static const char *hdr_format_str(char *dest, size_t destlen, size_t col, int co struct HdrFormatInfo *hfi = (struct HdrFormatInfo *) data; struct Header *hdr = NULL, *htmp = NULL; struct Context *ctx = NULL; - char fmt[SHORT_STRING], buf2[LONG_STRING], *p = NULL; + char fmt[SHORT_STRING], buf2[LONG_STRING], *p, *tags = NULL; char *wch = NULL; int do_locales, i; int optional = (flags & MUTT_FORMAT_OPTIONAL); @@ -840,20 +840,20 @@ static const char *hdr_format_str(char *dest, size_t destlen, size_t col, int co optional = 0; break; - case 'g': + case 'g':; + tags = driver_tags_get_transformed(&hdr->tags); if (!optional) { colorlen = add_index_color(dest, destlen, flags, MT_COLOR_INDEX_TAGS); - mutt_format_s(dest + colorlen, destlen - colorlen, prefix, - driver_tags_get_transformed(hdr->tags)); + mutt_format_s(dest + colorlen, destlen - colorlen, prefix, NONULL(tags)); add_index_color(dest + colorlen, destlen - colorlen, flags, MT_COLOR_INDEX); } - else if (!driver_tags_get_transformed(hdr->tags)) + else if (!tags) optional = 0; + FREE(&tags); break; case 'G':; - const char *tag_transformed = NULL; char format[3]; char *tag = NULL; @@ -866,11 +866,11 @@ static const char *hdr_format_str(char *dest, size_t destlen, size_t col, int co tag = hash_find(TagFormats, format); if (tag) { - tag_transformed = driver_tags_get_transformed_for(tag, hdr->tags); + tags = driver_tags_get_transformed_for(tag, &hdr->tags); colorlen = add_index_color(dest, destlen, flags, MT_COLOR_INDEX_TAG); - mutt_format_s(dest + colorlen, destlen - colorlen, prefix, - (tag_transformed) ? tag_transformed : ""); + mutt_format_s(dest + colorlen, destlen - colorlen, prefix, NONULL(tags)); add_index_color(dest + colorlen, destlen - colorlen, flags, MT_COLOR_INDEX); + FREE(&tags); } src++; } @@ -881,9 +881,12 @@ static const char *hdr_format_str(char *dest, size_t destlen, size_t col, int co format[2] = 0; tag = hash_find(TagFormats, format); - if (tag) - if (driver_tags_get_transformed_for(tag, hdr->tags) == NULL) + if (tag) { + tags = driver_tags_get_transformed_for(tag, &hdr->tags); + if (!tags) optional = 0; + FREE(&tags); + } } break; @@ -904,22 +907,20 @@ static const char *hdr_format_str(char *dest, size_t destlen, size_t col, int co break; case 'J':; - const char *tags = driver_tags_get_transformed(hdr->tags); + tags = driver_tags_get_transformed(&hdr->tags); if (tags) { i = 1; /* reduce reuse recycle */ - htmp = NULL; - - if (flags & MUTT_FORMAT_TREE && - (hdr->thread->prev && hdr->thread->prev->message && - driver_tags_get_transformed(hdr->thread->prev->message->tags))) - htmp = hdr->thread->prev->message; - else if (flags & MUTT_FORMAT_TREE && - (hdr->thread->parent && hdr->thread->parent->message && - driver_tags_get_transformed(hdr->thread->parent->message->tags))) - htmp = hdr->thread->parent->message; - if (htmp && mutt_strcasecmp(tags, driver_tags_get_transformed(htmp->tags)) == 0) - i = 0; + if (flags & MUTT_FORMAT_TREE){ + char *parent_tags = NULL; + if (hdr->thread->prev && hdr->thread->prev->message) + parent_tags = driver_tags_get_transformed(&hdr->thread->prev->message->tags); + if (!parent_tags && hdr->thread->parent && hdr->thread->parent->message) + parent_tags = driver_tags_get_transformed(&hdr->thread->parent->message->tags); + if (parent_tags && mutt_strcasecmp(tags, parent_tags) == 0) + i = 0; + FREE(&parent_tags); + } } else i = 0; @@ -933,6 +934,7 @@ static const char *hdr_format_str(char *dest, size_t destlen, size_t col, int co else mutt_format_s(dest + colorlen, destlen - colorlen, prefix, ""); add_index_color(dest + colorlen, destlen - colorlen, flags, MT_COLOR_INDEX); + FREE(&tags); break; case 'l': diff --git a/header.h b/header.h index 278ff3e6f..75c2df138 100644 --- a/header.h +++ b/header.h @@ -109,7 +109,8 @@ struct Header int refno; /**< message number on server */ #endif - struct TagHead *tags; /**< for drivers that support server tagging */ + struct TagHead tags; /**< for drivers that support server tagging */ + #if defined(USE_POP) || defined(USE_IMAP) || defined(USE_NNTP) || defined(USE_NOTMUCH) void *data; /**< driver-specific data */ void (*free_cb)(struct Header *); /**< driver-specific data free function */ @@ -124,6 +125,7 @@ static inline struct Header *mutt_new_header(void) #ifdef MIXMASTER STAILQ_INIT(&h->chain); #endif + STAILQ_INIT(&h->tags); return h; } diff --git a/imap/imap.c b/imap/imap.c index cb06916e4..86595db46 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -1143,6 +1143,7 @@ int imap_sync_message_for_copy(struct ImapData *idata, struct Header *hdr, struct Buffer *cmd, int *err_continue) { char flags[LONG_STRING]; + char *tags; char uid[11]; if (!compare_flags_for_copy(hdr)) @@ -1172,8 +1173,11 @@ int imap_sync_message_for_copy(struct ImapData *idata, struct Header *hdr, if (HEADER_DATA(hdr)->flags_system) safe_strcat(flags, sizeof(flags), HEADER_DATA(hdr)->flags_system); /* set custom flags */ - if (driver_tags_get_with_hidden(hdr->tags)) - safe_strcat(flags, sizeof(flags), driver_tags_get_with_hidden(hdr->tags)); + tags = driver_tags_get_with_hidden(&hdr->tags); + if (tags) { + safe_strcat(flags, sizeof(flags), tags); + FREE(&tags); + } } mutt_remove_trailing_ws(flags); @@ -1221,7 +1225,7 @@ int imap_sync_message_for_copy(struct ImapData *idata, struct Header *hdr, /* server have now the updated flags */ FREE(&HEADER_DATA(hdr)->flags_remote); - HEADER_DATA(hdr)->flags_remote = safe_strdup(driver_tags_get_with_hidden(hdr->tags)); + HEADER_DATA(hdr)->flags_remote = driver_tags_get_with_hidden(&hdr->tags); hdr->active = true; if (hdr->deleted == HEADER_DATA(hdr)->deleted) @@ -1427,9 +1431,9 @@ static int imap_commit_message_tags(struct Context *ctx, struct Header *h, char /* We are good sync them */ mutt_debug(1, "NEW TAGS: %d\n", tags); - driver_tags_replace(h->tags, tags); + driver_tags_replace(&h->tags, tags); FREE(&HEADER_DATA(h)->flags_remote); - HEADER_DATA(h)->flags_remote = safe_strdup(driver_tags_get_with_hidden(h->tags)); + HEADER_DATA(h)->flags_remote = driver_tags_get_with_hidden(&h->tags); return 0; } diff --git a/imap/message.c b/imap/message.c index 319129b8e..c54d6a9ef 100644 --- a/imap/message.c +++ b/imap/message.c @@ -636,8 +636,8 @@ int imap_read_headers(struct ImapData *idata, unsigned int msn_begin, unsigned i ctx->hdrs[idx]->changed = h.data->changed; /* ctx->hdrs[msgno]->received is restored from mutt_hcache_restore */ ctx->hdrs[idx]->data = (void *) (h.data); - driver_tags_init(ctx->hdrs[idx]->tags); - driver_tags_replace(ctx->hdrs[idx]->tags, safe_strdup(h.data->flags_remote)); + STAILQ_INIT(&ctx->hdrs[idx]->tags); + driver_tags_replace(&ctx->hdrs[idx]->tags, safe_strdup(h.data->flags_remote)); ctx->msgcount++; ctx->size += ctx->hdrs[idx]->content->length; @@ -756,8 +756,8 @@ int imap_read_headers(struct ImapData *idata, unsigned int msn_begin, unsigned i ctx->hdrs[idx]->changed = h.data->changed; ctx->hdrs[idx]->received = h.received; ctx->hdrs[idx]->data = (void *) (h.data); - driver_tags_init(ctx->hdrs[idx]->tags); - driver_tags_replace(ctx->hdrs[idx]->tags, safe_strdup(h.data->flags_remote)); + STAILQ_INIT(&ctx->hdrs[idx]->tags); + driver_tags_replace(&ctx->hdrs[idx]->tags, safe_strdup(h.data->flags_remote)); if (maxuid < h.data->uid) maxuid = h.data->uid; @@ -1480,7 +1480,7 @@ char *imap_set_flags(struct ImapData *idata, struct Header *h, char *s, int *ser return NULL; /* Update tags system */ - driver_tags_replace(h->tags, safe_strdup(hd->flags_remote)); + driver_tags_replace(&h->tags, safe_strdup(hd->flags_remote)); /* YAUH (yet another ugly hack): temporarily set context to * read-write even if it's read-only, so *server* updates of diff --git a/mutt.h b/mutt.h index c97a1cb04..35da5ef25 100644 --- a/mutt.h +++ b/mutt.h @@ -34,6 +34,7 @@ struct ReplaceList; struct RegexList; struct State; struct ListHead; +struct TagHead; struct Mapping; /* On OS X 10.5.x, wide char functions are inlined by default breaking diff --git a/mutt_notmuch.c b/mutt_notmuch.c index a8015603c..484a890e2 100644 --- a/mutt_notmuch.c +++ b/mutt_notmuch.c @@ -842,6 +842,7 @@ static int update_header_tags(struct Header *h, notmuch_message_t *msg) #endif notmuch_tags_t *tags = NULL; char *new_tags = NULL; + char *old_tags = NULL; mutt_debug(2, "nm: tags update requested (%s)\n", data->virtual_id); @@ -856,17 +857,28 @@ static int update_header_tags(struct Header *h, notmuch_message_t *msg) mutt_str_append_item(&new_tags, t, ' '); } - if (driver_tags_get(h->tags) && new_tags && (strcmp(driver_tags_get(h->tags), new_tags) == 0)) + + old_tags = driver_tags_get(&h->tags); + + if (new_tags && old_tags && (strcmp(old_tags, new_tags) == 0)) { + FREE(&old_tags); FREE(&new_tags); mutt_debug(2, "nm: tags unchanged\n"); return 1; } /* new version */ - driver_tags_replace(h->tags, new_tags); - mutt_debug(2, "nm: new tags: '%s'\n", driver_tags_get(h->tags)); - mutt_debug(2, "nm: new tag transforms: '%s'\n", driver_tags_get_transformed(h->tags)); + driver_tags_replace(&h->tags, new_tags); + FREE(&new_tags); + + new_tags = driver_tags_get_transformed(&h->tags); + mutt_debug(2, "nm: new tags: '%s'\n", new_tags); + FREE(&new_tags); + + new_tags = driver_tags_get(&h->tags); + mutt_debug(2, "nm: new tag transforms: '%s'\n", new_tags); + FREE(&new_tags); return 0; } @@ -962,7 +974,6 @@ static int init_header(struct Header *h, const char *path, notmuch_message_t *ms h->data = safe_calloc(1, sizeof(struct NmHdrData)); h->free_cb = deinit_header; - driver_tags_init(h->tags); /* * Notmuch ensures that message Id exists (if not notmuch Notmuch will @@ -1597,7 +1608,10 @@ static int rename_filename(struct NmCtxData *data, const char *old, { notmuch_message_maildir_flags_to_tags(msg); update_header_tags(h, msg); - update_tags(msg, driver_tags_get(h->tags)); + + char *tags = driver_tags_get(&h->tags); + update_tags(msg, tags); + FREE(&tags); } rc = 0; @@ -2116,8 +2130,11 @@ int nm_record_message(struct Context *ctx, char *path, struct Header *h) if (st == NOTMUCH_STATUS_SUCCESS && msg) { notmuch_message_maildir_flags_to_tags(msg); - if (h) - update_tags(msg, driver_tags_get(h->tags)); + if (h) { + char *tags = driver_tags_get(&h->tags); + update_tags(msg, tags); + FREE(&tags); + } if (NmRecordTags) update_tags(msg, NmRecordTags); } diff --git a/mutt_tags.c b/mutt_tags.c index 0ead62048..30f153261 100644 --- a/mutt_tags.c +++ b/mutt_tags.c @@ -20,162 +20,134 @@ * this program. If not, see . */ +#include + #include "config.h" #include "mutt_tags.h" #include "globals.h" #include "lib/hash.h" #include "lib/string2.h" -#include "mx.h" +#include "queue.h" + /** - * driver_tags_free_tag_list - free tag - * @param[in] h: pointer to a Header struct + * driver_tags_free - Free tags from a header + * @param[in] head: pointer to the tags head * - * Free tag + * Free the whole tags structure */ -static void driver_tags_free_tag_list(struct TagNode **kw_list) +void driver_tags_free(struct TagHead *head) { - struct TagNode *tmp = NULL; + if (!head) + return; - while ((tmp = *kw_list) != NULL) + struct TagNode *np = STAILQ_FIRST(head), *next = NULL; + while (np) { - *kw_list = tmp->next; - FREE(&tmp->name); - FREE(&tmp->transformed); - FREE(&tmp); + next = STAILQ_NEXT(np, entries); + FREE(&np->name); + FREE(&np->transformed); + FREE(&np); + np = next; } - - *kw_list = 0; + STAILQ_INIT(head); } /** - * driver_tags_free - Free tags from a header - * @param[in] h: pointer to a header struct + * driver_tags_get_transformed - Get transformed tags + * @param[in] head: pointer to the tags head * - * Free the whole tags structure + * Return a new allocated string containing tags separated by space */ -void driver_tags_free(struct TagHead *head) +static char *driver_tags_getter(struct TagHead *head, bool show_hidden, bool show_tranformed, char *filter) { if (!head) - return; - FREE(&head->tags); - FREE(&head->tags_transformed); - FREE(&head->tags_with_hidden); - driver_tags_free_tag_list(&head->tag_list); - FREE(head); + return NULL; + + char *tags = NULL; + struct TagNode *np; + STAILQ_FOREACH(np, head, entries) + { + if(filter && mutt_strcmp(np->name, filter) != 0) + continue; + if (show_hidden || !np->hidden) + { + if (show_tranformed && np->transformed) + mutt_str_append_item(&tags, np->transformed, ' '); + else + mutt_str_append_item(&tags, np->name, ' '); + } + } + return tags; } + /** - * driver_tags_get_transformed - Get transformed tags from a header - * @param[in] h: pointer to a header struct - * - * @return string transformed tags + * driver_tags_get_transformed - Get transformed tags + * @param[in] head: pointer to the tags head * - * Return a string containing all transformed tags separated by space - * without hidden tags + * Return a new allocated string containing all tags separated by space with + * transformation */ -const char *driver_tags_get_transformed(struct TagHead *head) +char *driver_tags_get_transformed(struct TagHead *head) { - if (!head) - return NULL; - if(!head->tags_transformed) - return head->tags; - return head->tags_transformed; + return driver_tags_getter(head, false, true, NULL); } /** - * driver_tags_get - Get tags from a header - * @param[in] h: pointer to a header struct - * - * @return string tags + * driver_tags_get - Get tags + * @param[in] head: pointer to the tags head * - * Return a string containing all tags separated by space with - * hidden tags + * Return a new allocated string containing all tags separated by space */ -const char *driver_tags_get(struct TagHead *head) +char *driver_tags_get(struct TagHead *head) { - if (!head || !head->tags) - return NULL; - return head->tags; + return driver_tags_getter(head, false, false, NULL); } /** - * driver_tags_get_with_hidden - Get tags with hiddens from a header - * @param[in] h: pointer to a header struct - * - * @return string tags + * driver_tags_get_with_hidden - Get tags with hiddens + * @param[in] head: pointer to the tags head * - * Return a string containing all tags separated by space - * even the hiddens. + * Return a new allocated string containing all tags separated by space even + * the hiddens. */ -const char *driver_tags_get_with_hidden(struct TagHead *head) +char *driver_tags_get_with_hidden(struct TagHead *head) { - if (!head || !head->tags_with_hidden) - return NULL; - return head->tags_with_hidden; + return driver_tags_getter(head, true, false, NULL); } /** * driver_tags_get_transformed_for - Get tranformed tag for a tag name from a header * @param[in] tag: char* to the tag to get the transformed version - * @param[in] h: pointer to a header struct + * @param[in] head: pointer to the tags head * * @return string tag * - * Return a string containing transformed tag that match the tag - * even if this is a hidden tags + * Return a new allocated string containing all tags separated by space even + * the hiddens. */ -const char *driver_tags_get_transformed_for(char *name, struct TagHead *head) -{ - if (!head || !head->tag_list) - return NULL; - - struct TagNode *tag = head->tag_list; - while (tag) - { - if (strcmp(tag->name, name) == 0) { - if (!tag->transformed) - return tag->name; - else - return tag->transformed; - } - tag = tag->next; - } - return NULL; -} - -void driver_tags_init(struct TagHead *head) +char *driver_tags_get_transformed_for(char *name, struct TagHead *head) { - head = safe_calloc(1, sizeof(struct TagHead)); - head->tags = NULL; - head->tags_transformed = NULL; - head->tags_with_hidden = NULL; - head->tag_list = NULL; + return driver_tags_getter(head, true, true, name); } /** * driver_tags_add - Add a tag to header - * @param[in] h: pointer to a header struct + * @param[in] head: pointer to the tags head * @param[in] new_tag: string representing the new tag * * Add a tag to the header tags */ static void driver_tags_add(struct TagHead *head, char *new_tag) { - struct TagNode *ttmp = NULL; - char *new_tag_transformed = NULL; + char *new_tag_transformed = hash_find(TagTransforms, new_tag); - new_tag_transformed = hash_find(TagTransforms, new_tag); - - ttmp = safe_calloc(1, sizeof(*ttmp)); - ttmp->name = safe_strdup(new_tag); + struct TagNode *np = safe_calloc(1, sizeof(struct TagNode)); + np->name = safe_strdup(new_tag);; + np->hidden = false; if (new_tag_transformed) - ttmp->transformed = safe_strdup(new_tag_transformed); - ttmp->next = head->tag_list; - head->tag_list = ttmp; - - /* expand the all un-transformed tag string */ - mutt_str_append_item(&head->tags_with_hidden, new_tag, ' '); + np->transformed = safe_strdup(new_tag_transformed); /* filter out hidden tags */ if (HiddenTags) @@ -185,22 +157,15 @@ static void driver_tags_add(struct TagHead *head, char *new_tag) if (p && ((p == HiddenTags) || (*(p - 1) == ',') || (*(p - 1) == ' ')) && ((*(p + xsz) == '\0') || (*(p + xsz) == ',') || (*(p + xsz) == ' '))) - return; + np->hidden = true; } - /* expand the visible un-transformed tag string */ - mutt_str_append_item(&head->tags, new_tag, ' '); - - /* expand the transformed tag string */ - if (new_tag_transformed) - mutt_str_append_item(&head->tags_transformed, new_tag_transformed, ' '); - else - mutt_str_append_item(&head->tags_transformed, new_tag, ' '); + STAILQ_INSERT_TAIL(head, np, entries); } /** * driver_tags_replace - Replace all tags - * @param[in] h: pointer to a header struct + * @param[in] head: pointer to the tags head * @param[in] tags: string of all tags separated by space * * @retval 0 If no change are made @@ -211,12 +176,10 @@ static void driver_tags_add(struct TagHead *head, char *new_tag) */ int driver_tags_replace(struct TagHead *head, char *tags) { - if (tags && head && head->tags && - mutt_strcmp(head->tags, tags) == 0) + if (!head) return 0; driver_tags_free(head); - driver_tags_init(head); if (tags) { diff --git a/mutt_tags.h b/mutt_tags.h index 38006fdc0..ac19fcbd3 100644 --- a/mutt_tags.h +++ b/mutt_tags.h @@ -23,43 +23,33 @@ #ifndef _MUTT_TAG_H #define _MUTT_TAG_H +#include +#include +#include "queue.h" + /** - * struct TagNode - Tag element + * struct TagNode - LinkedList Tag Element * * Keep a linked list of header tags and their transformed values. * Textual tags can be transformed to symbols to save space. * - * @sa TagNodes + * @sa TagNode */ -struct TagNode -{ - char *name; - char *transformed; - struct TagNode *next; -}; -/** - * struct TagHead - tags data attached to an email - * - * This stores all tags data associated with an email. - */ -struct TagHead +STAILQ_HEAD(TagHead, TagNode); +struct TagNode { - /* Without hidden tags */ - char *tags; - char *tags_transformed; - - /* With hidden tags */ - char *tags_with_hidden; - struct TagNode *tag_list; + char *name; + char *transformed; + bool hidden; + STAILQ_ENTRY(TagNode) entries; }; void driver_tags_free(struct TagHead *head); -const char *driver_tags_get(struct TagHead *head); -const char *driver_tags_get_with_hidden(struct TagHead *head); -const char *driver_tags_get_transformed(struct TagHead *head); -const char *driver_tags_get_transformed_for(char *name, struct TagHead *head); -void driver_tags_init(struct TagHead *head); +char *driver_tags_get(struct TagHead *head); +char *driver_tags_get_with_hidden(struct TagHead *head); +char *driver_tags_get_transformed(struct TagHead *head); +char *driver_tags_get_transformed_for(char *name, struct TagHead *head); int driver_tags_replace(struct TagHead *head, char *tags); #endif /* _MUTT_TAG_H */ diff --git a/muttlib.c b/muttlib.c index f6acfb1a8..1643a4129 100644 --- a/muttlib.c +++ b/muttlib.c @@ -167,7 +167,7 @@ void mutt_free_header(struct Header **h) #ifdef MIXMASTER mutt_list_free(&(*h)->chain); #endif - driver_tags_free((*h)->tags); + driver_tags_free(&(*h)->tags); #if defined(USE_POP) || defined(USE_IMAP) || defined(USE_NNTP) || defined(USE_NOTMUCH) if ((*h)->free_cb) (*h)->free_cb(*h); diff --git a/pattern.c b/pattern.c index 4ada30d87..3a1532bcf 100644 --- a/pattern.c +++ b/pattern.c @@ -1714,8 +1714,10 @@ int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, return (pat->not ^ (h->env->x_label && patmatch(pat, h->env->x_label) == 0)); case MUTT_DRIVER_LABEL: { - const char *tags = driver_tags_get(h->tags); - return (pat->not ^ (tags && patmatch(pat, tags) == 0)); + char *tags = driver_tags_get(&h->tags); + bool ret = (pat->not ^ (tags && patmatch(pat, tags) == 0)); + FREE(&tags); + return ret; } case MUTT_HORMEL: return (pat->not ^ (h->env->spam && h->env->spam->data &&