core: fix evaluation of condition with nested "if" (closes #1434)
parent
a13099aa63
commit
e612e63140
|
@ -25,6 +25,7 @@ New features::
|
||||||
|
|
||||||
Bug fixes::
|
Bug fixes::
|
||||||
|
|
||||||
|
* core: fix evaluation of condition with nested "if" (issue #1434)
|
||||||
* irc: fix memory leak when the channel topic is changed
|
* irc: fix memory leak when the channel topic is changed
|
||||||
|
|
||||||
Build::
|
Build::
|
||||||
|
|
|
@ -102,7 +102,8 @@ eval_is_true (const char *value)
|
||||||
*
|
*
|
||||||
* If escape is 1, the prefix can be escaped with '\' (and then is ignored).
|
* If escape is 1, the prefix can be escaped with '\' (and then is ignored).
|
||||||
*
|
*
|
||||||
* For example: eval_strstr_level ("(x || y) || z", "||")
|
* For example:
|
||||||
|
* eval_strstr_level ("(x || y) || z", "||", eval_context, "(", ")", 0)
|
||||||
* will return a pointer on "|| z" (because the first "||" is
|
* will return a pointer on "|| z" (because the first "||" is
|
||||||
* in a sub-expression, which is skipped).
|
* in a sub-expression, which is skipped).
|
||||||
*
|
*
|
||||||
|
@ -111,37 +112,63 @@ eval_is_true (const char *value)
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
eval_strstr_level (const char *string, const char *search,
|
eval_strstr_level (const char *string, const char *search,
|
||||||
const char *prefix, const char *suffix, int escape)
|
struct t_eval_context *eval_context,
|
||||||
|
const char *extra_prefix, const char *extra_suffix,
|
||||||
|
int escape)
|
||||||
{
|
{
|
||||||
const char *ptr_string;
|
const char *ptr_string;
|
||||||
int level, length_search, length_prefix, length_suffix;
|
int level, length_search;
|
||||||
|
int length_prefix, length_prefix2, length_suffix, length_suffix2;
|
||||||
|
|
||||||
|
EVAL_DEBUG("eval_strstr_level(\"%s\", \"%s\", \"%s\", \"%s\", %d)",
|
||||||
|
string, search, extra_prefix, extra_suffix, escape);
|
||||||
|
|
||||||
if (!string || !search)
|
if (!string || !search)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
length_search = strlen (search);
|
length_search = strlen (search);
|
||||||
length_prefix = strlen (prefix);
|
|
||||||
length_suffix = strlen (suffix);
|
length_prefix = strlen (eval_context->prefix);
|
||||||
|
length_suffix = strlen (eval_context->suffix);
|
||||||
|
|
||||||
|
length_prefix2 = (extra_prefix) ? strlen (extra_prefix) : 0;
|
||||||
|
length_suffix2 = (extra_suffix) ? strlen (extra_suffix) : 0;
|
||||||
|
|
||||||
ptr_string = string;
|
ptr_string = string;
|
||||||
level = 0;
|
level = 0;
|
||||||
while (ptr_string[0])
|
while (ptr_string[0])
|
||||||
{
|
{
|
||||||
if (escape && (ptr_string[0] == '\\') && (ptr_string[1] == prefix[0]))
|
if (escape
|
||||||
|
&& (ptr_string[0] == '\\')
|
||||||
|
&& ((ptr_string[1] == eval_context->prefix[0])
|
||||||
|
|| ((length_suffix2 > 0) && ptr_string[1] == extra_prefix[0])))
|
||||||
{
|
{
|
||||||
ptr_string++;
|
ptr_string++;
|
||||||
}
|
}
|
||||||
else if (strncmp (ptr_string, prefix, length_prefix) == 0)
|
else if (strncmp (ptr_string, eval_context->prefix, length_prefix) == 0)
|
||||||
{
|
{
|
||||||
level++;
|
level++;
|
||||||
ptr_string += length_prefix;
|
ptr_string += length_prefix;
|
||||||
}
|
}
|
||||||
else if (strncmp (ptr_string, suffix, length_suffix) == 0)
|
else if ((length_prefix2 > 0)
|
||||||
|
&& (strncmp (ptr_string, extra_prefix, length_prefix2) == 0))
|
||||||
|
{
|
||||||
|
level++;
|
||||||
|
ptr_string += length_prefix2;
|
||||||
|
}
|
||||||
|
else if (strncmp (ptr_string, eval_context->suffix, length_suffix) == 0)
|
||||||
{
|
{
|
||||||
if (level > 0)
|
if (level > 0)
|
||||||
level--;
|
level--;
|
||||||
ptr_string += length_suffix;
|
ptr_string += length_suffix;
|
||||||
}
|
}
|
||||||
|
else if ((length_suffix2 > 0)
|
||||||
|
&& (strncmp (ptr_string, extra_suffix, length_suffix2) == 0))
|
||||||
|
{
|
||||||
|
if (level > 0)
|
||||||
|
level--;
|
||||||
|
ptr_string += length_suffix2;
|
||||||
|
}
|
||||||
else if ((level == 0)
|
else if ((level == 0)
|
||||||
&& (strncmp (ptr_string, search, length_search) == 0))
|
&& (strncmp (ptr_string, search, length_search) == 0))
|
||||||
{
|
{
|
||||||
|
@ -643,17 +670,11 @@ eval_replace_vars_cb (void *data, const char *text)
|
||||||
if (strncmp (text, "if:", 3) == 0)
|
if (strncmp (text, "if:", 3) == 0)
|
||||||
{
|
{
|
||||||
value = NULL;
|
value = NULL;
|
||||||
pos = (char *)eval_strstr_level (text + 3,
|
pos = (char *)eval_strstr_level (text + 3, "?",
|
||||||
"?",
|
eval_context, NULL, NULL, 1);
|
||||||
eval_context->prefix,
|
|
||||||
eval_context->suffix,
|
|
||||||
1);
|
|
||||||
pos2 = (pos) ?
|
pos2 = (pos) ?
|
||||||
(char *)eval_strstr_level (pos + 1,
|
(char *)eval_strstr_level (pos + 1, ":",
|
||||||
":",
|
eval_context, NULL, NULL, 1) : NULL;
|
||||||
eval_context->prefix,
|
|
||||||
eval_context->suffix,
|
|
||||||
1) : NULL;
|
|
||||||
condition = (pos) ?
|
condition = (pos) ?
|
||||||
strndup (text + 3, pos - (text + 3)) : strdup (text + 3);
|
strndup (text + 3, pos - (text + 3)) : strdup (text + 3);
|
||||||
if (!condition)
|
if (!condition)
|
||||||
|
@ -1037,7 +1058,8 @@ eval_expression_condition (const char *expr,
|
||||||
*/
|
*/
|
||||||
for (logic = 0; logic < EVAL_NUM_LOGICAL_OPS; logic++)
|
for (logic = 0; logic < EVAL_NUM_LOGICAL_OPS; logic++)
|
||||||
{
|
{
|
||||||
pos = eval_strstr_level (expr2, logical_ops[logic], "(", ")", 0);
|
pos = eval_strstr_level (expr2, logical_ops[logic], eval_context,
|
||||||
|
"(", ")", 0);
|
||||||
if (pos > expr2)
|
if (pos > expr2)
|
||||||
{
|
{
|
||||||
pos_end = pos - 1;
|
pos_end = pos - 1;
|
||||||
|
@ -1086,7 +1108,8 @@ eval_expression_condition (const char *expr,
|
||||||
*/
|
*/
|
||||||
for (comp = 0; comp < EVAL_NUM_COMPARISONS; comp++)
|
for (comp = 0; comp < EVAL_NUM_COMPARISONS; comp++)
|
||||||
{
|
{
|
||||||
pos = eval_strstr_level (expr2, comparisons[comp], "(", ")", 0);
|
pos = eval_strstr_level (expr2, comparisons[comp], eval_context,
|
||||||
|
"(", ")", 0);
|
||||||
if (pos >= expr2)
|
if (pos >= expr2)
|
||||||
{
|
{
|
||||||
if (pos > expr2)
|
if (pos > expr2)
|
||||||
|
|
|
@ -147,6 +147,9 @@ TEST(CoreEval, EvalCondition)
|
||||||
WEE_CHECK_EVAL("0", "${window.buffer.number} == 2");
|
WEE_CHECK_EVAL("0", "${window.buffer.number} == 2");
|
||||||
WEE_CHECK_EVAL("0", "${calc:2+3} < 5");
|
WEE_CHECK_EVAL("0", "${calc:2+3} < 5");
|
||||||
WEE_CHECK_EVAL("0", "${calc:1.5*3} < 4.5");
|
WEE_CHECK_EVAL("0", "${calc:1.5*3} < 4.5");
|
||||||
|
WEE_CHECK_EVAL("0", "${if:${buffer.number}==2?yes:}");
|
||||||
|
WEE_CHECK_EVAL("0", "${if:${buffer.number}==2?yes:no} == yes");
|
||||||
|
WEE_CHECK_EVAL("0", "yes == ${if:${buffer.number}==2?yes:no}");
|
||||||
|
|
||||||
/* conditions evaluated as true */
|
/* conditions evaluated as true */
|
||||||
WEE_CHECK_EVAL("1", "1");
|
WEE_CHECK_EVAL("1", "1");
|
||||||
|
@ -207,6 +210,9 @@ TEST(CoreEval, EvalCondition)
|
||||||
WEE_CHECK_EVAL("1", "${window.buffer.number} == 1");
|
WEE_CHECK_EVAL("1", "${window.buffer.number} == 1");
|
||||||
WEE_CHECK_EVAL("1", "${calc:2+3} >= 5");
|
WEE_CHECK_EVAL("1", "${calc:2+3} >= 5");
|
||||||
WEE_CHECK_EVAL("1", "${calc:1.5*3} >= 4.5");
|
WEE_CHECK_EVAL("1", "${calc:1.5*3} >= 4.5");
|
||||||
|
WEE_CHECK_EVAL("1", "${if:${buffer.number}==1?yes:}");
|
||||||
|
WEE_CHECK_EVAL("1", "${if:${buffer.number}==1?yes:no} == yes");
|
||||||
|
WEE_CHECK_EVAL("1", "yes == ${if:${buffer.number}==1?yes:no}");
|
||||||
|
|
||||||
/* evaluation of extra_vars */
|
/* evaluation of extra_vars */
|
||||||
hashtable_set (options, "extra", "eval");
|
hashtable_set (options, "extra", "eval");
|
||||||
|
|
Loading…
Reference in New Issue