54#define MUTT_PDR_NO_FLAGS 0
55#define MUTT_PDR_MINUS (1 << 0)
56#define MUTT_PDR_PLUS (1 << 1)
57#define MUTT_PDR_WINDOW (1 << 2)
58#define MUTT_PDR_ABSOLUTE (1 << 3)
59#define MUTT_PDR_DONE (1 << 4)
60#define MUTT_PDR_ERROR (1 << 8)
63#define MUTT_PDR_ERRORDONE (MUTT_PDR_ERROR | MUTT_PDR_DONE)
73 char *pexpr = s->
dptr;
76 buf_printf(err,
_(
"Error in expression: %s"), pexpr);
97#ifdef USE_DEBUG_GRAPHVIZ
104 char errmsg[256] = { 0 };
105 regerror(rc2, pat->
p.
regex, errmsg,
sizeof(errmsg));
125 struct ListHead *msgid_list = (
struct ListHead *) (user_data);
153 if (!c_external_search_command)
159 char *pexpr = s->
dptr;
163 buf_printf(err,
_(
"Error in expression: %s"), pexpr);
166 if (*tok_buf->
data ==
'\0')
172 buf_addstr(cmd_buf, c_external_search_command);
224static const char *
get_offset(
struct tm *tm,
const char *s,
int sign)
227 int offset = strtol(s, &ps, 0);
228 if (((sign < 0) && (offset > 0)) || ((sign > 0) && (offset < 0)))
234 tm->tm_year += offset;
237 tm->tm_mon += offset;
240 tm->tm_mday += 7 * offset;
243 tm->tm_mday += offset;
246 tm->tm_hour += offset;
249 tm->tm_min += offset;
252 tm->tm_sec += offset;
284 for (
int v = 0; v < 8; v++)
286 if (s[v] && (s[v] >=
'0') && (s[v] <=
'9'))
298 sscanf(s,
"%4d%2d%2d", &year, &month, &mday);
301 if (t->tm_year > 1900)
303 t->tm_mon = month - 1;
306 if ((t->tm_mday < 1) || (t->tm_mday > 31))
311 if ((t->tm_mon < 0) || (t->tm_mon > 11))
320 t->tm_mday = strtol(s, &p, 10);
321 if ((t->tm_mday < 1) || (t->tm_mday > 31))
329 t->tm_mon = tm.tm_mon;
330 t->tm_year = tm.tm_year;
334 t->tm_mon = strtol(p, &p, 10) - 1;
335 if ((t->tm_mon < 0) || (t->tm_mon > 11))
342 t->tm_year = tm.tm_year;
346 t->tm_year = strtol(p, &p, 10);
349 else if (t->tm_year > 1900)
365 bool have_min,
struct tm *base_min,
struct Buffer *err)
370 const char *pt = NULL;
391 memcpy(min, base_min,
sizeof(
struct tm));
405 max->tm_year = min->tm_year;
406 max->tm_mon = min->tm_mon;
407 max->tm_mday = min->tm_mday;
448 buf_printf(err,
_(
"Invalid relative date: %s"), pc - 1);
460 if ((min->tm_year > max->tm_year) ||
461 ((min->tm_year == max->tm_year) && (min->tm_mon > max->tm_mon)) ||
462 ((min->tm_year == max->tm_year) && (min->tm_mon == max->tm_mon) &&
463 (min->tm_mday > max->tm_mday)))
468 min->tm_year = max->tm_year;
472 min->tm_mon = max->tm_mon;
476 min->tm_mday = max->tm_mday;
500 struct tm min = { 0 };
507 struct tm max = { 0 };
515 if (strchr(
"<>=", s[0]))
521 struct tm *tm = NULL;
540 char *offset_type = NULL;
541 strtol(s + 1, &offset_type, 0);
542 if (!(*offset_type && strchr(
"HMS", *offset_type)))
555 memcpy(&min, &max,
sizeof(max));
565 bool have_min =
false;
566 bool until_now =
false;
567 if (isdigit((
unsigned char) *pc))
579 const char *pt = pc + 1;
581 until_now = (*pt ==
'\0');
588 struct tm base_min = { 0 };
592 memcpy(&base_min, &min,
sizeof(base_min));
601 max.tm_year = min.tm_year;
602 max.tm_mon = min.tm_mon;
603 max.tm_mday = min.tm_mday;
628 bool do_exclusive =
false;
629 bool skip_quote =
false;
640 if ((*s->
dptr !=
'-') && (*s->
dptr !=
'<'))
646 pat->
min = strtol(s->
dptr + 1, &tmp, 0) + 1;
650 pat->
min = strtol(s->
dptr, &tmp, 0);
652 if (toupper((
unsigned char) *tmp) ==
'K')
657 else if (toupper((
unsigned char) *tmp) ==
'M')
682 if (isdigit((
unsigned char) *tmp))
685 pat->
max = strtol(tmp, &tmp, 0);
686 if (toupper((
unsigned char) *tmp) ==
'K')
691 else if (toupper((
unsigned char) *tmp) ==
'M')
704 if (skip_quote && (*tmp ==
'"'))
721 char *pexpr = s->
dptr;
724 buf_printf(err,
_(
"Error in expression: %s"), pexpr);
807#ifdef USE_DEBUG_GRAPHVIZ
808 FREE(&np->raw_pattern);
834 struct PatternList *h =
mutt_mem_calloc(1,
sizeof(
struct PatternList));
873 leaf->
child = *curlist;
912 struct PatternList *curlist = NULL;
913 bool pat_not =
false;
914 bool all_addr =
false;
916 bool implicit =
true;
917 bool is_alias =
false;
923 if (!s || (s[0] ==
'\0'))
940 all_addr = !all_addr;
948 is_alias = !is_alias;
980 if (ps->
dptr[1] ==
'\0')
986 if (ps->
dptr[1] ==
'(')
988 else if ((ps->
dptr[1] ==
'<') && (ps->
dptr[2] ==
'('))
990 else if ((ps->
dptr[1] ==
'>') && (ps->
dptr[2] ==
'('))
1004 leaf->
op = thread_op;
1023 if (implicit && pat_or)
1037 if (entry->
flags && ((flags & entry->
flags) == 0))
1050 leaf->
op = entry->
op;
1060 if (ps->
dptr[0] ==
'\0')
1072 if (!
eat_date(leaf, flags, ps, err))
1084 if (!
eat_query(leaf, flags, ps, err, m))
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
void buf_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into 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.
uint16_t ParseDateRangeFlags
Flags for parse_date_range(), e.g. MUTT_PDR_MINUS.
#define MUTT_PDR_ERROR
Invalid pattern.
#define MUTT_PDR_ABSOLUTE
Absolute pattern range.
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.
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.
static struct PatternList * mutt_pattern_list_new(void)
Create a new list containing a Pattern.
struct PatternList * mutt_pattern_comp(struct MailboxView *mv, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
#define MUTT_PDR_ERRORDONE
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
#define MUTT_PDR_MINUS
Pattern contains a range.
#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.
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
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_file_fclose(FP)
#define MUTT_RL_NO_FLAGS
No flags are set.
char ** EnvList
Private copy of the environment variables.
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 -.
bool eat_message_range(struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err, struct MailboxView *mv)
Parse a range of message numbers - 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_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.
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.
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.
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, char **envlist)
Set up filter program.
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.
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.
@ 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.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to 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.
char * data
Pointer to data.
struct Mailbox * mailbox
Current Mailbox.
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)