NeoMutt  2025-09-05-55-g97fc89
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
config_type.c
Go to the documentation of this file.
1
23
35
36#include "config.h"
37#include <limits.h>
38#include <stdbool.h>
39#include <stdint.h>
40#include <stdio.h>
41#include "mutt/lib.h"
42#include "config/lib.h"
43#include "expando.h"
44
48static void expando_destroy(void *var, const struct ConfigDef *cdef)
49{
50 struct Expando **a = var;
51 if (!*a)
52 return;
53
54 expando_free(a);
55}
56
60static int expando_string_set(void *var, struct ConfigDef *cdef,
61 const char *value, struct Buffer *err)
62{
63 /* Store empty string list as NULL */
64 if (value && (value[0] == '\0'))
65 value = NULL;
66
67 if (!value && (cdef->type & D_NOT_EMPTY))
68 {
69 buf_printf(err, _("Option %s may not be empty"), cdef->name);
71 }
72
73 int rc = CSR_SUCCESS;
74
75 if (var)
76 {
77 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *)
78 cdef->data;
79 struct Expando *exp = expando_parse(value, defs, err);
80 if (!exp && !buf_is_empty(err))
81 {
82 char opt[128] = { 0 };
83 // L10N: e.g. "Option index_format:" plus an error message
84 snprintf(opt, sizeof(opt), _("Option %s: "), cdef->name);
85 buf_insert(err, 0, opt);
86 return CSR_ERR_INVALID;
87 }
88
89 if (expando_equal(exp, *(struct Expando **) var))
90 {
91 expando_free(&exp);
93 }
94
95 if (startup_only(cdef, err))
96 {
97 expando_free(&exp);
99 }
100
101 if (cdef->validator)
102 {
103 rc = cdef->validator(cdef, (intptr_t) exp, err);
104
105 if (CSR_RESULT(rc) != CSR_SUCCESS)
106 {
107 expando_free(&exp);
108 return rc | CSR_INV_VALIDATOR;
109 }
110 }
111
112 expando_destroy(var, cdef);
113
114 *(struct Expando **) var = exp;
115
116 if (!exp)
117 rc |= CSR_SUC_EMPTY;
118 }
119 else
120 {
121 if (cdef->type & D_INTERNAL_INITIAL_SET)
122 FREE(&cdef->initial);
123
125 cdef->initial = (intptr_t) mutt_str_dup(value);
126 }
127
128 return rc;
129}
130
134static int expando_string_get(void *var, const struct ConfigDef *cdef, struct Buffer *result)
135{
136 const char *str = NULL;
137
138 if (var)
139 {
140 struct Expando *exp = *(struct Expando **) var;
141 if (exp)
142 str = exp->string;
143 }
144 else
145 {
146 str = (char *) cdef->initial;
147 }
148
149 if (!str)
150 return CSR_SUCCESS | CSR_SUC_EMPTY; /* empty string */
151
152 buf_addstr(result, str);
153 return CSR_SUCCESS;
154}
155
159static int expando_native_set(void *var, const struct ConfigDef *cdef,
160 intptr_t value, struct Buffer *err)
161{
162 int rc;
163
164 struct Expando *exp_value = (struct Expando *) value;
165 if (!exp_value && (cdef->type & D_NOT_EMPTY))
166 {
167 buf_printf(err, _("Option %s may not be empty"), cdef->name);
169 }
170
171 struct Expando *exp_old = *(struct Expando **) var;
172 if (expando_equal(exp_value, exp_old))
174
175 if (startup_only(cdef, err))
177
178 if (cdef->validator)
179 {
180 rc = cdef->validator(cdef, value, err);
181
182 if (CSR_RESULT(rc) != CSR_SUCCESS)
183 return rc | CSR_INV_VALIDATOR;
184 }
185
186 expando_free(var);
187
188 struct Expando *exp_copy = NULL;
189
190 if (exp_value)
191 {
192 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *)
193 cdef->data;
194 exp_copy = expando_parse(exp_value->string, defs, err);
195 }
196
197 rc = CSR_SUCCESS;
198 if (!exp_copy)
199 rc |= CSR_SUC_EMPTY;
200
201 *(struct Expando **) var = exp_copy;
202 return rc;
203}
204
208static intptr_t expando_native_get(void *var, const struct ConfigDef *cdef, struct Buffer *err)
209{
210 struct Expando *exp = *(struct Expando **) var;
211
212 return (intptr_t) exp;
213}
214
218static int expando_string_plus_equals(void *var, const struct ConfigDef *cdef,
219 const char *value, struct Buffer *err)
220{
221 /* Skip if the value is missing or empty string*/
222 if (!value || (value[0] == '\0'))
224
225 if (value && startup_only(cdef, err))
227
228 int rc = CSR_SUCCESS;
229
230 char *str = NULL;
231 struct Expando *exp_old = *(struct Expando **) var;
232
233 if (exp_old && exp_old->string)
234 mutt_str_asprintf(&str, "%s%s", exp_old->string, value);
235 else
236 str = mutt_str_dup(value);
237
238 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *) cdef->data;
239 struct Expando *exp_new = expando_parse(str, defs, err);
240 FREE(&str);
241
242 if (!exp_new && !buf_is_empty(err))
243 {
244 char opt[128] = { 0 };
245 // L10N: e.g. "Option index_format:" plus an error message
246 snprintf(opt, sizeof(opt), _("Option %s: "), cdef->name);
247 buf_insert(err, 0, opt);
248 return CSR_ERR_INVALID;
249 }
250
251 if (expando_equal(exp_new, exp_old))
252 {
253 expando_free(&exp_new); // LCOV_EXCL_LINE
254 return CSR_SUCCESS | CSR_SUC_NO_CHANGE; // LCOV_EXCL_LINE
255 }
256
257 if (cdef->validator)
258 {
259 rc = cdef->validator(cdef, (intptr_t) exp_new, err);
260
261 if (CSR_RESULT(rc) != CSR_SUCCESS)
262 {
263 expando_free(&exp_new);
264 return rc | CSR_INV_VALIDATOR;
265 }
266 }
267
268 expando_destroy(var, cdef);
269 *(struct Expando **) var = exp_new;
270
271 return rc;
272}
273
277static bool expando_has_been_set(void *var, const struct ConfigDef *cdef)
278{
279 const char *initial = (const char *) cdef->initial;
280
281 struct Expando *exp = *(struct Expando **) var;
282 const char *exp_str = exp ? exp->string : NULL;
283
284 return !mutt_str_equal(initial, exp_str);
285}
286
290static int expando_reset(void *var, const struct ConfigDef *cdef, struct Buffer *err)
291{
292 struct Expando *exp = NULL;
293 const char *initial = (const char *) cdef->initial;
294
295 if (initial)
296 {
297 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *)
298 cdef->data;
299 exp = expando_parse(initial, defs, err);
300 }
301
302 if (expando_equal(exp, *(struct Expando **) var))
303 {
304 expando_free(&exp);
306 }
307
308 if (startup_only(cdef, err))
309 {
310 expando_free(&exp);
312 }
313
314 int rc = CSR_SUCCESS;
315
316 if (cdef->validator)
317 {
318 rc = cdef->validator(cdef, (intptr_t) exp, err);
319
320 if (CSR_RESULT(rc) != CSR_SUCCESS)
321 {
322 expando_destroy(&exp, cdef);
323 return rc | CSR_INV_VALIDATOR;
324 }
325 }
326
327 if (!exp)
328 rc |= CSR_SUC_EMPTY;
329
330 expando_destroy(var, cdef);
331
332 *(struct Expando **) var = exp;
333 return rc;
334}
335
339const struct ConfigSetType CstExpando = {
341 "expando",
347 NULL, // string_minus_equals
351};
352
360const struct Expando *cs_subset_expando(const struct ConfigSubset *sub, const char *name)
361{
362 ASSERT(sub && name);
363
364 struct HashElem *he = cs_subset_create_inheritance(sub, name);
365 ASSERT(he);
366
367#ifndef NDEBUG
368 struct HashElem *he_base = cs_get_base(he);
369 ASSERT(CONFIG_TYPE(he_base->type) == DT_EXPANDO);
370#endif
371
372 intptr_t value = cs_subset_he_native_get(sub, he, NULL);
373 ASSERT(value != INT_MIN);
374
375 return (const struct Expando *) value;
376}
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
size_t buf_insert(struct Buffer *buf, size_t offset, const char *s)
Add a string in the middle of a buffer.
Definition buffer.c:256
Convenience wrapper for the config headers.
struct HashElem * cs_get_base(struct HashElem *he)
Find the root Config Item.
Definition set.c:160
static bool startup_only(const struct ConfigDef *cdef, struct Buffer *err)
Validator function for D_ON_STARTUP.
Definition set.h:293
#define CSR_ERR_INVALID
Value hasn't been set.
Definition set.h:36
#define CSR_INV_VALIDATOR
Value was rejected by the validator.
Definition set.h:46
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition set.h:42
#define CSR_RESULT(x)
Definition set.h:50
#define CSR_SUC_EMPTY
Value is empty/unset.
Definition set.h:40
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
const struct ConfigSetType CstExpando
Config type representing an Expando.
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
struct Expando * expando_parse(const char *str, const struct ExpandoDefinition *defs, struct Buffer *err)
Parse an Expando string.
Definition expando.c:81
void expando_free(struct Expando **ptr)
Free an Expando object.
Definition expando.c:61
bool expando_equal(const struct Expando *a, const struct Expando *b)
Compare two expandos.
Definition expando.c:137
Parsed Expando.
static void expando_destroy(void *var, const struct ConfigDef *cdef)
Destroy an Expando object - Implements ConfigSetType::destroy() -.
Definition config_type.c:48
static bool expando_has_been_set(void *var, const struct ConfigDef *cdef)
Is the config value different to its initial value?
static int expando_native_set(void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Set an Expando object from an Expando config item - Implements ConfigSetType::native_get() -.
static intptr_t expando_native_get(void *var, const struct ConfigDef *cdef, struct Buffer *err)
Get an Expando object from an Expando config item - Implements ConfigSetType::native_get() -.
static int expando_reset(void *var, const struct ConfigDef *cdef, struct Buffer *err)
Reset an Expando to its initial value - Implements ConfigSetType::reset() -.
static int expando_string_get(void *var, const struct ConfigDef *cdef, struct Buffer *result)
Get an Expando as a string - Implements ConfigSetType::string_get() -.
static int expando_string_plus_equals(void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err)
Add to an Expando by string - Implements ConfigSetType::string_plus_equals() -.
static int expando_string_set(void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err)
Set an Expando by string - Implements ConfigSetType::string_set() -.
Definition config_type.c:60
#define FREE(x)
Definition memory.h:62
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:255
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition string.c:803
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:660
#define ASSERT(COND)
Definition signal2.h:60
String manipulation buffer.
Definition buffer.h:36
const char * name
User-visible name.
Definition set.h:63
int(* validator)(const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Definition set.h:79
intptr_t data
Extra variable data.
Definition set.h:66
intptr_t initial
Initial value.
Definition set.h:65
uint32_t type
Variable type, e.g. DT_STRING.
Definition set.h:64
A set of inherited config items.
Definition subset.h:46
Definition of a format string.
Definition definition.h:44
Parsed Expando trees.
Definition expando.h:41
const char * string
Pointer to the parsed string.
Definition expando.h:42
The item stored in a Hash Table.
Definition hash.h:44
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition hash.h:45
intptr_t cs_subset_he_native_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Natively get the value of a HashElem config item.
Definition subset.c:264
struct HashElem * cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
Create a Subset config item (inherited)
Definition subset.c:214
#define CONFIG_TYPE(t)
Definition types.h:49
#define D_INTERNAL_INITIAL_SET
Config item must have its initial value freed.
Definition types.h:89
@ DT_EXPANDO
an expando
Definition types.h:34
#define D_NOT_EMPTY
Empty strings are not allowed.
Definition types.h:79