52#define MUTT_PDR_NO_FLAGS 0
53#define MUTT_PDR_MINUS (1 << 0)
54#define MUTT_PDR_PLUS (1 << 1)
55#define MUTT_PDR_WINDOW (1 << 2)
56#define MUTT_PDR_ABSOLUTE (1 << 3)
57#define MUTT_PDR_DONE (1 << 4)
58#define MUTT_PDR_ERROR (1 << 8)
61#define MUTT_PDR_ERRORDONE (MUTT_PDR_ERROR | MUTT_PDR_DONE)
84 char *pexpr = s->
dptr;
90 if (buf->
data[0] ==
'\0')
108#ifdef USE_DEBUG_GRAPHVIZ
115 char errmsg[256] = { 0 };
116 regerror(rc2, pat->
p.
regex, errmsg,
sizeof(errmsg));
136 struct ListHead *msgid_list = (
struct ListHead *) (user_data);
164 if (!c_external_search_command)
170 char *pexpr = s->
dptr;
177 if (*tok_buf->
data ==
'\0')
235static const char *
get_offset(
struct tm *tm,
const char *s,
int sign)
238 int offset = strtol(s, &ps, 0);
239 if (((sign < 0) && (offset > 0)) || ((sign > 0) && (offset < 0)))
245 tm->tm_year += offset;
248 tm->tm_mon += offset;
251 tm->tm_mday += 7 * offset;
254 tm->tm_mday += offset;
257 tm->tm_hour += offset;
260 tm->tm_min += offset;
263 tm->tm_sec += offset;
295 for (
int v = 0; v < 8; v++)
297 if (s[v] && (s[v] >=
'0') && (s[v] <=
'9'))
309 sscanf(s,
"%4d%2d%2d", &year, &month, &mday);
312 if (t->tm_year > 1900)
314 t->tm_mon = month - 1;
317 if ((t->tm_mday < 1) || (t->tm_mday > 31))
322 if ((t->tm_mon < 0) || (t->tm_mon > 11))
331 t->tm_mday = strtol(s, &p, 10);
332 if ((t->tm_mday < 1) || (t->tm_mday > 31))
340 t->tm_mon = tm.tm_mon;
341 t->tm_year = tm.tm_year;
345 t->tm_mon = strtol(p, &p, 10) - 1;
346 if ((t->tm_mon < 0) || (t->tm_mon > 11))
353 t->tm_year = tm.tm_year;
357 t->tm_year = strtol(p, &p, 10);
360 else if (t->tm_year > 1900)
376 bool have_min,
struct tm *base_min,
struct Buffer *err)
381 const char *pt = NULL;
400 memcpy(min, base_min,
sizeof(
struct tm));
412 max->tm_year = min->tm_year;
413 max->tm_mon = min->tm_mon;
414 max->tm_mday = min->tm_mday;
463 if ((min->tm_year > max->tm_year) ||
464 ((min->tm_year == max->tm_year) && (min->tm_mon > max->tm_mon)) ||
465 ((min->tm_year == max->tm_year) && (min->tm_mon == max->tm_mon) &&
466 (min->tm_mday > max->tm_mday)))
471 min->tm_year = max->tm_year;
475 min->tm_mon = max->tm_mon;
479 min->tm_mday = max->tm_mday;
503 struct tm min = { 0 };
510 struct tm max = { 0 };
518 if (strchr(
"<>=", s[0]))
524 struct tm *tm = NULL;
543 char *offset_type = NULL;
544 strtol(s + 1, &offset_type, 0);
545 if (!(*offset_type && strchr(
"HMS", *offset_type)))
558 memcpy(&min, &max,
sizeof(max));
568 bool have_min =
false;
569 bool until_now =
false;
570 if (isdigit((
unsigned char) *pc))
582 const char *pt = pc + 1;
584 until_now = (*pt ==
'\0');
595 memcpy(&base_min, &min,
sizeof(base_min));
604 max.tm_year = min.tm_year;
605 max.tm_mon = min.tm_mon;
606 max.tm_mday = min.tm_mday;
631 bool do_exclusive =
false;
632 bool skip_quote =
false;
643 if ((*s->
dptr !=
'-') && (*s->
dptr !=
'<'))
649 pat->
min = strtol(s->
dptr + 1, &tmp, 0) + 1;
652 pat->
min = strtol(s->
dptr, &tmp, 0);
653 if (toupper((
unsigned char) *tmp) ==
'K')
658 else if (toupper((
unsigned char) *tmp) ==
'M')
683 if (isdigit((
unsigned char) *tmp))
686 pat->
max = strtol(tmp, &tmp, 0);
687 if (toupper((
unsigned char) *tmp) ==
'K')
692 else if (toupper((
unsigned char) *tmp) ==
'M')
703 if (skip_quote && (*tmp ==
'"'))
720 size_t ds = err->
dsize;
722 if (regerror(regerr, preg, err->
data, ds) > ds)
741 const char *context_req_chars[] = {
752 char *context_loc = strpbrk(s->
dptr + pmatch[0].rm_so, context_req_chars[kind]);
753 if (!context_loc || (context_loc >= &s->
dptr[pmatch[0].rm_eo]))
778 int num = (int) strtol(&s->
dptr[pmatch[group].rm_so], NULL, 0);
779 unsigned char c = (
unsigned char) (s->
dptr[pmatch[group].rm_eo - 1]);
780 if (toupper(c) ==
'K')
782 else if (toupper(c) ==
'M')
789 return num +
EMSG(e);
812 int side,
int kind,
struct Mailbox *m,
struct Menu *menu)
815 if ((pmatch[grp].rm_so == -1) || (pmatch[grp].rm_so == pmatch[grp].rm_eo))
823 unsigned char c = (
unsigned char) (s->
dptr[pmatch[grp].rm_so]);
877 regerr = regcomp(&pspec->
cooked, pspec->
raw, REG_EXTENDED);
917 s->
dptr += pmatch[0].rm_eo;
942 bool skip_quote =
false;
964 if (skip_quote && (*s->
dptr ==
'"'))
982 char *pexpr = s->
dptr;
1060#ifdef USE_DEBUG_GRAPHVIZ
1061 FREE(&np->raw_pattern);
1087 struct PatternList *h =
mutt_mem_calloc(1,
sizeof(
struct PatternList));
1126 leaf->
child = *curlist;
1164 struct PatternList *curlist = NULL;
1165 bool pat_not =
false;
1166 bool all_addr =
false;
1167 bool pat_or =
false;
1168 bool implicit =
true;
1169 bool is_alias =
false;
1175 if (!s || (s[0] ==
'\0'))
1182 ps.
dptr = (
char *) s;
1192 all_addr = !all_addr;
1200 is_alias = !is_alias;
1231 if (ps.
dptr[1] ==
'\0')
1236 short thread_op = 0;
1237 if (ps.
dptr[1] ==
'(')
1239 else if ((ps.
dptr[1] ==
'<') && (ps.
dptr[2] ==
'('))
1241 else if ((ps.
dptr[1] ==
'>') && (ps.
dptr[2] ==
'('))
1255 leaf->
op = thread_op;
1275 if (implicit && pat_or)
1289 if (entry->
flags && ((flags & entry->
flags) == 0))
1302 leaf->
op = entry->
op;
1312 if (ps.
dptr[0] ==
'\0')
1324 if (!
eat_date(leaf, flags, &ps, err))
1336 if (!
eat_query(leaf, flags, &ps, err, m))
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
#define MUTT_PDR_PLUS
Extend the range using '+'.
#define MUTT_PDR_NO_FLAGS
No flags are set.
bool eval_date_minmax(struct Pattern *pat, const char *s, struct Buffer *err)
Evaluate a date-range pattern against 'now'.
static struct Pattern * attach_new_root(struct PatternList **curlist)
Create a new Pattern as a parent for a List.
static int scan_range_slot(struct Buffer *s, regmatch_t pmatch[], int grp, int side, int kind, struct Mailbox *m, struct Menu *menu)
Parse a range of message numbers.
uint16_t ParseDateRangeFlags
Flags for parse_date_range(), e.g. MUTT_PDR_MINUS.
#define MUTT_PDR_ERROR
Invalid pattern.
static int scan_range_num(struct Buffer *s, regmatch_t pmatch[], int group, int kind, struct Mailbox *m, struct Menu *menu)
Parse a number range.
#define MUTT_PDR_ABSOLUTE
Absolute pattern range.
static int eat_range_by_regex(struct Pattern *pat, struct Buffer *s, int kind, struct Buffer *err, struct Mailbox *m, struct Menu *menu)
Parse a range given as a regex.
static struct Pattern * attach_new_leaf(struct PatternList **curlist)
Attach a new Pattern to a List.
static struct Pattern * attach_leaf(struct PatternList *list, struct Pattern *leaf)
Attach a Pattern to a Pattern List.
static const char * parse_date_range(const char *pc, struct tm *min, struct tm *max, bool have_min, struct tm *base_min, struct Buffer *err)
Parse a date range.
static char * find_matching_paren(char *s)
Find the matching parenthesis.
static void adjust_date_range(struct tm *min, struct tm *max)
Put a date range in the correct order.
static struct Pattern * mutt_pattern_new(void)
Create a new Pattern.
EatRangeError
Error codes for eat_range_by_regex()
@ RANGE_E_MVIEW
Range requires MailboxView, but none available.
@ RANGE_E_OK
Range is valid.
@ RANGE_E_SYNTAX
Range contains syntax error.
static const char * get_offset(struct tm *tm, const char *s, int sign)
Calculate a symbolic offset.
#define MUTT_PDR_DONE
Pattern parse successfully.
static const char * get_date(const char *s, struct tm *t, struct Buffer *err)
Parse a (partial) date in dd/mm/yyyy format.
struct PatternList * mutt_pattern_comp(struct Mailbox *m, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
static struct PatternList * mutt_pattern_list_new(void)
Create a new list containing a Pattern.
static void order_range(struct Pattern *pat)
Put a range in order.
#define MUTT_PDR_ERRORDONE
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
#define MUTT_PDR_MINUS
Pattern contains a range.
static int report_regerror(int regerr, regex_t *preg, struct Buffer *err)
Create a regex error message.
static bool is_menu_available(struct Buffer *s, regmatch_t pmatch[], int kind, struct Buffer *err, const struct Menu *menu)
Do we need a MailboxView for this Pattern?
#define MUTT_PDR_WINDOW
Extend the range in both directions using '*'.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
time_t mutt_date_make_time(struct tm *t, bool local)
Convert struct tm to time_t
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
void mutt_date_normalize_time(struct tm *tm)
Fix the contents of a struct tm.
Structs that make up an email.
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
bool mutt_file_map_lines(mutt_file_map_t func, void *user_data, FILE *fp, ReadLineFlags flags)
Process lines of text read from a file pointer.
#define MUTT_RL_NO_FLAGS
No flags are set.
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
static bool eat_query(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err, struct Mailbox *m)
Parse a query for an external search program - Implements eat_arg_t -.
static bool eat_range(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Parse a number range - Implements eat_arg_t -.
static bool eat_date(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Parse a date pattern - Implements eat_arg_t -.
static bool eat_message_range(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err, struct Mailbox *m, struct Menu *menu)
Parse a range of message numbers - Implements eat_arg_t -.
static bool eat_regex(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
Parse a regex - Implements eat_arg_t -.
#define mutt_message(...)
#define mutt_debug(LEVEL,...)
static bool add_query_msgid(char *line, int line_num, void *user_data)
Parse a Message-Id and add it to a list - Implements mutt_file_map_t -.
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
void mutt_list_clear(struct ListHead *h)
Free a list, but NOT its strings.
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
@ LL_DEBUG2
Log at debug level 2.
@ LL_DEBUG1
Log at debug level 1.
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Convenience wrapper for the library headers.
char * mutt_path_escape(const char *src)
Escapes single quotes in a path for a command string.
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
char * mutt_str_dup(const char *str)
Copy a string, safely.
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
The "currently-open" mailbox.
const struct PatternFlags * lookup_tag(char tag)
Lookup a pattern modifier.
#define MUTT_PC_SEND_MODE_SEARCH
Allow send-mode body searching.
uint8_t PatternCompFlags
Flags for mutt_pattern_comp(), e.g. MUTT_PC_FULL_MSG.
@ MUTT_PAT_OR
Either pattern can match.
@ MUTT_PAT_CHILDREN
Pattern matches a child email.
@ MUTT_PAT_PARENT
Pattern matches parent.
@ MUTT_PAT_AND
Both patterns must match.
@ MUTT_PAT_THREAD
Pattern matches email thread.
#define MUTT_PC_PATTERN_DYNAMIC
Enable runtime date range evaluation.
@ RANGE_S_LEFT
Left side of range.
@ RANGE_S_RIGHT
Right side of range.
@ EAT_RANGE
Process a number (range)
@ EAT_MESSAGE_RANGE
Process a message number (range)
@ EAT_DATE
Process a date (range)
@ EAT_QUERY
Process a query string.
@ EAT_REGEX
Process a regex.
@ RANGE_K_REL
Relative range.
@ RANGE_K_ABS
Absolute range.
@ RANGE_K_LT
Less-than range.
@ RANGE_K_INVALID
Range is invalid.
@ RANGE_K_BARE
Single symbol.
@ RANGE_K_GT
Greater-than range.
struct RangeRegex RangeRegexes[]
Set of Regexes for various range types.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
#define SLIST_FOREACH(var, head, field)
#define SLIST_INSERT_HEAD(head, elm, field)
#define SLIST_NEXT(elm, field)
#define SLIST_FIRST(head)
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
String manipulation buffer.
char * dptr
Current read/write position.
size_t dsize
Length of data.
char * data
Pointer to data.
The envelope/body of an email.
int msg_count
Total number of messages.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.
Mapping between user character and internal constant.
enum PatternEat eat_arg
Type of function needed to parse flag, e.g. EAT_DATE.
PatternCompFlags flags
Pattern flags, e.g. MUTT_PC_FULL_MSG.
int op
Operation to perform, e.g. MUTT_PAT_SCORE.
A simple (non-regex) pattern.
bool group_match
Check a group of Addresses.
bool all_addr
All Addresses in the list must match.
struct Group * group
Address group if group_match is set.
struct PatternList * child
Arguments to logical operation.
long min
Minimum for range checks.
bool string_match
Check a string for a match.
regex_t * regex
Compiled regex, for non-pattern matching.
struct ListHead multi_cases
Multiple strings for ~I pattern.
char * str
String, if string_match is set.
bool is_alias
Is there an alias for this Address?
bool ign_case
Ignore case for local string_match searches.
long max
Maximum for range checks.
bool dynamic
Evaluate date ranges at run time.
short op
Operation, e.g. MUTT_PAT_SCORE.
bool sendmode
Evaluate searches in send-mode.
bool is_multi
Multiple case (only for ~I pattern now)
bool pat_not
Pattern should be inverted (not)
Regular expression representing a range.
int lgrp
Paren group matching the left side.
int rgrp
Paren group matching the right side.
regex_t cooked
Compiled form.
const char * raw
Regex as string.