NeoMutt  2025-12-11-911-gd8d604
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
Parse a pattern API

Prototype for a function to parse a pattern. More...

Functions

static bool eat_regex (struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
 Parse a regex - Implements eat_arg_t -.
 
static bool eat_string (struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
 Parse a plain string - Implements eat_arg_t -.
 
static bool eat_group (struct Pattern *pat, PatternCompFlags flags, struct Buffer *s, struct Buffer *err)
 Parse a group name - Implements eat_arg_t -.
 
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 -.
 
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 -.
 

Detailed Description

Prototype for a function to parse a pattern.

Parameters
patPattern to store the results in
flagsFlags, e.g. MUTT_PC_PATTERN_DYNAMIC
sString to parse
errBuffer for error messages
Return values
trueThe pattern was read successfully

Function Documentation

◆ eat_regex()

static bool eat_regex ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err )
static

Parse a regex - Implements eat_arg_t -.

Definition at line 72 of file compile.c.

74{
75 struct Buffer *token = buf_pool_get();
76 bool rc = false;
77 const char *pexpr = s->dptr;
78 if ((parse_extract_token(token, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
79 !token->data)
80 {
81 buf_printf(err, _("Error in expression: %s"), pexpr);
82 goto out;
83 }
84 if (buf_is_empty(token))
85 {
86 buf_addstr(err, _("Empty expression"));
87 goto out;
88 }
89
90 pat->p.regex = MUTT_MEM_CALLOC(1, regex_t);
91#ifdef USE_DEBUG_GRAPHVIZ
92 pat->raw_pattern = buf_strdup(token);
93#endif
94 uint16_t case_flags = mutt_mb_is_lower(token->data) ? REG_ICASE : 0;
95 int rc2 = REG_COMP(pat->p.regex, token->data, REG_NEWLINE | REG_NOSUB | case_flags);
96 if (rc2 != 0)
97 {
98 char errmsg[256] = { 0 };
99 regerror(rc2, pat->p.regex, errmsg, sizeof(errmsg));
100 buf_printf(err, "'%s': %s", token->data, errmsg);
101 FREE(&pat->p.regex);
102 goto out;
103 }
104
105 rc = true;
106
107out:
108 buf_pool_release(&token);
109 return rc;
110}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
int parse_extract_token(struct Buffer *dest, struct Buffer *line, TokenFlags flags)
Extract one token from a string.
Definition extract.c:49
@ TOKEN_COMMENT
Don't reap comments.
Definition extract.h:55
@ TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition extract.h:54
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition mbyte.c:355
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
#define _(a)
Definition message.h:28
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition regex3.h:49
String manipulation buffer.
Definition buffer.h:36
char * dptr
Current read/write position.
Definition buffer.h:38
char * data
Pointer to data.
Definition buffer.h:37
union Pattern::@006112053024257132210207314205210350156165326341 p
regex_t * regex
Compiled regex, for non-pattern matching.
Definition lib.h:99
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eat_string()

static bool eat_string ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err )
static

Parse a plain string - Implements eat_arg_t -.

Definition at line 115 of file compile.c.

117{
118 struct Buffer *token = buf_pool_get();
119 bool rc = false;
120 const char *pexpr = s->dptr;
121 if ((parse_extract_token(token, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
122 !token->data)
123 {
124 buf_printf(err, _("Error in expression: %s"), pexpr);
125 goto out;
126 }
127 if (buf_is_empty(token))
128 {
129 buf_addstr(err, _("Empty expression"));
130 goto out;
131 }
132
133 pat->string_match = true;
134 pat->p.str = buf_strdup(token);
135 pat->ign_case = mutt_mb_is_lower(token->data);
136
137 rc = true;
138
139out:
140 buf_pool_release(&token);
141 return rc;
142}
bool string_match
Check a string for a match.
Definition lib.h:88
char * str
String, if string_match is set.
Definition lib.h:101
bool ign_case
Ignore case for local string_match searches.
Definition lib.h:90
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eat_group()

static bool eat_group ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err )
static

Parse a group name - Implements eat_arg_t -.

Definition at line 147 of file compile.c.

149{
150 struct Buffer *token = buf_pool_get();
151 bool rc = false;
152 const char *pexpr = s->dptr;
153 if ((parse_extract_token(token, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
154 !token->data)
155 {
156 buf_printf(err, _("Error in expression: %s"), pexpr);
157 goto out;
158 }
159 if (buf_is_empty(token))
160 {
161 buf_addstr(err, _("Empty expression"));
162 goto out;
163 }
164
166 ASSERT(mod_data);
167
168 pat->group_match = true;
169 pat->p.group = groups_get_group(mod_data->groups, token->data);
170
171 rc = true;
172
173out:
174 buf_pool_release(&token);
175 return rc;
176}
struct Group * groups_get_group(struct HashTable *groups, const char *name)
Get a Group by its name.
Definition group.c:291
@ MODULE_ID_ALIAS
ModuleAlias, Alias
Definition module_api.h:48
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:663
#define ASSERT(COND)
Definition signal2.h:59
Alias private Module data.
Definition module_data.h:33
struct HashTable * groups
Hash Table: "group-name" -> Group.
Definition module_data.h:45
Container for Accounts, Notifications.
Definition neomutt.h:41
bool group_match
Check a group of Addresses.
Definition lib.h:89
struct Group * group
Address group if group_match is set.
Definition lib.h:100
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eat_query()

static bool eat_query ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err,
struct Mailbox * m )
static

Parse a query for an external search program - Implements eat_arg_t -.

Parameters
patPattern to store the results in
flagsFlags, e.g. MUTT_PC_PATTERN_DYNAMIC
sString to parse
errBuffer for error messages
mMailbox
Return values
trueThe pattern was read successfully

Definition at line 202 of file compile.c.

204{
205 struct Buffer *cmd = buf_pool_get();
206 struct Buffer *tok = buf_pool_get();
207 bool rc = false;
208
209 FILE *fp = NULL;
210
211 const char *const c_external_search_command = cs_subset_string(NeoMutt->sub, "external_search_command");
212 if (!c_external_search_command)
213 {
214 buf_addstr(err, _("No search command defined"));
215 goto out;
216 }
217
218 char *pexpr = s->dptr;
219 if ((parse_extract_token(tok, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) || !tok->data)
220 {
221 buf_printf(err, _("Error in expression: %s"), pexpr);
222 goto out;
223 }
224 if (*tok->data == '\0')
225 {
226 buf_addstr(err, _("Empty expression"));
227 goto out;
228 }
229
230 buf_addstr(cmd, c_external_search_command);
231 buf_addch(cmd, ' ');
232
233 if (m)
234 {
235 char *escaped_folder = mutt_path_escape(mailbox_path(m));
236 mutt_debug(LL_DEBUG2, "escaped folder path: %s\n", escaped_folder);
237 buf_addch(cmd, '\'');
238 buf_addstr(cmd, escaped_folder);
239 buf_addch(cmd, '\'');
240 }
241 else
242 {
243 buf_addch(cmd, '/');
244 }
245 buf_addch(cmd, ' ');
246 buf_addstr(cmd, tok->data);
247
248 mutt_message(_("Running search command: %s ..."), cmd->data);
249 pat->is_multi = true;
251 pid_t pid = filter_create(cmd->data, NULL, &fp, NULL, NeoMutt->env);
252 if (pid < 0)
253 {
254 buf_printf(err, "unable to fork command: %s\n", cmd->data);
255 goto out;
256 }
257
259 mutt_file_fclose(&fp);
260 filter_wait(pid);
261
262 rc = true;
263
264out:
265 buf_pool_release(&cmd);
266 buf_pool_release(&tok);
267 return rc;
268}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:216
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.
Definition file.c:780
#define mutt_file_fclose(FP)
Definition file.h:144
@ MUTT_RL_NONE
No flags are set.
Definition file.h:43
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
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 -.
Definition compile.c:182
void mutt_list_clear(struct ListHead *h)
Free a list, but NOT its strings.
Definition list.c:166
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:228
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition filter.c:217
char * mutt_path_escape(const char *src)
Escapes single quotes in a path for a command string.
Definition path.c:433
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition lib.h:102
bool is_multi
Multiple case (only for ~I pattern now)
Definition lib.h:94
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eat_range()

static bool eat_range ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err )
static

Parse a number range - Implements eat_arg_t -.

Definition at line 682 of file compile.c.

684{
685 char *tmp = NULL;
686 bool do_exclusive = false;
687 bool skip_quote = false;
688
689 /* If simple_search is set to "~m %s", the range will have double quotes
690 * around it... */
691 if (*s->dptr == '"')
692 {
693 s->dptr++;
694 skip_quote = true;
695 }
696 if (*s->dptr == '<')
697 do_exclusive = true;
698 if ((*s->dptr != '-') && (*s->dptr != '<'))
699 {
700 /* range minimum */
701 if (*s->dptr == '>')
702 {
703 pat->max = MUTT_MAXRANGE;
704 pat->min = strtol(s->dptr + 1, &tmp, 0) + 1; /* exclusive range */
705 }
706 else
707 {
708 pat->min = strtol(s->dptr, &tmp, 0);
709 }
710 if (mutt_toupper(*tmp) == 'K') /* is there a prefix? */
711 {
712 pat->min *= 1024;
713 tmp++;
714 }
715 else if (mutt_toupper(*tmp) == 'M')
716 {
717 pat->min *= 1048576;
718 tmp++;
719 }
720 if (*s->dptr == '>')
721 {
722 s->dptr = tmp;
723 return true;
724 }
725 if (*tmp != '-')
726 {
727 /* exact value */
728 pat->max = pat->min;
729 s->dptr = tmp;
730 return true;
731 }
732 tmp++;
733 }
734 else
735 {
736 s->dptr++;
737 tmp = s->dptr;
738 }
739
740 if (mutt_isdigit(*tmp))
741 {
742 /* range maximum */
743 pat->max = strtol(tmp, &tmp, 0);
744 if (mutt_toupper(*tmp) == 'K')
745 {
746 pat->max *= 1024;
747 tmp++;
748 }
749 else if (mutt_toupper(*tmp) == 'M')
750 {
751 pat->max *= 1048576;
752 tmp++;
753 }
754 if (do_exclusive)
755 (pat->max)--;
756 }
757 else
758 {
759 pat->max = MUTT_MAXRANGE;
760 }
761
762 if (skip_quote && (*tmp == '"'))
763 tmp++;
764
765 SKIPWS(tmp);
766 s->dptr = tmp;
767 return true;
768}
int mutt_toupper(int arg)
Wrapper for toupper(3)
Definition ctype.c:140
bool mutt_isdigit(int arg)
Wrapper for isdigit(3)
Definition ctype.c:66
#define MUTT_MAXRANGE
Definition private.h:149
#define SKIPWS(ch)
Definition string2.h:52
long min
Minimum for range checks.
Definition lib.h:95
long max
Maximum for range checks.
Definition lib.h:96
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eat_date()

static bool eat_date ( struct Pattern * pat,
PatternCompFlags flags,
struct Buffer * s,
struct Buffer * err )
static

Parse a date pattern - Implements eat_arg_t -.

Definition at line 773 of file compile.c.

775{
776 struct Buffer *tmp = buf_pool_get();
777 bool rc = false;
778
779 char *pexpr = s->dptr;
781 {
782 buf_printf(err, _("Error in expression: %s"), pexpr);
783 goto out;
784 }
785
786 if (buf_is_empty(tmp))
787 {
788 buf_addstr(err, _("Empty expression"));
789 goto out;
790 }
791
792 if (flags & MUTT_PC_PATTERN_DYNAMIC)
793 {
794 pat->dynamic = true;
795 pat->p.str = buf_strdup(tmp);
796 }
797
798 rc = eval_date_minmax(pat, tmp->data, err);
799
800out:
801 buf_pool_release(&tmp);
802 return rc;
803}
bool eval_date_minmax(struct Pattern *pat, const char *s, struct Buffer *err)
Evaluate a date-range pattern against 'now'.
Definition compile.c:554
@ MUTT_PC_PATTERN_DYNAMIC
Enable runtime date range evaluation.
Definition lib.h:75
bool dynamic
Evaluate date ranges at run time.
Definition lib.h:92
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ eat_message_range()

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 -.

Parameters
patPattern to store the results in
flagsFlags, e.g. MUTT_PC_PATTERN_DYNAMIC
sString to parse
errBuffer for error messages
mvMailbox view
Return values
trueThe pattern was read successfully

Definition at line 283 of file message.c.

285{
286 if (!mv || !mv->mailbox || !mv->menu)
287 {
288 // We need these for pretty much anything
289 buf_strcpy(err, _("No mailbox is open"));
290 return false;
291 }
292
293 bool skip_quote = false;
294
295 /* If simple_search is set to "~m %s", the range will have double quotes
296 * around it... */
297 if (*s->dptr == '"')
298 {
299 s->dptr++;
300 skip_quote = true;
301 }
302
303 for (int i_kind = 0; i_kind != RANGE_K_INVALID; i_kind++)
304 {
305 switch (eat_range_by_regex(pat, s, i_kind, err, mv))
306 {
307 case RANGE_E_MVIEW:
308 /* This means it matched syntactically but lacked context.
309 * No point in continuing. */
310 break;
311 case RANGE_E_SYNTAX:
312 /* Try another syntax, then */
313 continue;
314 case RANGE_E_OK:
315 if (skip_quote && (*s->dptr == '"'))
316 s->dptr++;
317 SKIPWS(s->dptr);
318 return true;
319 }
320 }
321 return false;
322}
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static int eat_range_by_regex(struct Pattern *pat, struct Buffer *s, int kind, struct Buffer *err, struct MailboxView *mv)
Parse a range given as a regex.
Definition message.c:217
@ RANGE_E_MVIEW
Range requires MailboxView, but none available.
Definition message.c:52
@ RANGE_E_OK
Range is valid.
Definition message.c:50
@ RANGE_E_SYNTAX
Range contains syntax error.
Definition message.c:51
@ RANGE_K_INVALID
Range is invalid.
Definition private.h:99
struct Menu * menu
Needed for pattern compilation.
Definition mview.h:47
struct Mailbox * mailbox
Current Mailbox.
Definition mview.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function: