core: fix evaluation of expressions with parentheses

First evaluate sub-expressions between parentheses.

Before the fix:
>> 1 && (0 || 0)
== [1]

After the fix:
>> 1 && (0 || 0)
== [0]
This commit is contained in:
Sebastien Helleu 2013-08-25 13:34:51 +02:00
parent f250be4aa8
commit 86e7d95b9c
2 changed files with 35 additions and 18 deletions

View File

@ -42,7 +42,8 @@ Version 0.4.2 (under dev!)
man page (off by default) man page (off by default)
* core: add option "-o" for command /color * core: add option "-o" for command /color
* core: fix priority of logical operators in evaluation of expression * core: fix priority of logical operators in evaluation of expression
(AND takes precedence over the OR) (AND takes precedence over the OR) and first evaluate sub-expressions between
parentheses
* core: remove gap after read marker line when there is no bar on the right * core: remove gap after read marker line when there is no bar on the right
(bug #39548) (bug #39548)
* core: add CA_FILE option in cmake and configure to setup default * core: add CA_FILE option in cmake and configure to setup default

View File

@ -496,7 +496,7 @@ eval_expression_condition (const char *expr, struct t_hashtable *pointers,
{ {
int logic, comp, length, level, rc; int logic, comp, length, level, rc;
const char *pos_end; const char *pos_end;
char *expr2, *sub_expr, *pos, *value, *tmp_value, *tmp_value2; char *expr2, *sub_expr, *pos, *pos2, *value, *tmp_value, *tmp_value2;
value = NULL; value = NULL;
@ -506,9 +506,7 @@ eval_expression_condition (const char *expr, struct t_hashtable *pointers,
if (!expr[0]) if (!expr[0])
return strdup (expr); return strdup (expr);
/* /* skip spaces at beginning of string */
* skip spaces at beginning of string
*/
while (expr[0] == ' ') while (expr[0] == ' ')
{ {
expr++; expr++;
@ -527,29 +525,32 @@ eval_expression_condition (const char *expr, struct t_hashtable *pointers,
if (!expr2) if (!expr2)
return NULL; return NULL;
/* evaluate sub-expression in parentheses and replace it with value */ /*
* evaluate sub-expressions between parentheses and replace them with their
* value
*/
if (!keep_parentheses) if (!keep_parentheses)
{ {
while (expr2[0] == '(') while ((pos = strchr (expr2, '(')) != NULL)
{ {
level = 0; level = 0;
pos = expr2 + 1; pos2 = pos + 1;
while (pos[0]) while (pos2[0])
{ {
if (pos[0] == '(') if (pos2[0] == '(')
level++; level++;
else if (pos[0] == ')') else if (pos2[0] == ')')
{ {
if (level == 0) if (level == 0)
break; break;
level--; level--;
} }
pos++; pos2++;
} }
/* closing parenthesis not found */ /* closing parenthesis not found */
if (pos[0] != ')') if (pos2[0] != ')')
goto end; goto end;
sub_expr = string_strndup (expr2 + 1, pos - expr2 - 1); sub_expr = string_strndup (pos + 1, pos2 - pos - 1);
if (!sub_expr) if (!sub_expr)
goto end; goto end;
tmp_value = eval_expression_condition (sub_expr, pointers, tmp_value = eval_expression_condition (sub_expr, pointers,
@ -558,19 +559,34 @@ eval_expression_condition (const char *expr, struct t_hashtable *pointers,
free (sub_expr); free (sub_expr);
if (!pos[1]) if (!pos[1])
{ {
/* nothing after ')', then return value of sub-expression as-is */ /* nothing around parentheses, then return value of sub-expression as-is */
value = tmp_value; value = tmp_value;
goto end; goto end;
} }
length = ((tmp_value) ? strlen (tmp_value) : 0) + 1 + strlen (pos + 1) + 1; /*
* 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); tmp_value2 = malloc (length);
if (!tmp_value2) if (!tmp_value2)
goto end; goto end;
tmp_value2[0] = '\0'; tmp_value2[0] = '\0';
if (pos > expr2)
{
strncat (tmp_value2, expr2, pos - expr2);
strcat (tmp_value2, " ");
}
if (tmp_value) if (tmp_value)
strcat (tmp_value2, tmp_value); strcat (tmp_value2, tmp_value);
if (pos2[1])
{
strcat (tmp_value2, " "); strcat (tmp_value2, " ");
strcat (tmp_value2, pos + 1); strcat (tmp_value2, pos2 + 1);
}
free (expr2); free (expr2);
expr2 = tmp_value2; expr2 = tmp_value2;
} }