NeoMutt  2025-12-11-435-g4ac674
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 65 of file compile.c.

67{
68 struct Buffer *token = buf_pool_get();
69 bool rc = false;
70 const char *pexpr = s->dptr;
71 if ((parse_extract_token(token, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
72 !token->data)
73 {
74 buf_printf(err, _("Error in expression: %s"), pexpr);
75 goto out;
76 }
77 if (buf_is_empty(token))
78 {
79 buf_addstr(err, _("Empty expression"));
80 goto out;
81 }
82
83 pat->p.regex = MUTT_MEM_CALLOC(1, regex_t);
84#ifdef USE_DEBUG_GRAPHVIZ
85 pat->raw_pattern = buf_strdup(token);
86#endif
87 uint16_t case_flags = mutt_mb_is_lower(token->data) ? REG_ICASE : 0;
88 int rc2 = REG_COMP(pat->p.regex, token->data, REG_NEWLINE | REG_NOSUB | case_flags);
89 if (rc2 != 0)
90 {
91 char errmsg[256] = { 0 };
92 regerror(rc2, pat->p.regex, errmsg, sizeof(errmsg));
93 buf_printf(err, "'%s': %s", token->data, errmsg);
94 FREE(&pat->p.regex);
95 goto out;
96 }
97
98 rc = true;
99
100out:
101 buf_pool_release(&token);
102 return rc;
103}
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
#define TOKEN_COMMENT
Don't reap comments.
Definition extract.h:51
#define TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition extract.h:50
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:93
+ 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 108 of file compile.c.

110{
111 struct Buffer *token = buf_pool_get();
112 bool rc = false;
113 const char *pexpr = s->dptr;
114 if ((parse_extract_token(token, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
115 !token->data)
116 {
117 buf_printf(err, _("Error in expression: %s"), pexpr);
118 goto out;
119 }
120 if (buf_is_empty(token))
121 {
122 buf_addstr(err, _("Empty expression"));
123 goto out;
124 }
125
126 pat->string_match = true;
127 pat->p.str = buf_strdup(token);
128 pat->ign_case = mutt_mb_is_lower(token->data);
129
130 rc = true;
131
132out:
133 buf_pool_release(&token);
134 return rc;
135}
bool string_match
Check a string for a match.
Definition lib.h:82
char * str
String, if string_match is set.
Definition lib.h:95
bool ign_case
Ignore case for local string_match searches.
Definition lib.h:84
+ 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 140 of file compile.c.

142{
143 struct Buffer *token = buf_pool_get();
144 bool rc = false;
145 const char *pexpr = s->dptr;
146 if ((parse_extract_token(token, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) ||
147 !token->data)
148 {
149 buf_printf(err, _("Error in expression: %s"), pexpr);
150 goto out;
151 }
152 if (buf_is_empty(token))
153 {
154 buf_addstr(err, _("Empty expression"));
155 goto out;
156 }
157
158 pat->group_match = true;
159 pat->p.group = groups_get_group(NeoMutt->groups, token->data);
160
161 rc = true;
162
163out:
164 buf_pool_release(&token);
165 return rc;
166}
struct Group * groups_get_group(struct HashTable *groups, const char *name)
Get a Group by its name.
Definition group.c:291
Container for Accounts, Notifications.
Definition neomutt.h:41
struct HashTable * groups
Hash Table: "group-name" -> Group.
Definition neomutt.h:54
bool group_match
Check a group of Addresses.
Definition lib.h:83
struct Group * group
Address group if group_match is set.
Definition lib.h:94
+ 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 192 of file compile.c.

194{
195 struct Buffer *cmd = buf_pool_get();
196 struct Buffer *tok = buf_pool_get();
197 bool rc = false;
198
199 FILE *fp = NULL;
200
201 const char *const c_external_search_command = cs_subset_string(NeoMutt->sub, "external_search_command");
202 if (!c_external_search_command)
203 {
204 buf_addstr(err, _("No search command defined"));
205 goto out;
206 }
207
208 char *pexpr = s->dptr;
209 if ((parse_extract_token(tok, s, TOKEN_PATTERN | TOKEN_COMMENT) != 0) || !tok->data)
210 {
211 buf_printf(err, _("Error in expression: %s"), pexpr);
212 goto out;
213 }
214 if (*tok->data == '\0')
215 {
216 buf_addstr(err, _("Empty expression"));
217 goto out;
218 }
219
220 buf_addstr(cmd, c_external_search_command);
221 buf_addch(cmd, ' ');
222
223 if (m)
224 {
225 char *escaped_folder = mutt_path_escape(mailbox_path(m));
226 mutt_debug(LL_DEBUG2, "escaped folder path: %s\n", escaped_folder);
227 buf_addch(cmd, '\'');
228 buf_addstr(cmd, escaped_folder);
229 buf_addch(cmd, '\'');
230 }
231 else
232 {
233 buf_addch(cmd, '/');
234 }
235 buf_addch(cmd, ' ');
236 buf_addstr(cmd, tok->data);
237
238 mutt_message(_("Running search command: %s ..."), cmd->data);
239 pat->is_multi = true;
241 pid_t pid = filter_create(cmd->data, NULL, &fp, NULL, NeoMutt->env);
242 if (pid < 0)
243 {
244 buf_printf(err, "unable to fork command: %s\n", cmd->data);
245 goto out;
246 }
247
249 mutt_file_fclose(&fp);
250 filter_wait(pid);
251
252 rc = true;
253
254out:
255 buf_pool_release(&cmd);
256 buf_pool_release(&tok);
257 return rc;
258}
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:213
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:784
#define mutt_file_fclose(FP)
Definition file.h:139
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition file.h:40
#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:172
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:220
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:209
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:58
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
struct ListHead multi_cases
Multiple strings for ~I pattern.
Definition lib.h:96
bool is_multi
Multiple case (only for ~I pattern now)
Definition lib.h:88
+ 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 672 of file compile.c.

674{
675 char *tmp = NULL;
676 bool do_exclusive = false;
677 bool skip_quote = false;
678
679 /* If simple_search is set to "~m %s", the range will have double quotes
680 * around it... */
681 if (*s->dptr == '"')
682 {
683 s->dptr++;
684 skip_quote = true;
685 }
686 if (*s->dptr == '<')
687 do_exclusive = true;
688 if ((*s->dptr != '-') && (*s->dptr != '<'))
689 {
690 /* range minimum */
691 if (*s->dptr == '>')
692 {
693 pat->max = MUTT_MAXRANGE;
694 pat->min = strtol(s->dptr + 1, &tmp, 0) + 1; /* exclusive range */
695 }
696 else
697 {
698 pat->min = strtol(s->dptr, &tmp, 0);
699 }
700 if (mutt_toupper(*tmp) == 'K') /* is there a prefix? */
701 {
702 pat->min *= 1024;
703 tmp++;
704 }
705 else if (mutt_toupper(*tmp) == 'M')
706 {
707 pat->min *= 1048576;
708 tmp++;
709 }
710 if (*s->dptr == '>')
711 {
712 s->dptr = tmp;
713 return true;
714 }
715 if (*tmp != '-')
716 {
717 /* exact value */
718 pat->max = pat->min;
719 s->dptr = tmp;
720 return true;
721 }
722 tmp++;
723 }
724 else
725 {
726 s->dptr++;
727 tmp = s->dptr;
728 }
729
730 if (mutt_isdigit(*tmp))
731 {
732 /* range maximum */
733 pat->max = strtol(tmp, &tmp, 0);
734 if (mutt_toupper(*tmp) == 'K')
735 {
736 pat->max *= 1024;
737 tmp++;
738 }
739 else if (mutt_toupper(*tmp) == 'M')
740 {
741 pat->max *= 1048576;
742 tmp++;
743 }
744 if (do_exclusive)
745 (pat->max)--;
746 }
747 else
748 {
749 pat->max = MUTT_MAXRANGE;
750 }
751
752 if (skip_quote && (*tmp == '"'))
753 tmp++;
754
755 SKIPWS(tmp);
756 s->dptr = tmp;
757 return true;
758}
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:89
long max
Maximum for range checks.
Definition lib.h:90
+ 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 763 of file compile.c.

765{
766 struct Buffer *tmp = buf_pool_get();
767 bool rc = false;
768
769 char *pexpr = s->dptr;
771 {
772 buf_printf(err, _("Error in expression: %s"), pexpr);
773 goto out;
774 }
775
776 if (buf_is_empty(tmp))
777 {
778 buf_addstr(err, _("Empty expression"));
779 goto out;
780 }
781
782 if (flags & MUTT_PC_PATTERN_DYNAMIC)
783 {
784 pat->dynamic = true;
785 pat->p.str = buf_strdup(tmp);
786 }
787
788 rc = eval_date_minmax(pat, tmp->data, err);
789
790out:
791 buf_pool_release(&tmp);
792 return rc;
793}
bool eval_date_minmax(struct Pattern *pat, const char *s, struct Buffer *err)
Evaluate a date-range pattern against 'now'.
Definition compile.c:544
#define MUTT_PC_PATTERN_DYNAMIC
Enable runtime date range evaluation.
Definition lib.h:71
bool dynamic
Evaluate date ranges at run time.
Definition lib.h:86
+ 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 281 of file message.c.

283{
284 if (!mv || !mv->mailbox || !mv->menu)
285 {
286 // We need these for pretty much anything
287 buf_strcpy(err, _("No mailbox is open"));
288 return false;
289 }
290
291 bool skip_quote = false;
292
293 /* If simple_search is set to "~m %s", the range will have double quotes
294 * around it... */
295 if (*s->dptr == '"')
296 {
297 s->dptr++;
298 skip_quote = true;
299 }
300
301 for (int i_kind = 0; i_kind != RANGE_K_INVALID; i_kind++)
302 {
303 switch (eat_range_by_regex(pat, s, i_kind, err, mv))
304 {
305 case RANGE_E_MVIEW:
306 /* This means it matched syntactically but lacked context.
307 * No point in continuing. */
308 break;
309 case RANGE_E_SYNTAX:
310 /* Try another syntax, then */
311 continue;
312 case RANGE_E_OK:
313 if (skip_quote && (*s->dptr == '"'))
314 s->dptr++;
315 SKIPWS(s->dptr);
316 return true;
317 }
318 }
319 return false;
320}
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:216
@ RANGE_E_MVIEW
Range requires MailboxView, but none available.
Definition message.c:51
@ RANGE_E_OK
Range is valid.
Definition message.c:49
@ RANGE_E_SYNTAX
Range contains syntax error.
Definition message.c:50
@ 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: