mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
2002-05-21 Joshua Sled <jsled@asynchronous.org>
* src/gnome/dialog-sx-from-trans.c (sxftd_get_end_info): Changed to do the strtoul before we free the data itself; fixes "can't create once/number-of-occurance SXes" [in from-transaction dialog] bug. * src/gnome/dialog-scheduledxaction.c (editor_ok_button_clicked): Do a very lame but good-enough-for-now check to see if we can determine if the template transactions will still balance. Note that we don't do anything with the result of that check, yet, but we perform it. * src/app-utils/gnc-exp-parser.c (gnc_exp_parser_real_init): Added so we can conditionaly add the "predefined variables" to the binding table for parsing a given expression. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6886 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
b443bcf002
commit
9ca6b3d830
17
ChangeLog
17
ChangeLog
@ -1,3 +1,20 @@
|
||||
2002-05-21 Joshua Sled <jsled@asynchronous.org>
|
||||
|
||||
* src/gnome/dialog-sx-from-trans.c (sxftd_get_end_info): Changed
|
||||
to do the strtoul before we free the data itself; fixes "can't
|
||||
create once/number-of-occurance SXes" [in from-transaction dialog]
|
||||
bug.
|
||||
|
||||
* src/gnome/dialog-scheduledxaction.c (editor_ok_button_clicked):
|
||||
Do a very lame but good-enough-for-now check to see if we can
|
||||
determine if the template transactions will still balance. Note
|
||||
that we don't do anything with the result of that check, yet, but
|
||||
we perform it.
|
||||
|
||||
* src/app-utils/gnc-exp-parser.c (gnc_exp_parser_real_init): Added
|
||||
so we can conditionaly add the "predefined variables" to the
|
||||
binding table for parsing a given expression.
|
||||
|
||||
2002-05-18 David Hampton <hampton@employees.org>
|
||||
|
||||
* configure.in: Work around incompatibilities between autoconf
|
||||
|
@ -50,7 +50,13 @@ static gboolean parser_inited = FALSE;
|
||||
/** Implementations ************************************************/
|
||||
|
||||
void
|
||||
gnc_exp_parser_init (void)
|
||||
gnc_exp_parser_init ( void )
|
||||
{
|
||||
gnc_exp_parser_real_init( TRUE );
|
||||
}
|
||||
|
||||
void
|
||||
gnc_exp_parser_real_init ( gboolean addPredefined )
|
||||
{
|
||||
SCM alist;
|
||||
|
||||
@ -62,57 +68,60 @@ gnc_exp_parser_init (void)
|
||||
/* This comes after the statics have been initialized. Not at the end! */
|
||||
parser_inited = TRUE;
|
||||
|
||||
alist = gnc_lookup_option ("__exp_parser", "defined_variables", SCM_EOL);
|
||||
if ( addPredefined ) {
|
||||
alist = gnc_lookup_option ("__exp_parser", "defined_variables", SCM_EOL);
|
||||
|
||||
while (gh_list_p(alist) && !gh_null_p(alist))
|
||||
{
|
||||
char *name;
|
||||
SCM assoc;
|
||||
SCM val_scm;
|
||||
gnc_numeric value;
|
||||
gboolean good;
|
||||
while (gh_list_p(alist) && !gh_null_p(alist))
|
||||
{
|
||||
char *name;
|
||||
SCM assoc;
|
||||
SCM val_scm;
|
||||
gnc_numeric value;
|
||||
gboolean good;
|
||||
|
||||
assoc = gh_car (alist);
|
||||
alist = gh_cdr (alist);
|
||||
assoc = gh_car (alist);
|
||||
alist = gh_cdr (alist);
|
||||
|
||||
if (!gh_pair_p (assoc))
|
||||
continue;
|
||||
if (!gh_pair_p (assoc))
|
||||
continue;
|
||||
|
||||
name = gh_scm2newstr (gh_car (assoc), NULL);
|
||||
if (name == NULL)
|
||||
continue;
|
||||
name = gh_scm2newstr (gh_car (assoc), NULL);
|
||||
if (name == NULL)
|
||||
continue;
|
||||
|
||||
val_scm = gh_cdr (assoc);
|
||||
good = TRUE;
|
||||
val_scm = gh_cdr (assoc);
|
||||
good = TRUE;
|
||||
|
||||
if (gh_number_p (val_scm))
|
||||
{
|
||||
double dvalue;
|
||||
if (gh_number_p (val_scm))
|
||||
{
|
||||
double dvalue;
|
||||
|
||||
dvalue = gh_scm2double (val_scm);
|
||||
value = double_to_gnc_numeric (dvalue, GNC_DENOM_AUTO,
|
||||
GNC_DENOM_SIGFIGS(6) | GNC_RND_ROUND);
|
||||
}
|
||||
else if (gh_string_p (val_scm))
|
||||
{
|
||||
char *s;
|
||||
const char *err;
|
||||
dvalue = gh_scm2double (val_scm);
|
||||
value = double_to_gnc_numeric (dvalue, GNC_DENOM_AUTO,
|
||||
GNC_DENOM_SIGFIGS(6)
|
||||
| GNC_RND_ROUND);
|
||||
}
|
||||
else if (gh_string_p (val_scm))
|
||||
{
|
||||
char *s;
|
||||
const char *err;
|
||||
|
||||
s = gh_scm2newstr (val_scm, NULL);
|
||||
s = gh_scm2newstr (val_scm, NULL);
|
||||
|
||||
err = string_to_gnc_numeric (s, &value);
|
||||
if (err == NULL)
|
||||
good = FALSE;
|
||||
err = string_to_gnc_numeric (s, &value);
|
||||
if (err == NULL)
|
||||
good = FALSE;
|
||||
|
||||
free (s);
|
||||
}
|
||||
else
|
||||
good = FALSE;
|
||||
free (s);
|
||||
}
|
||||
else
|
||||
good = FALSE;
|
||||
|
||||
if (good)
|
||||
gnc_exp_parser_set_value (name, gnc_numeric_reduce (value));
|
||||
if (good)
|
||||
gnc_exp_parser_set_value (name, gnc_numeric_reduce (value));
|
||||
|
||||
free (name);
|
||||
free (name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,7 +440,7 @@ gnc_exp_parser_parse_separate_vars (const char * expression,
|
||||
return FALSE;
|
||||
|
||||
if (!parser_inited)
|
||||
gnc_exp_parser_init ();
|
||||
gnc_exp_parser_real_init ( (varHash == NULL) );
|
||||
|
||||
result.variable_name = NULL;
|
||||
result.value = NULL;
|
||||
@ -509,7 +518,6 @@ gnc_exp_parser_parse_separate_vars (const char * expression,
|
||||
}
|
||||
} else {
|
||||
update_variables (vars);
|
||||
update_variables (parser_get_vars (pe));
|
||||
}
|
||||
|
||||
free_predefined_variables (vars);
|
||||
|
@ -32,6 +32,15 @@
|
||||
*/
|
||||
void gnc_exp_parser_init (void);
|
||||
|
||||
/**
|
||||
* The real init function, which takes an option to add the pre-defined vars
|
||||
* to the variable table. This option is used by
|
||||
* gnc_exp_parser_parse_seperate_vars [itself used by the Scheduled
|
||||
* Transaction code] to parse without using any "predefined" application
|
||||
* variables.
|
||||
**/
|
||||
void gnc_exp_parser_real_init( gboolean addPredefined );
|
||||
|
||||
/* Shutdown the expression parser and free any associated memory in the ParserState. */
|
||||
void gnc_exp_parser_shutdown (void);
|
||||
|
||||
|
@ -121,8 +121,6 @@ X create a template register
|
||||
|
||||
. make-from-transaction
|
||||
. bugs
|
||||
. number-of-instances in 'simple' results in "Warning:
|
||||
sxftd_advanced_clicked: something bad happened in sxftd_compute_sx"
|
||||
. general: there's going to be all sorts of interaction issues like these
|
||||
between these things [SX-from-trans, SX list, SX editor] that should be
|
||||
handled.
|
||||
@ -138,6 +136,8 @@ X create a template register
|
||||
X 20020419 - Wilddev manages to create two SXes from one; the first is
|
||||
okay, but the second is h0rk3d [deleting it causes segfault, though it
|
||||
can be instantiated correctly].
|
||||
X number-of-instances in 'simple' results in "Warning:
|
||||
sxftd_advanced_clicked: something bad happened in sxftd_compute_sx"
|
||||
. tab-order
|
||||
. better frequency guess?
|
||||
[ related... ]
|
||||
@ -237,9 +237,10 @@ X create a template register
|
||||
. recn?
|
||||
|
||||
. deal better with formulas in template transactions [real FormulaCell]
|
||||
. recognize purely numeric template transactions and balance at
|
||||
. actually do something with the result of the balancing computation
|
||||
/ recognize purely numeric template transactions and balance at
|
||||
template-creation time.
|
||||
. balance transaction with vars?
|
||||
/ balance transaction with vars?
|
||||
|
||||
. GNCFrequency
|
||||
. initial-settings synchronization [start date, optionmenus]
|
||||
|
@ -230,6 +230,16 @@ local_print_helper( gpointer key, gpointer value, gpointer ud )
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
set_var_to_random_value( gpointer key, gpointer value, gpointer ud )
|
||||
{
|
||||
gnc_numeric *val;
|
||||
val = g_new0( gnc_numeric, 1 );
|
||||
*val = double_to_gnc_numeric( rand() + 2, 1,
|
||||
GNC_NUMERIC_RND_MASK | GNC_RND_FLOOR );
|
||||
g_hash_table_insert( ud, key, val );
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
editor_ok_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed )
|
||||
@ -259,20 +269,37 @@ editor_ok_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed )
|
||||
gnc_split_register_save ( gnc_ledger_display_get_split_register(sxed->ledger),
|
||||
FALSE );
|
||||
|
||||
#if 0
|
||||
/* FIXME: leave for now; will use for numeric-formulas-get-balanced
|
||||
* determination later. */
|
||||
/* numeric-formulas-get-balanced determination */
|
||||
{
|
||||
GHashTable *ht;
|
||||
GHashTable *vars;
|
||||
GList *splitList = NULL;
|
||||
char *str;
|
||||
kvp_frame *f;
|
||||
kvp_value *v;
|
||||
Split *s;
|
||||
gnc_numeric creditSum, debitSum, tmp;
|
||||
|
||||
ht = g_hash_table_new( NULL, NULL );
|
||||
|
||||
creditSum = debitSum = gnc_numeric_zero();
|
||||
vars = g_hash_table_new( g_str_hash, g_str_equal );
|
||||
splitList = xaccSchedXactionGetSplits( sxed->sx );
|
||||
/**
|
||||
* Plan:
|
||||
* . Do a first pass to get the variables.
|
||||
* . Set each variable to random values.
|
||||
* . see if we balance after that
|
||||
* . true: all good
|
||||
* . false: indicate to user, allow decision.
|
||||
*/
|
||||
sxsl_get_sx_vars( sxed->sx, vars );
|
||||
if ( g_hash_table_size( vars ) == 0 ) {
|
||||
/* FIXME: just balance as is, DTRT. */
|
||||
}
|
||||
|
||||
/* FIXME: since we have variables, we can deal with any
|
||||
* possible auto-create flaggage. */
|
||||
g_hash_table_foreach( vars, set_var_to_random_value,
|
||||
(gpointer)vars );
|
||||
|
||||
for ( ; splitList; splitList = splitList->next ) {
|
||||
s = (Split*)splitList->data;
|
||||
f = xaccSplitGetSlots( s );
|
||||
@ -283,7 +310,14 @@ editor_ok_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed )
|
||||
if ( v
|
||||
&& (str = kvp_value_get_string(v))
|
||||
&& strlen( str ) != 0 ) {
|
||||
parse_vars_from_formula( str, ht );
|
||||
if ( parse_vars_from_formula( str, vars, &tmp ) < 0 ) {
|
||||
PERR( "Couldn't parse credit formula for "
|
||||
"\"%s\" on second pass",
|
||||
xaccSchedXactionGetName( sxed->sx ) );
|
||||
return;
|
||||
}
|
||||
creditSum = gnc_numeric_add_fixed( creditSum, tmp );
|
||||
tmp = gnc_numeric_zero();
|
||||
}
|
||||
v = kvp_frame_get_slot_path( f,
|
||||
GNC_SX_ID,
|
||||
@ -292,16 +326,29 @@ editor_ok_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed )
|
||||
if ( v
|
||||
&& (str = kvp_value_get_string(v))
|
||||
&& strlen(str) != 0 ) {
|
||||
parse_vars_from_formula( str, ht );
|
||||
if ( parse_vars_from_formula( str, vars, &tmp ) < 0 ) {
|
||||
PERR( "Couldn't parse debit formula for "
|
||||
"\"%s\" on second pass",
|
||||
xaccSchedXactionGetName( sxed->sx ) );
|
||||
return;
|
||||
}
|
||||
debitSum = gnc_numeric_add_fixed( debitSum, tmp );
|
||||
tmp = gnc_numeric_zero();
|
||||
}
|
||||
g_hash_table_foreach( ht, local_print_helper, NULL );
|
||||
}
|
||||
if ( g_hash_table_size( ht ) == 0 ) {
|
||||
|
||||
if ( gnc_numeric_zero_p( gnc_numeric_sub_fixed( debitSum, creditSum ) ) ) {
|
||||
printf( "true [%s - %s = %s]\n",
|
||||
gnc_numeric_to_string( debitSum ),
|
||||
gnc_numeric_to_string( creditSum ),
|
||||
gnc_numeric_to_string(gnc_numeric_sub_fixed( debitSum, creditSum )) );
|
||||
} else {
|
||||
printf( "false [%s - %s = %s]\n",
|
||||
gnc_numeric_to_string( debitSum ),
|
||||
gnc_numeric_to_string( creditSum ),
|
||||
gnc_numeric_to_string(gnc_numeric_sub_fixed( debitSum, creditSum )) );
|
||||
}
|
||||
g_hash_table_destroy( ht );
|
||||
g_hash_table_destroy( vars );
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/* read out data back into SchedXaction object. */
|
||||
|
||||
|
@ -128,8 +128,9 @@ sxftd_get_end_info(SXFromTransInfo *sxfti)
|
||||
getEndTuple retval;
|
||||
GtkWidget *w;
|
||||
|
||||
retval.type = BAD_END;
|
||||
|
||||
w = glade_xml_get_widget(sxfti->gxml, SXFTD_NEVER_END_BUTTON);
|
||||
|
||||
if(gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(w)))
|
||||
{
|
||||
retval.type = NEVER_END;
|
||||
@ -137,7 +138,6 @@ sxftd_get_end_info(SXFromTransInfo *sxfti)
|
||||
}
|
||||
|
||||
w = glade_xml_get_widget(sxfti->gxml, SXFTD_END_ON_DATE_BUTTON);
|
||||
|
||||
if(gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(w)))
|
||||
{
|
||||
time_t end_tt;
|
||||
@ -160,9 +160,11 @@ sxftd_get_end_info(SXFromTransInfo *sxfti)
|
||||
text = gtk_editable_get_chars(GTK_EDITABLE(w), 0, -1);
|
||||
|
||||
n_occs = strtoul(text, &endptr, 10);
|
||||
|
||||
free(text);
|
||||
if(!endptr && n_occs > 0)
|
||||
if ( !endptr ) {
|
||||
n_occs = -1;
|
||||
}
|
||||
g_free(text);
|
||||
if(n_occs > 0)
|
||||
{
|
||||
retval.type = END_AFTER_N_OCCS;
|
||||
retval.n_occurrences = n_occs;
|
||||
@ -170,7 +172,6 @@ sxftd_get_end_info(SXFromTransInfo *sxfti)
|
||||
}
|
||||
}
|
||||
|
||||
retval.type = BAD_END;
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -386,7 +387,7 @@ sxftd_compute_sx(SXFromTransInfo *sxfti)
|
||||
break;
|
||||
}
|
||||
|
||||
sxftd_add_template_trans( sxfti);
|
||||
sxftd_add_template_trans( sxfti );
|
||||
|
||||
return sxftd_errno;
|
||||
}
|
||||
@ -415,7 +416,11 @@ sxftd_ok_clicked(GtkWidget *w, gpointer user_data)
|
||||
GList *sx_list;
|
||||
guint sx_error = sxftd_compute_sx(sxfti);
|
||||
|
||||
if (sx_error == 0)
|
||||
if (sx_error != 0)
|
||||
{
|
||||
PERR( "Error in sxftd_compute_sx after ok_clicked [%d]", sx_error );
|
||||
}
|
||||
else
|
||||
{
|
||||
book = gnc_get_current_book ();
|
||||
sx_list = gnc_book_get_schedxactions(book);
|
||||
@ -474,7 +479,7 @@ sxftd_advanced_clicked(GtkWidget *w, gpointer user_data)
|
||||
|
||||
if (sx_error != 0)
|
||||
{
|
||||
PWARN( "something bad happened in sxftd_compute_sx" );
|
||||
PWARN( "something bad happened in sxftd_compute_sx [%d]", sx_error );
|
||||
return;
|
||||
}
|
||||
gtk_widget_hide( sxfti->dialog );
|
||||
|
@ -257,8 +257,6 @@ static gboolean inform_or_add( GList *reminders,
|
||||
reminderTuple *rt, gboolean okFlag,
|
||||
GList *badList, GList **goodList );
|
||||
|
||||
int parse_vars_from_formula( const char *formula, GHashTable *varHash );
|
||||
|
||||
static void sx_obsolete_select_all_clicked(GtkButton *button,
|
||||
gpointer user_data);
|
||||
static void sx_obsolete_unselect_all_clicked(GtkButton *button,
|
||||
@ -1383,7 +1381,7 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud )
|
||||
gchar *varName;
|
||||
toCreateTuple *tct;
|
||||
gchar *entryText;
|
||||
gnc_numeric *num;
|
||||
gnc_numeric *num, *ourNum;
|
||||
GHashTable *dummyVarHash;
|
||||
|
||||
sxsld = (sxSinceLastData*)ud;
|
||||
@ -1397,17 +1395,14 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud )
|
||||
if ( !gnc_exp_parser_parse_separate_vars( entryText, num,
|
||||
NULL, dummyVarHash ) ) {
|
||||
DEBUG( "error parsing entry \"%s\"", entryText );
|
||||
g_free( num );
|
||||
num = NULL;
|
||||
} else if ( g_hash_table_size( dummyVarHash ) != 0 ) {
|
||||
DEBUG( "no new variables allowed in variable "
|
||||
"bindings for expression \"%s\"", entryText );
|
||||
g_free( num );
|
||||
num = NULL;
|
||||
} else if ( gnc_numeric_check( *num ) != GNC_ERROR_OK ) {
|
||||
DEBUG( "entry \"%s\" is not "
|
||||
"gnc_numeric-parseable", entryText );
|
||||
g_free( num );
|
||||
num = NULL;
|
||||
} else {
|
||||
DEBUG( "\"%s\" parses as \"%f\"", entryText,
|
||||
@ -1419,13 +1414,21 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud )
|
||||
{
|
||||
gpointer maybeKey, maybeValue;
|
||||
|
||||
ourNum = NULL;
|
||||
if ( num ) {
|
||||
ourNum = g_new0( gnc_numeric, 1 );
|
||||
*ourNum = *num;
|
||||
}
|
||||
if ( g_hash_table_lookup_extended( tct->varBindings, varName,
|
||||
&maybeKey, &maybeValue ) ) {
|
||||
g_hash_table_remove( tct->varBindings, maybeKey );
|
||||
g_free( maybeValue );
|
||||
/* only if not null. */
|
||||
if ( maybeValue ) {
|
||||
g_free( maybeValue );
|
||||
}
|
||||
/* FIXME: Does the maybeKey need to be freed? */
|
||||
}
|
||||
g_hash_table_insert( tct->varBindings, maybeKey, num );
|
||||
g_hash_table_insert( tct->varBindings, maybeKey, ourNum );
|
||||
}
|
||||
|
||||
{
|
||||
@ -1810,7 +1813,7 @@ sxsl_get_sx_vars( SchedXaction *sx, GHashTable *varHash )
|
||||
if ( kvp_val != NULL ) {
|
||||
str = kvp_value_get_string( kvp_val );
|
||||
if ( str && strlen(str) != 0 ) {
|
||||
parse_vars_from_formula( str, varHash );
|
||||
parse_vars_from_formula( str, varHash, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1821,7 +1824,7 @@ sxsl_get_sx_vars( SchedXaction *sx, GHashTable *varHash )
|
||||
if ( kvp_val != NULL ) {
|
||||
str = kvp_value_get_string( kvp_val );
|
||||
if ( str && strlen(str) != 0 ) {
|
||||
parse_vars_from_formula( str, varHash );
|
||||
parse_vars_from_formula( str, varHash, NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2014,6 +2017,7 @@ sxsincelast_tc_row_unsel( GtkCList *clist,
|
||||
|
||||
sxsld = (sxSinceLastData*)user_data;
|
||||
clean_variable_table( sxsld );
|
||||
/* FIXME: need to cleanup the gnc_numerics we allocated */
|
||||
}
|
||||
|
||||
void
|
||||
@ -2025,18 +2029,34 @@ print_vars_helper( gpointer key, gpointer value, gpointer user_data )
|
||||
}
|
||||
|
||||
int
|
||||
parse_vars_from_formula( const char *formula, GHashTable *varHash )
|
||||
parse_vars_from_formula( const char *formula,
|
||||
GHashTable *varHash,
|
||||
gnc_numeric *result )
|
||||
{
|
||||
gnc_numeric numeric;
|
||||
char *foo;
|
||||
|
||||
if ( ! gnc_exp_parser_parse_separate_vars( formula, &numeric,
|
||||
&foo, varHash ) ) {
|
||||
PERR( "Error parsing at \"%s\": %s",
|
||||
foo, gnc_exp_parser_error_string() );
|
||||
return -1;
|
||||
gnc_numeric *num;
|
||||
char *errLoc;
|
||||
int toRet;
|
||||
|
||||
if ( result ) {
|
||||
num = result;
|
||||
} else {
|
||||
num = g_new0( gnc_numeric, 1 );
|
||||
}
|
||||
return 0;
|
||||
|
||||
if ( ! gnc_exp_parser_parse_separate_vars( formula, num,
|
||||
&errLoc, varHash ) ) {
|
||||
PERR( "Error parsing at \"%s\": %s",
|
||||
errLoc, gnc_exp_parser_error_string() );
|
||||
toRet = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
toRet = 0;
|
||||
|
||||
cleanup:
|
||||
if ( !result ) {
|
||||
g_free( num );
|
||||
}
|
||||
return toRet;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,8 +35,11 @@ void sxsl_get_sx_vars( SchedXaction *sx, GHashTable *varHash );
|
||||
/**
|
||||
* Returns the variables from the given formula [free-form non-numeric
|
||||
* character strings] as the keys of the given GHashTable.
|
||||
* @param result can be NULL if you're not interested in the result
|
||||
**/
|
||||
int parse_vars_from_formula( const char *formula, GHashTable *varHash );
|
||||
int parse_vars_from_formula( const char *formula,
|
||||
GHashTable *varHash,
|
||||
gnc_numeric *result );
|
||||
|
||||
void print_vars_helper( gpointer key, gpointer value, gpointer user_data );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user