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:
Joshua Sled 2002-10-17 05:26:40 +00:00
parent 8fe4bf789c
commit b4986ed2de
4 changed files with 93 additions and 7 deletions

View File

@ -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>
* src/import-export/hbci/hbci-account-picker.c,

View File

@ -44,9 +44,10 @@ typedef struct ParserNum
/** Static Globals *************************************************/
static GHashTable *variable_bindings = NULL;
static ParseError last_error = PARSER_NO_ERROR;
static gboolean parser_inited = FALSE;
static GHashTable *variable_bindings = NULL;
static ParseError last_error = PARSER_NO_ERROR;
static GNCParseError last_gncp_error = NO_ERR;
static gboolean parser_inited = FALSE;
/** Implementations ************************************************/
@ -169,6 +170,7 @@ gnc_exp_parser_shutdown (void)
variable_bindings = NULL;
last_error = PARSER_NO_ERROR;
last_gncp_error = NO_ERR;
parser_inited = FALSE;
}
@ -470,12 +472,58 @@ negate_numeric(void *value)
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
gnc_exp_parser_parse( const char * expression, gnc_numeric *value_p,
char **error_loc_p )
{
return gnc_exp_parser_parse_separate_vars( expression, value_p,
error_loc_p, NULL );
GHashTable *tmpVarHash;
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
@ -567,7 +615,8 @@ gnc_exp_parser_parse_separate_vars (const char * expression,
}
numericValue = g_new0( gnc_numeric, 1 );
*numericValue = ((ParserNum*)newVars->value)->value;
numericValue = NULL;
// WTF?
// numericValue = NULL;
g_hash_table_insert( varHash,
g_strdup(newVars->variable_name),
numericValue );
@ -586,6 +635,16 @@ gnc_exp_parser_parse_separate_vars (const char * expression,
const char *
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)
{
default:

View File

@ -26,6 +26,15 @@
#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
* called before one of the other parsing routines (other than
* 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
* being parsed. This is a hashTable of variable names mapping to
* gnc_numeric pointers.
*
* @note It is the CALLER'S RESPONSIBILITY to g_free() both the keys and
* values of varHash when done.
**/

View File

@ -122,6 +122,8 @@ test_parser (void)
add_fail_test ("whitespace", " \t\n", 4);
add_fail_test ("bad expression", "\\", 0);
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)/ ", 17);
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 (" 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 ("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,
gnc_numeric_create(-211, 1) );
add_pass_test( "Conrad's bug",