-- Change gnc-trace.h to use the glib g_log() routine for all error

printing and tracing.
-- ongoing cap-gains work


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@9290 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 2003-09-12 13:17:26 +00:00
parent 499a4d5e76
commit dff9fa3b3b
34 changed files with 715 additions and 620 deletions

View File

@ -39,6 +39,7 @@
#include "gnc-lot.h"
#include "gnc-lot-p.h"
#include "gnc-pricedb.h"
#include "gnc-trace.h"
#include "kvp_frame.h"
#include "kvp-util-p.h"
#include "messages.h"
@ -1494,6 +1495,7 @@ xaccAccountSetCommodity (Account * acc, gnc_commodity * com)
{
acc->commodity = com;
acc->commodity_scu = gnc_commodity_get_fraction(com);
acc->non_standard_scu = FALSE;
update_split_commodity(acc);
acc->sort_dirty = TRUE;
@ -1502,25 +1504,13 @@ xaccAccountSetCommodity (Account * acc, gnc_commodity * com)
mark_account (acc);
}
acc->core_dirty = TRUE;
xaccAccountCommitEdit(acc);
if (gnc_commodity_is_iso(com)) {
if (gnc_commodity_is_iso(com))
{
/* compatability hack - Gnucash 1.8 gets currency quotes when a
non-default currency is assigned to an account. */
gnc_commodity_set_quote_flag(com, TRUE);
}
}
void
xaccAccountSetCommoditySCU (Account *acc, int scu)
{
if (!acc) return;
xaccAccountBeginEdit(acc);
{
acc->commodity_scu = scu;
mark_account (acc);
}
acc->core_dirty = TRUE;
xaccAccountCommitEdit(acc);
}
@ -1531,7 +1521,7 @@ xaccAccountSetCommoditySCU (Account *acc, int scu)
* to mismatched values in the past.
*/
void
xaccAccountSetCommoditySCUandFlag (Account *acc, int scu)
xaccAccountSetCommoditySCU (Account *acc, int scu)
{
if (!acc) return;
@ -1613,69 +1603,6 @@ DxaccAccountSetCurrency (Account * acc, gnc_commodity * currency)
}
}
void
DxaccAccountSetSecurity (Account *acc, gnc_commodity * security)
{
const char *string;
gnc_commodity *commodity;
if ((!acc) || (!security)) return;
xaccAccountBeginEdit(acc);
string = gnc_commodity_get_unique_name (security);
kvp_frame_set_slot_nc(acc->kvp_data, "old-security",
kvp_value_new_string(string));
mark_account (acc);
acc->core_dirty = TRUE;
xaccAccountCommitEdit(acc);
commodity = DxaccAccountGetSecurity (acc);
if (!commodity)
{
gnc_commodity_table_insert (gnc_commodity_table_get_table (acc->book), security);
}
}
void
DxaccAccountSetCurrencySCU (Account * acc, int scu)
{
if (!acc) return;
xaccAccountBeginEdit(acc);
kvp_frame_set_slot_nc(acc->kvp_data, "old-currency-scu",
kvp_value_new_gint64(scu));
mark_account (acc);
acc->core_dirty = TRUE;
xaccAccountCommitEdit(acc);
}
int
DxaccAccountGetCurrencySCU (Account * acc)
{
KvpValue *v;
if (!acc) return 0;
v = kvp_frame_get_slot(acc->kvp_data, "old-currency-scu");
if (v) return kvp_value_get_gint64 (v);
return 0;
}
/********************************************************************\
\********************************************************************/
void
xaccAccountDeleteOldData (Account *account)
{
if (!account) return;
kvp_frame_set_slot_nc (account->kvp_data, "old-currency", NULL);
kvp_frame_set_slot_nc (account->kvp_data, "old-security", NULL);
kvp_frame_set_slot_nc (account->kvp_data, "old-currency-scu", NULL);
kvp_frame_set_slot_nc (account->kvp_data, "old-security-scu", NULL);
}
/********************************************************************\
\********************************************************************/
@ -1833,26 +1760,6 @@ xaccAccountGetCommodity (Account *acc)
return (acc->commodity);
}
gnc_commodity *
DxaccAccountGetSecurity (Account *acc)
{
KvpValue *v;
const char *s;
gnc_commodity_table *table;
if (!acc) return NULL;
v = kvp_frame_get_slot(acc->kvp_data, "old-security");
if (!v) return NULL;
s = kvp_value_get_string (v);
if (!s) return NULL;
table = gnc_commodity_table_get_table (acc->book);
return gnc_commodity_table_lookup_unique (table, s);
}
gnc_numeric
xaccAccountGetBalance (Account *acc)
{

View File

@ -260,53 +260,71 @@ void xaccAccountSetAutoInterestXfer (Account *account, gboolean value);
/** @} */
/* @name Account Commodity setters/getters
* Accounts are used to store an amount of 'something', that 'something'
* is called the 'commodity'. An account can only hold one kind of
* commodity. The following are used to get and set the commodity,
* and also to set the SCU, the 'Smallest Commodity Unit'.
*
* New commodity access routines.
* Note that when we say that a 'split' holds an 'amount', that amount
* is denominated in the account commodity. Do not confuse 'amount'
* and 'value'. The 'value' of a split is the value of the amount
* expressed in the currency fo the transaction. Thus, for example,
* the 'amount' may be 12 apples, where the account commodity is
* 'apples'. The value of these 12 apples may be 12 dollars, where
* the transaction currency is 'dollars'.
*
* The account structure no longer stores two commodities ('currency'
* and 'security'). Instead it stores only one commodity. This single
* commodity is the one formerly known as 'security'. Use
* xaccAccountSetCommodity() and xaccAccountGetCommodity() to set and
* fetch it. (This transition has been done between version 1.6.x and
* 1.7.0.)
* The SCU is the 'Smallest Commodity Unit', signifying the smallest
* non-zero amount that can be stored in the account. It is
* represented as the integer denominator of a fraction. Thus,
* for example, a SCU of 12 means that 1/12 of something is the
* smallest amount that can be stored in the account. SCU's can
* be any value; they do not need to be decimal. This allows
* the use of accounts with unusual, non-decimal commodities and
* currencies.
*
* Basically, the engine eliminates the 'currency' field of the
* Account structure. Instead, the common currency is stored with the
* transaction. The 'value' of a split is a translation of the
* Split's 'amount' (which is the amount of the Account's commodity
* involved) into the Transaction's balancing currency. */
* Normally, the SCU is determined by the commodity of the account.
* However, this default SCU can be over-ridden and set to an
* account-specific value. This is account-specific value is
* called the 'non-standard' value in the documentation below.
*/
/** @{ */
/** Set the account's commodity */
void xaccAccountSetCommodity (Account *account, gnc_commodity *comm);
/** Get the account's commodity
*
* This is from the new commodity access routines.
*
* The account structure no longer stores two commodities ('currency'
* and 'security'). Instead it stores only one commodity. This single
* commodity is the one formerly known as 'security'. Use
* xaccAccountSetCommodity() and xaccAccountGetCommodity() to set and
* fetch it. (This transition has been done between version 1.6.x and
* 1.7.0.)
*
* Basically, the engine eliminates the 'currency' field of the
* Account structure. Instead, the common currency is stored with the
* transaction. The 'value' of a split is a translation of the
* Split's 'amount' (which is the amount of the Account's commodity
* involved) into the Transaction's balancing currency. */
/* deprecated do not use */
#define DxaccAccountSetSecurity xaccAccountSetCommodity
/** Get the account's commodity */
gnc_commodity * xaccAccountGetCommodity (Account *account);
/** DOCUMENT ME! */
/* deprecated do not use */
#define DxaccAccountGetSecurity xaccAccountGetCommodity
/** Return the SCU for the account. If a non-standard SCU has been
* set for the account, that s returned; else the default SCU for
* the account commodity is returned.
*/
int xaccAccountGetCommoditySCU (Account *account);
/** DOCUMENT ME! */
/** Return the 'internal' SCU setting. This returns the over-ride
* SCU for the account (which might not be set, and might be zero). */
int xaccAccountGetCommoditySCUi (Account *account);
/** DOCUMENT ME! */
/** Set the SCU for the account. Normally, this routine is not
* required, as the default SCU for an account is given by its
* commodity.
*/
void xaccAccountSetCommoditySCU (Account *account, int frac);
/** DOCUMENT ME! */
void xaccAccountSetCommoditySCUandFlag (Account *account, int frac);
/** DOCUMENT ME! */
/* deprecated -- do not use for future development */
#define xaccAccountSetCommoditySCUandFlag xaccAccountSetCommoditySCU
/** Set the flag indicating that this account uses a non-standard SCU. */
void xaccAccountSetNonStdSCU (Account *account, gboolean flag);
/** DOCUMENT ME! */
/** Return boolean, indicating whether this account uses a
* non-standard SCU. */
gboolean xaccAccountGetNonStdSCU (Account *account);
/**@}*/
@ -406,10 +424,6 @@ gboolean xaccAccountHasAncestor (Account *account, Account *ancestor);
/** @{ */
KvpFrame * xaccAccountGetSlots (Account *account);
void xaccAccountSetSlots_nc(Account *account, KvpFrame *frame);
/** Delete any old data in the account's kvp data.
* This includes the old currency and security fields. */
void xaccAccountDeleteOldData (Account *account);
/** @} */
/* ------------------ */
@ -679,38 +693,18 @@ void xaccClearMarkDownGr (AccountGroup *group, short val);
* These two funcs take control of their gnc_commodity args. Don't free */
void DxaccAccountSetCurrency (Account *account, gnc_commodity *currency);
/** @deprecated The current API associates only one thing with an
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
* it.
*
* These two funcs take control of their gnc_commodity args. Don't free */
void DxaccAccountSetSecurity (Account *account, gnc_commodity *security);
/** @deprecated The current API associates only one thing with an
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
* it. */
gnc_commodity * DxaccAccountGetCurrency (Account *account);
/** @deprecated The current API associates only one thing with an
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
* it. */
gnc_commodity * DxaccAccountGetSecurity (Account *account);
/** @deprecated The current API associates only one thing with an
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
* it. */
void DxaccAccountSetCurrencySCU (Account *account, int frac);
/** @deprecated The current API associates only one thing with an
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
* it. */
int DxaccAccountGetCurrencySCU (Account *account);
/** Set the timezone to be used when interpreting the results from a
* given Finance::Quote backend. Unfortunately, the upstream sources
* don't label their output, so the user has to specify this bit.
*
* @deprecated Price quote information is now stored on the
* commodity, not the account. */
void dxaccAccountSetQuoteTZ (Account *account, const char *tz);
/** Get the timezone to be used when interpreting the results from a
* given Finance::Quote backend. Unfortunately, the upstream sources

View File

@ -89,6 +89,7 @@
#include "gnc-engine-util.h"
#include "gnc-event-p.h"
#include "messages.h"
#include "gnc-trace.h"
#include "qofbook.h"
#include "qofbook-p.h"
#include "qofid-p.h"

View File

@ -35,6 +35,7 @@
#include "gnc-engine-util.h"
#include "gnc-event-p.h"
#include "gnc-numeric.h"
#include "gnc-trace.h"
#include "qofbackend.h"
#include "qofbook.h"
#include "qofbook-p.h"

View File

@ -20,6 +20,7 @@ libgncmod_engine_la_SOURCES = \
SX-ttinfo.c \
Scrub.c \
Scrub2.c \
Scrub3.c \
TransLog.c \
Transaction.c \
cap-gains.c \
@ -67,6 +68,7 @@ gncinclude_HEADERS = \
QueryCore.h \
Scrub.h \
Scrub2.h \
Scrub3.h \
TransLog.h \
Transaction.h \
cap-gains.h \

View File

@ -40,6 +40,7 @@
#include "gnc-lot-p.h"
#include "gnc-pricedb.h"
#include "gnc-pricedb-p.h"
#include "gnc-trace.h"
#include "Group.h"
#include "GroupP.h"
#include "kvp-util-p.h"

View File

@ -35,11 +35,12 @@
#include "gnc-engine-util.h"
#include "gnc-numeric.h"
#include "gnc-lot.h"
#include "gnc-trace.h"
#include "Account.h"
#include "Query.h"
#include "Transaction.h"
#include "TransactionP.h"
#include "gnc-lot.h"
static short module = MOD_QUERY;

View File

@ -37,6 +37,7 @@
#include "gnc-engine.h"
#include "gnc-engine-util.h"
#include "gnc-event-p.h"
#include "gnc-trace.h"
#include "guid.h"
#include "messages.h"
#include "qofbook.h"

View File

@ -52,6 +52,7 @@
#include "gnc-engine-util.h"
#include "messages.h"
#include "gnc-commodity.h"
#include "gnc-trace.h"
static short module = MOD_SCRUB;
@ -409,6 +410,118 @@ xaccTransScrubImbalance (Transaction *trans, AccountGroup *root,
}
}
/* ================================================================ */
/* The xaccTransFindCommonCurrency () method returns
* a gnc_commodity indicating a currency denomination that all
* of the splits in this transaction have in common, using the
* old/obsolete currency/security fields of the split accounts.
*/
static gnc_commodity *
FindCommonExclSCurrency (SplitList *splits,
gnc_commodity * ra, gnc_commodity * rb,
Split *excl_split)
{
GList *node;
if (!splits) return NULL;
for (node = splits; node; node = node->next)
{
Split *s = node->data;
gnc_commodity * sa, * sb;
if (s == excl_split) continue;
g_return_val_if_fail (s->acc, NULL);
sa = DxaccAccountGetCurrency (s->acc);
sb = xaccAccountGetCommodity (s->acc);
if (ra && rb) {
int aa = !gnc_commodity_equiv(ra,sa);
int ab = !gnc_commodity_equiv(ra,sb);
int ba = !gnc_commodity_equiv(rb,sa);
int bb = !gnc_commodity_equiv(rb,sb);
if ( (!aa) && bb) rb = NULL;
else
if ( (!ab) && ba) rb = NULL;
else
if ( (!ba) && ab) ra = NULL;
else
if ( (!bb) && aa) ra = NULL;
else
if ( aa && bb && ab && ba ) { ra = NULL; rb = NULL; }
if (!ra) { ra = rb; rb = NULL; }
}
else
if (ra && !rb) {
int aa = !gnc_commodity_equiv(ra,sa);
int ab = !gnc_commodity_equiv(ra,sb);
if ( aa && ab ) ra = NULL;
}
if ((!ra) && (!rb)) return NULL;
}
return (ra);
}
/* This is the wrapper for those calls (i.e. the older ones) which
* don't exclude one split from the splitlist when looking for a
* common currency.
*/
static gnc_commodity *
FindCommonCurrency (GList *splits, gnc_commodity * ra, gnc_commodity * rb)
{
return FindCommonExclSCurrency(splits, ra, rb, NULL);
}
static gnc_commodity *
xaccTransFindOldCommonCurrency (Transaction *trans, QofBook *book)
{
gnc_commodity *ra, *rb, *retval;
Split *split;
if (!trans) return NULL;
if (trans->splits == NULL) return NULL;
g_return_val_if_fail (book, NULL);
split = trans->splits->data;
if (!split || NULL == split->acc) return NULL;
ra = DxaccAccountGetCurrency (split->acc);
rb = xaccAccountGetCommodity (split->acc);
retval = FindCommonCurrency (trans->splits, ra, rb);
/* Compare this value to what we think should be the 'right' value */
if (!trans->common_currency)
{
trans->common_currency = retval;
}
else if (!gnc_commodity_equiv (retval,trans->common_currency))
{
PWARN ("expected common currency %s but found %s\n",
gnc_commodity_get_unique_name (trans->common_currency),
gnc_commodity_get_unique_name (retval));
}
if (NULL == retval)
{
/* In every situation I can think of, this routine should return
* common currency. So make note of this ... */
PWARN ("unable to find a common currency, and that is strange.");
}
return retval;
}
/* ================================================================ */
void
@ -544,6 +657,17 @@ xaccAccountScrubCommodity (Account *account)
/* ================================================================ */
static void
xaccAccountDeleteOldData (Account *account)
{
if (!account) return;
kvp_frame_set_slot_nc (account->kvp_data, "old-currency", NULL);
kvp_frame_set_slot_nc (account->kvp_data, "old-security", NULL);
kvp_frame_set_slot_nc (account->kvp_data, "old-currency-scu", NULL);
kvp_frame_set_slot_nc (account->kvp_data, "old-security-scu", NULL);
}
static int
scrub_trans_currency_helper (Transaction *t, gpointer data)
{

View File

@ -47,6 +47,7 @@
#include "gnc-engine-util.h"
#include "gnc-lot.h"
#include "gnc-lot-p.h"
#include "gnc-trace.h"
#include "kvp-util-p.h"
#include "messages.h"

172
src/engine/Scrub3.c Normal file
View File

@ -0,0 +1,172 @@
/********************************************************************\
* Scrub3.c -- Constrain Cap Gains to Track Sources of Gains *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
\********************************************************************/
/* @file Scrub3.c
* @breif Constrain Cap Gains to Track Sources of Gains
* @author Created by Linas Vepstas Sept 2003
* @author Copyright (c) 2003 Linas Vepstas <linas@linas.org>
*
* Provides a set of functions and utilities for checking and
* repairing ('scrubbing clean') the usage of Cap Gains
* transactions in stock and commodity accounts.
*/
#include "config.h"
#include <glib.h>
#include "gnc-commodity.h"
#include "gnc-engine.h"
#include "gnc-numeric.h"
#include "gnc-trace.h"
#include "kvp_frame.h"
#include "Scrub3.h"
#include "Transaction.h"
#include "TransactionP.h"
static short module = MOD_LOT;
/* ================================================================= */
static KvpFrame *
is_subsplit (Split *split)
{
KvpValue *kval;
KvpFrame *ksub;
if (!split) return NULL;
g_return_val_if_fail (split->parent, NULL);
/* If there are no sub-splits, then there's nothing to do. */
kval = kvp_frame_get_slot (split->kvp_data, "lot-split");
if (!kval) return NULL;
ksub = kvp_value_get_frame (kval);
g_return_val_if_fail (ksub, NULL);
return ksub;
}
/* ================================================================= */
void
xaccScrubSubSplitPrice (Split *split)
{
gnc_numeric src_amt, src_val;
SplitList *node;
if (NULL == is_subsplit (split)) return;
ENTER (" ");
/* Get 'price' of the indicated split */
src_amt = xaccSplitGetAmount (split);
src_val = xaccSplitGetValue (split);
/* Loop over splits, adjust each so that it has the same
* ratio (i.e. price). Change the value to get things
* right; do not change the amount */
for (node=split->parent->splits; node; node=node->next)
{
Split *s = node->data;
Transaction *txn = s->parent;
gnc_numeric dst_amt, dst_val, target_val;
gnc_numeric delta;
int scu;
/* Skip the reference split */
if (s == split) continue;
scu = gnc_commodity_get_fraction (txn->common_currency);
dst_amt = xaccSplitGetAmount (s);
dst_val = xaccSplitGetValue (s);
target_val = gnc_numeric_mul (dst_amt, src_val,
GNC_DENOM_AUTO, GNC_DENOM_REDUCE);
target_val = gnc_numeric_div (target_val, src_amt,
scu, GNC_DENOM_EXACT);
/* If the required price changes are 'small', do nothing.
* That is a case that the user will have to deal with
* manually. This routine is really intended only for
* a gross level of synchronization.
*/
delta = gnc_numeric_sub_fixed (target_val, dst_val);
delta = gnc_numeric_abs (delta);
if (3 * delta.num < delta.denom) continue;
/* If the amount is small, pass on that too */
if ((-2 < dst_amt.num) && (dst_amt.num < 2)) continue;
/* Make the actual adjustment */
xaccTransBeginEdit (txn);
xaccSplitSetValue (s, target_val);
xaccTransCommitEdit (txn);
}
LEAVE (" ");
}
/* ================================================================= */
#if LATER
static void
merge_splits (Split *sa, Split *sb)
{
Transaction *txn;
txn = sa->parent;
xaccTransBeginEdit (txn);
/* whack kvp of b, remove gem kvp of a */
/* whack memo etc. b */
/* set reconsile to no */
/* add amounts, values */
xaccTransCommitEdit (txn);
}
void
xaccScrubMergeSubSplits (Split *split)
{
KvpFrame *sf;
SplitList *node;
GNCLot *lot;
sf = is_subsplit (split);
if (!sf) return;
lot = xaccSplitGetLot (split);
ENTER (" ");
for (node=split->parent->splits; node; node=node->next)
{
Split *s = node->data;
if (xaccSplitGetLot (s) != lot) continue;
/* OK, this split is in the same lot (and thus same account)
* as the indicated split. It must be a subsplit. Merge the
* two back together again. */
}
LEAVE (" ");
}
#endif
/* ========================== END OF FILE ========================= */

54
src/engine/Scrub3.h Normal file
View File

@ -0,0 +1,54 @@
/********************************************************************\
* Scrub3.h -- Constrain Cap Gains to Track Sources of Gains *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
\********************************************************************/
/** @addtogroup Engine
@{ */
/** @file Scrub3.h
* @breif Constrain Cap Gains to Track Sources of Gains
* @author Created by Linas Vepstas Sept 2003
* @author Copyright (c) 2003 Linas Vepstas <linas@linas.org>
*
* Provides a set of functions and utilities for checking and
* repairing ('scrubbing clean') the usage of Cap Gains
* transactions in stock and commodity accounts.
*/
#ifndef XACC_SCRUB3_H
#define XACC_SCRUB3_H
#include "gnc-engine.h"
/** If a split has been pulled apart to make it fit into two (or more)
* lots, then it becomes theoretically possible for each subsplit to
* have a distinct price. But this would be wrong: each subsplit should
* have the same price, within rounding errors. This routine will
* examine the indicated split for sub-splits, and adjust the value
* of each so that they all have the same price.
*
* There is a bit of a problem with the interpretation of 'rounding
* errors' because there are pathological corner cases of small
* amounts. So this routine is fairly loose, hopefully loose enough
* so that the user can manually fine tune without having this routine
* clobber thier work.
*/
void xaccScrubSubSplitPrice (Split *split);
#endif /* XACC_SCRUB3_H */
/** @} */

View File

@ -43,6 +43,7 @@
#include "gnc-event-p.h"
#include "gnc-lot-p.h"
#include "gnc-lot.h"
#include "gnc-trace.h"
#include "messages.h"
#include "qofbackend-p.h"
@ -66,23 +67,6 @@
* of the GUI should ignore the data until its commited.
*/
/*
* The "force_double_entry" flag determines how
* the splits in a transaction will be balanced.
*
* The following values have significance:
* 0 -- anything goes
* 1 -- The sum of all splits in a transaction will be
* forced to be zero, even if this requires the
* creation of additional splits. Note that a split
* whose value is zero (e.g. a stock price) can exist
* by itself. Otherwise, all splits must come in at
* least pairs.
* 2 -- splits without parents will be forced into a
* lost & found account. (Not implemented)
*/
int force_double_entry = 0;
const char *trans_notes_str = "notes";
const char *void_reason_str = "void-reason";
const char *void_time_str = "void-time";
@ -510,21 +494,6 @@ xaccSplitLookupDirect (GUID guid, QofBook *book)
&guid, GNC_ID_SPLIT);
}
/********************************************************************\
\********************************************************************/
void
xaccConfigSetForceDoubleEntry (int force)
{
force_double_entry = force;
}
int
xaccConfigGetForceDoubleEntry (void)
{
return (force_double_entry);
}
/********************************************************************\
\********************************************************************/
/* Routines for marking splits dirty, and for sending out change
@ -730,6 +699,7 @@ void
DxaccSplitSetSharePriceAndAmount (Split *s, double price, double amt)
{
if (!s) return;
ENTER (" ");
check_open (s->parent);
s->amount = double_to_gnc_numeric(amt, get_commodity_denom(s),
@ -747,6 +717,7 @@ xaccSplitSetSharePriceAndAmount (Split *s, gnc_numeric price,
gnc_numeric amt)
{
if (!s) return;
ENTER (" ");
check_open (s->parent);
s->amount = gnc_numeric_convert(amt, get_commodity_denom(s), GNC_RND_ROUND);
@ -762,6 +733,7 @@ void
xaccSplitSetSharePrice (Split *s, gnc_numeric price)
{
if (!s) return;
ENTER (" ");
check_open (s->parent);
s->value = gnc_numeric_mul(xaccSplitGetAmount(s),
@ -781,6 +753,7 @@ DxaccSplitSetShareAmount (Split *s, double damt)
gnc_numeric amt = double_to_gnc_numeric(damt, commodity_denom,
GNC_RND_ROUND);
if (!s) return;
ENTER (" ");
check_open (s->parent);
old_amt = xaccSplitGetAmount (s);
@ -809,6 +782,8 @@ void
xaccSplitSetAmount (Split *s, gnc_numeric amt)
{
if(!s) return;
ENTER ("old amt=%lld/%lld new amt=%lld/%lld",
s->amount.num, s->amount.denom, amt.num, amt.denom);
check_open (s->parent);
s->amount = gnc_numeric_convert(amt, get_commodity_denom(s), GNC_RND_ROUND);
@ -823,6 +798,8 @@ void
xaccSplitSetValue (Split *s, gnc_numeric amt)
{
if(!s) return;
ENTER ("old val=%lld/%lld new val=%lld/%lld",
s->value.num, s->value.denom, amt.num, amt.denom);
check_open (s->parent);
s->value = gnc_numeric_convert(amt, get_currency_denom(s), GNC_RND_ROUND);
@ -1373,25 +1350,9 @@ xaccSplitSetBaseValue (Split *s, gnc_numeric value,
if (!s) return;
check_open (s->parent);
/* Novice/casual users may not want or use the double entry
* features of this engine. So, in particular, there may be the
* occasional split without a parent account. Well, that's ok,
* we'll just go with the flow. */
if (NULL == s->acc)
{
if (force_double_entry)
{
PERR ("split must have a parent\n");
g_return_if_fail (s->acc);
}
else
{
s->value = value;
s->amount = value;
SET_GAINS_A_VDIRTY(s);
}
mark_split (s);
/* gen_event (s); No! only in TransCommit() ! */
PERR ("split must have a parent\n");
return;
}
@ -1415,10 +1376,6 @@ xaccSplitSetBaseValue (Split *s, gnc_numeric value,
s->amount = gnc_numeric_convert(value, get_commodity_denom(s),
GNC_RND_NEVER);
}
else if ((NULL==base_currency) && (0 == force_double_entry)) {
s->value = gnc_numeric_convert(value, get_currency_denom(s),
GNC_RND_NEVER);
}
else {
PERR ("inappropriate base currency %s "
"given split currency=%s and commodity=%s\n",
@ -1443,20 +1400,9 @@ xaccSplitGetBaseValue (const Split *s,
if (!s) return gnc_numeric_zero();
/* ahh -- users may not want or use the double entry
* features of this engine. So, in particular, there
* may be the occasional split without a parent account.
* Well, that's ok, we'll just go with the flow.
*/
if (NULL == s->acc)
{
if (force_double_entry)
{
g_return_val_if_fail (s->acc, gnc_numeric_zero ());
}
else {
return xaccSplitGetValue((Split *)s);
}
g_return_val_if_fail (s->acc, gnc_numeric_zero ());
}
currency = xaccTransGetCurrency (s->parent);
@ -1472,10 +1418,6 @@ xaccSplitGetBaseValue (const Split *s,
{
value = xaccSplitGetAmount (s);
}
else if ((NULL == base_currency) && (0 == force_double_entry))
{
value = xaccSplitGetValue(s);
}
else
{
PERR ("inappropriate base currency %s "
@ -1497,78 +1439,64 @@ xaccSplitsComputeValue (GList *splits, Split * skip_me,
const gnc_commodity * base_currency)
{
GList *node;
gnc_numeric value;
gnc_numeric value = gnc_numeric_zero();
g_return_val_if_fail (base_currency, value);
ENTER (" currency=%s", gnc_commodity_get_mnemonic (base_currency));
value = gnc_numeric_zero();
for (node = splits; node; node = node->next)
{
Split *s = node->data;
const gnc_commodity *currency;
const gnc_commodity *commodity;
if (s == skip_me) continue;
/* ahh -- users may not want or use the double entry features of
* this engine. So, in particular, there may be the occasional
* split without a parent account. Well, that's ok, we'll just
* go with the flow. */
/* The split-editor often sends us 'temp' splits whose account
* hasn't yet been set. Be lenient, and assume an implied base
* currency. If theres a problem later, teh scrub routines will
* pick it up.
*/
if (NULL == s->acc)
{
if (force_double_entry)
{
g_return_val_if_fail (s->acc, gnc_numeric_zero ());
}
else
{
value = gnc_numeric_add(value, xaccSplitGetValue(s),
GNC_DENOM_AUTO, GNC_DENOM_LCD);
}
commodity = base_currency;
}
else if ((NULL == base_currency) && (0 == force_double_entry))
else
{
commodity = xaccAccountGetCommodity (s->acc);
}
currency = xaccTransGetCurrency (s->parent);
if (gnc_commodity_equiv(currency, base_currency))
{
value = gnc_numeric_add(value, xaccSplitGetValue(s),
GNC_DENOM_AUTO, GNC_DENOM_LCD);
}
else
else if (gnc_commodity_equiv(commodity, base_currency))
{
const gnc_commodity *currency;
const gnc_commodity *commodity;
currency = xaccTransGetCurrency (s->parent);
commodity = xaccAccountGetCommodity (s->acc);
/* OK, we've got a parent account, we've got currency, lets
* behave like professionals now, instead of the shenanigans
* above. Note that just because the currencies are equivalent
* doesn't mean the denominators are the same! */
if (base_currency &&
gnc_commodity_equiv(currency, base_currency)) {
value = gnc_numeric_add(value, xaccSplitGetValue(s),
GNC_DENOM_AUTO, GNC_DENOM_LCD);
}
else if (base_currency &&
gnc_commodity_equiv(commodity, base_currency)) {
value = gnc_numeric_add(value, xaccSplitGetAmount(s),
GNC_DENOM_AUTO, GNC_DENOM_LCD);
}
else {
PERR ("inconsistent currencies\n"
"\tbase = '%s', curr='%s', sec='%s'\n",
gnc_commodity_get_printname(base_currency),
gnc_commodity_get_printname(currency),
gnc_commodity_get_printname(commodity));
g_return_val_if_fail (FALSE, gnc_numeric_zero ());
}
value = gnc_numeric_add(value, xaccSplitGetAmount(s),
GNC_DENOM_AUTO, GNC_DENOM_LCD);
}
else {
PERR ("inconsistent currencies\n"
"\tbase = '%s', curr='%s', sec='%s'\n",
gnc_commodity_get_printname(base_currency),
gnc_commodity_get_printname(currency),
gnc_commodity_get_printname(commodity));
g_return_val_if_fail (FALSE, value);
}
}
if (base_currency)
return gnc_numeric_convert (value,
/* Note that just because the currencies are equivalent
* doesn't mean the denominators are the same! */
value = gnc_numeric_convert (value,
gnc_commodity_get_fraction (base_currency),
GNC_RND_ROUND);
else
return gnc_numeric_convert (value, GNC_DENOM_AUTO, GNC_DENOM_REDUCE);
LEAVE (" ");
LEAVE (" total=%lld/%lld", value.num, value.denom);
return value;
}
gnc_numeric
@ -1602,126 +1530,6 @@ xaccTransGetAccountValue (const Transaction *trans,
return total;
}
/********************************************************************\
\********************************************************************/
static gnc_commodity *
FindCommonExclSCurrency (SplitList *splits,
gnc_commodity * ra, gnc_commodity * rb,
Split *excl_split)
{
GList *node;
if (!splits) return NULL;
for (node = splits; node; node = node->next)
{
Split *s = node->data;
gnc_commodity * sa, * sb;
if (s == excl_split) continue;
/* Novice/casual users may not want or use the double entry
* features of this engine. Because of this, there
* may be the occasional split without a parent account.
* Well, that's ok, we'll just go with the flow.
*/
if (force_double_entry)
{
g_return_val_if_fail (s->acc, NULL);
}
else if (NULL == s->acc)
{
continue;
}
sa = DxaccAccountGetCurrency (s->acc);
sb = DxaccAccountGetSecurity (s->acc);
if (ra && rb) {
int aa = !gnc_commodity_equiv(ra,sa);
int ab = !gnc_commodity_equiv(ra,sb);
int ba = !gnc_commodity_equiv(rb,sa);
int bb = !gnc_commodity_equiv(rb,sb);
if ( (!aa) && bb) rb = NULL;
else
if ( (!ab) && ba) rb = NULL;
else
if ( (!ba) && ab) ra = NULL;
else
if ( (!bb) && aa) ra = NULL;
else
if ( aa && bb && ab && ba ) { ra = NULL; rb = NULL; }
if (!ra) { ra = rb; rb = NULL; }
}
else
if (ra && !rb) {
int aa = !gnc_commodity_equiv(ra,sa);
int ab = !gnc_commodity_equiv(ra,sb);
if ( aa && ab ) ra = NULL;
}
if ((!ra) && (!rb)) return NULL;
}
return (ra);
}
/* This is the wrapper for those calls (i.e. the older ones) which
* don't exclude one split from the splitlist when looking for a
* common currency.
*/
static gnc_commodity *
FindCommonCurrency (GList *splits, gnc_commodity * ra, gnc_commodity * rb)
{
return FindCommonExclSCurrency(splits, ra, rb, NULL);
}
gnc_commodity *
xaccTransFindOldCommonCurrency (Transaction *trans, QofBook *book)
{
gnc_commodity *ra, *rb, *retval;
Split *split;
if (!trans) return NULL;
if (trans->splits == NULL) return NULL;
g_return_val_if_fail (book, NULL);
split = trans->splits->data;
if (!split || NULL == split->acc) return NULL;
ra = DxaccAccountGetCurrency (split->acc);
rb = DxaccAccountGetSecurity (split->acc);
retval = FindCommonCurrency (trans->splits, ra, rb);
/* compare this value to what we think should be the 'right' value */
if (!trans->common_currency)
{
trans->common_currency = retval;
}
else if (!gnc_commodity_equiv (retval,trans->common_currency))
{
PWARN ("expected common currency %s but found %s\n",
gnc_commodity_get_unique_name (trans->common_currency),
gnc_commodity_get_unique_name (retval));
}
if (NULL == retval)
{
/* in every situation I can think of, this routine should return
* common currency. So make note of this ... */
PWARN ("unable to find a common currency, and that is strange.");
}
return retval;
}
/********************************************************************\
\********************************************************************/
/* The new routine for setting the common currency */
@ -1910,16 +1718,20 @@ xaccTransCommitEdit (Transaction *trans)
trans->date_entered.tv_nsec = 1000 * tv.tv_usec;
}
#if SCRUB_BEFORE_COMMITTING
/* XXX the below is a weak attempt to scrub the transaction
* before committing it. Not clear if this is a good idea
* or not, since the scrubbers can run independently/in parallel.
*/
/* Alternately the transaction may have only one split in
* it, in which case that's OK if and only if the split has no
* value (i.e. is only recording a price). Otherwise, a single
* split with a value can't possibly balance, thus violating the
* rules of double-entry, and that's way bogus. So create
* a matching opposite and place it either here (if force==1),
* or in some dummy account (if force==2).
* a matching opposite and place it here.
* XXX should be using Scrub routine to do this correctly ...
*/
if ((1 == force_double_entry) &&
(NULL == g_list_nth(trans->splits, 1)) &&
if ((NULL == g_list_nth(trans->splits, 1)) &&
(!gnc_numeric_zero_p(xaccSplitGetAmount(split))))
{
Split * s = xaccMallocSplit(trans->book);
@ -1931,6 +1743,7 @@ xaccTransCommitEdit (Transaction *trans)
xaccSplitSetAction (s, split->action);
SET_GAINS_A_VDIRTY(s);
}
#endif
}
/* ------------------------------------------------- */
@ -3398,25 +3211,54 @@ xaccGetAccountByFullName (Transaction *trans, const char * name,
/********************************************************************\
\********************************************************************/
/* In the old world, the 'other split' was the other split of a
* transaction that contained only two splits. In the new world,
* a split may have been cut up between multiple lots, although
* in a conceptual sense, if lots hadn't been used, there would be
* only a pair. So we handle this conceptual case: we can still
* identify, unambiguously, the 'other' split when 'this' split
* as been cut up across lots. We do thins by looking for the
* 'lot-split' keyword, which occurs only in cut-up splits.
*/
Split *
xaccSplitGetOtherSplit (const Split *split)
{
Split *s1, *s2;
SplitList *node;
Transaction *trans;
int count;
Split *other = NULL;
KvpValue *sva;
if (!split) return NULL;
trans = split->parent;
if (!trans) return NULL;
#ifdef OLD_ALGO_HAS_ONLY_TWO_SPLITS
Split *s1, *s2;
if (g_list_length (trans->splits) != 2) return NULL;
s1 = g_list_nth_data (trans->splits, 0);
s2 = g_list_nth_data (trans->splits, 1);
if (s1 == split) return s2;
return s1;
#endif
count = g_list_length (trans->splits);
sva = kvp_frame_get_slot (split->kvp_data, "lot-split");
if (!sva && (2 != count)) return NULL;
for (node=trans->splits; node; node=node->next)
{
Split *s = node->data;
KvpValue *va = kvp_frame_get_slot (s->kvp_data, "lot-split");
if (s == split) { --count; continue; }
if (va) { --count; continue; }
other = s;
}
if (1 == count) return other;
return NULL;
}
/********************************************************************\

View File

@ -57,39 +57,6 @@
#define TXN_TYPE_PAYMENT 'P' /**< Transaction is a payment */
/**@}*/
/** @name Configuration ForceDoubleEntry getters/setters
*/
/**@{*/
/**
* The xaccConfigSetForceDoubleEntry() and xaccConfigGetForceDoubleEntry()
* set and get the "force_double_entry" flag. This flag determines how
* the splits in a transaction will be balanced.
*
* The following values have significance:
*
* 0 -- anything goes
*
* 1 -- The sum of all splits in a transaction will be
* forced to be zero, even if this requires the
* creation of additional splits. Note that a split
* whose value is zero (e.g. a stock price) can exist
* by itself. Otherwise, all splits must come in at
* least pairs.
*
* 2 -- splits without parents will be forced into a
* lost & found account. (Not implemented)
*/
void xaccConfigSetForceDoubleEntry (int force);
/**
* The xaccConfigSetForceDoubleEntry() and xaccConfigGetForceDoubleEntry()
* set and get the "force_double_entry" flag. This flag determines how
* the splits in a transaction will be balanced.
*/
int xaccConfigGetForceDoubleEntry (void);
/**@}*/
/***************************************************************
* Transaction
*/

View File

@ -289,14 +289,6 @@ void DxaccSplitSetSharePriceAndAmount (Split *split,
double amount);
void DxaccSplitSetShareAmount (Split *split, double amount);
/* The deprecated xaccTransFindCommonCurrency () method returns
* a gnc_commodity indicating a currency denomination that all
* of the splits in this transaction have in common, using the
* old currency/security fields of the split accounts. DO NOT
* USE THIS ROUTINE! */
gnc_commodity * xaccTransFindOldCommonCurrency (Transaction *trans,
QofBook *book);
/*@}*/

View File

@ -75,6 +75,7 @@ ToDo List:
#include "gnc-engine-util.h"
#include "gnc-lot.h"
#include "gnc-lot-p.h"
#include "gnc-trace.h"
#include "kvp-util-p.h"
#include "messages.h"
#include "qofid-p.h"

View File

@ -36,6 +36,7 @@
#include "gnc-engine-util.h"
#include "gnc-engine.h"
#include "gnc-numeric.h"
#include "gnc-trace.h"
#include "guile-mappings.h"
#include "qofbook.h"
#include "qofquery.h"

View File

@ -32,6 +32,7 @@
#include "gnc-associate-account.h"
#include "gnc-engine.h"
#include "gnc-engine-util.h"
#include "gnc-trace.h"
#include "qofbook.h"
#include "qofid.h"

View File

@ -43,6 +43,7 @@
#include "gnc-date.h"
#include "gnc-engine-util.h"
#include "gnc-trace.h"
#ifndef HAVE_STRPTIME
#include "strptime.h"

View File

@ -34,7 +34,7 @@
#include <glib.h>
#include <stddef.h>
#include "gnc-trace.h"
#include "gnc-trace.h" // XXX eliminate me eventually
/** Macros *****************************************************/

View File

@ -25,6 +25,7 @@
#include "gnc-engine-util.h"
#include "gnc-event-p.h"
#include "gnc-trace.h"
/** Declarations ****************************************************/

View File

@ -44,6 +44,7 @@
#include "gnc-event-p.h"
#include "gnc-lot.h"
#include "gnc-lot-p.h"
#include "gnc-trace.h"
#include "Transaction.h"
#include "TransactionP.h"
#include "qofqueryobject.h"

View File

@ -31,6 +31,7 @@
#include "gnc-engine-util.h"
#include "gnc-event-p.h"
#include "gnc-pricedb-p.h"
#include "gnc-trace.h"
#include "guid.h"
#include "kvp-util.h"
#include "qofbackend-p.h"

View File

@ -35,10 +35,10 @@
/* This static indicates the debugging module that this .o belongs to. */
/* static short module = MOD_ENGINE; */
static gncLogLevel loglevel[MOD_LAST + 1] =
gncLogLevel gnc_log_modules[MOD_LAST + 1] =
{
GNC_LOG_FATAL, /* DUMMY */
GNC_LOG_WARNING, /* ENGINE */
GNC_LOG_TRACE, /* ENGINE */
GNC_LOG_WARNING, /* IO */
GNC_LOG_WARNING, /* REGISTER */
GNC_LOG_WARNING, /* LEDGER */
@ -47,16 +47,16 @@ static gncLogLevel loglevel[MOD_LAST + 1] =
GNC_LOG_WARNING, /* SCRUB */
GNC_LOG_WARNING, /* GTK_REG */
GNC_LOG_WARNING, /* GUILE */
GNC_LOG_WARNING, /* BACKEND */
GNC_LOG_WARNING, /* QUERY */
GNC_LOG_TRACE, /* BACKEND */
GNC_LOG_TRACE, /* QUERY */
GNC_LOG_WARNING, /* PRICE */
GNC_LOG_WARNING, /* SQL EVENT */
GNC_LOG_WARNING, /* SQL TXN */
GNC_LOG_WARNING, /* KVP */
GNC_LOG_WARNING, /* SX */
GNC_LOG_WARNING, /* BOOK */
GNC_LOG_TRACE, /* BOOK */
GNC_LOG_TRACE, /* TEST */
GNC_LOG_WARNING, /* LOT */
GNC_LOG_TRACE, /* LOT */
GNC_LOG_WARNING, /* ACCOUNT */
GNC_LOG_WARNING, /* IMPORT */
GNC_LOG_WARNING, /* BUSINESS */
@ -66,6 +66,24 @@ static gncLogLevel loglevel[MOD_LAST + 1] =
static FILE *fout = NULL;
static void
fh_printer (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
FILE *fh = user_data;
fprintf (fh, "%s\n", message);
}
void
gnc_log_init (void)
{
fout = stderr;
fout = stdout;
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, fh_printer, fout);
}
/* Set the logging level of the given module. */
void
gnc_set_log_level(gncModuleType module, gncLogLevel level)
@ -73,7 +91,7 @@ gnc_set_log_level(gncModuleType module, gncLogLevel level)
if ((module < 0) || (module > MOD_LAST))
return;
loglevel[module] = level;
gnc_log_modules[module] = level;
}
/* Set the logging level for all modules. */
@ -83,7 +101,7 @@ gnc_set_log_level_global(gncLogLevel level)
gncModuleType module;
for (module = 0; module <= MOD_LAST; module++)
loglevel[module] = level;
gnc_log_modules[module] = level;
}
void
@ -92,13 +110,13 @@ gnc_set_logfile (FILE *outfile)
fout = outfile;
}
/* prettify() cleans up subroutine names. AIX/xlC has the habit of
* printing signatures not names; clean this up. On other operating
/* gnc_log_prettify() cleans up subroutine names. AIX/xlC has the habit
* of printing signatures not names; clean this up. On other operating
* systems, truncate name to 30 chars. Note this routine is not thread
* safe. Note we wouldn't need this routine if AIX did something more
* reasonable. Hope thread safety doesn't poke us in eye. */
static const char *
prettify (const char *name)
const char *
gnc_log_prettify (const char *name)
{
static char bf[128];
char *p;
@ -120,46 +138,6 @@ prettify (const char *name)
return bf;
}
gboolean
gnc_should_log (gncModuleType module, gncLogLevel log_level)
{
if (module < 0 || module > MOD_LAST)
{
PERR ("Bad module: %d", module);
return FALSE;
}
if (log_level > loglevel[module])
return FALSE;
return TRUE;
}
void
gnc_log (gncModuleType module, gncLogLevel log_level, const char *prefix,
const char *function_name, const char *format, ...)
{
va_list ap;
if (!gnc_should_log (module, log_level))
return;
if (!fout) fout = stderr;
fprintf (fout, "%s: %s: ",
prefix ? prefix : "(null)",
prettify (function_name));
va_start (ap, format);
vfprintf (fout, format, ap);
va_end (ap);
fprintf (fout, "\n");
}
/********************************************************************\
\********************************************************************/
@ -187,10 +165,10 @@ gnc_start_clock (int clockno, gncModuleType module, gncLogLevel log_level,
if ((0>clockno) || (NUM_CLOCKS <= clockno)) return;
gettimeofday (&gnc_clock[clockno], &tz);
if (!fout) fout = stderr;
if (!fout) gnc_log_init();
fprintf (fout, "Clock %d Start: %s: ",
clockno, prettify (function_name));
clockno, gnc_log_prettify (function_name));
va_start (ap, format);
@ -224,10 +202,10 @@ gnc_report_clock (int clockno, gncModuleType module, gncLogLevel log_level,
gnc_clock_total[clockno].tv_sec += now.tv_sec;
gnc_clock_total[clockno].tv_usec += now.tv_usec;
if (!fout) fout = stderr;
if (!fout) gnc_log_init();
fprintf (fout, "Clock %d Elapsed: %ld.%06lds %s: ",
clockno, now.tv_sec, now.tv_usec, prettify (function_name));
clockno, now.tv_sec, now.tv_usec, gnc_log_prettify (function_name));
va_start (ap, format);
@ -254,13 +232,13 @@ gnc_report_clock_total (int clockno,
gnc_clock_total[clockno].tv_usec -= 1000000;
}
if (!fout) fout = stderr;
if (!fout) gnc_log_init();
fprintf (fout, "Clock %d Total Elapsed: %ld.%06lds %s: ",
clockno,
gnc_clock_total[clockno].tv_sec,
gnc_clock_total[clockno].tv_usec,
prettify (function_name));
gnc_log_prettify (function_name));
va_start (ap, format);
@ -278,12 +256,14 @@ gnc_report_clock_total (int clockno,
static GNCGuiMessage gnc_gui_warning_func = NULL;
static GNCGuiMessage gnc_gui_error_func = NULL;
void gnc_set_warning_message (GNCGuiMessage func)
void
gnc_set_warning_message (GNCGuiMessage func)
{
gnc_gui_warning_func = func;
}
void gnc_set_error_message (GNCGuiMessage func)
void
gnc_set_error_message (GNCGuiMessage func)
{
gnc_gui_error_func = func;
}
@ -293,10 +273,17 @@ gnc_send_gui_warning(const gchar *format, ...)
{
va_list args;
va_start (args, format);
if (!gnc_gui_warning_func)
return(FALSE);
{
if (!fout) gnc_log_init();
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
format, args);
va_end (args);
return(FALSE);
}
va_start(args, format);
gnc_gui_warning_func(format, args);
va_end(args);
return(TRUE);
@ -307,10 +294,17 @@ gnc_send_gui_error(const gchar *format, ...)
{
va_list args;
va_start (args, format);
if (!gnc_gui_error_func)
return(FALSE);
{
if (!fout) gnc_log_init();
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
format, args);
va_end (args);
return(FALSE);
}
va_start(args, format);
gnc_gui_error_func(format, args);
va_end(args);
return(TRUE);

View File

@ -76,93 +76,128 @@ typedef enum
GNC_LOG_TRACE = 6,
} gncLogLevel;
extern gncLogLevel gnc_log_modules[MOD_LAST + 1];
/** Initialize the error logging subsystem */
void gnc_log_init (void);
/** Set the logging level of the given module. */
void gnc_set_log_level(gncModuleType module, gncLogLevel level);
/** Set the logging level for all modules. */
void gnc_set_log_level_global(gncLogLevel level);
/** Specify an alternate log output, to pipe or file. By default,
* all logging goes to STDERR. */
void gnc_set_logfile (FILE *outfile);
/** gnc_log_prettify() cleans up subroutine names. AIX/xlC has the habit
* of printing signatures not names; clean this up. On other operating
* systems, truncate name to 30 chars. Note this routine is not thread
* safe. Note we wouldn't need this routine if AIX did something more
* reasonable. Hope thread safety doesn't poke us in eye. */
const char * gnc_log_prettify (const char *name);
/* We want logging decisions to be made inline, rather than through
* a CPU-cucking subroutine call. Thus, this is a #define, not a
* subroutine call. The prototype would have been:
* gboolean gnc_should_log (gncModuleType module, gncLogLevel log_level);
*/
#define gnc_should_log(module,log_level) \
(log_level <= gnc_log_modules[module])
#define FUNK gnc_log_prettify(__FUNCTION__)
/** Log error/waring/info messages to stderr or to other pipe.
* This logging infrastructure is meant for validating the
* correctness of the execution of the code. 'Info' level
* messages help trace program flow. 'Error' messages are
* meant to indicate internal data inconsistencies.
*
* Messages can be logged to stdout, stderr, or to any desired
* FILE * file handle. Use fdopen() to get a file handle from a
* file descriptor. Use gnc_set_logfile to set the logging file
* handle.
*/
#define FATAL(format, args...) { \
if (gnc_should_log (module, GNC_LOG_FATAL)) { \
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, \
"Fatal Error: %s: " format, FUNK, ## args); \
} \
}
#define PERR(format, args...) { \
if (gnc_should_log (module, GNC_LOG_ERROR)) { \
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
"Error: %s: " format, FUNK, ## args); \
} \
}
#define PWARN(format, args...) { \
if (gnc_should_log (module, GNC_LOG_WARNING)) { \
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, \
"Warning: %s: " format, FUNK, ## args); \
} \
}
#define PWARN_GUI(format, args...) { \
gnc_send_gui_error(format, ## args); \
}
#define PINFO(format, args...) { \
if (gnc_should_log (module, GNC_LOG_INFO)) { \
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, \
"Info: %s: " format, FUNK, ## args); \
} \
}
#define DEBUG(format, args...) { \
if (gnc_should_log (module, GNC_LOG_DEBUG)) { \
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
"Debug: %s: " format, FUNK, ## args); \
} \
}
#define ENTER(format, args...) { \
if (gnc_should_log (module, GNC_LOG_DEBUG)) { \
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
"Enter: %s: " format, FUNK, ## args); \
} \
}
#define LEAVE(format, args...) { \
if (gnc_should_log (module, GNC_LOG_DEBUG)) { \
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
"Leave: %s: " format, FUNK, ## args); \
} \
}
#define TRACE(format, args...) { \
if (gnc_should_log (module, GNC_LOG_TRACE)) { \
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
"Trace: %s: " format, FUNK, ## args); \
} \
}
#define DEBUGCMD(x) { if (gnc_should_log (module, GNC_LOG_DEBUG)) { (x); }}
/* -------------------------------------------------------- */
/* Infrastructure to send messages go to GUI popups, not to stderr!
* Incompletely implemented, needs work.
*/
typedef void (*GNCGuiMessage) (const char *format, va_list args);
void gnc_set_warning_message (GNCGuiMessage func);
void gnc_set_error_message (GNCGuiMessage func);
gboolean gnc_send_gui_warning (const char *format, ...);
gboolean gnc_send_gui_error (const char *format, ...);
gboolean gnc_send_gui_warning (const char *format, ...) G_GNUC_PRINTF(1,2);
gboolean gnc_send_gui_error (const char *format, ...) G_GNUC_PRINTF(1,2);
/* FIXME: these logging functions should proably get replaced by
* the glib.h g_error(), etc functions. That way, we would have
* unified logging mechanism, instead of having some messages
* work one way, and other a different way ...
*
* FIXME: the if test should not be a subroutine call, it should
* not use that many CPU cycles. These logging functions are supposed
* to be lightweight. Who changed this ??? Why ???
*
/* -------------------------------------------------------- */
/* Infrastructure to make timing measurements for critical peices
* of code. Used for only for performance tuning & debugging.
*/
gboolean gnc_should_log (gncModuleType module, gncLogLevel log_level);
void gnc_log (gncModuleType module, gncLogLevel log_level,
const char *prefix, const char *function_name,
const char *format, ...) G_GNUC_PRINTF(5,6);
#define FATAL(format, args...) { \
if (gnc_should_log (module, GNC_LOG_FATAL)) \
gnc_log (module, GNC_LOG_FATAL, "Fatal Error", \
__FUNCTION__, format, ## args); \
}
#define PERR(format, args...) { \
if (gnc_should_log (module, GNC_LOG_ERROR)) \
gnc_log (module, GNC_LOG_ERROR, "Error", \
__FUNCTION__, format, ##args); \
}
#define PWARN(format, args...) { \
if (gnc_should_log (module, GNC_LOG_WARNING)) \
gnc_log (module, GNC_LOG_WARNING, "Warning", \
__FUNCTION__, format, ## args); \
}
#define PWARN_GUI(format, args...) { \
if (!gnc_send_gui_error(format, ## args)) \
PWARN(format, ## args); \
}
#define PINFO(format, args...) { \
if (gnc_should_log (module, GNC_LOG_INFO)) \
gnc_log (module, GNC_LOG_INFO, "Info", \
__FUNCTION__, format, ## args); \
}
#define DEBUG(format, args...) { \
if (gnc_should_log (module, GNC_LOG_DEBUG)) \
gnc_log (module, GNC_LOG_DEBUG, "Debug", \
__FUNCTION__, format, ## args); \
}
#define ENTER(format, args...) { \
if (gnc_should_log (module, GNC_LOG_DEBUG)) \
gnc_log (module, GNC_LOG_DEBUG, "Enter", \
__FUNCTION__, format, ## args); \
}
#define LEAVE(format, args...) { \
if (gnc_should_log (module, GNC_LOG_DEBUG)) \
gnc_log (module, GNC_LOG_DEBUG, "Leave", \
__FUNCTION__, format, ## args); \
}
#define DETAIL(format, args...) { \
if (gnc_should_log (module, GNC_LOG_DETAIL)) \
gnc_log (module, GNC_LOG_DETAIL, "Detail", \
__FUNCTION__, format, ## args); \
}
#define DEBUGCMD(x) { if (gnc_should_log (module, GNC_LOG_DEBUG)) { x; }}
#define ERROR() fprintf(stderr,"%s: Line %d, error = %s\n", \
__FILE__, __LINE__, strerror(errno));
#define TRACE(format, args...) { \
if (gnc_should_log (module, GNC_LOG_TRACE)) \
gnc_log (module, GNC_LOG_TRACE, "Trace", \
__FUNCTION__, format, ## args); \
}
void gnc_start_clock (int clockno, gncModuleType module, gncLogLevel log_level,
const char *function_name, const char *format, ...);
@ -179,16 +214,16 @@ void gnc_report_clock_total (int clockno,
const char *function_name,
const char *format, ...);
#define START_CLOCK(clockno,format, args...) { \
if (gnc_should_log (module, GNC_LOG_INFO)) \
gnc_start_clock (clockno, module, GNC_LOG_INFO,\
__FUNCTION__, format, ## args); \
#define START_CLOCK(clockno,format, args...) { \
if (gnc_should_log (module, GNC_LOG_INFO)) \
gnc_start_clock (clockno, module, GNC_LOG_INFO, \
__FUNCTION__, format, ## args); \
}
#define REPORT_CLOCK(clockno,format, args...) { \
if (gnc_should_log (module, GNC_LOG_INFO)) \
gnc_report_clock (clockno, module, GNC_LOG_INFO,\
__FUNCTION__, format, ## args); \
#define REPORT_CLOCK(clockno,format, args...) { \
if (gnc_should_log (module, GNC_LOG_INFO)) \
gnc_report_clock (clockno, module, GNC_LOG_INFO, \
__FUNCTION__, format, ## args); \
}
#define REPORT_CLOCK_TOTAL(clockno,format, args...) { \
@ -197,13 +232,4 @@ void gnc_report_clock_total (int clockno,
__FUNCTION__, format, ## args); \
}
/* Set the logging level of the given module. */
void gnc_set_log_level(gncModuleType module, gncLogLevel level);
/* Set the logging level for all modules. */
void gnc_set_log_level_global(gncLogLevel level);
/* Pipe log output to pipe or file */
void gnc_set_logfile (FILE *outfile);
#endif /* GNC_TRACE_H */

View File

@ -23,21 +23,22 @@
(list
"#include <glib.h>\n"
"#include <guid.h>\n"
"#include <Query.h>\n"
"#include <Group.h>\n"
"#include <Query.h>\n"
"#include <gnc-commodity.h>\n"
"#include <gnc-date.h>\n"
"#include <gnc-engine.h>\n"
"#include <gnc-engine-util.h>\n"
"#include <gnc-event.h>\n"
"#include <gnc-numeric.h>\n"
"#include <gnc-pricedb.h>\n"
"#include <gnc-lot.h>\n"
"#include <gnc-trace.h>\n"
"#include <gnc-session-scm.h>\n"
"#include <qofbackend.h>\n"
"#include <qofbook.h>\n"
"#include <qofsession.h>\n"
"#include <gnc-session-scm.h>\n"
"#include <gnc-engine-util.h>\n"
"#include <gnc-event.h>\n"
"#include <gnc-pricedb.h>\n"
"#include <gnc-lot.h>\n"
"#include <gnc-date.h>\n"
"#include <engine-helpers.h>\n"
"#include <gnc-engine.h>\n"
"#include <gnc-commodity.h>\n"
"#include <gnc-numeric.h>\n")))
"#include <engine-helpers.h>\n")))
(gw:wrapset-add-cs-initializers!
ws

View File

@ -34,6 +34,7 @@
#include "gnc-date.h"
#include "gnc-engine-util.h"
#include "gnc-numeric.h"
#include "gnc-trace.h"
#include "guid.h"
#include "kvp_frame.h"

View File

@ -29,6 +29,7 @@
#include "qofid.h"
#include "qofid-p.h"
#include "gnc-engine-util.h"
#include "gnc-trace.h"
#define CACHE_INSERT(str) g_cache_insert(gnc_engine_get_string_cache(), (gpointer)(str));
#define CACHE_REMOVE(str) g_cache_remove(gnc_engine_get_string_cache(), (gpointer)(str));

View File

@ -29,6 +29,7 @@
#include <glib.h>
#include "gnc-engine-util.h"
#include "gnc-trace.h"
#include "qofobject.h"
#include "qofobject-p.h"
#include "qofbook.h"

View File

@ -30,6 +30,7 @@
#include <string.h>
#include "gnc-engine-util.h"
#include "gnc-trace.h"
#include "qofbackend-p.h"
#include "qofbook.h"

View File

@ -26,6 +26,7 @@
#include <glib.h>
#include "gnc-engine-util.h"
#include "gnc-trace.h"
#include "qofquery.h"
#include "qofquerycore.h"
#include "qofquerycore-p.h"

View File

@ -26,6 +26,7 @@
#include <glib.h>
#include "gnc-engine-util.h"
#include "gnc-trace.h"
#include "qofqueryobject-p.h"
#include "qofquery.h"

View File

@ -272,7 +272,7 @@ static void
qof_session_int_backend_load_error(QofSession *session,
char *message, char *dll_err)
{
PWARN (message, dll_err ? dll_err : "");
PWARN ("%s %s", message, dll_err ? dll_err : "");
g_free(session->fullpath);
session->fullpath = NULL;

View File

@ -1,5 +1,6 @@
#include <glib.h>
#include <libguile.h>
#include <stdio.h>
#include "guid.h"
#include "gnc-module.h"