Parse a format string into ExpandoNodes.
129{
130 if (!str || (*str == '\0'))
131 return NULL;
132
133 while (*str && (end ? (str <= end) : true))
134 {
135
136
137 if ((*str == '%') ||
138 ((condition_start ==
CON_START) && ((*str ==
'?') || (*str ==
'<'))))
139 {
140 str++;
141
142
143 if (*str == '%')
144 {
145 *parsed_until = str + 1;
147 }
148
149 else if ((*str == '?') || (*str == '<'))
150 {
151 bool old_style = (*str == '?');
152 char end_terminator = old_style ? '?' : '>';
153
155 const char *next = NULL;
157 &next, defs, err);
158 if (!node_cond)
159 return NULL;
160
161 if (*next != '?')
162 {
165
166
167 _(
"Conditional expando is missing '%c'"),
'?');
169 return NULL;
170 }
171
172 str = next + 1;
173
174 const char *start_true = str;
175
177 bool only_true = (*end_true == end_terminator);
178 bool invalid = ((*end_true != '&') && !only_true);
179
180 if (invalid)
181 {
184
185
186 _(
"Conditional expando is missing '&' or '%c'"), end_terminator);
188 return NULL;
189 }
190
191 const char *if_true_parsed = NULL;
193
194 while (start_true < end_true)
195 {
197 &if_true_parsed, defs, err);
198 if (!node)
199 {
202 return NULL;
203 }
204
206
207 start_true = if_true_parsed;
208 }
209
210 if (only_true)
211 {
212 *parsed_until = end_true + 1;
214 }
215 else
216 {
217 const char *start_false = end_true + 1;
218
220
221 if (*end_false != end_terminator)
222 {
225
226
227 _(
"Conditional expando is missing '%c'"), end_terminator);
230 return NULL;
231 }
232
233 const char *if_false_parsed = NULL;
235
236 while (start_false < end_false)
237 {
239 &if_false_parsed, defs, err);
240 if (!node)
241 {
245 return NULL;
246 }
247
249
250 start_false = if_false_parsed;
251 }
252
253 *parsed_until = end_false + 1;
255 }
256 }
257 else
258 {
262 {
264 }
265 else
266 {
268 }
269
271 {
273 return NULL;
274 }
275
276 return node;
277 }
278 }
279 else
280 {
282 }
283 }
284
285 ASSERT(
false &&
"Internal parsing error");
286 return NULL;
287}
#define EP_NO_FLAGS
No flags are set.
uint8_t ExpandoParserFlags
Flags for expando_parse(), e.g. EP_CONDITIONAL.
#define EP_CONDITIONAL
Expando is being used as a condition.
const char * skip_until_ch(const char *start, char terminator)
Search a string for a terminator character.
static const char * skip_until_if_true_end(const char *start, char end_terminator)
Search for the end of an 'if true' condition.
static const char * skip_until_if_false_end(const char *start, char end_terminator)
Search for the end of an 'if false' condition.
struct ExpandoNode * node_parse(const char *str, const char *end, enum ExpandoConditionStart condition_start, const char **parsed_until, const struct ExpandoDefinition *defs, struct ExpandoParseError *err)
Parse a format string into ExpandoNodes.
struct ExpandoNode * node_condbool_parse(const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, const char **parsed_until, struct ExpandoParseError *err)
Parse a CondBool format string - Implements ExpandoDefinition::parse() -.
void node_add_child(struct ExpandoNode *node, struct ExpandoNode *child)
Add a child to an ExpandoNode.
void node_free(struct ExpandoNode **ptr)
Free an ExpandoNode and its private data.
struct ExpandoNode * node_condition_new(struct ExpandoNode *condition, struct ExpandoNode *node_true, struct ExpandoNode *node_false)
Create a new Condition Expando Node.
@ CON_NO_CONDITION
Parser is not currently in a condition.
@ CON_START
Parser is working on a condition.
struct ExpandoNode * node_container_new(void)
Create a new Container ExpandoNode.
struct ExpandoNode * node_expando_parse(const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, const char **parsed_until, struct ExpandoParseError *err)
Parse an Expando format string.
struct ExpandoNode * node_text_new(const char *start, const char *end)
Create a new Text ExpandoNode.
struct ExpandoNode * node_text_parse(const char *str, const char *end, const char **parsed_until)
Extract a block of text.
const char * position
Position of error in original string.
char message[256]
Error message.