core: fix wrong results with the unary minus in calc expressions
This commit is contained in:
parent
dc5e334f5c
commit
7d795c4d53
@ -33,6 +33,15 @@
|
|||||||
#include "wee-arraylist.h"
|
#include "wee-arraylist.h"
|
||||||
#include "wee-string.h"
|
#include "wee-string.h"
|
||||||
|
|
||||||
|
enum t_calc_symbol
|
||||||
|
{
|
||||||
|
CALC_SYMBOL_NONE = 0,
|
||||||
|
CALC_SYMBOL_PARENTHESIS_OPEN,
|
||||||
|
CALC_SYMBOL_PARENTHESIS_CLOSE,
|
||||||
|
CALC_SYMBOL_VALUE,
|
||||||
|
CALC_SYMBOL_OPERATOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callback called to free a value or op in the arraylist.
|
* Callback called to free a value or op in the arraylist.
|
||||||
@ -178,7 +187,10 @@ calc_format_result (double value, char *result, int max_size)
|
|||||||
* used (instead of a comma in French for example)
|
* used (instead of a comma in French for example)
|
||||||
*/
|
*/
|
||||||
setlocale (LC_ALL, "C");
|
setlocale (LC_ALL, "C");
|
||||||
snprintf (result, max_size, "%.10f", value);
|
snprintf (result, max_size,
|
||||||
|
"%.10f",
|
||||||
|
/* ensure result is not "-0" */
|
||||||
|
(value == -0.0) ? 0.0 : value);
|
||||||
setlocale (LC_ALL, "");
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
pos_point = strchr (result, '.');
|
pos_point = strchr (result, '.');
|
||||||
@ -225,7 +237,8 @@ calc_expression (const char *expr)
|
|||||||
struct t_arraylist *list_values, *list_ops;
|
struct t_arraylist *list_values, *list_ops;
|
||||||
char str_result[64], *ptr_operator, *operator;
|
char str_result[64], *ptr_operator, *operator;
|
||||||
int i, i2, index_op, decimals;
|
int i, i2, index_op, decimals;
|
||||||
double value, *ptr_value;
|
enum t_calc_symbol last_symbol;
|
||||||
|
double value, factor, *ptr_value;
|
||||||
|
|
||||||
list_values = NULL;
|
list_values = NULL;
|
||||||
list_ops = NULL;
|
list_ops = NULL;
|
||||||
@ -250,6 +263,7 @@ calc_expression (const char *expr)
|
|||||||
if (!list_ops)
|
if (!list_ops)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
last_symbol = CALC_SYMBOL_NONE;
|
||||||
for (i = 0; expr[i]; i++)
|
for (i = 0; expr[i]; i++)
|
||||||
{
|
{
|
||||||
if (expr[i] == ' ')
|
if (expr[i] == ' ')
|
||||||
@ -261,11 +275,22 @@ calc_expression (const char *expr)
|
|||||||
{
|
{
|
||||||
ptr_operator = string_strndup (expr + i, 1);
|
ptr_operator = string_strndup (expr + i, 1);
|
||||||
arraylist_add (list_ops, ptr_operator);
|
arraylist_add (list_ops, ptr_operator);
|
||||||
|
last_symbol = CALC_SYMBOL_PARENTHESIS_OPEN;
|
||||||
}
|
}
|
||||||
else if (isdigit (expr[i]) || (expr[i] == '.'))
|
else if (isdigit (expr[i]) || (expr[i] == '.')
|
||||||
|
|| ((expr[i] == '-')
|
||||||
|
&& ((last_symbol == CALC_SYMBOL_NONE)
|
||||||
|
|| (last_symbol == CALC_SYMBOL_PARENTHESIS_OPEN)
|
||||||
|
|| (last_symbol == CALC_SYMBOL_OPERATOR))))
|
||||||
{
|
{
|
||||||
value = 0;
|
value = 0;
|
||||||
decimals = 0;
|
decimals = 0;
|
||||||
|
factor = 1;
|
||||||
|
if (expr[i] == '-')
|
||||||
|
{
|
||||||
|
factor = -1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
while (expr[i] && (isdigit (expr[i]) || (expr[i] == '.')))
|
while (expr[i] && (isdigit (expr[i]) || (expr[i] == '.')))
|
||||||
{
|
{
|
||||||
if (expr[i] == '.')
|
if (expr[i] == '.')
|
||||||
@ -288,9 +313,11 @@ calc_expression (const char *expr)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
i--;
|
i--;
|
||||||
|
value *= factor;
|
||||||
ptr_value = malloc (sizeof (value));
|
ptr_value = malloc (sizeof (value));
|
||||||
*ptr_value = value;
|
*ptr_value = value;
|
||||||
arraylist_add (list_values, ptr_value);
|
arraylist_add (list_values, ptr_value);
|
||||||
|
last_symbol = CALC_SYMBOL_VALUE;
|
||||||
}
|
}
|
||||||
else if (expr[i] == ')')
|
else if (expr[i] == ')')
|
||||||
{
|
{
|
||||||
@ -307,6 +334,7 @@ calc_expression (const char *expr)
|
|||||||
index_op = arraylist_size (list_ops) - 1;
|
index_op = arraylist_size (list_ops) - 1;
|
||||||
if (index_op >= 0)
|
if (index_op >= 0)
|
||||||
arraylist_remove (list_ops, index_op);
|
arraylist_remove (list_ops, index_op);
|
||||||
|
last_symbol = CALC_SYMBOL_PARENTHESIS_CLOSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -314,7 +342,7 @@ calc_expression (const char *expr)
|
|||||||
i2 = i + 1;
|
i2 = i + 1;
|
||||||
while (expr[i2] && (expr[i2] != ' ') && (expr[i2] != '(')
|
while (expr[i2] && (expr[i2] != ' ') && (expr[i2] != '(')
|
||||||
&& (expr[i2] != ')') && (expr[i2] != '.')
|
&& (expr[i2] != ')') && (expr[i2] != '.')
|
||||||
&& !isdigit (expr[i2]))
|
&& (expr[i2] != '-') && !isdigit (expr[i2]))
|
||||||
{
|
{
|
||||||
i2++;
|
i2++;
|
||||||
}
|
}
|
||||||
@ -334,6 +362,7 @@ calc_expression (const char *expr)
|
|||||||
}
|
}
|
||||||
arraylist_add (list_ops, operator);
|
arraylist_add (list_ops, operator);
|
||||||
}
|
}
|
||||||
|
last_symbol = CALC_SYMBOL_OPERATOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +53,13 @@ TEST(CoreCalc, Expression)
|
|||||||
WEE_CHECK_CALC("0", "-");
|
WEE_CHECK_CALC("0", "-");
|
||||||
WEE_CHECK_CALC("0", "*");
|
WEE_CHECK_CALC("0", "*");
|
||||||
WEE_CHECK_CALC("0", "/");
|
WEE_CHECK_CALC("0", "/");
|
||||||
|
WEE_CHECK_CALC("0", "%");
|
||||||
WEE_CHECK_CALC("0", "0/0");
|
WEE_CHECK_CALC("0", "0/0");
|
||||||
WEE_CHECK_CALC("0", "0//0");
|
WEE_CHECK_CALC("0", "0//0");
|
||||||
WEE_CHECK_CALC("0", "0%0");
|
WEE_CHECK_CALC("0", "0%0");
|
||||||
|
|
||||||
/* no operator */
|
/* no operator */
|
||||||
WEE_CHECK_CALC("123", "123");
|
WEE_CHECK_CALC("123", "123");
|
||||||
WEE_CHECK_CALC("-2", "-2");
|
|
||||||
WEE_CHECK_CALC("1.5", "1.5");
|
WEE_CHECK_CALC("1.5", "1.5");
|
||||||
|
|
||||||
/* addition */
|
/* addition */
|
||||||
@ -71,6 +71,25 @@ TEST(CoreCalc, Expression)
|
|||||||
WEE_CHECK_CALC("5", "8-3");
|
WEE_CHECK_CALC("5", "8-3");
|
||||||
WEE_CHECK_CALC("-5", "3-8");
|
WEE_CHECK_CALC("-5", "3-8");
|
||||||
|
|
||||||
|
/* unary minus */
|
||||||
|
WEE_CHECK_CALC("0", "-0");
|
||||||
|
WEE_CHECK_CALC("-0.001", "-0.001");
|
||||||
|
WEE_CHECK_CALC("0", "(-0)");
|
||||||
|
WEE_CHECK_CALC("0", "0-0");
|
||||||
|
WEE_CHECK_CALC("-1", "-1");
|
||||||
|
WEE_CHECK_CALC("-2", "-1+-1");
|
||||||
|
WEE_CHECK_CALC("0", "-1+1");
|
||||||
|
WEE_CHECK_CALC("-2", "-3+1");
|
||||||
|
WEE_CHECK_CALC("-3", "1+-4");
|
||||||
|
WEE_CHECK_CALC("-4", "2*-2");
|
||||||
|
WEE_CHECK_CALC("-6", "-3*2");
|
||||||
|
WEE_CHECK_CALC("9", "-3*-3");
|
||||||
|
WEE_CHECK_CALC("-6", "3*(-2)");
|
||||||
|
WEE_CHECK_CALC("6", "-3*(-2)");
|
||||||
|
WEE_CHECK_CALC("12", "(-3)*(-4)");
|
||||||
|
WEE_CHECK_CALC("15", "(-3)*-5");
|
||||||
|
WEE_CHECK_CALC("9", "(-3)*(-4+1)");
|
||||||
|
|
||||||
/* multiplication */
|
/* multiplication */
|
||||||
WEE_CHECK_CALC("20", "10*2");
|
WEE_CHECK_CALC("20", "10*2");
|
||||||
WEE_CHECK_CALC("-8", "-2*4");
|
WEE_CHECK_CALC("-8", "-2*4");
|
||||||
@ -86,6 +105,8 @@ TEST(CoreCalc, Expression)
|
|||||||
/* modulo */
|
/* modulo */
|
||||||
WEE_CHECK_CALC("4", "9%5");
|
WEE_CHECK_CALC("4", "9%5");
|
||||||
WEE_CHECK_CALC("0.2", "9.2%3");
|
WEE_CHECK_CALC("0.2", "9.2%3");
|
||||||
|
WEE_CHECK_CALC("-2", "-2%4");
|
||||||
|
WEE_CHECK_CALC("0", "-2%2");
|
||||||
|
|
||||||
/* multiple operators */
|
/* multiple operators */
|
||||||
WEE_CHECK_CALC("11", "5+2*3");
|
WEE_CHECK_CALC("11", "5+2*3");
|
||||||
@ -105,6 +126,8 @@ TEST(CoreCalc, Expression)
|
|||||||
WEE_CHECK_CALC("0", "1/123456789012");
|
WEE_CHECK_CALC("0", "1/123456789012");
|
||||||
|
|
||||||
/* expressions with parentheses */
|
/* expressions with parentheses */
|
||||||
|
WEE_CHECK_CALC("6", "((6))");
|
||||||
|
WEE_CHECK_CALC("-7.234", "((-7.234))");
|
||||||
WEE_CHECK_CALC("21", "(5+2)*3");
|
WEE_CHECK_CALC("21", "(5+2)*3");
|
||||||
WEE_CHECK_CALC("3.15", "(1.5+2)*(1.8/2)");
|
WEE_CHECK_CALC("3.15", "(1.5+2)*(1.8/2)");
|
||||||
WEE_CHECK_CALC("-1.26", "(1.5+2)*(1.8/(2-7))");
|
WEE_CHECK_CALC("-1.26", "(1.5+2)*(1.8/(2-7))");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user