145{
146 if (!str || (str[0] != '%'))
147 return NULL;
148
149 str++;
150
155
156
157
160 goto fail;
161
162 str = *parsed_until;
163
164 if ((str[0] != '<') && (str[0] != '?'))
165 goto fail;
166
167 const bool old_style = (str[0] == '?');
168 str++;
169
170
171
172
173 if (str[0] == '{')
174 {
176 if (node_cond)
177 {
178 if ((*parsed_until)[0] != '}')
179 {
181 snprintf(err->
message,
sizeof(err->
message),
_(
"Expando is missing closing '}'"));
182 goto fail;
183 }
184 (*parsed_until)++;
185 }
187 {
188 goto fail;
189 }
190 else
191 {
192
193 const char *name_start = str + 1;
194 const char *end = name_start + strspn(name_start, "abcdefghijklmnopqrstuvwxyz0123456789-");
195 if (end != name_start)
196 {
198 if (*end != '}')
199 snprintf(err->
message,
sizeof(err->
message),
_(
"Expando is missing closing '}'"));
200 else
201
202 snprintf(err->
message,
sizeof(err->
message),
_(
"Unknown expando: %%{%.*s}"),
203 (int) (end - name_start), name_start);
204 goto fail;
205 }
206
207 }
208 }
209
210 if (!node_cond)
211 {
213 if (!node_cond)
214 goto fail;
215 }
216
218 {
221 }
222
223 str = *parsed_until;
224 if (str[0] != '?')
225 {
228
229
230 _(
"Conditional expando is missing '%c'"),
'?');
231 goto fail;
232 }
233 str++;
234
235
236
239
243 goto fail;
244
245 str = *parsed_until;
246
247
248
249
250 node_false = NULL;
251 if (str[0] == '&')
252 {
253 str++;
255
259 goto fail;
260
261 str = *parsed_until;
262 }
263
264
265
266 const char terminator = old_style ? '?' : '>';
267
268 if (str[0] != terminator)
269 {
272
273
274 _(
"Conditional expando is missing '%c'"),
'?');
275 goto fail;
276 }
277
278 *parsed_until = str + 1;
279
281
282fail:
287 return NULL;
288}
#define EP_CONDITIONAL
Expando is being used as a condition.
bool node_parse_many(struct ExpandoNode *node_cont, const char *str, NodeTextTermFlags term_chars, const struct ExpandoDefinition *defs, const char **parsed_until, struct ExpandoParseError *err)
Parse a format string.
int node_condbool_render(const struct ExpandoNode *node, const struct ExpandoRenderCallback *erc, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Callback for every bool node - Implements ExpandoNode::render() -.
#define FREE(x)
Free memory and set the pointer to NULL.
void node_free(struct ExpandoNode **ptr)
Free an ExpandoNode and its private data.
@ ENT_EXPANDO
Expando, e.g. 'n'.
@ ENT_CONDBOOL
True/False boolean condition.
struct ExpandoNode * node_condition_new(struct ExpandoNode *node_cond, struct ExpandoNode *node_true, struct ExpandoNode *node_false, struct ExpandoFormat *fmt)
Create a new Condition Expando Node.
struct ExpandoNode * node_container_new(void)
Create a new Container ExpandoNode.
struct ExpandoNode * parse_long_name(const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, struct ExpandoFormat *fmt, const char **parsed_until, struct ExpandoParseError *err)
Create an expando by its long name.
struct ExpandoNode * parse_short_name(const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, struct ExpandoFormat *fmt, const char **parsed_until, struct ExpandoParseError *err)
Create an expando by its short name.
struct ExpandoFormat * parse_format(const char *str, const char **parsed_until, struct ExpandoParseError *err)
Parse a format string.
#define NTE_QUESTION
'?' Question mark
#define NTE_GREATER
'>' Greater than
uint8_t NodeTextTermFlags
Special characters that end a text string.
#define NTE_AMPERSAND
'&' Ampersand
int(* render)(const struct ExpandoNode *node, const struct ExpandoRenderCallback *erc, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
enum ExpandoNodeType type
Type of Node, e.g. ENT_EXPANDO.
char message[1024]
Error message.
const char * position
Position of error in original string.