mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
2002-10-16 Joshua Sled <jsled@asynchronous.org>
* src/app-utils/gnc-exp-parser.c (gnc_exp_parser_parse): This function now fails correctly if there are un-bound variables in the expression. This causes expressions like 'AUD 1.23' to fail. This is related to, but not a fix for, Bug#95474. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@7328 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
8fe4bf789c
commit
b4986ed2de
@ -1,3 +1,10 @@
|
|||||||
|
2002-10-16 Joshua Sled <jsled@asynchronous.org>
|
||||||
|
|
||||||
|
* src/app-utils/gnc-exp-parser.c (gnc_exp_parser_parse): This
|
||||||
|
function now fails correctly if there are un-bound variables in
|
||||||
|
the expression. This causes expressions like 'AUD 1.23' to fail.
|
||||||
|
This is related to, but not a fix for, Bug#95474.
|
||||||
|
|
||||||
2002-10-16 Christian Stimming <stimming@tuhh.de>
|
2002-10-16 Christian Stimming <stimming@tuhh.de>
|
||||||
|
|
||||||
* src/import-export/hbci/hbci-account-picker.c,
|
* src/import-export/hbci/hbci-account-picker.c,
|
||||||
|
@ -44,9 +44,10 @@ typedef struct ParserNum
|
|||||||
|
|
||||||
|
|
||||||
/** Static Globals *************************************************/
|
/** Static Globals *************************************************/
|
||||||
static GHashTable *variable_bindings = NULL;
|
static GHashTable *variable_bindings = NULL;
|
||||||
static ParseError last_error = PARSER_NO_ERROR;
|
static ParseError last_error = PARSER_NO_ERROR;
|
||||||
static gboolean parser_inited = FALSE;
|
static GNCParseError last_gncp_error = NO_ERR;
|
||||||
|
static gboolean parser_inited = FALSE;
|
||||||
|
|
||||||
|
|
||||||
/** Implementations ************************************************/
|
/** Implementations ************************************************/
|
||||||
@ -169,6 +170,7 @@ gnc_exp_parser_shutdown (void)
|
|||||||
variable_bindings = NULL;
|
variable_bindings = NULL;
|
||||||
|
|
||||||
last_error = PARSER_NO_ERROR;
|
last_error = PARSER_NO_ERROR;
|
||||||
|
last_gncp_error = NO_ERR;
|
||||||
|
|
||||||
parser_inited = FALSE;
|
parser_inited = FALSE;
|
||||||
}
|
}
|
||||||
@ -470,12 +472,58 @@ negate_numeric(void *value)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
gnc_ep_tmpvarhash_check_vals( gpointer key, gpointer value, gpointer user_data )
|
||||||
|
{
|
||||||
|
gboolean *allVarsHaveValues = (gboolean*)user_data;
|
||||||
|
gnc_numeric *num = (gnc_numeric*)value;
|
||||||
|
printf( "var %s with value %s\n",
|
||||||
|
(char*)key, num ? gnc_numeric_to_string( *num ) : "(null)" );
|
||||||
|
*allVarsHaveValues &= ( num && gnc_numeric_check( *num ) != GNC_ERROR_ARG );
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
gnc_ep_tmpvarhash_clean( gpointer key, gpointer value, gpointer user_data )
|
||||||
|
{
|
||||||
|
if ( key ) {
|
||||||
|
g_free( (gchar*)key );
|
||||||
|
}
|
||||||
|
if ( value ) {
|
||||||
|
g_free( (gnc_numeric*)value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gnc_exp_parser_parse( const char * expression, gnc_numeric *value_p,
|
gnc_exp_parser_parse( const char * expression, gnc_numeric *value_p,
|
||||||
char **error_loc_p )
|
char **error_loc_p )
|
||||||
{
|
{
|
||||||
return gnc_exp_parser_parse_separate_vars( expression, value_p,
|
GHashTable *tmpVarHash;
|
||||||
error_loc_p, NULL );
|
gboolean ret, toRet = TRUE;
|
||||||
|
gboolean allVarsHaveValues = TRUE;
|
||||||
|
|
||||||
|
tmpVarHash = g_hash_table_new( g_str_hash, g_str_equal );
|
||||||
|
ret = gnc_exp_parser_parse_separate_vars( expression, value_p,
|
||||||
|
error_loc_p, tmpVarHash );
|
||||||
|
if ( !ret ) {
|
||||||
|
toRet = ret;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_foreach( tmpVarHash,
|
||||||
|
gnc_ep_tmpvarhash_check_vals,
|
||||||
|
&allVarsHaveValues );
|
||||||
|
if ( !allVarsHaveValues ) {
|
||||||
|
toRet = FALSE;
|
||||||
|
last_gncp_error = VARIABLE_IN_EXP;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
g_hash_table_foreach( tmpVarHash, gnc_ep_tmpvarhash_clean, NULL );
|
||||||
|
g_hash_table_destroy( tmpVarHash );
|
||||||
|
|
||||||
|
return toRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -567,7 +615,8 @@ gnc_exp_parser_parse_separate_vars (const char * expression,
|
|||||||
}
|
}
|
||||||
numericValue = g_new0( gnc_numeric, 1 );
|
numericValue = g_new0( gnc_numeric, 1 );
|
||||||
*numericValue = ((ParserNum*)newVars->value)->value;
|
*numericValue = ((ParserNum*)newVars->value)->value;
|
||||||
numericValue = NULL;
|
// WTF?
|
||||||
|
// numericValue = NULL;
|
||||||
g_hash_table_insert( varHash,
|
g_hash_table_insert( varHash,
|
||||||
g_strdup(newVars->variable_name),
|
g_strdup(newVars->variable_name),
|
||||||
numericValue );
|
numericValue );
|
||||||
@ -586,6 +635,16 @@ gnc_exp_parser_parse_separate_vars (const char * expression,
|
|||||||
const char *
|
const char *
|
||||||
gnc_exp_parser_error_string (void)
|
gnc_exp_parser_error_string (void)
|
||||||
{
|
{
|
||||||
|
if ( last_error == PARSER_NO_ERROR ) {
|
||||||
|
switch ( last_gncp_error ) {
|
||||||
|
default:
|
||||||
|
case NO_ERR:
|
||||||
|
return NULL; break;
|
||||||
|
case VARIABLE_IN_EXP:
|
||||||
|
return _("Illegal variable in expression." ); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (last_error)
|
switch (last_error)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -26,6 +26,15 @@
|
|||||||
|
|
||||||
#include "gnc-numeric.h"
|
#include "gnc-numeric.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The errors which can be determined at the gnc-exp-parser level.
|
||||||
|
**/
|
||||||
|
typedef enum {
|
||||||
|
NO_ERR,
|
||||||
|
VARIABLE_IN_EXP,
|
||||||
|
NUM_ERRORS
|
||||||
|
} GNCParseError;
|
||||||
|
|
||||||
/* Initialize the expression parser. If this function is not
|
/* Initialize the expression parser. If this function is not
|
||||||
* called before one of the other parsing routines (other than
|
* called before one of the other parsing routines (other than
|
||||||
* gnc_exp_parser_shutdown), it will be called if needed.
|
* gnc_exp_parser_shutdown), it will be called if needed.
|
||||||
@ -82,6 +91,7 @@ gboolean gnc_exp_parser_parse (const char * expression,
|
|||||||
* dealing with a non-shared variable list and state, local to the expression
|
* dealing with a non-shared variable list and state, local to the expression
|
||||||
* being parsed. This is a hashTable of variable names mapping to
|
* being parsed. This is a hashTable of variable names mapping to
|
||||||
* gnc_numeric pointers.
|
* gnc_numeric pointers.
|
||||||
|
*
|
||||||
* @note It is the CALLER'S RESPONSIBILITY to g_free() both the keys and
|
* @note It is the CALLER'S RESPONSIBILITY to g_free() both the keys and
|
||||||
* values of varHash when done.
|
* values of varHash when done.
|
||||||
**/
|
**/
|
||||||
|
@ -122,6 +122,8 @@ test_parser (void)
|
|||||||
add_fail_test ("whitespace", " \t\n", 4);
|
add_fail_test ("whitespace", " \t\n", 4);
|
||||||
add_fail_test ("bad expression", "\\", 0);
|
add_fail_test ("bad expression", "\\", 0);
|
||||||
add_fail_test ("bad expression", "1 +", 3);
|
add_fail_test ("bad expression", "1 +", 3);
|
||||||
|
/* FIXME: This should be a failure test... */
|
||||||
|
//add_fail_test ("bad expression", "1 2", 2);
|
||||||
add_fail_test ("bad expression", " (5 + 23)/ ", 14);
|
add_fail_test ("bad expression", " (5 + 23)/ ", 14);
|
||||||
add_fail_test ("bad expression", " ((((5 + 23)/ ", 17);
|
add_fail_test ("bad expression", " ((((5 + 23)/ ", 17);
|
||||||
add_fail_test ("divide by zero", " 4 / (1 - 1)", -1);
|
add_fail_test ("divide by zero", " 4 / (1 - 1)", -1);
|
||||||
@ -133,7 +135,15 @@ test_parser (void)
|
|||||||
add_pass_test ("5 * 6", NULL, gnc_numeric_create (30, 1));
|
add_pass_test ("5 * 6", NULL, gnc_numeric_create (30, 1));
|
||||||
add_pass_test (" 34 / (22) ", NULL, gnc_numeric_create (34, 22));
|
add_pass_test (" 34 / (22) ", NULL, gnc_numeric_create (34, 22));
|
||||||
add_pass_test (" (4 + 5 * 2) - 7 / 3", NULL, gnc_numeric_create (35, 3));
|
add_pass_test (" (4 + 5 * 2) - 7 / 3", NULL, gnc_numeric_create (35, 3));
|
||||||
add_pass_test ("1 + 2 * 3 + 4 + 5 * 6 * 7", NULL, gnc_numeric_create(221, 1) );
|
add_pass_test( "(a = 42) + (b = 12) - a", NULL, gnc_numeric_create( 12, 1 ) );
|
||||||
|
add_fail_test( "AUD $1.23", NULL, 0 );
|
||||||
|
add_fail_test( "AUD $0.0", NULL, 0 );
|
||||||
|
add_fail_test( "AUD 1.23", NULL, 0 );
|
||||||
|
add_fail_test( "AUD 0.0", NULL, 0 );
|
||||||
|
add_fail_test( "AUD 1.2 + CAN 2.3", NULL, 0 );
|
||||||
|
add_fail_test( "AUD $1.2 + CAN $2.3", NULL, 0 );
|
||||||
|
|
||||||
|
add_pass_test( "1 + 2 * 3 + 4 + 5 * 6 * 7", NULL, gnc_numeric_create(221, 1) );
|
||||||
add_pass_test( "1 - 2 * 3 + 4 - 5 * 6 * 7", NULL,
|
add_pass_test( "1 - 2 * 3 + 4 - 5 * 6 * 7", NULL,
|
||||||
gnc_numeric_create(-211, 1) );
|
gnc_numeric_create(-211, 1) );
|
||||||
add_pass_test( "Conrad's bug",
|
add_pass_test( "Conrad's bug",
|
||||||
|
Loading…
Reference in New Issue
Block a user