core: fix evaluation of expressions with regex condition (closes #63)
The regex itself is not evaluated any more (so parentheses are kept). Before the fix: >> abcd =~ (?-i)^abc == [0] >> (abcd) =~ \(abcd\) == [0] After the fix: >> abcd =~ (?-i)^abc == [1] >> (abcd) =~ \(abcd\) == [1]
This commit is contained in:
parent
e0312f7ecf
commit
c5710c6f24
@ -34,8 +34,8 @@ http://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes]
|
||||
* core: add hidden buffers, add options hide/unhide in command /buffer
|
||||
* core: fix "/buffer clear" with a name (don't clear all merged buffers with
|
||||
same number)
|
||||
* core: fix evaluation of expression with regex when a comparison char is in
|
||||
the regex
|
||||
* core: fix evaluation of expression with regex: when a comparison char is in
|
||||
the regex and don't evaluate the regex itself (closes #63)
|
||||
* core: close .upgrade files before deleting them after /upgrade
|
||||
* core: add default key key[alt--] (toggle filters in current buffer)
|
||||
(closes #17)
|
||||
|
@ -510,10 +510,52 @@ end:
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluates a condition (this function must not be called directly).
|
||||
* Searches a string in another at same level (skip sub-expressions between
|
||||
* parentheses).
|
||||
*
|
||||
* Argument keep_parentheses is almost always 0, it is 1 only if the expression
|
||||
* is a regex (to keep flags inside the parentheses).
|
||||
* For example: eval_strstr_level ("(x || y) || z", "||")
|
||||
* will return a pointer on "|| z" (because the first "||" is
|
||||
* in a sub-expression, which is skipped).
|
||||
*
|
||||
* Returns pointer to string found, or NULL if not found.
|
||||
*/
|
||||
|
||||
const char *
|
||||
eval_strstr_level (const char *string, const char *search)
|
||||
{
|
||||
const char *ptr_string;
|
||||
int level, length;
|
||||
|
||||
if (!string || !search)
|
||||
return NULL;
|
||||
|
||||
length = strlen (search);
|
||||
|
||||
ptr_string = string;
|
||||
level = 0;
|
||||
while (ptr_string[0])
|
||||
{
|
||||
if (ptr_string[0] == '(')
|
||||
{
|
||||
level++;
|
||||
}
|
||||
else if (ptr_string[0] == ')')
|
||||
{
|
||||
if (level > 0)
|
||||
level--;
|
||||
}
|
||||
|
||||
if ((level == 0) && (strncmp (ptr_string, search, length) == 0))
|
||||
return ptr_string;
|
||||
|
||||
ptr_string++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluates a condition (this function must not be called directly).
|
||||
*
|
||||
* For return value, see function eval_expression().
|
||||
*
|
||||
@ -524,15 +566,12 @@ char *
|
||||
eval_expression_condition (const char *expr,
|
||||
struct t_hashtable *pointers,
|
||||
struct t_hashtable *extra_vars,
|
||||
int keep_parentheses,
|
||||
int search_logical_op,
|
||||
int search_comparison,
|
||||
const char *prefix,
|
||||
const char *suffix)
|
||||
{
|
||||
int logic, comp, length, level, regex, rc;
|
||||
const char *pos_end;
|
||||
char *expr2, *sub_expr, *pos, *pos2, *value, *tmp_value, *tmp_value2;
|
||||
int logic, comp, length, level, rc;
|
||||
const char *pos, *pos_end;
|
||||
char *expr2, *sub_expr, *value, *tmp_value, *tmp_value2;
|
||||
|
||||
value = NULL;
|
||||
|
||||
@ -561,85 +600,6 @@ eval_expression_condition (const char *expr,
|
||||
if (!expr2)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* evaluate sub-expressions between parentheses and replace them with their
|
||||
* value
|
||||
*/
|
||||
if (!keep_parentheses)
|
||||
{
|
||||
while ((pos = strchr (expr2, '(')) != NULL)
|
||||
{
|
||||
level = 0;
|
||||
pos2 = pos + 1;
|
||||
while (pos2[0])
|
||||
{
|
||||
if (pos2[0] == '(')
|
||||
level++;
|
||||
else if (pos2[0] == ')')
|
||||
{
|
||||
if (level == 0)
|
||||
break;
|
||||
level--;
|
||||
}
|
||||
pos2++;
|
||||
}
|
||||
/* closing parenthesis not found */
|
||||
if (pos2[0] != ')')
|
||||
goto end;
|
||||
sub_expr = string_strndup (pos + 1, pos2 - pos - 1);
|
||||
if (!sub_expr)
|
||||
goto end;
|
||||
tmp_value = eval_expression_condition (sub_expr,
|
||||
pointers,
|
||||
extra_vars,
|
||||
/* keep parentheses */
|
||||
0,
|
||||
search_logical_op,
|
||||
search_comparison,
|
||||
prefix,
|
||||
suffix);
|
||||
free (sub_expr);
|
||||
if (!pos[1])
|
||||
{
|
||||
/* nothing around parentheses, then return value of sub-expression as-is */
|
||||
value = tmp_value;
|
||||
goto end;
|
||||
}
|
||||
/*
|
||||
* build a string with string before '(' +
|
||||
* result of sub-expression + string after ')'
|
||||
*/
|
||||
length = (pos - expr2) + 1
|
||||
+ ((tmp_value) ? strlen (tmp_value) : 0)
|
||||
+ 1 + strlen (pos2 + 1)
|
||||
+ 1;
|
||||
tmp_value2 = malloc (length);
|
||||
if (!tmp_value2)
|
||||
{
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
goto end;
|
||||
}
|
||||
tmp_value2[0] = '\0';
|
||||
if (pos > expr2)
|
||||
{
|
||||
strncat (tmp_value2, expr2, pos - expr2);
|
||||
strcat (tmp_value2, " ");
|
||||
}
|
||||
if (tmp_value)
|
||||
strcat (tmp_value2, tmp_value);
|
||||
if (pos2[1])
|
||||
{
|
||||
strcat (tmp_value2, " ");
|
||||
strcat (tmp_value2, pos2 + 1);
|
||||
}
|
||||
free (expr2);
|
||||
expr2 = tmp_value2;
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* search for a logical operator, and if one is found:
|
||||
* - split expression into two sub-expressions
|
||||
@ -647,64 +607,48 @@ eval_expression_condition (const char *expr,
|
||||
* - if needed, evaluate second sub-expression
|
||||
* - return result
|
||||
*/
|
||||
if (search_logical_op)
|
||||
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]);
|
||||
if (pos > expr2)
|
||||
{
|
||||
pos = strstr (expr2, logical_ops[logic]);
|
||||
if (pos > expr2)
|
||||
pos_end = pos - 1;
|
||||
while ((pos_end > expr2) && (pos_end[0] == ' '))
|
||||
{
|
||||
pos_end--;
|
||||
}
|
||||
sub_expr = string_strndup (expr2, pos_end + 1 - expr2);
|
||||
if (!sub_expr)
|
||||
goto end;
|
||||
tmp_value = eval_expression_condition (sub_expr, pointers,
|
||||
extra_vars,
|
||||
prefix, suffix);
|
||||
free (sub_expr);
|
||||
rc = eval_is_true (tmp_value);
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
/*
|
||||
* if rc == 0 with "&&" or rc == 1 with "||", no need to
|
||||
* evaluate second sub-expression, just return the rc
|
||||
*/
|
||||
if ((!rc && (logic == EVAL_LOGICAL_OP_AND))
|
||||
|| (rc && (logic == EVAL_LOGICAL_OP_OR)))
|
||||
{
|
||||
pos_end = pos - 1;
|
||||
while ((pos_end > expr2) && (pos_end[0] == ' '))
|
||||
{
|
||||
pos_end--;
|
||||
}
|
||||
sub_expr = string_strndup (expr2, pos_end + 1 - expr2);
|
||||
if (!sub_expr)
|
||||
goto end;
|
||||
tmp_value = eval_expression_condition (sub_expr,
|
||||
pointers,
|
||||
extra_vars,
|
||||
/* keep parentheses */
|
||||
0,
|
||||
search_logical_op,
|
||||
search_comparison,
|
||||
prefix,
|
||||
suffix);
|
||||
free (sub_expr);
|
||||
rc = eval_is_true (tmp_value);
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
/*
|
||||
* if rc == 0 with "&&" or rc == 1 with "||", no need to
|
||||
* evaluate second sub-expression, just return the rc
|
||||
*/
|
||||
if ((!rc && (logic == EVAL_LOGICAL_OP_AND))
|
||||
|| (rc && (logic == EVAL_LOGICAL_OP_OR)))
|
||||
{
|
||||
value = strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
|
||||
goto end;
|
||||
}
|
||||
pos += strlen (logical_ops[logic]);
|
||||
while (pos[0] == ' ')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
tmp_value = eval_expression_condition (pos,
|
||||
pointers,
|
||||
extra_vars,
|
||||
/* keep parentheses */
|
||||
0,
|
||||
search_logical_op,
|
||||
search_comparison,
|
||||
prefix,
|
||||
suffix);
|
||||
rc = eval_is_true (tmp_value);
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
value = strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
|
||||
goto end;
|
||||
}
|
||||
pos += strlen (logical_ops[logic]);
|
||||
while (pos[0] == ' ')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
tmp_value = eval_expression_condition (pos, pointers, extra_vars,
|
||||
prefix, suffix);
|
||||
rc = eval_is_true (tmp_value);
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
value = strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
@ -715,59 +659,113 @@ eval_expression_condition (const char *expr,
|
||||
* - compare sub-expressions
|
||||
* - return result
|
||||
*/
|
||||
if (search_comparison)
|
||||
for (comp = 0; comp < EVAL_NUM_COMPARISONS; comp++)
|
||||
{
|
||||
for (comp = 0; comp < EVAL_NUM_COMPARISONS; comp++)
|
||||
pos = eval_strstr_level (expr2, comparisons[comp]);
|
||||
if (pos > expr2)
|
||||
{
|
||||
pos = strstr (expr2, comparisons[comp]);
|
||||
if (pos > expr2)
|
||||
pos_end = pos - 1;
|
||||
while ((pos_end > expr2) && (pos_end[0] == ' '))
|
||||
{
|
||||
pos_end = pos - 1;
|
||||
while ((pos_end > expr2) && (pos_end[0] == ' '))
|
||||
{
|
||||
pos_end--;
|
||||
}
|
||||
sub_expr = string_strndup (expr2, pos_end + 1 - expr2);
|
||||
if (!sub_expr)
|
||||
goto end;
|
||||
tmp_value = eval_expression_condition (sub_expr,
|
||||
pointers,
|
||||
extra_vars,
|
||||
/* keep parentheses */
|
||||
0,
|
||||
search_logical_op,
|
||||
search_comparison,
|
||||
prefix,
|
||||
suffix);
|
||||
free (sub_expr);
|
||||
pos += strlen (comparisons[comp]);
|
||||
while (pos[0] == ' ')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
regex = ((comp == EVAL_COMPARE_REGEX_MATCHING)
|
||||
|| (comp == EVAL_COMPARE_REGEX_NOT_MATCHING));
|
||||
tmp_value2 = eval_expression_condition (pos,
|
||||
pointers,
|
||||
extra_vars,
|
||||
/* keep parentheses */
|
||||
(regex) ? 1 : 0,
|
||||
/* search logical op */
|
||||
0,
|
||||
/* search comparison */
|
||||
0,
|
||||
prefix,
|
||||
suffix);
|
||||
value = eval_compare (tmp_value, comp, tmp_value2);
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
if (tmp_value2)
|
||||
free (tmp_value2);
|
||||
goto end;
|
||||
pos_end--;
|
||||
}
|
||||
sub_expr = string_strndup (expr2, pos_end + 1 - expr2);
|
||||
if (!sub_expr)
|
||||
goto end;
|
||||
pos += strlen (comparisons[comp]);
|
||||
while (pos[0] == ' ')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
if ((comp == EVAL_COMPARE_REGEX_MATCHING)
|
||||
|| (comp == EVAL_COMPARE_REGEX_NOT_MATCHING))
|
||||
{
|
||||
/* for regex: just replace vars in both expressions */
|
||||
tmp_value = eval_replace_vars (sub_expr, pointers,
|
||||
extra_vars,
|
||||
prefix, suffix);
|
||||
tmp_value2 = eval_replace_vars (pos, pointers,
|
||||
extra_vars,
|
||||
prefix, suffix);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* other comparison: fully evaluate both expressions */
|
||||
tmp_value = eval_expression_condition (sub_expr, pointers,
|
||||
extra_vars,
|
||||
prefix, suffix);
|
||||
tmp_value2 = eval_expression_condition (pos, pointers,
|
||||
extra_vars,
|
||||
prefix, suffix);
|
||||
}
|
||||
free (sub_expr);
|
||||
value = eval_compare (tmp_value, comp, tmp_value2);
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
if (tmp_value2)
|
||||
free (tmp_value2);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* evaluate sub-expressions between parentheses and replace them with their
|
||||
* value
|
||||
*/
|
||||
while (expr2[0] == '(')
|
||||
{
|
||||
level = 0;
|
||||
pos = expr2 + 1;
|
||||
while (pos[0])
|
||||
{
|
||||
if (pos[0] == '(')
|
||||
level++;
|
||||
else if (pos[0] == ')')
|
||||
{
|
||||
if (level == 0)
|
||||
break;
|
||||
level--;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
/* closing parenthesis not found */
|
||||
if (pos[0] != ')')
|
||||
goto end;
|
||||
sub_expr = string_strndup (expr2 + 1, pos - expr2 - 1);
|
||||
if (!sub_expr)
|
||||
goto end;
|
||||
tmp_value = eval_expression_condition (sub_expr, pointers, extra_vars,
|
||||
prefix, suffix);
|
||||
free (sub_expr);
|
||||
if (!pos[1])
|
||||
{
|
||||
/*
|
||||
* nothing around parentheses, then return value of
|
||||
* sub-expression as-is
|
||||
*/
|
||||
value = tmp_value;
|
||||
goto end;
|
||||
}
|
||||
length = ((tmp_value) ? strlen (tmp_value) : 0) + 1 +
|
||||
strlen (pos + 1) + 1;
|
||||
tmp_value2 = malloc (length);
|
||||
if (!tmp_value2)
|
||||
{
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
goto end;
|
||||
}
|
||||
tmp_value2[0] = '\0';
|
||||
if (tmp_value)
|
||||
strcat (tmp_value2, tmp_value);
|
||||
strcat (tmp_value2, " ");
|
||||
strcat (tmp_value2, pos + 1);
|
||||
free (expr2);
|
||||
expr2 = tmp_value2;
|
||||
if (tmp_value)
|
||||
free (tmp_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* at this point, there is no more logical operator neither comparison,
|
||||
* so we just replace variables in string and return the result
|
||||
@ -892,17 +890,8 @@ eval_expression (const char *expr, struct t_hashtable *pointers,
|
||||
if (condition)
|
||||
{
|
||||
/* evaluate as condition (return a boolean: "0" or "1") */
|
||||
value = eval_expression_condition (expr,
|
||||
pointers,
|
||||
extra_vars,
|
||||
/* keep parentheses */
|
||||
0,
|
||||
/* search logical op */
|
||||
1,
|
||||
/* search comparison */
|
||||
1,
|
||||
prefix,
|
||||
suffix);
|
||||
value = eval_expression_condition (expr, pointers, extra_vars,
|
||||
prefix, suffix);
|
||||
rc = eval_is_true (value);
|
||||
if (value)
|
||||
free (value);
|
||||
|
Loading…
x
Reference in New Issue
Block a user