From 696e7fa97f527fc1aaafb3f6206da57d923ddcca Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Sat, 18 Aug 2018 15:37:13 +0100 Subject: [PATCH] Convert ReplaceList to use STAILQ --- email/email_globals.c | 2 +- email/email_globals.h | 8 +-- email/parse.c | 2 +- globals.h | 2 +- hcache/hcache.c | 8 +-- hdrline.c | 6 +- init.c | 4 +- mutt/regex.c | 149 ++++++++++++++++++------------------------ mutt/regex3.h | 35 +++++----- 9 files changed, 98 insertions(+), 118 deletions(-) diff --git a/email/email_globals.c b/email/email_globals.c index 8f53c0527..c99c5e9fa 100644 --- a/email/email_globals.c +++ b/email/email_globals.c @@ -39,6 +39,6 @@ bool Weed = false; ///< Config: Filter headers when displaying/forwarding/printi /* Global variables */ struct RegexList NoSpamList = STAILQ_HEAD_INITIALIZER(NoSpamList); -struct ReplaceList *SpamList = NULL; +struct ReplaceList SpamList = STAILQ_HEAD_INITIALIZER(SpamList); struct ListHead Ignore = STAILQ_HEAD_INITIALIZER(Ignore); struct ListHead UnIgnore = STAILQ_HEAD_INITIALIZER(UnIgnore); diff --git a/email/email_globals.h b/email/email_globals.h index 63b70e955..3b2fc5e0e 100644 --- a/email/email_globals.h +++ b/email/email_globals.h @@ -34,9 +34,9 @@ extern char * SpamSeparator; extern bool Weed; /* Global variables */ -extern struct ListHead Ignore; -extern struct RegexList NoSpamList; -extern struct ReplaceList *SpamList; -extern struct ListHead UnIgnore; +extern struct ListHead Ignore; +extern struct RegexList NoSpamList; +extern struct ReplaceList SpamList; +extern struct ListHead UnIgnore; #endif /* _EMAIL_GLOBALS_H */ diff --git a/email/parse.c b/email/parse.c index b71c4a5fb..5c0e91124 100644 --- a/email/parse.c +++ b/email/parse.c @@ -1011,7 +1011,7 @@ struct Envelope *mutt_rfc822_read_header(FILE *f, struct Header *hdr, bool user_ *buf = '\0'; - if (mutt_replacelist_match(SpamList, buf, sizeof(buf), line)) + if (mutt_replacelist_match(&SpamList, buf, sizeof(buf), line)) { if (!mutt_regexlist_match(&NoSpamList, line)) { diff --git a/globals.h b/globals.h index dfd4d80f4..51c9d4c9f 100644 --- a/globals.h +++ b/globals.h @@ -83,7 +83,7 @@ WHERE struct RegexList MailLists INITVAL(STAILQ_HEAD_INITIALIZER(MailLists)); WHERE struct RegexList UnMailLists INITVAL(STAILQ_HEAD_INITIALIZER(UnMailLists)); WHERE struct RegexList SubscribedLists INITVAL(STAILQ_HEAD_INITIALIZER(SubscribedLists)); WHERE struct RegexList UnSubscribedLists INITVAL(STAILQ_HEAD_INITIALIZER(UnSubscribedLists)); -WHERE struct ReplaceList *SubjectRegexList; +WHERE struct ReplaceList SubjectRegexList INITVAL(STAILQ_HEAD_INITIALIZER(SubjectRegexList)); WHERE unsigned short Counter; diff --git a/hcache/hcache.c b/hcache/hcache.c index a8d69c149..6de331386 100644 --- a/hcache/hcache.c +++ b/hcache/hcache.c @@ -268,7 +268,6 @@ header_cache_t *mutt_hcache_open(const char *path, const char *folder, hcache_na unsigned int intval; } digest; struct Md5Ctx ctx; - struct ReplaceList *spam = NULL; hcachever = HCACHEVER; @@ -278,10 +277,11 @@ header_cache_t *mutt_hcache_open(const char *path, const char *folder, hcache_na mutt_md5_process_bytes(&hcachever, sizeof(hcachever), &ctx); /* Mix in user's spam list */ - for (spam = SpamList; spam; spam = spam->next) + struct ReplaceListNode *sp = NULL; + STAILQ_FOREACH(sp, &SpamList, entries) { - mutt_md5_process(spam->regex->pattern, &ctx); - mutt_md5_process(spam->template, &ctx); + mutt_md5_process(sp->regex->pattern, &ctx); + mutt_md5_process(sp->template, &ctx); } /* Mix in user's nospam list */ diff --git a/hdrline.c b/hdrline.c index ab185aee0..a6e5f7292 100644 --- a/hdrline.c +++ b/hdrline.c @@ -426,7 +426,7 @@ static char *apply_subject_mods(struct Envelope *env) if (!env) return NULL; - if (!SubjectRegexList) + if (STAILQ_EMPTY(&SubjectRegexList)) return env->subject; if (env->subject == NULL || *env->subject == '\0') @@ -435,7 +435,7 @@ static char *apply_subject_mods(struct Envelope *env) return NULL; } - env->disp_subj = mutt_replacelist_apply(SubjectRegexList, NULL, 0, env->subject); + env->disp_subj = mutt_replacelist_apply(&SubjectRegexList, NULL, 0, env->subject); return env->disp_subj; } @@ -1089,7 +1089,7 @@ static const char *index_format_str(char *buf, size_t buflen, size_t col, int co char *subj = NULL; if (hdr->env->disp_subj) subj = hdr->env->disp_subj; - else if (SubjectRegexList) + else if (!STAILQ_EMPTY(&SubjectRegexList)) subj = apply_subject_mods(hdr->env); else subj = hdr->env->subject; diff --git a/init.c b/init.c index fe3a76d48..29cd3466a 100644 --- a/init.c +++ b/init.c @@ -604,7 +604,7 @@ bail: static int parse_replace_list(struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err) { - struct ReplaceList **list = (struct ReplaceList **) data; + struct ReplaceList *list = (struct ReplaceList *) data; struct Buffer templ = { 0 }; /* First token is a regex. */ @@ -702,7 +702,7 @@ static int parse_unattach_list(struct Buffer *buf, struct Buffer *s, static int parse_unreplace_list(struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err) { - struct ReplaceList **list = (struct ReplaceList **) data; + struct ReplaceList *list = (struct ReplaceList *) data; /* First token is a regex. */ if (!MoreArgs(s)) diff --git a/mutt/regex.c b/mutt/regex.c index 436c7adbe..a720855da 100644 --- a/mutt/regex.c +++ b/mutt/regex.c @@ -257,17 +257,13 @@ int mutt_regexlist_remove(struct RegexList *rl, const char *str) * @retval 0 Success, pattern added to the ReplaceList * @retval -1 Error, see message in 'err' */ -int mutt_replacelist_add(struct ReplaceList **rl, const char *pat, +int mutt_replacelist_add(struct ReplaceList *rl, const char *pat, const char *templ, struct Buffer *err) { - struct ReplaceList *t = NULL, *last = NULL; - struct Regex *rx = NULL; - const char *p = NULL; - if (!pat || !*pat || !templ) return 0; - rx = mutt_regex_compile(pat, REG_ICASE); + struct Regex *rx = mutt_regex_compile(pat, REG_ICASE); if (!rx) { mutt_buffer_printf(err, _("Bad regex: %s"), pat); @@ -275,9 +271,10 @@ int mutt_replacelist_add(struct ReplaceList **rl, const char *pat, } /* check to make sure the item is not already on this rl */ - for (last = *rl; last; last = last->next) + struct ReplaceListNode *np = NULL; + STAILQ_FOREACH(np, rl, entries) { - if (mutt_str_strcasecmp(rx->pattern, last->regex->pattern) == 0) + if (mutt_str_strcasecmp(rx->pattern, np->regex->pattern) == 0) { /* Already on the rl. Formerly we just skipped this case, but * now we're supporting removals, which means we're supporting @@ -285,42 +282,38 @@ int mutt_replacelist_add(struct ReplaceList **rl, const char *pat, * removal, then do an add. We can achieve the removal by freeing * the template, and leaving t pointed at the current item. */ - t = last; - FREE(&t->template); + FREE(&np->template); break; } - if (!last->next) - break; } - /* If t is set, it's pointing into an extant ReplaceList* that we want to + /* If np is set, it's pointing into an extant ReplaceList* that we want to * update. Otherwise we want to make a new one to link at the rl's end. */ - if (!t) + if (np) { - t = mutt_replacelist_new(); - t->regex = rx; - rx = NULL; - if (last) - last->next = t; - else - *rl = t; + mutt_regex_free(&rx); } else - mutt_regex_free(&rx); + { + np = mutt_replacelist_new(); + np->regex = rx; + rx = NULL; + STAILQ_INSERT_TAIL(rl, np, entries); + } - /* Now t is the ReplaceList* that we want to modify. It is prepared. */ - t->template = mutt_str_strdup(templ); + /* Now np is the ReplaceListNode that we want to modify. It is prepared. */ + np->template = mutt_str_strdup(templ); /* Find highest match number in template string */ - t->nmatch = 0; - for (p = templ; *p;) + np->nmatch = 0; + for (const char *p = templ; *p;) { if (*p == '%') { int n = atoi(++p); - if (n > t->nmatch) - t->nmatch = n; + if (n > np->nmatch) + np->nmatch = n; while (*p && isdigit((int) *p)) p++; } @@ -328,15 +321,14 @@ int mutt_replacelist_add(struct ReplaceList **rl, const char *pat, p++; } - if (t->nmatch > t->regex->regex->re_nsub) + if (np->nmatch > np->regex->regex->re_nsub) { mutt_buffer_printf(err, "%s", _("Not enough subexpressions for template")); mutt_replacelist_remove(rl, pat); return -1; } - t->nmatch++; /* match 0 is always the whole expr */ - + np->nmatch++; /* match 0 is always the whole expr */ return 0; } @@ -355,7 +347,6 @@ int mutt_replacelist_add(struct ReplaceList **rl, const char *pat, */ char *mutt_replacelist_apply(struct ReplaceList *rl, char *buf, size_t buflen, const char *str) { - struct ReplaceList *l = NULL; static regmatch_t *pmatch = NULL; static size_t nmatch = 0; static char twinbuf[2][LONG_STRING]; @@ -377,27 +368,28 @@ char *mutt_replacelist_apply(struct ReplaceList *rl, char *buf, size_t buflen, c mutt_str_strfcpy(src, str, LONG_STRING); - for (l = rl; l; l = l->next) + struct ReplaceListNode *np = NULL; + STAILQ_FOREACH(np, rl, entries) { /* If this pattern needs more matches, expand pmatch. */ - if (l->nmatch > nmatch) + if (np->nmatch > nmatch) { - mutt_mem_realloc(&pmatch, l->nmatch * sizeof(regmatch_t)); - nmatch = l->nmatch; + mutt_mem_realloc(&pmatch, np->nmatch * sizeof(regmatch_t)); + nmatch = np->nmatch; } - if (regexec(l->regex->regex, src, l->nmatch, pmatch, 0) == 0) + if (regexec(np->regex->regex, src, np->nmatch, pmatch, 0) == 0) { tlen = 0; switcher ^= 1; dst = twinbuf[switcher]; - mutt_debug(5, "%s matches %s\n", src, l->regex->pattern); + mutt_debug(5, "%s matches %s\n", src, np->regex->pattern); /* Copy into other twinbuf with substitutions */ - if (l->template) + if (np->template) { - for (p = l->template; *p && (tlen < LONG_STRING - 1);) + for (p = np->template; *p && (tlen < LONG_STRING - 1);) { if (*p == '%') { @@ -449,19 +441,18 @@ char *mutt_replacelist_apply(struct ReplaceList *rl, char *buf, size_t buflen, c * mutt_replacelist_free - Free a ReplaceList object * @param rl ReplaceList to free */ -void mutt_replacelist_free(struct ReplaceList **rl) +void mutt_replacelist_free(struct ReplaceList *rl) { - struct ReplaceList *p = NULL; - if (!rl) return; - while (*rl) + + struct ReplaceListNode *np = NULL, *tmp = NULL; + STAILQ_FOREACH_SAFE(np, rl, entries, tmp) { - p = *rl; - *rl = (*rl)->next; - mutt_regex_free(&p->regex); - FREE(&p->template); - FREE(&p); + STAILQ_REMOVE(rl, np, ReplaceListNode, entries); + mutt_regex_free(&np->regex); + FREE(&np->template); + FREE(&np); } } @@ -480,31 +471,32 @@ void mutt_replacelist_free(struct ReplaceList **rl) */ bool mutt_replacelist_match(struct ReplaceList *rl, char *buf, size_t buflen, const char *str) { + if (!rl || !buf || !str) + return false; + static regmatch_t *pmatch = NULL; static size_t nmatch = 0; int tlen = 0; char *p = NULL; - if (!str) - return false; - - for (; rl; rl = rl->next) + struct ReplaceListNode *np = NULL; + STAILQ_FOREACH(np, rl, entries) { /* If this pattern needs more matches, expand pmatch. */ - if (rl->nmatch > nmatch) + if (np->nmatch > nmatch) { - mutt_mem_realloc(&pmatch, rl->nmatch * sizeof(regmatch_t)); - nmatch = rl->nmatch; + mutt_mem_realloc(&pmatch, np->nmatch * sizeof(regmatch_t)); + nmatch = np->nmatch; } /* Does this pattern match? */ - if (regexec(rl->regex->regex, str, (size_t) rl->nmatch, pmatch, 0) == 0) + if (regexec(np->regex->regex, str, (size_t) np->nmatch, pmatch, 0) == 0) { - mutt_debug(5, "%s matches %s\n", str, rl->regex->pattern); - mutt_debug(5, "%d subs\n", (int) rl->regex->regex->re_nsub); + mutt_debug(5, "%s matches %s\n", str, np->regex->pattern); + mutt_debug(5, "%d subs\n", (int) np->regex->regex->re_nsub); /* Copy template into buf, with substitutions. */ - for (p = rl->template; *p && tlen < buflen - 1;) + for (p = np->template; *p && tlen < buflen - 1;) { /* backreference to pattern match substring, eg. %1, %2, etc) */ if (*p == '%') @@ -516,7 +508,7 @@ bool mutt_replacelist_match(struct ReplaceList *rl, char *buf, size_t buflen, co /* Ensure that the integer conversion succeeded (e!=p) and bounds check. The upper bound check * should not strictly be necessary since add_to_spam_list() finds the largest value, and * the static array above is always large enough based on that value. */ - if (e != p && n >= 0 && n <= rl->nmatch && pmatch[n].rm_so != -1) + if (e != p && n >= 0 && n <= np->nmatch && pmatch[n].rm_so != -1) { /* copy as much of the substring match as will fit in the output buffer, saving space for * the terminating nul char */ @@ -555,9 +547,9 @@ bool mutt_replacelist_match(struct ReplaceList *rl, char *buf, size_t buflen, co * mutt_replacelist_new - Create a new ReplaceList * @retval ptr New ReplaceList */ -struct ReplaceList *mutt_replacelist_new(void) +struct ReplaceListNode *mutt_replacelist_new(void) { - return mutt_mem_calloc(1, sizeof(struct ReplaceList)); + return mutt_mem_calloc(1, sizeof(struct ReplaceListNode)); } /** @@ -566,36 +558,23 @@ struct ReplaceList *mutt_replacelist_new(void) * @param pat Pattern to remove * @retval num Matching patterns removed */ -int mutt_replacelist_remove(struct ReplaceList **rl, const char *pat) +int mutt_replacelist_remove(struct ReplaceList *rl, const char *pat) { - /* Being first is a special case. */ - struct ReplaceList *cur = *rl; - if (!cur) + if (!rl || !pat) return 0; - if (cur->regex && (mutt_str_strcmp(cur->regex->pattern, pat) == 0)) - { - *rl = cur->next; - mutt_regex_free(&cur->regex); - FREE(&cur->template); - FREE(&cur); - return 1; - } int nremoved = 0; - struct ReplaceList *prev = cur; - for (cur = prev->next; cur;) + struct ReplaceListNode *np = NULL, *tmp = NULL; + STAILQ_FOREACH_SAFE(np, rl, entries, tmp) { - if (mutt_str_strcmp(cur->regex->pattern, pat) == 0) + if (mutt_str_strcmp(np->regex->pattern, pat) == 0) { - prev->next = cur->next; - mutt_regex_free(&cur->regex); - FREE(&cur->template); - FREE(&cur); - cur = prev->next; + STAILQ_REMOVE(rl, np, ReplaceListNode, entries); + mutt_regex_free(&np->regex); + FREE(&np->template); + FREE(&np); nremoved++; } - else - cur = cur->next; } return nremoved; diff --git a/mutt/regex3.h b/mutt/regex3.h index 7ffdb9581..c3bbfa2bb 100644 --- a/mutt/regex3.h +++ b/mutt/regex3.h @@ -73,31 +73,32 @@ struct RegexListNode STAILQ_HEAD(RegexList, RegexListNode); /** - * struct ReplaceList - List of regular expressions + * struct ReplaceListNode - List of regular expressions */ -struct ReplaceList +struct ReplaceListNode { struct Regex *regex; /**< Regex containing a regular expression */ size_t nmatch; /**< Match the 'nth' occurrence (0 means the whole expression) */ char *template; /**< Template to match */ - struct ReplaceList *next; /**< Next item in list */ + STAILQ_ENTRY(ReplaceListNode) entries; /**< Next item in list */ }; +STAILQ_HEAD(ReplaceList, ReplaceListNode); -struct Regex * mutt_regex_compile(const char *str, int flags); -struct Regex * mutt_regex_create(const char *str, int flags, struct Buffer *err); -void mutt_regex_free(struct Regex **r); +struct Regex *mutt_regex_compile(const char *str, int flags); +struct Regex *mutt_regex_create(const char *str, int flags, struct Buffer *err); +void mutt_regex_free(struct Regex **r); -int mutt_regexlist_add(struct RegexList *rl, const char *str, int flags, struct Buffer *err); -void mutt_regexlist_free(struct RegexList *rl); -bool mutt_regexlist_match(struct RegexList *rl, const char *str); -struct RegexListNode * mutt_regexlist_new(void); -int mutt_regexlist_remove(struct RegexList *rl, const char *str); +int mutt_regexlist_add(struct RegexList *rl, const char *str, int flags, struct Buffer *err); +void mutt_regexlist_free(struct RegexList *rl); +bool mutt_regexlist_match(struct RegexList *rl, const char *str); +struct RegexListNode *mutt_regexlist_new(void); +int mutt_regexlist_remove(struct RegexList *rl, const char *str); -int mutt_replacelist_add(struct ReplaceList **rl, const char *pat, const char *templ, struct Buffer *err); -char * mutt_replacelist_apply(struct ReplaceList *rl, char *buf, size_t buflen, const char *str); -void mutt_replacelist_free(struct ReplaceList **rl); -bool mutt_replacelist_match(struct ReplaceList *rl, char *buf, size_t buflen, const char *str); -struct ReplaceList *mutt_replacelist_new(void); -int mutt_replacelist_remove(struct ReplaceList **rl, const char *pat); +int mutt_replacelist_add(struct ReplaceList *rl, const char *pat, const char *templ, struct Buffer *err); +char * mutt_replacelist_apply(struct ReplaceList *rl, char *buf, size_t buflen, const char *str); +void mutt_replacelist_free(struct ReplaceList *rl); +bool mutt_replacelist_match(struct ReplaceList *rl, char *buf, size_t buflen, const char *str); +struct ReplaceListNode *mutt_replacelist_new(void); +int mutt_replacelist_remove(struct ReplaceList *rl, const char *pat); #endif /* _MUTT_REGEX_H */ -- 2.50.1