NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
regex.c File Reference

Type representing a regular expression. More...

#include "config.h"
#include <stddef.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include "mutt/lib.h"
#include "regex2.h"
#include "set.h"
#include "types.h"
+ Include dependency graph for regex.c:

Go to the source code of this file.

Functions

void regex_free (struct Regex **r)
 Free a Regex object. More...
 
static void regex_destroy (const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
 Destroy a Regex object - Implements ConfigSetType::destroy() More...
 
struct Regexregex_new (const char *str, int flags, struct Buffer *err)
 Create an Regex from a string. More...
 
static int regex_string_set (const struct ConfigSet *cs, void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err)
 Set a Regex by string - Implements ConfigSetType::string_set() More...
 
static int regex_string_get (const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *result)
 Get a Regex as a string - Implements ConfigSetType::string_get() More...
 
static int regex_native_set (const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
 Set a Regex config item by Regex object - Implements ConfigSetType::native_set() More...
 
static intptr_t regex_native_get (const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
 Get a Regex object from a Regex config item - Implements ConfigSetType::native_get() More...
 
static int regex_reset (const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
 Reset a Regex to its initial value - Implements ConfigSetType::reset() More...
 

Variables

const struct ConfigSetType cst_regex
 Config type representing a regular expression. More...
 

Detailed Description

Type representing a regular expression.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file regex.c.

Function Documentation

◆ regex_free()

void regex_free ( struct Regex **  r)

Free a Regex object.

Parameters
[out]rRegex to free

Definition at line 48 of file regex.c.

49 {
50  if (!r || !*r)
51  return;
52 
53  FREE(&(*r)->pattern);
54  if ((*r)->regex)
55  regfree((*r)->regex);
56  FREE(&(*r)->regex);
57  FREE(r);
58 }
#define FREE(x)
Definition: memory.h:40
+ Here is the caller graph for this function:

◆ regex_destroy()

static void regex_destroy ( const struct ConfigSet cs,
void *  var,
const struct ConfigDef cdef 
)
static

Destroy a Regex object - Implements ConfigSetType::destroy()

Definition at line 63 of file regex.c.

64 {
65  struct Regex **r = var;
66  if (!*r)
67  return;
68 
69  regex_free(r);
70 }
void regex_free(struct Regex **r)
Free a Regex object.
Definition: regex.c:48
Cached regular expression.
Definition: regex3.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ regex_new()

struct Regex* regex_new ( const char *  str,
int  flags,
struct Buffer err 
)

Create an Regex from a string.

Parameters
strRegular expression
flagsType flags, e.g. DT_REGEX_MATCH_CASE
errBuffer for error messages
Return values
ptrNew Regex object
NULLError

Definition at line 80 of file regex.c.

81 {
82  if (!str)
83  return NULL;
84 
85  int rflags = 0;
86  struct Regex *reg = mutt_mem_calloc(1, sizeof(struct Regex));
87 
88  reg->regex = mutt_mem_calloc(1, sizeof(regex_t));
89  reg->pattern = mutt_str_dup(str);
90 
91  /* Should we use smart case matching? */
92  if (((flags & DT_REGEX_MATCH_CASE) == 0) && mutt_mb_is_lower(str))
93  rflags |= REG_ICASE;
94 
95  if ((flags & DT_REGEX_NOSUB))
96  rflags |= REG_NOSUB;
97 
98  /* Is a prefix of '!' allowed? */
99  if (((flags & DT_REGEX_ALLOW_NOT) != 0) && (str[0] == '!'))
100  {
101  reg->pat_not = true;
102  str++;
103  }
104 
105  int rc = REG_COMP(reg->regex, str, rflags);
106  if (rc != 0)
107  {
108  if (err)
109  regerror(rc, reg->regex, err->data, err->dsize);
110  regex_free(&reg);
111  return NULL;
112  }
113 
114  return reg;
115 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
regex_t * regex
compiled expression
Definition: regex3.h:91
bool pat_not
do not match
Definition: regex3.h:92
#define DT_REGEX_MATCH_CASE
Case-sensitive matching.
Definition: regex3.h:35
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:53
size_t dsize
Length of data.
Definition: buffer.h:37
void regex_free(struct Regex **r)
Free a Regex object.
Definition: regex.c:48
#define DT_REGEX_NOSUB
Do not report what was matched (REG_NOSUB)
Definition: regex3.h:37
char * data
Pointer to data.
Definition: buffer.h:35
#define DT_REGEX_ALLOW_NOT
Regex can begin with &#39;!&#39;.
Definition: regex3.h:36
Cached regular expression.
Definition: regex3.h:88
char * pattern
printable version
Definition: regex3.h:90
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:358
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ regex_string_set()

static int regex_string_set ( const struct ConfigSet cs,
void *  var,
struct ConfigDef cdef,
const char *  value,
struct Buffer err 
)
static

Set a Regex by string - Implements ConfigSetType::string_set()

Definition at line 120 of file regex.c.

122 {
123  /* Store empty regexes as NULL */
124  if (value && (value[0] == '\0'))
125  value = NULL;
126 
127  struct Regex *r = NULL;
128 
129  int rc = CSR_SUCCESS;
130 
131  if (var)
132  {
133  struct Regex *curval = *(struct Regex **) var;
134  if (curval && mutt_str_equal(value, curval->pattern))
136 
137  if (value)
138  {
139  r = regex_new(value, cdef->type, err);
140  if (!r)
141  return CSR_ERR_INVALID;
142  }
143 
144  if (cdef->validator)
145  {
146  rc = cdef->validator(cs, cdef, (intptr_t) r, err);
147 
148  if (CSR_RESULT(rc) != CSR_SUCCESS)
149  {
150  regex_free(&r);
151  return rc | CSR_INV_VALIDATOR;
152  }
153  }
154 
155  regex_destroy(cs, var, cdef);
156 
157  *(struct Regex **) var = r;
158 
159  if (!r)
160  rc |= CSR_SUC_EMPTY;
161  }
162  else
163  {
164  if (cdef->type & DT_INITIAL_SET)
165  FREE(&cdef->initial);
166 
167  cdef->type |= DT_INITIAL_SET;
168  cdef->initial = IP mutt_str_dup(value);
169  }
170 
171  return rc;
172 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
#define IP
Definition: set.h:54
#define CSR_ERR_INVALID
Value hasn&#39;t been set.
Definition: set.h:38
intptr_t initial
Initial value.
Definition: set.h:66
struct Regex * regex_new(const char *str, int flags, struct Buffer *err)
Create an Regex from a string.
Definition: regex.c:80
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define DT_INITIAL_SET
Config item must have its initial value freed.
Definition: types.h:81
#define CSR_RESULT(x)
Definition: set.h:52
static void regex_destroy(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
Destroy a Regex object - Implements ConfigSetType::destroy()
Definition: regex.c:63
void regex_free(struct Regex **r)
Free a Regex object.
Definition: regex.c:48
#define CSR_SUC_EMPTY
Value is empty/unset.
Definition: set.h:42
#define CSR_SUC_NO_CHANGE
The value hasn&#39;t changed.
Definition: set.h:44
int(* validator)(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate a config variable.
Definition: set.h:78
unsigned int type
Variable type, e.g. DT_STRING.
Definition: set.h:64
Cached regular expression.
Definition: regex3.h:88
#define FREE(x)
Definition: memory.h:40
char * pattern
printable version
Definition: regex3.h:90
#define CSR_INV_VALIDATOR
Value was rejected by the validator.
Definition: set.h:48
+ Here is the call graph for this function:

◆ regex_string_get()

static int regex_string_get ( const struct ConfigSet cs,
void *  var,
const struct ConfigDef cdef,
struct Buffer result 
)
static

Get a Regex as a string - Implements ConfigSetType::string_get()

Definition at line 177 of file regex.c.

179 {
180  const char *str = NULL;
181 
182  if (var)
183  {
184  struct Regex *r = *(struct Regex **) var;
185  if (r)
186  str = r->pattern;
187  }
188  else
189  {
190  str = (char *) cdef->initial;
191  }
192 
193  if (!str)
194  return CSR_SUCCESS | CSR_SUC_EMPTY; /* empty string */
195 
196  mutt_buffer_addstr(result, str);
197  return CSR_SUCCESS;
198 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
intptr_t initial
Initial value.
Definition: set.h:66
#define CSR_SUC_EMPTY
Value is empty/unset.
Definition: set.h:42
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
Cached regular expression.
Definition: regex3.h:88
char * pattern
printable version
Definition: regex3.h:90
+ Here is the call graph for this function:

◆ regex_native_set()

static int regex_native_set ( const struct ConfigSet cs,
void *  var,
const struct ConfigDef cdef,
intptr_t  value,
struct Buffer err 
)
static

Set a Regex config item by Regex object - Implements ConfigSetType::native_set()

Definition at line 203 of file regex.c.

205 {
206  int rc;
207 
208  if (cdef->validator)
209  {
210  rc = cdef->validator(cs, cdef, value, err);
211 
212  if (CSR_RESULT(rc) != CSR_SUCCESS)
213  return rc | CSR_INV_VALIDATOR;
214  }
215 
216  rc = CSR_SUCCESS;
217  struct Regex *orig = (struct Regex *) value;
218  struct Regex *r = NULL;
219 
220  if (orig && orig->pattern)
221  {
222  const int flags = orig->pat_not ? DT_REGEX_ALLOW_NOT : 0;
223  r = regex_new(orig->pattern, flags, err);
224  if (!r)
225  rc = CSR_ERR_INVALID;
226  }
227  else
228  {
229  rc |= CSR_SUC_EMPTY;
230  }
231 
232  if (CSR_RESULT(rc) == CSR_SUCCESS)
233  {
234  regex_free(var);
235  *(struct Regex **) var = r;
236  }
237 
238  return rc;
239 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
#define CSR_ERR_INVALID
Value hasn&#39;t been set.
Definition: set.h:38
bool pat_not
do not match
Definition: regex3.h:92
struct Regex * regex_new(const char *str, int flags, struct Buffer *err)
Create an Regex from a string.
Definition: regex.c:80
#define CSR_RESULT(x)
Definition: set.h:52
void regex_free(struct Regex **r)
Free a Regex object.
Definition: regex.c:48
#define CSR_SUC_EMPTY
Value is empty/unset.
Definition: set.h:42
int(* validator)(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate a config variable.
Definition: set.h:78
#define DT_REGEX_ALLOW_NOT
Regex can begin with &#39;!&#39;.
Definition: regex3.h:36
Cached regular expression.
Definition: regex3.h:88
char * pattern
printable version
Definition: regex3.h:90
#define CSR_INV_VALIDATOR
Value was rejected by the validator.
Definition: set.h:48
+ Here is the call graph for this function:

◆ regex_native_get()

static intptr_t regex_native_get ( const struct ConfigSet cs,
void *  var,
const struct ConfigDef cdef,
struct Buffer err 
)
static

Get a Regex object from a Regex config item - Implements ConfigSetType::native_get()

Definition at line 244 of file regex.c.

246 {
247  struct Regex *r = *(struct Regex **) var;
248 
249  return (intptr_t) r;
250 }
Cached regular expression.
Definition: regex3.h:88

◆ regex_reset()

static int regex_reset ( const struct ConfigSet cs,
void *  var,
const struct ConfigDef cdef,
struct Buffer err 
)
static

Reset a Regex to its initial value - Implements ConfigSetType::reset()

Definition at line 255 of file regex.c.

257 {
258  struct Regex *r = NULL;
259  const char *initial = (const char *) cdef->initial;
260 
261  struct Regex *currx = *(struct Regex **) var;
262  const char *curval = currx ? currx->pattern : NULL;
263 
264  int rc = CSR_SUCCESS;
265  if (!currx)
266  rc |= CSR_SUC_EMPTY;
267 
268  if (mutt_str_equal(initial, curval))
269  return rc | CSR_SUC_NO_CHANGE;
270 
271  if (initial)
272  {
273  r = regex_new(initial, cdef->type, err);
274  if (!r)
275  return CSR_ERR_CODE;
276  }
277 
278  if (cdef->validator)
279  {
280  rc = cdef->validator(cs, cdef, (intptr_t) r, err);
281 
282  if (CSR_RESULT(rc) != CSR_SUCCESS)
283  {
284  regex_destroy(cs, &r, cdef);
285  return rc | CSR_INV_VALIDATOR;
286  }
287  }
288 
289  if (!r)
290  rc |= CSR_SUC_EMPTY;
291 
292  regex_destroy(cs, var, cdef);
293 
294  *(struct Regex **) var = r;
295  return rc;
296 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
intptr_t initial
Initial value.
Definition: set.h:66
struct Regex * regex_new(const char *str, int flags, struct Buffer *err)
Create an Regex from a string.
Definition: regex.c:80
#define CSR_RESULT(x)
Definition: set.h:52
static void regex_destroy(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
Destroy a Regex object - Implements ConfigSetType::destroy()
Definition: regex.c:63
#define CSR_SUC_EMPTY
Value is empty/unset.
Definition: set.h:42
#define CSR_SUC_NO_CHANGE
The value hasn&#39;t changed.
Definition: set.h:44
int(* validator)(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate a config variable.
Definition: set.h:78
unsigned int type
Variable type, e.g. DT_STRING.
Definition: set.h:64
Cached regular expression.
Definition: regex3.h:88
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:36
char * pattern
printable version
Definition: regex3.h:90
#define CSR_INV_VALIDATOR
Value was rejected by the validator.
Definition: set.h:48
+ Here is the call graph for this function:

Variable Documentation

◆ cst_regex

const struct ConfigSetType cst_regex
Initial value:
= {
"regex",
NULL,
NULL,
}
#define DT_REGEX
regular expressions
Definition: types.h:38
static intptr_t regex_native_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Get a Regex object from a Regex config item - Implements ConfigSetType::native_get() ...
Definition: regex.c:244
static void regex_destroy(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
Destroy a Regex object - Implements ConfigSetType::destroy()
Definition: regex.c:63
static int regex_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err)
Set a Regex by string - Implements ConfigSetType::string_set()
Definition: regex.c:120
static int regex_native_set(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Set a Regex config item by Regex object - Implements ConfigSetType::native_set()
Definition: regex.c:203
static int regex_string_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *result)
Get a Regex as a string - Implements ConfigSetType::string_get()
Definition: regex.c:177
static int regex_reset(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Reset a Regex to its initial value - Implements ConfigSetType::reset()
Definition: regex.c:255

Config type representing a regular expression.

Definition at line 301 of file regex.c.