diff options
-rw-r--r-- | amount.cc | 414 | ||||
-rw-r--r-- | amount.h | 37 | ||||
-rw-r--r-- | format.cc | 8 | ||||
-rw-r--r-- | format.h | 11 | ||||
-rw-r--r-- | gnucash.cc | 10 | ||||
-rw-r--r-- | ledger.h | 3 | ||||
-rw-r--r-- | main.cc | 6 | ||||
-rw-r--r-- | textual.cc | 7 | ||||
-rw-r--r-- | valexpr.cc | 2 |
9 files changed, 249 insertions, 249 deletions
@@ -4,68 +4,77 @@ #include "gmp.h" -#define MAX_PRECISION 10 - #define MPZ(x) ((MP_INT *)(x)) namespace ledger { -static mpz_t full_divisor; +static mpz_t divisor; static mpz_t true_value; static struct init_amounts { init_amounts() { - mpz_init(full_divisor); + mpz_init(divisor); mpz_init(true_value); - mpz_ui_pow_ui(full_divisor, 10, MAX_PRECISION); - mpz_mul_ui(true_value, full_divisor, 1); + mpz_set_ui(true_value, 1); } #ifndef NO_CLEANUP ~init_amounts() { - mpz_clear(full_divisor); mpz_clear(true_value); + mpz_clear(divisor); } #endif } initializer; -static void mpz_round(mpz_t out, mpz_t value, int precision) +static void mpz_round(mpz_t out, mpz_t value, int value_prec, int round_prec) { - mpz_t divisor; + // Round `value', with an encoding precision of `value_prec', to a + // rounded value with precision `round_prec'. Result is stored in + // `out'. + + assert(value_prec > round_prec); mpz_t quotient; mpz_t remainder; - mpz_init(divisor); mpz_init(quotient); mpz_init(remainder); - mpz_ui_pow_ui(divisor, 10, MAX_PRECISION - precision); + DEBUG_CLASS("ledger.amount.round"); + + DEBUG_PRINT_("mpz_round: value " << value); + mpz_ui_pow_ui(divisor, 10, value_prec - round_prec); + DEBUG_PRINT_("mpz_round: divisor " << divisor); mpz_tdiv_qr(quotient, remainder, value, divisor); - mpz_ui_pow_ui(divisor, 10, MAX_PRECISION - precision - 1); + DEBUG_PRINT_("mpz_round: quotient " << quotient); + DEBUG_PRINT_("mpz_round: remainder " << remainder); + mpz_divexact_ui(divisor, divisor, 10); mpz_mul_ui(divisor, divisor, 5); + DEBUG_PRINT_("mpz_round: divisor " << divisor); if (mpz_sgn(remainder) < 0) { - mpz_ui_sub(divisor, 0, divisor); - + mpz_neg(divisor, divisor); if (mpz_cmp(remainder, divisor) < 0) { - mpz_ui_pow_ui(divisor, 10, MAX_PRECISION - precision); + mpz_ui_pow_ui(divisor, 10, value_prec - round_prec); mpz_add(remainder, divisor, remainder); mpz_ui_sub(remainder, 0, remainder); + DEBUG_PRINT_("mpz_round: + remainder " << remainder); mpz_add(out, value, remainder); } else { + DEBUG_PRINT_("mpz_round: - remainder " << remainder); mpz_sub(out, value, remainder); } } else { if (mpz_cmp(remainder, divisor) >= 0) { - mpz_ui_pow_ui(divisor, 10, MAX_PRECISION - precision); + mpz_ui_pow_ui(divisor, 10, value_prec - round_prec); mpz_sub(remainder, divisor, remainder); + DEBUG_PRINT_("mpz_round: + remainder " << remainder); mpz_add(out, value, remainder); } else { + DEBUG_PRINT_("mpz_round: - remainder " << remainder); mpz_sub(out, value, remainder); } } - mpz_clear(divisor); mpz_clear(quotient); mpz_clear(remainder); } @@ -75,6 +84,7 @@ amount_t::amount_t(const bool value) { if (value) { commodity = commodity_t::null_commodity; + precision = 0; quantity = new MP_INT; mpz_init_set(MPZ(quantity), true_value); } @@ -86,8 +96,8 @@ amount_t::amount_t(const int value) if (value != 0) { _init(); commodity = commodity_t::null_commodity; + precision = 0; mpz_set_si(MPZ(quantity), value); - mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); } } @@ -97,8 +107,8 @@ amount_t::amount_t(const unsigned int value) if (value != 0) { _init(); commodity = commodity_t::null_commodity; + precision = 0; mpz_set_ui(MPZ(quantity), value); - mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); } } @@ -108,8 +118,9 @@ amount_t::amount_t(const double value) if (value != 0.0) { _init(); commodity = commodity_t::null_commodity; + // jww (2004-08-20): How do I calculate? + precision = 0; mpz_set_d(MPZ(quantity), value); - mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); } } @@ -134,6 +145,7 @@ void amount_t::_copy(const amount_t& amt) mpz_init_set(MPZ(quantity), MPZ(amt.quantity)); } commodity = amt.commodity; + precision = amt.precision; assert(commodity); } @@ -155,8 +167,12 @@ amount_t& amount_t::operator=(const char * value) // assignment operator amount_t& amount_t::operator=(const amount_t& amt) { - if (amt.quantity) + if (amt.quantity) { _copy(amt); + } else { + commodity = amt.commodity; + precision = amt.precision; + } return *this; } @@ -167,9 +183,11 @@ amount_t& amount_t::operator=(const bool value) _clear(); quantity = NULL; commodity = NULL; + precision = 0; } } else { commodity = commodity_t::null_commodity; + precision = 0; quantity = new MP_INT; mpz_init_set(MPZ(quantity), true_value); } @@ -183,11 +201,12 @@ amount_t& amount_t::operator=(const int value) _clear(); quantity = NULL; commodity = NULL; + precision = 0; } } else { commodity = commodity_t::null_commodity; + precision = 0; mpz_set_si(MPZ(quantity), value); - mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); } return *this; } @@ -199,11 +218,12 @@ amount_t& amount_t::operator=(const unsigned int value) _clear(); quantity = NULL; commodity = NULL; + precision = 0; } } else { commodity = commodity_t::null_commodity; + precision = 0; mpz_set_ui(MPZ(quantity), value); - mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); } return *this; } @@ -215,47 +235,65 @@ amount_t& amount_t::operator=(const double value) _clear(); quantity = NULL; commodity = NULL; + precision = 0; } } else { commodity = commodity_t::null_commodity; + // jww (2004-08-20): How do I calculate? + precision = 0; mpz_set_d(MPZ(quantity), value); - mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); } return *this; } -amount_t& amount_t::operator+=(const amount_t& amt) +void amount_t::_resize(int prec) { - if (amt.quantity) { - if (! quantity) { - _init(); - commodity = amt.commodity; - } + if (prec == precision) + return; - if (commodity != amt.commodity) - throw amount_error("Adding amounts with different commodities"); - - mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); - } - return *this; -} - -amount_t& amount_t::operator-=(const amount_t& amt) -{ - if (amt.quantity) { - if (! quantity) { - _init(); - commodity = amt.commodity; - } - - if (commodity != amt.commodity) - throw amount_error("Subtracting amounts with different commodities"); - - mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); - } - return *this; -} + if (prec < precision) { + mpz_ui_pow_ui(divisor, 10, precision - prec); + mpz_tdiv_q(MPZ(quantity), MPZ(quantity), divisor); + } else { + mpz_ui_pow_ui(divisor, 10, prec - precision); + mpz_mul(MPZ(quantity), MPZ(quantity), divisor); + } + + precision = prec; +} + + +#define DEF_OPERATOR(OP, FUNC) \ +amount_t& amount_t::operator OP(const amount_t& amt) \ +{ \ + if (amt.quantity) { \ + if (! quantity) { \ + _init(); \ + commodity = amt.commodity; \ + precision = amt.precision; \ + } \ + \ + if (commodity != amt.commodity) \ + throw amount_error("+/- amounts with different commodities"); \ + \ + if (precision == amt.precision) { \ + FUNC(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); \ + } \ + else if (precision < amt.precision) { \ + _resize(amt.precision); \ + FUNC(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); \ + } else { \ + amount_t temp = amt; \ + temp._resize(precision); \ + FUNC(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity)); \ + } \ + } \ + return *this; \ +} + +DEF_OPERATOR(+=, mpz_add) +DEF_OPERATOR(-=, mpz_sub) // unary negation amount_t& amount_t::negate() @@ -377,85 +415,53 @@ bool amount_t::operator==(const unsigned int num) const } // comparisons between amounts -bool amount_t::operator<(const amount_t& amt) const -{ - if (! quantity) // equivalent to zero - return amt > 0; - if (! amt.quantity) // equivalent to zero - return *this < 0; - - if (commodity != amt.commodity) - throw amount_error("Comparing amounts with different commodities"); - - return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) < 0; -} - -bool amount_t::operator<=(const amount_t& amt) const -{ - if (! quantity) // equivalent to zero - return amt >= 0; - if (! amt.quantity) // equivalent to zero - return *this <= 0; - - if (commodity != amt.commodity) - throw amount_error("Comparing amounts with different commodities"); - - return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) <= 0; -} - -bool amount_t::operator>(const amount_t& amt) const -{ - if (! quantity) // equivalent to zero - return amt < 0; - if (! amt.quantity) // equivalent to zero - return *this > 0; - - if (commodity != amt.commodity) - throw amount_error("Comparing amounts with different commodities"); - - return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) > 0; -} - -bool amount_t::operator>=(const amount_t& amt) const -{ - if (! quantity) // equivalent to zero - return amt <= 0; - if (! amt.quantity) // equivalent to zero - return *this >= 0; - - if (commodity != amt.commodity) - throw amount_error("Comparing amounts with different commodities"); - - return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) >= 0; -} - -bool amount_t::operator==(const amount_t& amt) const -{ - if (! quantity && ! amt.quantity) - return true; - else if (! quantity || ! amt.quantity) - return false; - - if (commodity != amt.commodity) - throw amount_error("Comparing amounts with different commodities"); - - return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) == 0; -} +#define DEF_CMP_OPERATOR(OP) \ +bool amount_t::operator OP(const amount_t& amt) const \ +{ \ + if (! quantity) \ + return amt > 0; \ + if (! amt.quantity) \ + return *this < 0; \ + \ + if (commodity != amt.commodity) \ + throw amount_error("Comparing amounts with different commodities"); \ + \ + if (precision == amt.precision) { \ + return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) OP 0; \ + } \ + else if (precision < amt.precision) { \ + amount_t temp = *this; \ + temp._resize(amt.precision); \ + return mpz_cmp(MPZ(temp.quantity), MPZ(amt.quantity)) OP 0; \ + } \ + else { \ + amount_t temp = amt; \ + temp._resize(precision); \ + return mpz_cmp(MPZ(quantity), MPZ(temp.quantity)) OP 0; \ + } \ +} + +DEF_CMP_OPERATOR(<) +DEF_CMP_OPERATOR(<=) +DEF_CMP_OPERATOR(>) +DEF_CMP_OPERATOR(>=) +DEF_CMP_OPERATOR(==) amount_t::operator bool() const { if (quantity) { - assert(commodity); - mpz_t temp; - mpz_t divisor; - mpz_init_set(temp, MPZ(quantity)); - mpz_init(divisor); - mpz_ui_pow_ui(divisor, 10, MAX_PRECISION - commodity->precision); - mpz_tdiv_q(temp, temp, divisor); - bool zero = mpz_sgn(temp) == 0; - mpz_clear(divisor); - mpz_clear(temp); - return ! zero; + if (precision <= commodity->precision) { + return mpz_sgn(MPZ(quantity)) != 0; + } else { + assert(commodity); + mpz_t temp; + mpz_init_set(temp, MPZ(quantity)); + mpz_ui_pow_ui(divisor, 10, precision - commodity->precision); + mpz_tdiv_q(temp, temp, divisor); + bool zero = mpz_sgn(temp) == 0; + mpz_clear(temp); + return ! zero; + } } else { return false; } @@ -472,60 +478,44 @@ amount_t amount_t::value(const std::time_t moment) const amount_t& amount_t::operator*=(const amount_t& amt) { - if (! amt.quantity) + if (! amt.quantity || ! quantity) return *this; - if (! quantity) { - _init(); - commodity = amt.commodity; - } - mpz_mul(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); - mpz_tdiv_q(MPZ(quantity), MPZ(quantity), full_divisor); + precision += amt.precision; return *this; } amount_t& amount_t::operator/=(const amount_t& amt) { - if (! amt.quantity) + if (! quantity) return *this; - if (! quantity) { - _init(); - commodity = amt.commodity; - } + if (! amt.quantity) + throw amount_error("Divide by zero"); - mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); + // Increase the value's precision, to capture fractional parts after + // the divide. + mpz_ui_pow_ui(divisor, 10, amt.precision + 6); + mpz_mul(MPZ(quantity), MPZ(quantity), divisor); mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); + precision += 6; return *this; } -amount_t& amount_t::operator%=(const amount_t& amt) +amount_t amount_t::round(int prec) const { - if (! amt.quantity) - return *this; + if (prec == -1) + prec = commodity->precision; - if (! quantity) { - _init(); - commodity = amt.commodity; - } - - mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); - mpz_tdiv_r(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); - - return *this; -} - -amount_t amount_t::round(int precision) const -{ - if (! quantity) { + if (! quantity || precision <= prec) { return *this; } else { amount_t temp = *this; mpz_round(MPZ(temp.quantity), MPZ(temp.quantity), - precision == -1 ? commodity->precision : precision); + precision, prec == -1 ? commodity->precision : prec); return temp; } } @@ -535,7 +525,6 @@ std::ostream& operator<<(std::ostream& out, const amount_t& amt) mpz_t quotient; mpz_t rquotient; mpz_t remainder; - mpz_t divisor; if (! amt.quantity) return out; @@ -543,44 +532,45 @@ std::ostream& operator<<(std::ostream& out, const amount_t& amt) mpz_init(quotient); mpz_init(rquotient); mpz_init(remainder); - mpz_init(divisor); bool negative = false; // Ensure the value is rounded to the commodity's precision before // outputting it. NOTE: `rquotient' is used here as a temp variable! - if (amt.commodity->precision != MAX_PRECISION) - mpz_round(rquotient, MPZ(amt.quantity), amt.commodity->precision); - - mpz_tdiv_qr(quotient, remainder, rquotient, full_divisor); + if (amt.commodity->precision < amt.precision) { + mpz_round(rquotient, MPZ(amt.quantity), + amt.precision, amt.commodity->precision); + mpz_ui_pow_ui(divisor, 10, amt.precision - amt.commodity->precision); + mpz_tdiv_q(rquotient, rquotient, divisor); + mpz_ui_pow_ui(divisor, 10, amt.commodity->precision); + mpz_tdiv_qr(quotient, remainder, rquotient, divisor); + } + else if (amt.commodity->precision > amt.precision) { + mpz_ui_pow_ui(divisor, 10, amt.commodity->precision - amt.precision); + mpz_mul(rquotient, MPZ(amt.quantity), divisor); + mpz_ui_pow_ui(divisor, 10, amt.commodity->precision); + mpz_tdiv_qr(quotient, remainder, rquotient, divisor); + } + else if (amt.precision) { + mpz_ui_pow_ui(divisor, 10, amt.precision); + mpz_tdiv_qr(quotient, remainder, MPZ(amt.quantity), divisor); + } + else { + mpz_set(quotient, MPZ(amt.quantity)); + mpz_set_ui(remainder, 0); + } - if (mpz_sgn(quotient) < 0 || mpz_sgn(remainder) < 0) + if (mpz_sgn(quotient) < 0 || mpz_sgn(remainder) < 0) { negative = true; - mpz_abs(quotient, quotient); - mpz_abs(remainder, remainder); - - if (amt.commodity->precision == MAX_PRECISION) { - mpz_set(rquotient, remainder); - } else { - assert(MAX_PRECISION - amt.commodity->precision > 0); - mpz_ui_pow_ui(divisor, 10, MAX_PRECISION - amt.commodity->precision); - mpz_tdiv_qr(rquotient, remainder, remainder, divisor); + mpz_abs(quotient, quotient); + mpz_abs(remainder, remainder); } - - bool odd_chars_in_symbol = false; - - for (const char * p = amt.commodity->symbol.c_str(); - *p; - p++) - if (std::isspace(*p) || std::isdigit(*p) || *p == '-' || *p == '.') { - odd_chars_in_symbol = true; - break; - } + mpz_set(rquotient, remainder); if (! (amt.commodity->flags & COMMODITY_STYLE_SUFFIXED)) { - if (odd_chars_in_symbol) + if (amt.commodity->quote) out << "\"" << amt.commodity->symbol << "\""; else out << amt.commodity->symbol; @@ -636,16 +626,18 @@ std::ostream& operator<<(std::ostream& out, const amount_t& amt) mpz_clear(temp); } - out << ((amt.commodity->flags & COMMODITY_STYLE_EUROPEAN) ? ',' : '.'); + if (amt.commodity->precision) { + out << ((amt.commodity->flags & COMMODITY_STYLE_EUROPEAN) ? ',' : '.'); - out.width(amt.commodity->precision); - out.fill('0'); - out << rquotient; + out.width(amt.commodity->precision); + out.fill('0'); + out << rquotient; + } if (amt.commodity->flags & COMMODITY_STYLE_SUFFIXED) { if (amt.commodity->flags & COMMODITY_STYLE_SEPARATED) out << " "; - if (odd_chars_in_symbol) + if (amt.commodity->quote) out << "\"" << amt.commodity->symbol << "\""; else out << amt.commodity->symbol; @@ -654,7 +646,6 @@ std::ostream& operator<<(std::ostream& out, const amount_t& amt) mpz_clear(quotient); mpz_clear(rquotient); mpz_clear(remainder); - mpz_clear(divisor); return out; } @@ -703,8 +694,7 @@ void amount_t::parse(std::istream& in) std::string symbol; std::string quant; - unsigned int flags = COMMODITY_STYLE_DEFAULTS;; - unsigned int precision = MAX_PRECISION; + unsigned int flags = COMMODITY_STYLE_DEFAULTS;; if (! quantity) _init(); @@ -752,9 +742,7 @@ void amount_t::parse(std::istream& in) } else { precision = 0; - quant = quant + ".0"; } - assert(precision <= MAX_PRECISION); // Create the commodity if has not already been seen. commodity = commodity_t::find_commodity(symbol, true); @@ -766,24 +754,15 @@ void amount_t::parse(std::istream& in) // flags telling how to parse it. int len = quant.length(); - int buf_len = len + MAX_PRECISION; - char * buf = new char[buf_len]; + char * buf = new char[len + 1]; - std::memset(buf, '0', buf_len - 1); - std::strncpy(buf, quant.c_str(), len); + const char * p = quant.c_str(); + char * t = buf; - if (flags & COMMODITY_STYLE_THOUSANDS) - while (char * t = - std::strchr(buf, flags & COMMODITY_STYLE_EUROPEAN ? '.' : ',')) - do { *t = *(t + 1); } while (*(t++ + 1)); - - char * t = std::strchr(buf, flags & COMMODITY_STYLE_EUROPEAN ? ',' : '.'); - if (! t) - t = buf + len; - - for (int prec = 0; prec < MAX_PRECISION; prec++) { - *t = *(t + 1); - t++; + while (*p) { + if (*p == ',' || *p == '.') + p++; + *t++ = *p++; } *t = '\0'; @@ -812,13 +791,15 @@ void amount_t::write_quantity(std::ostream& out) const mpz_export(buf, &size, 1, sizeof(int), 0, 0, MPZ(quantity)); len = size * sizeof(int); #endif - assert(len); out.write((char *)&len, sizeof(len)); - out.write(buf, len); + if (len) { + out.write(buf, len); #ifndef WRITE_AMOUNTS_TEXTUALLY - char negative = mpz_sgn(MPZ(quantity)) < 0 ? 1 : 0; - out.write(&negative, sizeof(negative)); + char negative = mpz_sgn(MPZ(quantity)) < 0 ? 1 : 0; + out.write(&negative, sizeof(negative)); #endif + out.write((char *)&precision, sizeof(precision)); + } } else { len = 0; out.write((char *)&len, sizeof(len)); @@ -843,6 +824,7 @@ void amount_t::read_quantity(std::istream& in) if (negative) mpz_neg(MPZ(quantity), MPZ(quantity)); #endif + in.read((char *)&precision, sizeof(precision)); } else { if (quantity) _clear(); @@ -18,10 +18,12 @@ class amount_t void _init(); void _copy(const amount_t& amt); void _clear(); + void _resize(int prec); public: - base_type quantity; // amount, to MAX_PRECISION - commodity_t * commodity; + base_type quantity; // amount, to MAX_PRECISION + unsigned short precision; + commodity_t * commodity; bool valid() const { if (quantity) @@ -32,13 +34,15 @@ class amount_t // constructors amount_t(commodity_t * _commodity = NULL) - : quantity(NULL), commodity(_commodity) {} + : quantity(NULL), precision(0), commodity(_commodity) {} amount_t(const amount_t& amt) : quantity(NULL) { - if (amt.quantity) + if (amt.quantity) { _copy(amt); - else + } else { commodity = amt.commodity; + precision = amt.precision; + } } amount_t(const std::string& value) { parse(value); @@ -67,12 +71,11 @@ class amount_t amount_t& operator=(const double value); // general methods - amount_t round(int precision = -1) const; + amount_t round(int prec = -1) const; // in-place arithmetic amount_t& operator*=(const amount_t& amt); amount_t& operator/=(const amount_t& amt); - amount_t& operator%=(const amount_t& amt); amount_t& operator+=(const amount_t& amt); amount_t& operator-=(const amount_t& amt); @@ -87,11 +90,6 @@ class amount_t temp /= amt; return temp; } - amount_t operator%(const amount_t& amt) const { - amount_t temp = *this; - temp %= amt; - return temp; - } amount_t operator+(const amount_t& amt) const { amount_t temp = *this; temp += amt; @@ -209,6 +207,7 @@ class commodity_t typedef unsigned long ident_t; std::string symbol; + bool quote; std::string name; std::string note; unsigned short precision; @@ -244,9 +243,19 @@ class commodity_t // Now the per-object constructor and methods commodity_t(const std::string& _symbol = "", - unsigned int _precision = 2, + unsigned int _precision = 0, unsigned int _flags = COMMODITY_STYLE_DEFAULTS) - : symbol(_symbol), precision(_precision), flags(_flags) {} + : symbol(_symbol), quote(false), precision(_precision), flags(_flags) { + check_symbol(); + } + + void check_symbol() { + for (const char * p = symbol.c_str(); *p; p++) + if (std::isspace(*p) || std::isdigit(*p) || *p == '-' || *p == '.') { + quote = true; + return; + } + } void add_price(const std::time_t date, const amount_t& price) { history.insert(history_pair(date, price)); @@ -385,12 +385,10 @@ bool format_account::disp_subaccounts_p(const account_t * account, } bool format_account::display_account(const account_t * account, - const item_predicate<account_t>& disp_pred, - const bool even_top) + const item_predicate<account_t>& disp_pred) { - // Never display the master account, or an account that has already - // been displayed. - if (! (account->parent || even_top) || account->dflags & ACCOUNT_DISPLAYED) + // Never display an account that has already been displayed. + if (account->dflags & ACCOUNT_DISPLAYED) return false; // At this point, one of two possibilities exists: the account is a @@ -153,8 +153,7 @@ class format_account : public item_handler<account_t> } static bool display_account(const account_t * account, - const item_predicate<account_t>& disp_pred, - const bool even_top = false); + const item_predicate<account_t>& disp_pred); virtual void flush() { output_stream.flush(); @@ -162,8 +161,12 @@ class format_account : public item_handler<account_t> virtual void operator()(account_t * account) { if (display_account(account, disp_pred)) { - format.format_elements(output_stream, details_t(account)); - account->dflags |= ACCOUNT_DISPLAYED; + if (! account->parent) { + account->dflags |= ACCOUNT_TO_DISPLAY; + } else { + format.format_elements(output_stream, details_t(account)); + account->dflags |= ACCOUNT_DISPLAYED; + } } } }; @@ -162,12 +162,16 @@ static void dataHandler(void *userData, const char *s, int len) } case COMM_SYM: - if (curr_comm) + if (curr_comm) { curr_comm->symbol = std::string(s, len); - else if (curr_account) + curr_comm->check_symbol(); + } + else if (curr_account) { curr_account_comm = commodity_t::find_commodity(std::string(s, len)); - else if (curr_entry) + } + else if (curr_entry) { entry_comm = commodity_t::find_commodity(std::string(s, len)); + } break; case COMM_NAME: @@ -106,7 +106,8 @@ class entry_t }; -#define ACCOUNT_DISPLAYED 0x1 +#define ACCOUNT_DISPLAYED 0x1 +#define ACCOUNT_TO_DISPLAY 0x2 typedef std::map<const std::string, account_t *> accounts_map; typedef std::pair<const std::string, account_t *> accounts_pair; @@ -334,7 +334,7 @@ int main(int argc, char * argv[], char * envp[]) if (! config->show_subtotal) { if (! config->display_predicate.empty()) config->display_predicate += "&"; - config->display_predicate += "!l"; + config->display_predicate += "l<=1"; } } else if (command == "E") { @@ -591,9 +591,7 @@ int main(int argc, char * argv[], char * envp[]) journal->master->value = journal->master->total; - if (format_account::display_account(journal->master, - item_predicate<account_t>("T"), - true)) { + if (journal->master->dflags & ACCOUNT_TO_DISPLAY) { std::string end_format = "--------------------\n"; format.reset(end_format + f); format.format_elements(OUT(), details_t(journal->master)); @@ -154,8 +154,11 @@ bool finalize_entry(entry_t * entry) x != entry->transactions.end(); x++) if (! ((*x)->flags & TRANSACTION_VIRTUAL) || - ((*x)->flags & TRANSACTION_BALANCE)) + ((*x)->flags & TRANSACTION_BALANCE)) { + DEBUG_PRINT("ledger.textual.finalize", + "item cost is " << (*x)->cost); balance += (*x)->cost; + } // If one transaction of a two-line transaction is of a different // commodity than the others, and it has no per-unit price, @@ -210,6 +213,8 @@ bool finalize_entry(entry_t * entry) balance = 0; } + DEBUG_PRINT("ledger.textual.finalize", "balance is " << balance); + return ! balance; } @@ -171,7 +171,7 @@ void value_expr_t::compute(value_t& result, const details_t& details, case DEPTH: if (details.account) - result = (unsigned int) (details.account->depth - 1); + result = (unsigned int) details.account->depth; else result = 0U; break; |