From c47350dce9c666987f924c54507973fc11587b2e Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 21 Feb 2012 03:53:00 -0600 Subject: Corrected handling of nested definitions --- src/report.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index f4dc450e..38ae596a 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1559,6 +1559,10 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (is_eq(p, "query")) return WRAP_FUNCTOR(query_command); break; + case 's': + if (is_eq(p, "script")) + return WRAP_FUNCTOR(source_command); + break; case 't': if (is_eq(p, "template")) return WRAP_FUNCTOR(template_command); -- cgit v1.2.3 From 4a18317e7c35fea0aafdd99fec93adfea694743d Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 26 Feb 2012 02:16:09 -0600 Subject: Added --auto-match option, for use with 'convert' --- doc/ledger.1 | 3 ++- src/convert.cc | 6 ++++-- src/report.cc | 1 + src/report.h | 2 ++ test/baseline/opt-auto-match.test | 0 5 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 test/baseline/opt-auto-match.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index 5a3bd6db..9fe5c84c 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -1,4 +1,4 @@ -.Dd June 22, 2010 +.Dd February 26, 2012 .Dt ledger 1 .Sh NAME .Nm ledger @@ -270,6 +270,7 @@ transactions they are contained in. See the manual for more information. .It Fl \-amount-width Ar INT .It Fl \-anon .It Fl \-args-only +.It Fl \-auto-match .It Fl \-average Pq Fl A .It Fl \-balance-format Ar FMT .It Fl \-base diff --git a/src/convert.cc b/src/convert.cc index 493fbb7a..1ef3a413 100644 --- a/src/convert.cc +++ b/src/convert.cc @@ -123,8 +123,10 @@ value_t convert_command(call_scope_t& args) if (xact->posts.front()->account == NULL) { // jww (2010-03-07): Bind this logic to an option: --auto-match if (account_t * acct = - lookup_probable_account(xact->payee, current_xacts.rbegin(), - current_xacts.rend(), bucket).second) + (report.HANDLED(auto_match) ? + lookup_probable_account(xact->payee, current_xacts.rbegin(), + current_xacts.rend(), bucket).second : + NULL)) xact->posts.front()->account = acct; else xact->posts.front()->account = unknown; diff --git a/src/report.cc b/src/report.cc index 38ae596a..b3b7233f 100644 --- a/src/report.cc +++ b/src/report.cc @@ -966,6 +966,7 @@ option_t * report_t::lookup_option(const char * p) else OPT(amount_data); else OPT(anon); else OPT_ALT(color, ansi); + else OPT(auto_match); else OPT(average); else OPT(account_width_); else OPT(amount_width_); diff --git a/src/report.h b/src/report.h index 5b403205..a001ffb1 100644 --- a/src/report.h +++ b/src/report.h @@ -229,6 +229,7 @@ public: HANDLER(amount_).report(out); HANDLER(amount_data).report(out); HANDLER(anon).report(out); + HANDLER(auto_match).report(out); HANDLER(average).report(out); HANDLER(balance_format_).report(out); HANDLER(base).report(out); @@ -381,6 +382,7 @@ public: OPTION(report_t, amount_data); // -j OPTION(report_t, anon); + OPTION(report_t, auto_match); OPTION_(report_t, average, DO() { // -A parent->HANDLER(display_total_) diff --git a/test/baseline/opt-auto-match.test b/test/baseline/opt-auto-match.test new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3 From aa9b07d79bff00506b913d1e56575c3859fc173f Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 26 Feb 2012 15:45:15 -0600 Subject: Added --rich-data for 'convert', and SHA1 checksum checking --- doc/ledger.1 | 1 + src/convert.cc | 91 ++++++++-------------- src/csv.cc | 162 ++++++++++++++++++--------------------- src/csv.h | 37 +++++++-- src/item.cc | 2 +- src/journal.cc | 11 +++ src/journal.h | 3 + src/report.cc | 1 + src/report.h | 3 + src/textual.cc | 10 ++- src/utils.cc | 4 +- test/baseline/opt-rich-data.test | 0 12 files changed, 167 insertions(+), 158 deletions(-) create mode 100644 test/baseline/opt-rich-data.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index 9fe5c84c..21d43ead 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -397,6 +397,7 @@ appeared in the original journal file. .It Fl \-revalued .It Fl \-revalued-only .It Fl \-revalued-total Ar EXPR +.It Fl \-rich-data .It Fl \-seed Ar INT .It Fl \-script .It Fl \-sort Ar EXPR Pq Fl S diff --git a/src/convert.cc b/src/convert.cc index 1ef3a413..da4569cc 100644 --- a/src/convert.cc +++ b/src/convert.cc @@ -56,72 +56,41 @@ value_t convert_command(call_scope_t& args) account_t * bucket = journal.master->find_account(bucket_name); account_t * unknown = journal.master->find_account(_("Expenses:Unknown")); - // Make an amounts mapping for the account under consideration - - typedef std::map > post_map_t; - post_map_t post_map; - - xacts_iterator journal_iter(journal); - while (xact_t * xact = *journal_iter++) { - post_t * post = NULL; - xact_posts_iterator xact_iter(*xact); - while ((post = *xact_iter++) != NULL) { - if (post->account == bucket) - break; - } - if (post) { - post_map_t::iterator i = post_map.find(post->amount); - if (i == post_map.end()) { - std::list post_list; - post_list.push_back(post); - post_map.insert(post_map_t::value_type(post->amount, post_list)); - } else { - (*i).second.push_back(post); - } - } - } - // Create a flat list xacts_list current_xacts(journal.xacts_begin(), journal.xacts_end()); // Read in the series of transactions from the CSV file print_xacts formatter(report); - ifstream data(path(args.get(0))); - csv_reader reader(data); - - while (xact_t * xact = reader.read_xact(journal, bucket)) { - if (report.HANDLED(invert)) { - foreach (post_t * post, xact->posts) - post->amount.in_place_negate(); - } + path csv_file_path(args.get(0)); + ifstream data(csv_file_path); + csv_reader reader(data, csv_file_path); + + try { + while (xact_t * xact = reader.read_xact(journal, bucket, + report.HANDLED(rich_data))) { + if (report.HANDLED(invert)) { + foreach (post_t * post, xact->posts) + post->amount.in_place_negate(); + } - bool matched = false; - if (! xact->posts.front()->amount.is_null()) { - post_map_t::iterator i = post_map.find(- xact->posts.front()->amount); - if (i != post_map.end()) { - std::list& post_list((*i).second); - foreach (post_t * post, post_list) { - if (xact->code && post->xact->code && - *xact->code == *post->xact->code) { - matched = true; - break; - } - else if (xact->actual_date() == post->actual_date()) { - matched = true; - break; - } - } + string ref = (xact->has_tag(_("SHA1")) ? + xact->get_tag(_("SHA1"))->to_string() : + sha1sum(reader.get_last_line())); + + checksum_map_t::const_iterator entry = journal.checksum_map.find(ref); + if (entry != journal.checksum_map.end()) { + INFO(file_context(reader.get_pathname(), + reader.get_linenum()) + << "Ignoring known SHA1 " << ref); + checked_delete(xact); // ignore it + continue; } - } - if (matched) { - DEBUG("convert.csv", "Ignored xact with code: " << *xact->code); - checked_delete(xact); // ignore it - } - else { + if (report.HANDLED(rich_data) && ! xact->has_tag(_("SHA1"))) + xact->set_tag(_("SHA1"), string_value(ref)); + if (xact->posts.front()->account == NULL) { - // jww (2010-03-07): Bind this logic to an option: --auto-match if (account_t * acct = (report.HANDLED(auto_match) ? lookup_probable_account(xact->payee, current_xacts.rbegin(), @@ -143,8 +112,16 @@ value_t convert_command(call_scope_t& args) formatter(*post); } } + formatter.flush(); + } + catch (const std::exception&) { + add_error_context(_("While parsing file %1") + << file_context(reader.get_pathname(), + reader.get_linenum())); + add_error_context(_("While parsing CSV line:")); + add_error_context(line_context(reader.get_last_line())); + throw; } - formatter.flush(); // If not, transform the payee according to regexps diff --git a/src/csv.cc b/src/csv.cc index e2ba523d..c253f246 100644 --- a/src/csv.cc +++ b/src/csv.cc @@ -70,10 +70,12 @@ string csv_reader::read_field(std::istream& sin) else { while (sin.good() && ! sin.eof()) { sin.get(c); - if (c == ',') - break; - if (c != '\0') - field += c; + if (sin.good()) { + if (c == ',') + break; + if (c != '\0') + field += c; + } } } trim(field); @@ -82,8 +84,6 @@ string csv_reader::read_field(std::istream& sin) char * csv_reader::next_line(std::istream& sin) { - static char linebuf[MAX_LINE + 1]; - while (sin.good() && ! sin.eof() && sin.peek() == '#') sin.getline(linebuf, MAX_LINE); @@ -130,11 +130,13 @@ void csv_reader::read_index(std::istream& sin) } } -xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket) +xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket, + bool rich_data) { char * line = next_line(in); if (! line || index.empty()) return NULL; + linenum++; std::istringstream instr(line); @@ -144,20 +146,18 @@ xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket) xact->set_state(item_t::CLEARED); xact->pos = position_t(); - xact->pos->pathname = "jww (2010-03-05): unknown"; + xact->pos->pathname = pathname; xact->pos->beg_pos = in.tellg(); - xact->pos->beg_line = 0; - xact->pos->sequence = 0; + xact->pos->beg_line = linenum; + xact->pos->sequence = sequence++; post->xact = xact.get(); -#if 0 post->pos = position_t(); post->pos->pathname = pathname; - post->pos->beg_pos = line_beg_pos; + post->pos->beg_pos = in.tellg(); post->pos->beg_line = linenum; - post->pos->sequence = context.sequence++; -#endif + post->pos->sequence = sequence++; post->set_state(item_t::CLEARED); post->account = NULL; @@ -167,88 +167,80 @@ xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket) string total; string field; - try { - while (instr.good() && ! instr.eof()) { - field = read_field(instr); + while (instr.good() && ! instr.eof()) { + field = read_field(instr); - switch (index[n]) { - case FIELD_DATE: - xact->_date = parse_date(field); - break; + switch (index[n]) { + case FIELD_DATE: + xact->_date = parse_date(field); + break; - case FIELD_DATE_EFF: - xact->_date_eff = parse_date(field); - break; + case FIELD_DATE_EFF: + xact->_date_eff = parse_date(field); + break; - case FIELD_CODE: - if (! field.empty()) - xact->code = field; - break; + case FIELD_CODE: + if (! field.empty()) + xact->code = field; + break; - case FIELD_PAYEE: { - bool found = false; - foreach (payee_mapping_t& value, journal.payee_mappings) { - DEBUG("csv.mappings", "Looking for payee mapping: " << value.first); - if (value.first.match(field)) { - xact->payee = value.second; - found = true; - break; - } + case FIELD_PAYEE: { + bool found = false; + foreach (payee_mapping_t& value, journal.payee_mappings) { + DEBUG("csv.mappings", "Looking for payee mapping: " << value.first); + if (value.first.match(field)) { + xact->payee = value.second; + found = true; + break; } - if (! found) - xact->payee = field; - break; } + if (! found) + xact->payee = field; + break; + } - case FIELD_AMOUNT: { - std::istringstream amount_str(field); - amt.parse(amount_str, PARSE_NO_REDUCE); - if (! amt.has_commodity() && - commodity_pool_t::current_pool->default_commodity) - amt.set_commodity(*commodity_pool_t::current_pool->default_commodity); - post->amount = amt; - break; - } + case FIELD_AMOUNT: { + std::istringstream amount_str(field); + amt.parse(amount_str, PARSE_NO_REDUCE); + if (! amt.has_commodity() && + commodity_pool_t::current_pool->default_commodity) + amt.set_commodity(*commodity_pool_t::current_pool->default_commodity); + post->amount = amt; + break; + } - case FIELD_COST: { - std::istringstream amount_str(field); - amt.parse(amount_str, PARSE_NO_REDUCE); - if (! amt.has_commodity() && - commodity_pool_t::current_pool->default_commodity) - amt.set_commodity - (*commodity_pool_t::current_pool->default_commodity); - post->cost = amt; - break; - } + case FIELD_COST: { + std::istringstream amount_str(field); + amt.parse(amount_str, PARSE_NO_REDUCE); + if (! amt.has_commodity() && + commodity_pool_t::current_pool->default_commodity) + amt.set_commodity + (*commodity_pool_t::current_pool->default_commodity); + post->cost = amt; + break; + } - case FIELD_TOTAL: - total = field; - break; + case FIELD_TOTAL: + total = field; + break; - case FIELD_NOTE: - xact->note = field; - break; + case FIELD_NOTE: + xact->note = field; + break; - case FIELD_UNKNOWN: - if (! names[n].empty() && ! field.empty()) - xact->set_tag(names[n], string_value(field)); - break; - } - n++; + case FIELD_UNKNOWN: + if (! names[n].empty() && ! field.empty()) + xact->set_tag(names[n], string_value(field)); + break; } - } - catch (const std::exception&) { - add_error_context(_("While parsing CSV field:")); - add_error_context(line_context(field)); - throw; + n++; } -#if 0 - xact->set_tag(_("Imported"), - string(format_date(CURRENT_DATE(), FMT_WRITTEN))); - xact->set_tag(_("Original"), string(line)); - xact->set_tag(_("SHA1"), string(sha1sum(line))); -#endif + if (rich_data) { + xact->set_tag(_("Imported"), + string_value(format_date(CURRENT_DATE(), FMT_WRITTEN))); + xact->set_tag(_("CSV"), string_value(line)); + } // Translate the account name, if we have enough information to do so @@ -267,13 +259,11 @@ xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket) post->xact = xact.get(); -#if 0 post->pos = position_t(); post->pos->pathname = pathname; - post->pos->beg_pos = line_beg_pos; + post->pos->beg_pos = in.tellg(); post->pos->beg_line = linenum; - post->pos->sequence = context.sequence++; -#endif + post->pos->sequence = sequence++; post->set_state(item_t::CLEARED); post->account = bucket; diff --git a/src/csv.h b/src/csv.h index 5ff8b59e..cf350e9d 100644 --- a/src/csv.h +++ b/src/csv.h @@ -52,9 +52,13 @@ class account_t; class csv_reader { - static const std::size_t MAX_LINE = 1024; + static const std::size_t MAX_LINE = 4096; std::istream& in; + path pathname; + char linebuf[MAX_LINE]; + std::size_t linenum; + std::size_t sequence; enum headers_t { FIELD_DATE = 0, @@ -80,13 +84,11 @@ class csv_reader std::vector index; std::vector names; - std::vector fields; - - typedef std::map string_map; public: - csv_reader(std::istream& _in) - : in(_in), + csv_reader(std::istream& _in, const path& _pathname) + : in(_in), pathname(_pathname), + linenum(0), sequence(0), date_mask("date"), date_eff_mask("posted( ?date)?"), code_mask("code"), @@ -98,11 +100,30 @@ public: read_index(in); } + void read_index(std::istream& in); string read_field(std::istream& in); char * next_line(std::istream& in); - void read_index(std::istream& in); - xact_t * read_xact(journal_t& journal, account_t * bucket); + xact_t * read_xact(journal_t& journal, account_t * bucket, bool rich_data); + + const char * get_last_line() const { + return linebuf; + } + + path get_pathname() const { + return pathname; + } + std::size_t get_linenum() const { + return linenum; + } + + void reset() { + pathname.clear(); + index.clear(); + names.clear(); + linenum = 0; + sequence = 0; + } }; } // namespace ledger diff --git a/src/item.cc b/src/item.cc index 056aa04c..7184c0ef 100644 --- a/src/item.cc +++ b/src/item.cc @@ -72,7 +72,7 @@ bool item_t::has_tag(const mask_t& tag_mask, return false; } - optional item_t::get_tag(const string& tag, bool) const +optional item_t::get_tag(const string& tag, bool) const { DEBUG("item.meta", "Getting item tag: " << tag); if (metadata) { diff --git a/src/journal.cc b/src/journal.cc index 0691954f..bbfa205c 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -107,6 +107,17 @@ account_t * journal_t::find_account_re(const string& regexp) bool journal_t::add_xact(xact_t * xact) { + if (optional ref = xact->get_tag(_("SHA1"))) { + std::pair result + = checksum_map.insert(checksum_map_t::value_type(ref->to_string(), xact)); + if (! result.second) { + throw_(std::runtime_error, + _("Found duplicated transaction with SHA1: ") + << ref->to_string()); + return false; + } + } + xact->journal = this; if (! xact->finalize()) { diff --git a/src/journal.h b/src/journal.h index ca6b6e4f..49a6292b 100644 --- a/src/journal.h +++ b/src/journal.h @@ -63,6 +63,7 @@ typedef std::pair payee_mapping_t; typedef std::list payee_mappings_t; typedef std::pair account_mapping_t; typedef std::list account_mappings_t; +typedef std::map checksum_map_t; class journal_t : public noncopyable { @@ -117,6 +118,7 @@ public: std::list sources; payee_mappings_t payee_mappings; account_mappings_t account_mappings; + checksum_map_t checksum_map; bool was_loaded; journal_t(); @@ -198,6 +200,7 @@ private: ar & sources; ar & payee_mappings; ar & account_mappings; + ar & checksum_map; } #endif // HAVE_BOOST_SERIALIZATION }; diff --git a/src/report.cc b/src/report.cc index b3b7233f..c562ab38 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1094,6 +1094,7 @@ option_t * report_t::lookup_option(const char * p) else OPT(revalued); else OPT(revalued_only); else OPT(revalued_total_); + else OPT(rich_data); break; case 's': OPT(sort_); diff --git a/src/report.h b/src/report.h index a001ffb1..565728df 100644 --- a/src/report.h +++ b/src/report.h @@ -313,6 +313,7 @@ public: HANDLER(revalued).report(out); HANDLER(revalued_only).report(out); HANDLER(revalued_total_).report(out); + HANDLER(rich_data).report(out); HANDLER(seed_).report(out); HANDLER(sort_).report(out); HANDLER(sort_all_).report(out); @@ -893,6 +894,8 @@ public: set_expr(args.get(0), args.get(1)); }); + OPTION(report_t, rich_data); + OPTION(report_t, seed_); OPTION_(report_t, sort_, DO_(args) { // -S diff --git a/src/textual.cc b/src/textual.cc index ddbd9943..13032236 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -1150,8 +1150,9 @@ post_t * instance_t::parse_post(char * line, if (context.strict && ! post->account->has_flags(ACCOUNT_KNOWN)) { if (post->_state == item_t::UNCLEARED) - warning_(_("\"%1\", line %2: Unknown account '%3'") - << pathname.string() << linenum << post->account->fullname()); + warning_(_("%1Unknown account '%2'") + << file_context(pathname, linenum) + << post->account->fullname()); post->account->add_flags(ACCOUNT_KNOWN); } @@ -1181,8 +1182,9 @@ post_t * instance_t::parse_post(char * line, if (context.strict && ! post->amount.commodity().has_flags(COMMODITY_KNOWN)) { if (post->_state == item_t::UNCLEARED) - warning_(_("\"%1\", line %2: Unknown commodity '%3'") - << pathname.string() << linenum << post->amount.commodity()); + warning_(_("%1Unknown commodity '%2'") + << file_context(pathname, linenum) + << post->amount.commodity()); post->amount.commodity().add_flags(COMMODITY_KNOWN); } diff --git a/src/utils.cc b/src/utils.cc index 42600db3..2f64bb0a 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -50,8 +50,8 @@ void debug_assert(const string& reason, std::size_t line) { std::ostringstream buf; - buf << "Assertion failed in \"" << file << "\", line " << line - << ": " << func << ": " << reason; + buf << "Assertion failed in " << file_context(file, line) + << func << ": " << reason; throw assertion_failed(buf.str()); } diff --git a/test/baseline/opt-rich-data.test b/test/baseline/opt-rich-data.test new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3 From 656e46e1823ce00285f08f72d8473a58f9bd561a Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 28 Feb 2012 03:02:16 -0600 Subject: Renamed actual/effective dates to primary/auxiliary --- doc/ledger.1 | 6 +++--- src/csv.cc | 8 ++++---- src/csv.h | 6 +++--- src/generate.cc | 10 +++++----- src/generate.h | 2 +- src/item.cc | 22 +++++++++++++--------- src/item.h | 20 ++++++++++---------- src/post.cc | 24 ++++++++++++------------ src/post.h | 6 +++--- src/print.cc | 8 ++++---- src/py_item.cc | 10 +++++----- src/py_post.cc | 2 +- src/report.cc | 9 ++++----- src/report.h | 10 +++++----- src/textual.cc | 2 +- src/xact.cc | 6 +++--- test/baseline/opt-actual-dates.test | 0 test/baseline/opt-aux-date.test | 20 ++++++++++++++++++++ test/baseline/opt-effective.test | 20 -------------------- test/baseline/opt-primary-date.test | 0 20 files changed, 97 insertions(+), 94 deletions(-) delete mode 100644 test/baseline/opt-actual-dates.test create mode 100644 test/baseline/opt-aux-date.test delete mode 100644 test/baseline/opt-effective.test create mode 100644 test/baseline/opt-primary-date.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index 656a3866..4829034f 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -1,4 +1,4 @@ -.Dd February 27, 2012 +.Dd February 28, 2012 .Dt ledger 1 .Sh NAME .Nm ledger @@ -263,7 +263,6 @@ transactions they are contained in. See the manual for more information. .It Fl \-account Ar STR .It Fl \-account-width Ar INT .It Fl \-actual Pq Fl L -.It Fl \-actual-dates .It Fl \-add-budget .It Fl \-amount Ar EXPR Pq Fl t .It Fl \-amount-data Pq Fl j @@ -271,6 +270,7 @@ transactions they are contained in. See the manual for more information. .It Fl \-anon .It Fl \-args-only .It Fl \-auto-match +.It Fl \-aux-date .It Fl \-average Pq Fl A .It Fl \-balance-format Ar FMT .It Fl \-base @@ -308,7 +308,6 @@ See .It Fl \-display-total Ar EXPR .It Fl \-dow .It Fl \-download -.It Fl \-effective .It Fl \-empty Pq Fl E .It Fl \-end Pq Fl e .It Fl \-equity @@ -387,6 +386,7 @@ See .Fl \-leeway . .It Fl \-prices-format Ar FMT .It Fl \-pricedb-format Ar FMT +.It Fl \-primary-date .It Fl \-quantity Pq Fl O .It Fl \-quarterly .It Fl \-raw diff --git a/src/csv.cc b/src/csv.cc index c253f246..82c28ff3 100644 --- a/src/csv.cc +++ b/src/csv.cc @@ -109,8 +109,8 @@ void csv_reader::read_index(std::istream& sin) if (date_mask.match(field)) index.push_back(FIELD_DATE); - else if (date_eff_mask.match(field)) - index.push_back(FIELD_DATE_EFF); + else if (date_aux_mask.match(field)) + index.push_back(FIELD_DATE_AUX); else if (code_mask.match(field)) index.push_back(FIELD_CODE); else if (payee_mask.match(field)) @@ -175,8 +175,8 @@ xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket, xact->_date = parse_date(field); break; - case FIELD_DATE_EFF: - xact->_date_eff = parse_date(field); + case FIELD_DATE_AUX: + xact->_date_aux = parse_date(field); break; case FIELD_CODE: diff --git a/src/csv.h b/src/csv.h index cf350e9d..909439ff 100644 --- a/src/csv.h +++ b/src/csv.h @@ -62,7 +62,7 @@ class csv_reader enum headers_t { FIELD_DATE = 0, - FIELD_DATE_EFF, + FIELD_DATE_AUX, FIELD_CODE, FIELD_PAYEE, FIELD_AMOUNT, @@ -74,7 +74,7 @@ class csv_reader }; mask_t date_mask; - mask_t date_eff_mask; + mask_t date_aux_mask; mask_t code_mask; mask_t payee_mask; mask_t amount_mask; @@ -90,7 +90,7 @@ public: : in(_in), pathname(_pathname), linenum(0), sequence(0), date_mask("date"), - date_eff_mask("posted( ?date)?"), + date_aux_mask("posted( ?date)?"), code_mask("code"), payee_mask("(payee|desc(ription)?|title)"), amount_mask("amount"), diff --git a/src/generate.cc b/src/generate.cc index 185e23e7..963cd845 100644 --- a/src/generate.cc +++ b/src/generate.cc @@ -69,9 +69,9 @@ generate_posts_iterator::generate_posts_iterator generate_date(next_date_buf); next_date = parse_date(next_date_buf.str()); - std::ostringstream next_eff_date_buf; - generate_date(next_eff_date_buf); - next_eff_date = parse_date(next_eff_date_buf.str()); + std::ostringstream next_aux_date_buf; + generate_date(next_aux_date_buf); + next_aux_date = parse_date(next_aux_date_buf.str()); } @@ -326,8 +326,8 @@ void generate_posts_iterator::generate_xact(std::ostream& out) next_date += gregorian::days(six_gen()); if (truth_gen()) { out << '='; - out << format_date(next_eff_date, FMT_WRITTEN); - next_eff_date += gregorian::days(six_gen()); + out << format_date(next_aux_date, FMT_WRITTEN); + next_aux_date += gregorian::days(six_gen()); } out << ' '; diff --git a/src/generate.h b/src/generate.h index 47abcd94..abf719d4 100644 --- a/src/generate.h +++ b/src/generate.h @@ -57,7 +57,7 @@ class generate_posts_iterator std::size_t quantity; bool allow_invalid; date_t next_date; - date_t next_eff_date; + date_t next_aux_date; mt19937 rnd_gen; diff --git a/src/item.cc b/src/item.cc index 97411512..653013ea 100644 --- a/src/item.cc +++ b/src/item.cc @@ -35,7 +35,7 @@ namespace ledger { -bool item_t::use_effective_date = false; +bool item_t::use_aux_date = false; bool item_t::has_tag(const string& tag, bool) const { @@ -150,7 +150,7 @@ void item_t::parse_tags(const char * p, if (char * pp = std::strchr(buf, '=')) { *pp++ = '\0'; - _date_eff = parse_date(pp); + _date_aux = parse_date(pp); } if (buf[0]) _date = parse_date(buf); @@ -239,12 +239,12 @@ namespace { value_t get_date(item_t& item) { return item.date(); } - value_t get_actual_date(item_t& item) { - return item.actual_date(); + value_t get_primary_date(item_t& item) { + return item.primary_date(); } - value_t get_effective_date(item_t& item) { - if (optional effective = item.effective_date()) - return *effective; + value_t get_aux_date(item_t& item) { + if (optional aux_date = item.aux_date()) + return *aux_date; return NULL_VALUE; } value_t get_note(item_t& item) { @@ -403,9 +403,11 @@ expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind, if (name == "actual") return WRAP_FUNCTOR(get_wrapper<&get_actual>); else if (name == "actual_date") - return WRAP_FUNCTOR(get_wrapper<&get_actual_date>); + return WRAP_FUNCTOR(get_wrapper<&get_primary_date>); else if (name == "addr") return WRAP_FUNCTOR(get_wrapper<&get_addr>); + else if (name == "auxiliary_date") + return WRAP_FUNCTOR(get_wrapper<&get_aux_date>); break; case 'b': @@ -435,7 +437,7 @@ expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind, else if (name == "end_pos") return WRAP_FUNCTOR(get_wrapper<&get_end_pos>); else if (name == "effective_date") - return WRAP_FUNCTOR(get_wrapper<&get_effective_date>); + return WRAP_FUNCTOR(get_wrapper<&get_aux_date>); break; case 'f': @@ -472,6 +474,8 @@ expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind, return WRAP_FUNCTOR(get_wrapper<&get_pending>); else if (name == "parent") return WRAP_FUNCTOR(get_wrapper<&ignore>); + else if (name == "primary_date") + return WRAP_FUNCTOR(get_wrapper<&get_primary_date>); break; case 's': diff --git a/src/item.h b/src/item.h index 908dd1b8..62575d8b 100644 --- a/src/item.h +++ b/src/item.h @@ -112,7 +112,7 @@ public: state_t _state; optional _date; - optional _date_eff; + optional _date_aux; optional note; optional pos; optional metadata; @@ -138,7 +138,7 @@ public: set_state(item.state()); _date = item._date; - _date_eff = item._date_eff; + _date_aux = item._date_aux; note = item.note; pos = item.pos; metadata = item.metadata; @@ -175,7 +175,7 @@ public: scope_t& scope, bool overwrite_existing = true); - static bool use_effective_date; + static bool use_aux_date; virtual bool has_date() const { return _date; @@ -183,17 +183,17 @@ public: virtual date_t date() const { assert(_date); - if (use_effective_date) - if (optional effective = effective_date()) - return *effective; + if (use_aux_date) + if (optional aux = aux_date()) + return *aux; return *_date; } - virtual date_t actual_date() const { + virtual date_t primary_date() const { assert(_date); return *_date; } - virtual optional effective_date() const { - return _date_eff; + virtual optional aux_date() const { + return _date_aux; } void set_state(state_t new_state) { @@ -220,7 +220,7 @@ private: ar & boost::serialization::base_object(*this); ar & _state; ar & _date; - ar & _date_eff; + ar & _date_aux; ar & note; ar & pos; ar & metadata; diff --git a/src/post.cc b/src/post.cc index d88dd869..125947e4 100644 --- a/src/post.cc +++ b/src/post.cc @@ -91,11 +91,11 @@ date_t post_t::date() const if (xdata_ && is_valid(xdata_->date)) return xdata_->date; - if (item_t::use_effective_date) { - if (_date_eff) - return *_date_eff; - else if (xact && xact->_date_eff) - return *xact->_date_eff; + if (item_t::use_aux_date) { + if (_date_aux) + return *_date_aux; + else if (xact && xact->_date_aux) + return *xact->_date_aux; } if (! _date) { @@ -105,7 +105,7 @@ date_t post_t::date() const return *_date; } -date_t post_t::actual_date() const +date_t post_t::primary_date() const { if (xdata_ && is_valid(xdata_->date)) return xdata_->date; @@ -117,11 +117,11 @@ date_t post_t::actual_date() const return *_date; } -optional post_t::effective_date() const +optional post_t::aux_date() const { - optional date = item_t::effective_date(); + optional date = item_t::aux_date(); if (! date && xact) - return xact->effective_date(); + return xact->aux_date(); return date; } @@ -657,9 +657,9 @@ void to_xml(std::ostream& out, const post_t& post) push_xml y(out, "date"); to_xml(out, *post._date, false); } - if (post._date_eff) { - push_xml y(out, "effective-date"); - to_xml(out, *post._date_eff, false); + if (post._date_aux) { + push_xml y(out, "aux-date"); + to_xml(out, *post._date_aux, false); } if (post.account) { diff --git a/src/post.h b/src/post.h index e626bca1..0cfd3e90 100644 --- a/src/post.h +++ b/src/post.h @@ -123,8 +123,8 @@ public: virtual date_t value_date() const; virtual date_t date() const; - virtual date_t actual_date() const; - virtual optional effective_date() const; + virtual date_t primary_date() const; + virtual optional aux_date() const; string payee() const; @@ -230,7 +230,7 @@ public: { bool operator()(const post_t * left, const post_t * right) const { gregorian::date_duration duration = - left->actual_date() - right->actual_date(); + left->primary_date() - right->primary_date(); if (duration.days() == 0) { return ((left->pos ? left->pos->sequence : 0) < (right->pos ? right->pos->sequence : 0)); diff --git a/src/print.cc b/src/print.cc index 56a2ec7b..63f38d80 100644 --- a/src/print.cc +++ b/src/print.cc @@ -112,11 +112,11 @@ namespace { std::ostringstream buf; - buf << format_date(item_t::use_effective_date ? - xact.date() : xact.actual_date(), + buf << format_date(item_t::use_aux_date ? + xact.date() : xact.primary_date(), format_type, format); - if (! item_t::use_effective_date && xact.effective_date()) - buf << '=' << format_date(*xact.effective_date(), + if (! item_t::use_aux_date && xact.aux_date()) + buf << '=' << format_date(*xact.aux_date(), format_type, format); buf << ' '; diff --git a/src/py_item.cc b/src/py_item.cc index 51d9e50c..361de914 100644 --- a/src/py_item.cc +++ b/src/py_item.cc @@ -149,13 +149,13 @@ void export_item() .def("parse_tags", &item_t::parse_tags) .def("append_note", &item_t::append_note) - .add_static_property("use_effective_date", - make_getter(&item_t::use_effective_date), - make_setter(&item_t::use_effective_date)) + .add_static_property("use_auxiliary_date", + make_getter(&item_t::use_aux_date), + make_setter(&item_t::use_aux_date)) .add_property("date", &item_t::date, make_setter(&item_t::_date)) - .add_property("effective_date", &item_t::effective_date, - make_setter(&item_t::_date_eff)) + .add_property("auxiliary_date", &item_t::aux_date, + make_setter(&item_t::_date_aux)) .add_property("state", &item_t::state, &item_t::set_state) diff --git a/src/py_post.cc b/src/py_post.cc index 62323eb1..cb6ebce7 100644 --- a/src/py_post.cc +++ b/src/py_post.cc @@ -160,7 +160,7 @@ void export_post() .def("get_tag", py_get_tag_2m) .def("date", &post_t::date) - .def("effective_date", &post_t::effective_date) + .def("auxiliary_date", &post_t::aux_date) .def("must_balance", &post_t::must_balance) diff --git a/src/report.cc b/src/report.cc index c562ab38..530e7727 100644 --- a/src/report.cc +++ b/src/report.cc @@ -76,8 +76,7 @@ void report_t::normalize_options(const string& verb) HANDLER(pager_).off(); } - item_t::use_effective_date = (HANDLED(effective) && - ! HANDLED(actual_dates)); + item_t::use_aux_date = (HANDLED(aux_date) && ! HANDLED(primary_date)); commodity_pool_t::current_pool->keep_base = HANDLED(base); commodity_pool_t::current_pool->get_quotes = session.HANDLED(download); @@ -960,10 +959,10 @@ option_t * report_t::lookup_option(const char * p) OPT(abbrev_len_); else OPT_(account_); else OPT(actual); - else OPT(actual_dates); else OPT(add_budget); else OPT(amount_); else OPT(amount_data); + else OPT_ALT(primary_date, actual_dates); else OPT(anon); else OPT_ALT(color, ansi); else OPT(auto_match); @@ -1005,12 +1004,12 @@ option_t * report_t::lookup_option(const char * p) else OPT(date_width_); break; case 'e': - OPT(effective); - else OPT(empty); + OPT(empty); else OPT_(end_); else OPT(equity); else OPT(exact); else OPT(exchange_); + else OPT_ALT(aux_date, effective); break; case 'f': OPT(flat); diff --git a/src/report.h b/src/report.h index 565728df..2b521aae 100644 --- a/src/report.h +++ b/src/report.h @@ -224,12 +224,12 @@ public: HANDLER(abbrev_len_).report(out); HANDLER(account_).report(out); HANDLER(actual).report(out); - HANDLER(actual_dates).report(out); HANDLER(add_budget).report(out); HANDLER(amount_).report(out); HANDLER(amount_data).report(out); HANDLER(anon).report(out); HANDLER(auto_match).report(out); + HANDLER(aux_date).report(out); HANDLER(average).report(out); HANDLER(balance_format_).report(out); HANDLER(base).report(out); @@ -256,7 +256,6 @@ public: HANDLER(display_amount_).report(out); HANDLER(display_total_).report(out); HANDLER(dow).report(out); - HANDLER(effective).report(out); HANDLER(empty).report(out); HANDLER(end_).report(out); HANDLER(equity).report(out); @@ -303,6 +302,7 @@ public: HANDLER(price).report(out); HANDLER(prices_format_).report(out); HANDLER(pricedb_format_).report(out); + HANDLER(primary_date).report(out); HANDLER(quantity).report(out); HANDLER(quarterly).report(out); HANDLER(raw).report(out); @@ -361,8 +361,6 @@ public: parent->HANDLER(limit_).on(string("--actual"), "actual"); }); - OPTION(report_t, actual_dates); - OPTION_(report_t, add_budget, DO() { parent->budget_flags |= BUDGET_BUDGETED | BUDGET_UNBUDGETED; }); @@ -571,7 +569,7 @@ public: }); OPTION(report_t, dow); - OPTION(report_t, effective); + OPTION(report_t, aux_date); OPTION(report_t, empty); // -E OPTION_(report_t, end_, DO_(args) { // -e @@ -822,6 +820,8 @@ public: "P %(datetime) %(display_account) %(scrub(display_amount))\n"); }); + OPTION(report_t, primary_date); + OPTION_(report_t, quantity, DO() { // -O parent->HANDLER(revalued).off(); parent->HANDLER(amount_).set_expr(string("--quantity"), "amount"); diff --git a/src/textual.cc b/src/textual.cc index 739b63f0..4de8d461 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -1603,7 +1603,7 @@ xact_t * instance_t::parse_xact(char * line, if (char * p = std::strchr(line, '=')) { *p++ = '\0'; - xact->_date_eff = parse_date(p); + xact->_date_aux = parse_date(p); } xact->_date = parse_date(line); diff --git a/src/xact.cc b/src/xact.cc index 6c07c862..8e1951a5 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -794,9 +794,9 @@ void to_xml(std::ostream& out, const xact_t& xact) push_xml y(out, "date"); to_xml(out, *xact._date, false); } - if (xact._date_eff) { - push_xml y(out, "effective-date"); - to_xml(out, *xact._date_eff, false); + if (xact._date_aux) { + push_xml y(out, "aux-date"); + to_xml(out, *xact._date_aux, false); } if (xact.code) { diff --git a/test/baseline/opt-actual-dates.test b/test/baseline/opt-actual-dates.test deleted file mode 100644 index e69de29b..00000000 diff --git a/test/baseline/opt-aux-date.test b/test/baseline/opt-aux-date.test new file mode 100644 index 00000000..9d1e73d0 --- /dev/null +++ b/test/baseline/opt-aux-date.test @@ -0,0 +1,20 @@ +2008/01/01 January + Expenses:Books $10.00 + Assets:Cash + +2008/01/31=2008/01/01 End of January + Expenses:Books $10.00 ; [=2008/02/01] + Assets:Cash + +2008/02/01 February + Expenses:Books $20.00 + Assets:Cash + +test reg --effective +08-Jan-01 January Expenses:Books $10.00 $10.00 + Assets:Cash $-10.00 0 +08-Feb-01 End of January Expenses:Books $10.00 $10.00 +08-Jan-01 End of January Assets:Cash $-10.00 0 +08-Feb-01 February Expenses:Books $20.00 $20.00 + Assets:Cash $-20.00 0 +end test diff --git a/test/baseline/opt-effective.test b/test/baseline/opt-effective.test deleted file mode 100644 index 9d1e73d0..00000000 --- a/test/baseline/opt-effective.test +++ /dev/null @@ -1,20 +0,0 @@ -2008/01/01 January - Expenses:Books $10.00 - Assets:Cash - -2008/01/31=2008/01/01 End of January - Expenses:Books $10.00 ; [=2008/02/01] - Assets:Cash - -2008/02/01 February - Expenses:Books $20.00 - Assets:Cash - -test reg --effective -08-Jan-01 January Expenses:Books $10.00 $10.00 - Assets:Cash $-10.00 0 -08-Feb-01 End of January Expenses:Books $10.00 $10.00 -08-Jan-01 End of January Assets:Cash $-10.00 0 -08-Feb-01 February Expenses:Books $20.00 $20.00 - Assets:Cash $-20.00 0 -end test diff --git a/test/baseline/opt-primary-date.test b/test/baseline/opt-primary-date.test new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3 From e2afc783db0dff1927b00dc506390353d9e3bbd2 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 29 Feb 2012 22:32:23 -0600 Subject: Increased file copyrights to 2012 --- src/account.cc | 2 +- src/account.h | 2 +- src/accum.cc | 2 +- src/accum.h | 2 +- src/amount.cc | 2 +- src/amount.h | 2 +- src/annotate.cc | 2 +- src/annotate.h | 2 +- src/archive.cc | 2 +- src/archive.h | 2 +- src/balance.cc | 2 +- src/balance.h | 2 +- src/chain.cc | 2 +- src/chain.h | 2 +- src/commodity.cc | 2 +- src/commodity.h | 2 +- src/compare.cc | 2 +- src/compare.h | 2 +- src/convert.cc | 2 +- src/convert.h | 2 +- src/csv.cc | 2 +- src/csv.h | 2 +- src/draft.cc | 2 +- src/draft.h | 2 +- src/emacs.cc | 2 +- src/emacs.h | 2 +- src/error.cc | 2 +- src/error.h | 2 +- src/expr.cc | 2 +- src/expr.h | 2 +- src/exprbase.h | 2 +- src/filters.cc | 2 +- src/filters.h | 2 +- src/flags.h | 2 +- src/format.cc | 2 +- src/format.h | 2 +- src/generate.cc | 2 +- src/generate.h | 2 +- src/global.cc | 2 +- src/global.h | 4 ++-- src/item.cc | 2 +- src/item.h | 2 +- src/iterators.cc | 2 +- src/iterators.h | 2 +- src/journal.cc | 2 +- src/journal.h | 2 +- src/lookup.cc | 2 +- src/lookup.h | 2 +- src/main.cc | 2 +- src/mask.cc | 2 +- src/mask.h | 2 +- src/op.cc | 2 +- src/op.h | 2 +- src/option.cc | 2 +- src/option.h | 2 +- src/org.cc | 2 +- src/org.h | 2 +- src/output.cc | 2 +- src/output.h | 2 +- src/parser.cc | 2 +- src/parser.h | 2 +- src/pool.cc | 2 +- src/pool.h | 2 +- src/post.cc | 2 +- src/post.h | 2 +- src/precmd.cc | 2 +- src/precmd.h | 2 +- src/predicate.cc | 2 +- src/predicate.h | 2 +- src/print.cc | 2 +- src/print.h | 2 +- src/pstream.h | 2 +- src/py_account.cc | 2 +- src/py_amount.cc | 2 +- src/py_balance.cc | 2 +- src/py_commodity.cc | 2 +- src/py_expr.cc | 2 +- src/py_format.cc | 2 +- src/py_item.cc | 2 +- src/py_journal.cc | 2 +- src/py_post.cc | 2 +- src/py_times.cc | 2 +- src/py_utils.cc | 2 +- src/py_value.cc | 2 +- src/py_xact.cc | 2 +- src/pyfstream.h | 2 +- src/pyinterp.cc | 2 +- src/pyinterp.h | 2 +- src/pyledger.cc | 2 +- src/pyutils.h | 2 +- src/query.cc | 2 +- src/query.h | 2 +- src/quotes.cc | 2 +- src/quotes.h | 2 +- src/report.cc | 2 +- src/report.h | 2 +- src/scope.cc | 2 +- src/scope.h | 2 +- src/series.h | 2 +- src/session.cc | 2 +- src/session.h | 2 +- src/stats.cc | 2 +- src/stats.h | 2 +- src/stream.cc | 2 +- src/stream.h | 2 +- src/system.hh.in | 2 +- src/temps.cc | 2 +- src/temps.h | 2 +- src/textual.cc | 2 +- src/timelog.cc | 2 +- src/timelog.h | 2 +- src/times.cc | 2 +- src/times.h | 2 +- src/token.cc | 2 +- src/token.h | 2 +- src/unistring.h | 2 +- src/utils.cc | 2 +- src/utils.h | 2 +- src/value.cc | 2 +- src/value.h | 2 +- src/xact.cc | 2 +- src/xact.h | 2 +- src/xml.cc | 2 +- src/xml.h | 2 +- 124 files changed, 125 insertions(+), 125 deletions(-) (limited to 'src/report.cc') diff --git a/src/account.cc b/src/account.cc index 42c10839..40ddf70b 100644 --- a/src/account.cc +++ b/src/account.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/account.h b/src/account.h index 7a632b35..8f0f915f 100644 --- a/src/account.h +++ b/src/account.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/accum.cc b/src/accum.cc index 0187995e..3add051b 100644 --- a/src/accum.cc +++ b/src/accum.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/accum.h b/src/accum.h index 411bcbe6..349aeba9 100644 --- a/src/accum.h +++ b/src/accum.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/amount.cc b/src/amount.cc index 85afc3d8..4d26a688 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/amount.h b/src/amount.h index f7e877a7..3a8e06b9 100644 --- a/src/amount.h +++ b/src/amount.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/annotate.cc b/src/annotate.cc index 8ba46f4f..cd1733ca 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/annotate.h b/src/annotate.h index b590ca45..3c6db8e8 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/archive.cc b/src/archive.cc index 28760512..72ec0419 100644 --- a/src/archive.cc +++ b/src/archive.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/archive.h b/src/archive.h index 1ebf3496..4ce5e0e7 100644 --- a/src/archive.h +++ b/src/archive.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/balance.cc b/src/balance.cc index 7ce9d994..4fba7344 100644 --- a/src/balance.cc +++ b/src/balance.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/balance.h b/src/balance.h index ac22f3e7..57e6ace4 100644 --- a/src/balance.h +++ b/src/balance.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/chain.cc b/src/chain.cc index 61388840..fc1be5bd 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/chain.h b/src/chain.h index 7bd76712..080c4231 100644 --- a/src/chain.h +++ b/src/chain.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/commodity.cc b/src/commodity.cc index 5fd54d11..643d0d1e 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/commodity.h b/src/commodity.h index d7747b2a..68f788e3 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/compare.cc b/src/compare.cc index cdc96a86..e2a298c2 100644 --- a/src/compare.cc +++ b/src/compare.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/compare.h b/src/compare.h index 0e7bf5e5..e1abbca1 100644 --- a/src/compare.h +++ b/src/compare.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/convert.cc b/src/convert.cc index 15995d05..1b1bf814 100644 --- a/src/convert.cc +++ b/src/convert.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/convert.h b/src/convert.h index 6d02f24a..de958108 100644 --- a/src/convert.h +++ b/src/convert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/csv.cc b/src/csv.cc index 82c28ff3..823238c7 100644 --- a/src/csv.cc +++ b/src/csv.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/csv.h b/src/csv.h index 909439ff..4d6e1253 100644 --- a/src/csv.h +++ b/src/csv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/draft.cc b/src/draft.cc index 9f9ec6e8..7c95caf7 100644 --- a/src/draft.cc +++ b/src/draft.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/draft.h b/src/draft.h index 59039f77..41485731 100644 --- a/src/draft.h +++ b/src/draft.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/emacs.cc b/src/emacs.cc index 5048a348..41c67cc6 100644 --- a/src/emacs.cc +++ b/src/emacs.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/emacs.h b/src/emacs.h index 97292728..a018ce68 100644 --- a/src/emacs.h +++ b/src/emacs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/error.cc b/src/error.cc index 88adfbdb..4a16f4e3 100644 --- a/src/error.cc +++ b/src/error.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/error.h b/src/error.h index b9960b03..7630f017 100644 --- a/src/error.h +++ b/src/error.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/expr.cc b/src/expr.cc index b3d4abcd..74d16ecc 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/expr.h b/src/expr.h index 79ae2864..e082efa5 100644 --- a/src/expr.h +++ b/src/expr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/exprbase.h b/src/exprbase.h index e0e2824f..0b1ef243 100644 --- a/src/exprbase.h +++ b/src/exprbase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/filters.cc b/src/filters.cc index fa1f6fa2..72ce9c32 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/filters.h b/src/filters.h index c972de82..22f2d2cb 100644 --- a/src/filters.h +++ b/src/filters.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/flags.h b/src/flags.h index 09b7eec4..e2046c08 100644 --- a/src/flags.h +++ b/src/flags.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/format.cc b/src/format.cc index 65c06488..a391fdf1 100644 --- a/src/format.cc +++ b/src/format.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/format.h b/src/format.h index f30b8184..74d77768 100644 --- a/src/format.h +++ b/src/format.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/generate.cc b/src/generate.cc index 963cd845..bf9a8036 100644 --- a/src/generate.cc +++ b/src/generate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/generate.h b/src/generate.h index abf719d4..1b22004b 100644 --- a/src/generate.h +++ b/src/generate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/global.cc b/src/global.cc index 34427f4b..ee921fc5 100644 --- a/src/global.cc +++ b/src/global.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/global.h b/src/global.h index 6504230d..28bffc3a 100644 --- a/src/global.h +++ b/src/global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -113,7 +113,7 @@ public: out << "Ledger " << ledger::version << _(", the command-line accounting tool"); out << - _("\n\nCopyright (c) 2003-2010, John Wiegley. All rights reserved.\n\n\ + _("\n\nCopyright (c) 2003-2012, John Wiegley. All rights reserved.\n\n\ This program is made available under the terms of the BSD Public License.\n\ See LICENSE file included with the distribution for details and disclaimer."); out << std::endl; diff --git a/src/item.cc b/src/item.cc index d123ee5a..3a2b0b60 100644 --- a/src/item.cc +++ b/src/item.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/item.h b/src/item.h index af3992c0..3a9c55bb 100644 --- a/src/item.h +++ b/src/item.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/iterators.cc b/src/iterators.cc index b398646e..72e0481c 100644 --- a/src/iterators.cc +++ b/src/iterators.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/iterators.h b/src/iterators.h index 93782400..6d490259 100644 --- a/src/iterators.h +++ b/src/iterators.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/journal.cc b/src/journal.cc index ea90fa05..2ebe90fb 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/journal.h b/src/journal.h index 70820cbd..6d10ffda 100644 --- a/src/journal.h +++ b/src/journal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/lookup.cc b/src/lookup.cc index 452727d6..ce22529d 100644 --- a/src/lookup.cc +++ b/src/lookup.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/lookup.h b/src/lookup.h index 8e83b84e..ba64b0b5 100644 --- a/src/lookup.h +++ b/src/lookup.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/main.cc b/src/main.cc index 9031341f..2202a5de 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/mask.cc b/src/mask.cc index 52907cfe..5bc10d5f 100644 --- a/src/mask.cc +++ b/src/mask.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/mask.h b/src/mask.h index e72347ad..15929b2e 100644 --- a/src/mask.h +++ b/src/mask.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/op.cc b/src/op.cc index 6dff031c..372101f0 100644 --- a/src/op.cc +++ b/src/op.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/op.h b/src/op.h index c4d353dc..192c1f5e 100644 --- a/src/op.h +++ b/src/op.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/option.cc b/src/option.cc index 2843c775..170b94af 100644 --- a/src/option.cc +++ b/src/option.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/option.h b/src/option.h index 8f89d081..dc1099db 100644 --- a/src/option.h +++ b/src/option.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/org.cc b/src/org.cc index 7c8e8c0d..3c897f54 100644 --- a/src/org.cc +++ b/src/org.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/org.h b/src/org.h index ed023be2..0b34b610 100644 --- a/src/org.h +++ b/src/org.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/output.cc b/src/output.cc index b26881a3..aaf81f60 100644 --- a/src/output.cc +++ b/src/output.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/output.h b/src/output.h index ac3925c4..281f69b6 100644 --- a/src/output.h +++ b/src/output.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/parser.cc b/src/parser.cc index 6197af6b..2c9069d7 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/parser.h b/src/parser.h index 09e12d95..75fd9a41 100644 --- a/src/parser.h +++ b/src/parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/pool.cc b/src/pool.cc index 65edbd6a..ba408fc5 100644 --- a/src/pool.cc +++ b/src/pool.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/pool.h b/src/pool.h index 4b935f69..87b315f9 100644 --- a/src/pool.h +++ b/src/pool.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/post.cc b/src/post.cc index 125947e4..e0ca149f 100644 --- a/src/post.cc +++ b/src/post.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/post.h b/src/post.h index 0cfd3e90..ce33fefc 100644 --- a/src/post.h +++ b/src/post.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/precmd.cc b/src/precmd.cc index 663b638d..6f8becb6 100644 --- a/src/precmd.cc +++ b/src/precmd.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/precmd.h b/src/precmd.h index 277933c3..1c52d8a7 100644 --- a/src/precmd.h +++ b/src/precmd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/predicate.cc b/src/predicate.cc index fd301a7d..58d6c752 100644 --- a/src/predicate.cc +++ b/src/predicate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/predicate.h b/src/predicate.h index 673f1d5d..7d58dc2f 100644 --- a/src/predicate.h +++ b/src/predicate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/print.cc b/src/print.cc index 63f38d80..c544c4e0 100644 --- a/src/print.cc +++ b/src/print.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/print.h b/src/print.h index 527f1912..42bfc8b6 100644 --- a/src/print.h +++ b/src/print.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/pstream.h b/src/pstream.h index 8134495d..a894325d 100644 --- a/src/pstream.h +++ b/src/pstream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/py_account.cc b/src/py_account.cc index 5ef86871..64a7ae54 100644 --- a/src/py_account.cc +++ b/src/py_account.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_amount.cc b/src/py_amount.cc index 9ce4a02d..f10595e8 100644 --- a/src/py_amount.cc +++ b/src/py_amount.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_balance.cc b/src/py_balance.cc index 0140a625..6c9ccb24 100644 --- a/src/py_balance.cc +++ b/src/py_balance.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_commodity.cc b/src/py_commodity.cc index 6d8a29b3..11ebe844 100644 --- a/src/py_commodity.cc +++ b/src/py_commodity.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_expr.cc b/src/py_expr.cc index 027125e2..dd9df1f5 100644 --- a/src/py_expr.cc +++ b/src/py_expr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_format.cc b/src/py_format.cc index fc2103c7..482eaf5b 100644 --- a/src/py_format.cc +++ b/src/py_format.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_item.cc b/src/py_item.cc index a12784ff..e3e49457 100644 --- a/src/py_item.cc +++ b/src/py_item.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_journal.cc b/src/py_journal.cc index bd781225..4f5427f5 100644 --- a/src/py_journal.cc +++ b/src/py_journal.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_post.cc b/src/py_post.cc index cace419f..bd599604 100644 --- a/src/py_post.cc +++ b/src/py_post.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_times.cc b/src/py_times.cc index c2e0b8f8..17f9ec7e 100644 --- a/src/py_times.cc +++ b/src/py_times.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_utils.cc b/src/py_utils.cc index 710dca4b..45ffe545 100644 --- a/src/py_utils.cc +++ b/src/py_utils.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_value.cc b/src/py_value.cc index f8f36453..3b67c4c6 100644 --- a/src/py_value.cc +++ b/src/py_value.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/py_xact.cc b/src/py_xact.cc index af1fcdd5..97d5df47 100644 --- a/src/py_xact.cc +++ b/src/py_xact.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/pyfstream.h b/src/pyfstream.h index 49b072f2..972f976f 100644 --- a/src/pyfstream.h +++ b/src/pyfstream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/pyinterp.cc b/src/pyinterp.cc index e48f16c6..44bea2cd 100644 --- a/src/pyinterp.cc +++ b/src/pyinterp.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/pyinterp.h b/src/pyinterp.h index ea947c5a..ae8dd9c2 100644 --- a/src/pyinterp.h +++ b/src/pyinterp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/pyledger.cc b/src/pyledger.cc index 4a53532a..cf5e362e 100644 --- a/src/pyledger.cc +++ b/src/pyledger.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/pyutils.h b/src/pyutils.h index 7e016502..44bb6d90 100644 --- a/src/pyutils.h +++ b/src/pyutils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/query.cc b/src/query.cc index 812123cb..8bdabb38 100644 --- a/src/query.cc +++ b/src/query.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/query.h b/src/query.h index 8f7917b2..52168539 100644 --- a/src/query.h +++ b/src/query.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/quotes.cc b/src/quotes.cc index 0cc8d06b..b29eb8bd 100644 --- a/src/quotes.cc +++ b/src/quotes.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/quotes.h b/src/quotes.h index 376d8918..52092fbc 100644 --- a/src/quotes.h +++ b/src/quotes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/report.cc b/src/report.cc index 530e7727..2c0c3970 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/report.h b/src/report.h index 2b521aae..35d45437 100644 --- a/src/report.h +++ b/src/report.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/scope.cc b/src/scope.cc index 2b9851b0..b2a7b17b 100644 --- a/src/scope.cc +++ b/src/scope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/scope.h b/src/scope.h index 2720e8fc..6fcd67e9 100644 --- a/src/scope.h +++ b/src/scope.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/series.h b/src/series.h index 40f34051..75b98194 100644 --- a/src/series.h +++ b/src/series.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/session.cc b/src/session.cc index 31122daa..9d994a9b 100644 --- a/src/session.cc +++ b/src/session.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/session.h b/src/session.h index 680b8a0e..93bee8ba 100644 --- a/src/session.h +++ b/src/session.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/stats.cc b/src/stats.cc index 524f5a87..0966fee2 100644 --- a/src/stats.cc +++ b/src/stats.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/stats.h b/src/stats.h index b7bf94c5..7b00fec8 100644 --- a/src/stats.h +++ b/src/stats.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/stream.cc b/src/stream.cc index 5d4cf5e0..ce40bfcc 100644 --- a/src/stream.cc +++ b/src/stream.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/stream.h b/src/stream.h index 42c85534..c317ebdf 100644 --- a/src/stream.h +++ b/src/stream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/system.hh.in b/src/system.hh.in index 42a82e41..e14166b2 100644 --- a/src/system.hh.in +++ b/src/system.hh.in @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/temps.cc b/src/temps.cc index 365c33c5..cb471d41 100644 --- a/src/temps.cc +++ b/src/temps.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/temps.h b/src/temps.h index 1e7eb69f..ad4e5672 100644 --- a/src/temps.h +++ b/src/temps.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/textual.cc b/src/textual.cc index 4977852c..15642cae 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/timelog.cc b/src/timelog.cc index 5ab6a25c..8d3d69c1 100644 --- a/src/timelog.cc +++ b/src/timelog.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/timelog.h b/src/timelog.h index 020ae4f2..12083302 100644 --- a/src/timelog.h +++ b/src/timelog.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/times.cc b/src/times.cc index 8ea90892..21ec1859 100644 --- a/src/times.cc +++ b/src/times.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/times.h b/src/times.h index bc462efa..6eadcad3 100644 --- a/src/times.h +++ b/src/times.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/token.cc b/src/token.cc index 77092d49..9449d9b7 100644 --- a/src/token.cc +++ b/src/token.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/token.h b/src/token.h index cbdf1258..01ff7ee9 100644 --- a/src/token.h +++ b/src/token.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/unistring.h b/src/unistring.h index 4be36b0d..a33c6e3f 100644 --- a/src/unistring.h +++ b/src/unistring.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/utils.cc b/src/utils.cc index 5260fd42..09526267 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/utils.h b/src/utils.h index c7aaac52..e37f37aa 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/value.cc b/src/value.cc index 61066f03..5fa748f6 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/value.h b/src/value.h index f8495002..1e4d0ce9 100644 --- a/src/value.h +++ b/src/value.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/xact.cc b/src/xact.cc index 8e1951a5..0fedb42a 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/xact.h b/src/xact.h index ff4b7bc2..cb7bdeb3 100644 --- a/src/xact.h +++ b/src/xact.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/xml.cc b/src/xml.cc index 90efd4b3..560db805 100644 --- a/src/xml.cc +++ b/src/xml.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/src/xml.h b/src/xml.h index 5d14dab3..871fd120 100644 --- a/src/xml.h +++ b/src/xml.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are -- cgit v1.2.3 From 44061554756fce740de949f4a4585b963c9aa1cb Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 3 Mar 2012 02:26:15 -0600 Subject: Make --change a synonym for --gain --- src/report.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 2c0c3970..d0dcd091 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1021,7 +1021,7 @@ option_t * report_t::lookup_option(const char * p) else OPT_ALT(head_, first_); break; case 'g': - OPT(gain); + OPT_ALT(gain, change); else OPT(group_by_); else OPT(group_title_format_); else OPT(generated); -- cgit v1.2.3 From 58d912827d2c6bd90c063537378baffff014c0f2 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 3 Mar 2012 02:26:28 -0600 Subject: Make --value a synonym for market --- src/report.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index d0dcd091..647df3d2 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1046,7 +1046,7 @@ option_t * report_t::lookup_option(const char * p) else OPT_ALT(tail_, last_); break; case 'm': - OPT(market); + OPT_ALT(market, value); else OPT(monthly); else OPT(meta_); else OPT(meta_width_); -- cgit v1.2.3 From 48ab6ad1dbab100bb8abd87029a0ca5bc501a3db Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 4 Mar 2012 03:35:06 -0600 Subject: Switched to using Boost.Graph for commodity pricing --- src/commodity.cc | 442 +++++------------------------------------------------- src/commodity.h | 114 +------------- src/filters.cc | 3 + src/history.cc | 196 ++++++++++++++++++++++++ src/history.h | 184 +++++++++++++++++++++++ src/iterators.cc | 3 + src/pool.cc | 88 ++--------- src/pool.h | 23 ++- src/report.cc | 10 +- src/system.hh.in | 15 ++ tools/Makefile.am | 2 + 11 files changed, 476 insertions(+), 604 deletions(-) create mode 100644 src/history.cc create mode 100644 src/history.h (limited to 'src/report.cc') diff --git a/src/commodity.cc b/src/commodity.cc index 643d0d1e..c0ccae11 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -40,410 +40,68 @@ namespace ledger { bool commodity_t::decimal_comma_by_default = false; -void commodity_t::history_t::add_price(commodity_t& source, - const datetime_t& date, - const amount_t& price, - const bool reflexive) +void commodity_t::add_price(const datetime_t& date, const amount_t& price, + const bool reflexive) { - DEBUG("commodity.prices.add", "add_price to " << source - << (reflexive ? " (secondary)" : " (primary)") - << " : " << date << ", " << price); + if (! reflexive) + add_flags(COMMODITY_PRIMARY); + pool().commodity_price_history.add_price(*this, date, price); - history_map::iterator i = prices.find(date); - if (i != prices.end()) { - (*i).second = price; - } else { - std::pair result - = prices.insert(history_map::value_type(date, price)); - assert(result.second); - } - - if (reflexive) { - amount_t inverse = price.inverted(); - inverse.set_commodity(const_cast(source)); - price.commodity().add_price(date, inverse, false); - } else { - DEBUG("commodity.prices.add", - "marking commodity " << source.symbol() << " as primary"); - source.add_flags(COMMODITY_PRIMARY); - } -} - -bool commodity_t::history_t::remove_price(const datetime_t& date) -{ - DEBUG("commodity.prices.add", "remove_price: " << date); - - history_map::size_type n = prices.erase(date); - if (n > 0) - return true; - return false; -} - -void commodity_t::varied_history_t:: - add_price(commodity_t& source, - const datetime_t& date, - const amount_t& price, - const bool reflexive) -{ - optional hist = history(price.commodity()); - if (! hist) { - std::pair result - = histories.insert(history_by_commodity_map::value_type - (&price.commodity(), history_t())); - assert(result.second); - - hist = (*result.first).second; - } - assert(hist); - - hist->add_price(source, date, price, reflexive); + DEBUG("commodity.prices.find", "Price added, clearing price_map"); + base->price_map.clear(); // a price was added, invalid the map } -bool commodity_t::varied_history_t::remove_price(const datetime_t& date, - commodity_t& comm) +void commodity_t::remove_price(const datetime_t& date, commodity_t& commodity) { - DEBUG("commodity.prices.add", "varied_remove_price: " << date << ", " << comm); + pool().commodity_price_history.remove_price(*this, commodity, date); - if (optional hist = history(comm)) - return hist->remove_price(date); - return false; + DEBUG("commodity.prices.find", "Price removed, clearing price_map"); + base->price_map.clear(); // a price was added, invalid the map } optional -commodity_t::history_t::find_price(const optional& moment, - const optional& oldest -#if defined(DEBUG_ON) - , const int indent -#endif - ) const +commodity_t::find_price(const optional& target = none, + const optional& moment = none, + const optional& oldest = none) const { - price_point_t point; - bool found = false; - -#if defined(DEBUG_ON) -#define DEBUG_INDENT(cat, indent) \ - do { \ - if (SHOW_DEBUG(cat)) \ - for (int _i = 0; _i < indent; _i++) \ - ledger::_log_buffer << " "; \ - } while (false) -#else -#define DEBUG_INDENT(cat, indent) -#endif - -#if defined(DEBUG_ON) + pair = base_t::time_and_commodity_t + (base_t::optional_time_pair_t(moment, oldest), + commodity ? &(*commodity) : NULL); DEBUG_INDENT("commodity.prices.find", indent); - if (moment) - DEBUG("commodity.prices.find", "find price nearest before or on: " << *moment); - else - DEBUG("commodity.prices.find", "find any price"); + DEBUG("commodity.prices.find", "looking for memoized args: " + << (moment ? format_datetime(*moment) : "NONE") << ", " + << (oldest ? format_datetime(*oldest) : "NONE") << ", " + << (commodity ? commodity->symbol() : "NONE")); - if (oldest) { + base_t::memoized_price_map::iterator i = base->price_map.find(*pair); + if (i != base->price_map.end()) { DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "but no older than: " << *oldest); - } -#endif - - if (prices.size() == 0) { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "there are no prices in this history"); - return none; + DEBUG("commodity.prices.find", "found! returning: " + << ((*i).second ? (*i).second->price : amount_t(0L))); + return (*i).second; } - if (! moment) { - history_map::const_reverse_iterator r = prices.rbegin(); - point.when = (*r).first; - point.price = (*r).second; - found = true; - - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "using most recent price"); - } else { - history_map::const_iterator i = prices.upper_bound(*moment); - if (i == prices.end()) { - history_map::const_reverse_iterator r = prices.rbegin(); - point.when = (*r).first; - point.price = (*r).second; - found = true; + optional point = + pool().commodity_price_history.find_price + (*this, commodity, moment ? *moment : epoch, oldest); + if (pair) { + if (base->price_map.size() > base_t::max_price_map_size) { DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "using last price"); - } else { - point.when = (*i).first; - if (*moment < point.when) { - if (i != prices.begin()) { - --i; - point.when = (*i).first; - point.price = (*i).second; - found = true; - } - } else { - point.price = (*i).second; - found = true; - } - - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "using found price"); - } - } - - if (! found) { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "could not find a price"); - return none; - } - else if (moment && point.when > *moment) { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "price is too young "); - return none; - } - else if (oldest && point.when < *oldest) { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "price is too old "); - return none; - } - else { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", - "returning price: " << point.when << ", " << point.price); - return point; - } -} - -optional -commodity_t::varied_history_t::find_price(const commodity_t& source, - const optional& commodity, - const optional& moment, - const optional& oldest -#if defined(DEBUG_ON) - , const int indent -#endif - ) const -{ - optional point; - optional limit = oldest; - -#if defined(VERIFY_ON) - if (commodity) { - VERIFY(source != *commodity); - VERIFY(! commodity->has_annotation()); - VERIFY(source.referent() != commodity->referent()); - } -#endif - -#if defined(DEBUG_ON) - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "varied_find_price for: " << source); - - DEBUG_INDENT("commodity.prices.find", indent); - if (commodity) - DEBUG("commodity.prices.find", "looking for: commodity '" << *commodity << "'"); - else - DEBUG("commodity.prices.find", "looking for: any commodity"); - - if (moment) { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "time index: " << *moment); - } - - if (oldest) { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "only consider prices younger than: " << *oldest); - } -#endif - - // Either we couldn't find a history for the target commodity, or we - // couldn't find a price. In either case, search all histories known - // to this commodity for a price which we can calculate in terms of - // the goal commodity. - price_point_t best; - bool found = false; - - foreach (const history_by_commodity_map::value_type& hist, histories) { - commodity_t& comm(*hist.first); - if (comm == source) - continue; - - DEBUG_INDENT("commodity.prices.find", indent + 1); - DEBUG("commodity.prices.find", - "searching for price via commodity '" << comm << "'"); - - point = hist.second.find_price(moment, limit -#if defined(DEBUG_ON) - , indent + 2 -#endif - ); - assert(! point || point->price.commodity() == comm); - - if (point) { - optional xlat; - - if (commodity && comm != *commodity) { - DEBUG_INDENT("commodity.prices.find", indent + 1); - DEBUG("commodity.prices.find", "looking for translation price"); - - xlat = comm.find_price(commodity, moment, limit, true -#if defined(DEBUG_ON) - , indent + 2 -#endif - ); - if (xlat) { - DEBUG_INDENT("commodity.prices.find", indent + 1); - DEBUG("commodity.prices.find", "found translated price " - << xlat->price << " from " << xlat->when); - - point->price = xlat->price * point->price; - if (xlat->when < point->when) { - point->when = xlat->when; - - DEBUG_INDENT("commodity.prices.find", indent + 1); - DEBUG("commodity.prices.find", - "adjusting date of result back to " << point->when); - } - } else { - DEBUG_INDENT("commodity.prices.find", indent + 1); - DEBUG("commodity.prices.find", "saw no translated price there"); - continue; - } - } - - assert(! commodity || point->price.commodity() == *commodity); - - DEBUG_INDENT("commodity.prices.find", indent + 1); DEBUG("commodity.prices.find", - "saw a price there: " << point->price << " from " << point->when); - - if (! limit || point->when > *limit) { - limit = point->when; - best = *point; - found = true; + "price map has grown too large, clearing it by half"); - DEBUG_INDENT("commodity.prices.find", indent + 1); - DEBUG("commodity.prices.find", - "search limit adjusted to " << *limit); - } - } else { - DEBUG_INDENT("commodity.prices.find", indent + 1); - DEBUG("commodity.prices.find", "saw no price there"); + for (std::size_t i = 0; i < base_t::max_price_map_size >> 1; i++) + base->price_map.erase(base->price_map.begin()); } - } - if (found) { DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.download", - "found price " << best.price << " from " << best.when); - return best; - } - return none; -} - -optional -commodity_t::varied_history_t::history(const optional& commodity) -{ - commodity_t * comm = NULL; - if (! commodity) { - if (histories.size() > 1) - return none; - comm = (*histories.begin()).first; - } else { - comm = &(*commodity); - } - - history_by_commodity_map::iterator i = histories.find(comm); - if (i != histories.end()) - return (*i).second; - - return none; -} - -optional -commodity_t::find_price(const optional& commodity, - const optional& moment, - const optional& oldest, - const bool nested -#if defined(DEBUG_ON) - , const int indent -#endif - ) const -{ - if (! has_flags(COMMODITY_WALKED) && base->varied_history) { - optional pair; -#if defined(VERIFY_ON) - optional checkpoint; - bool found = false; -#endif - - if (! nested) { - pair = base_t::time_and_commodity_t - (base_t::optional_time_pair_t(moment, oldest), - commodity ? &(*commodity) : NULL); - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "looking for memoized args: " - << (moment ? format_datetime(*moment) : "NONE") << ", " - << (oldest ? format_datetime(*oldest) : "NONE") << ", " - << (commodity ? commodity->symbol() : "NONE")); - - base_t::memoized_price_map::iterator i = base->price_map.find(*pair); - if (i != base->price_map.end()) { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "found! returning: " - << ((*i).second ? (*i).second->price : amount_t(0L))); -#if defined(VERIFY_ON) - IF_VERIFY() { - found = true; - checkpoint = (*i).second; - } else -#endif // defined(VERIFY_ON) - return (*i).second; - } - } - - optional point; - - const_cast(*this).add_flags(COMMODITY_WALKED); - try { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", "manually finding price..."); - - point = base->varied_history->find_price(*this, commodity, - moment, oldest -#if defined(DEBUG_ON) - , indent -#endif - ); - } - catch (...) { - const_cast(*this).drop_flags(COMMODITY_WALKED); - throw; - } - const_cast(*this).drop_flags(COMMODITY_WALKED); - -#if defined(VERIFY_ON) - if (DO_VERIFY() && found) { - VERIFY(checkpoint == point); - return checkpoint; - } -#endif // defined(VERIFY_ON) - - if (! nested && pair) { - if (base->price_map.size() > base_t::max_price_map_size) { - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", - "price map has grown too large, clearing it by half"); - - for (std::size_t i = 0; i < base_t::max_price_map_size >> 1; i++) - base->price_map.erase(base->price_map.begin()); - } - - DEBUG_INDENT("commodity.prices.find", indent); - DEBUG("commodity.prices.find", - "remembered: " << (point ? point->price : amount_t(0L))); - base->price_map.insert - (base_t::memoized_price_map::value_type(*pair, point)); - } - return point; + DEBUG("commodity.prices.find", + "remembered: " << (point ? point->price : amount_t(0L))); + base->price_map.insert + (base_t::memoized_price_map::value_type(*pair, point)); } - return none; + return point; } optional @@ -767,28 +425,6 @@ void to_xml(std::ostream& out, const commodity_t& comm, if (commodity_details) { if (comm.has_annotation()) to_xml(out, as_annotated_commodity(comm).details); - - if (comm.varied_history()) { - push_xml y(out, "varied-history"); - - foreach (const commodity_t::history_by_commodity_map::value_type& pair, - comm.varied_history()->histories) { - { - push_xml z(out, "symbol"); - out << y.guard(pair.first->symbol()); - } - { - push_xml z(out, "history"); - - foreach (const commodity_t::history_map::value_type& inner_pair, - pair.second.prices) { - push_xml w(out, "price-point"); - to_xml(out, inner_pair.first); - to_xml(out, inner_pair.second); - } - } - } - } } } diff --git a/src/commodity.h b/src/commodity.h index 68f788e3..1505fe24 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -85,78 +85,6 @@ class commodity_t : public delegates_flags, public equality_comparable1 { -public: - typedef std::map history_map; - - struct history_t - { - history_map prices; - - void add_price(commodity_t& source, - const datetime_t& date, - const amount_t& price, - const bool reflexive = true); - bool remove_price(const datetime_t& date); - - optional - find_price(const optional& moment = none, - const optional& oldest = none -#if defined(DEBUG_ON) - , const int indent = 0 -#endif - ) const; - -#if defined(HAVE_BOOST_SERIALIZATION) - private: - /** Serialization. */ - - friend class boost::serialization::access; - - template - void serialize(Archive& ar, const unsigned int /* version */) { - ar & prices; - } -#endif // HAVE_BOOST_SERIALIZATION - }; - - typedef std::map history_by_commodity_map; - - struct varied_history_t - { - history_by_commodity_map histories; - - void add_price(commodity_t& source, - const datetime_t& date, - const amount_t& price, - const bool reflexive = true); - bool remove_price(const datetime_t& date, commodity_t& commodity); - - optional - find_price(const commodity_t& source, - const optional& commodity = none, - const optional& moment = none, - const optional& oldest = none -#if defined(DEBUG_ON) - , const int indent = 0 -#endif - ) const; - - optional - history(const optional& commodity = none); - -#if defined(HAVE_BOOST_SERIALIZATION) - private: - /** Serialization. */ - - friend class boost::serialization::access; - - template - void serialize(Archive& ar, const unsigned int /* version */) { - ar & histories; - } -#endif // HAVE_BOOST_SERIALIZATION - }; - protected: friend class commodity_pool_t; friend class annotated_commodity_t; @@ -182,7 +110,6 @@ protected: amount_t::precision_t precision; optional name; optional note; - optional varied_history; optional smaller; optional larger; @@ -228,7 +155,6 @@ protected: ar & precision; ar & name; ar & note; - ar & varied_history; ar & smaller; ar & larger; } @@ -335,48 +261,14 @@ public: base->larger = arg; } - optional varied_history() { - if (base->varied_history) - return *base->varied_history; - return none; - } - optional varied_history() const { - if (base->varied_history) - return *base->varied_history; - return none; - } - - optional history(const optional& commodity); - - // These methods provide a transparent pass-through to the underlying - // base->varied_history object. - void add_price(const datetime_t& date, const amount_t& price, - const bool reflexive = true) { - if (! base->varied_history) - base->varied_history = varied_history_t(); - base->varied_history->add_price(*this, date, price, reflexive); - DEBUG("commodity.prices.find", "Price added, clearing price_map"); - base->price_map.clear(); // a price was added, invalid the map - } - bool remove_price(const datetime_t& date, commodity_t& commodity) { - if (base->varied_history) { - base->varied_history->remove_price(date, commodity); - DEBUG("commodity.prices.find", "Price removed, clearing price_map"); - base->price_map.clear(); // a price was added, invalid the map - } - return false; - } + const bool reflexive = true); + void remove_price(const datetime_t& date, commodity_t& commodity); optional find_price(const optional& commodity = none, const optional& moment = none, - const optional& oldest = none, - const bool nested = false -#if defined(DEBUG_ON) - , const int indent = 0 -#endif - ) const; + const optional& oldest = none) const; optional check_for_updated_price(const optional& point, diff --git a/src/filters.cc b/src/filters.cc index 72ce9c32..0c6222d7 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -754,6 +754,8 @@ void changed_value_posts::output_intermediate_prices(post_t& post, // fall through... case value_t::BALANCE: { +#if 0 + // jww (2012-03-04): TODO commodity_t::history_map all_prices; foreach (const balance_t::amounts_map::value_type& amt_comm, @@ -797,6 +799,7 @@ void changed_value_posts::output_intermediate_prices(post_t& post, output_revaluation(post, price.first); last_total = repriced_total; } +#endif break; } default: diff --git a/src/history.cc b/src/history.cc new file mode 100644 index 00000000..44d19f5a --- /dev/null +++ b/src/history.cc @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "history.h" + +template +struct f_max : public std::binary_function { + T operator()(const T& x, const T& y) const { + return std::max(x, y); + } +}; + +namespace ledger { + +void commodity_history_t::add_commodity(const commodity_t& comm) +{ + const vertex_descriptor vert = add_vertex(&comm, price_graph); + put(indexmap, vert, reinterpret_cast(&comm)); +} + +void commodity_history_t::add_price(const commodity_t& source, + const datetime_t& when, + const amount_t& price) +{ + vertex_descriptor sv = + vertex(reinterpret_cast(&source), price_graph); + vertex_descriptor tv = + vertex(reinterpret_cast(&price.commodity()), price_graph); + + std::pair e1 = add_edge(sv, tv, 0, price_graph); + price_map_t& prices(get(ratiomap, e1.first)); + + std::pair result = + prices.insert(price_map_t::value_type(when, price)); + if (! result.second) { + // There is already an entry for this moment, so update it + (*result.first).second = price; + } +} + +void commodity_history_t::remove_price(const commodity_t& source, + const commodity_t& target, + const datetime_t& date) +{ + vertex_descriptor sv = + vertex(reinterpret_cast(&source), price_graph); + vertex_descriptor tv = + vertex(reinterpret_cast(&target), price_graph); + + std::pair e1 = add_edge(sv, tv, 0, price_graph); + price_map_t& prices(get(ratiomap, e1.first)); + + // jww (2012-03-04): If it fails, should we give a warning? + prices.erase(date); +} + +optional +commodity_history_t::find_price(const commodity_t& source, + const datetime_t& moment, + const optional& oldest, + const optional& target) +{ + vertex_descriptor sv = + vertex(reinterpret_cast(&source), price_graph); + vertex_descriptor tv = + vertex(reinterpret_cast(&*target), price_graph); + + // Filter out edges which came into being after the reference time + + FGraph fg(price_graph, + recent_edge_weight + (get(edge_weight, price_graph), pricemap, ratiomap, + moment, oldest)); + + std::vector predecessors(num_vertices(fg)); + std::vector distances(num_vertices(fg)); + + PredecessorMap predecessorMap(&predecessors[0]); + DistanceMap distanceMap(&distances[0]); + + dijkstra_shortest_paths(fg, /* start= */ sv, + predecessor_map(predecessorMap) + .distance_map(distanceMap) + .distance_combine(f_max())); + + // Extract the shortest path and performance the calculations + datetime_t least_recent = moment; + amount_t price; + + vertex_descriptor v = tv; + for (vertex_descriptor u = predecessorMap[v]; + u != v; + v = u, u = predecessorMap[v]) + { + std::pair edgePair = edge(u, v, fg); + Graph::edge_descriptor edge = edgePair.first; + + const price_point_t& point(get(pricemap, edge)); + + if (price.is_null()) { + least_recent = point.when; + price = point.price; + } + else if (point.when < least_recent) + least_recent = point.when; + + // jww (2012-03-04): TODO + //price *= point.price; + } + + return price_point_t(least_recent, price); +} + +#if 0 + print_vertices(fg, f_commmap); + print_edges(fg, f_commmap); + print_graph(fg, f_commmap); + + graph_traits::vertex_iterator f_vi, f_vend; + for(tie(f_vi, f_vend) = vertices(fg); f_vi != f_vend; ++f_vi) + std::cerr << get(f_commmap, *f_vi) << " is in the filtered graph" + << std::endl; + + for (tie(f_vi, f_vend) = vertices(fg); f_vi != f_vend; ++f_vi) { + std::cerr << "distance(" << get(f_commmap, *f_vi) << ") = " + << distanceMap[*f_vi] << ", "; + std::cerr << "parent(" << get(f_commmap, *f_vi) << ") = " + << get(f_commmap, predecessorMap[*f_vi]) + << std::endl; + } + + // Write shortest path + FCommMap f_commmap = get(vertex_comm, fg); + + std::cerr << "Shortest path from CAD to EUR:" << std::endl; + for (PathType::reverse_iterator pathIterator = path.rbegin(); + pathIterator != path.rend(); + ++pathIterator) + { + std::cerr << get(f_commmap, source(*pathIterator, fg)) + << " -> " << get(f_commmap, target(*pathIterator, fg)) + << " = " << get(edge_weight, fg, *pathIterator) + << std::endl; + } + std::cerr << std::endl; + + std::cerr << "Distance: " << distanceMap[vd4] << std::endl; +#endif + +#if 0 + #include + + // Writing graph to file + { + std::ofstream f("test.dot"); + + dynamic_properties p; + p.property("label", get(edge_weight, g)); + p.property("weight", get(edge_weight, g)); + p.property("node_id", get(vertex_comm, g)); + write_graphviz(f,g,p); + f.close(); + } +#endif + +} // namespace ledger diff --git a/src/history.h b/src/history.h new file mode 100644 index 00000000..486602dd --- /dev/null +++ b/src/history.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup math + */ + +/** + * @file history.h + * @author John Wiegley + * + * @ingroup math + * + * @brief Types for managing commodity historys + * + * Long. + */ +#ifndef _HISTORY_H +#define _HISTORY_H + +#include "amount.h" +#include "commodity.h" + +namespace boost { + enum edge_price_point_t { edge_price_point }; + enum edge_price_ratio_t { edge_price_ratio }; + BOOST_INSTALL_PROPERTY(edge, price_point); + BOOST_INSTALL_PROPERTY(edge, price_ratio); +} + +namespace ledger { + +typedef std::map price_map_t; + +template +class recent_edge_weight +{ +public: + EdgeWeightMap weight; + PricePointMap price_point; + PriceRatioMap ratios; + + datetime_t reftime; + optional oldest; + + recent_edge_weight() { } + recent_edge_weight(EdgeWeightMap _weight, + PricePointMap _price_point, + PriceRatioMap _ratios, + datetime_t _reftime, + const optional& _oldest = none) + : weight(_weight), price_point(_price_point), ratios(_ratios), + reftime(_reftime), oldest(_oldest) { } + + template + bool operator()(const Edge& e) const { + const price_map_t& prices(get(ratios, e)); + price_map_t::const_iterator low = prices.upper_bound(reftime); + if (prices.empty() || + (low != prices.end() && low == prices.begin())) { + return false; + } else { + if (low == prices.end()) + --low; + assert(((*low).first <= reftime)); + + if (oldest && (*low).first <= *oldest) + return false; + + long secs = (reftime - (*low).first).total_seconds(); + assert(secs >= 0); + + put(weight, e, secs); + put(price_point, e, price_point_t((*low).first, (*low).second)); + + return true; + } + } +}; + +class commodity_history_t : public noncopyable +{ +public: + typedef adjacency_list + >, + + // All edges are weights computed as the absolute difference between + // the reference time of a search and a known price point. A + // filtered_graph is used to select the recent price point to the + // reference time before performing the search. + property > >, + + // Graph itself has a std::string name + property + > Graph; + + Graph price_graph; + + typedef graph_traits::vertex_descriptor vertex_descriptor; + typedef graph_traits::edge_descriptor edge_descriptor; + + typedef property_map::type IndexMap; + typedef property_map::type NameMap; + + typedef iterator_property_map PredecessorMap; + typedef iterator_property_map DistanceMap; + + typedef property_map::type EdgeWeightMap; + typedef property_map::type PricePointMap; + typedef property_map::type PriceRatioMap; + + IndexMap indexmap; + PricePointMap pricemap; + PriceRatioMap ratiomap; + + typedef filtered_graph > FGraph; + typedef property_map::type FNameMap; + + commodity_history_t() + : indexmap(get(vertex_index, price_graph)), + pricemap(get(edge_price_point, price_graph)), + ratiomap(get(edge_price_ratio, price_graph)) {} + + void add_commodity(const commodity_t& comm); + + void add_price(const commodity_t& source, + const datetime_t& when, + const amount_t& price); + void remove_price(const commodity_t& source, + const commodity_t& target, + const datetime_t& date); + + optional + find_price(const commodity_t& source, + const datetime_t& moment, + const optional& oldest = none, + const optional& commodity = none); +}; + +} // namespace ledger + +#endif // _HISTORY_H diff --git a/src/iterators.cc b/src/iterators.cc index 72e0481c..b7ed011e 100644 --- a/src/iterators.cc +++ b/src/iterators.cc @@ -90,6 +90,8 @@ void posts_commodities_iterator::reset(journal_t& journal) std::map xacts_by_commodity; +#if 0 + // jww (2012-03-04): TODO foreach (commodity_t * comm, commodities) { if (optional history = comm->varied_history()) { @@ -136,6 +138,7 @@ void posts_commodities_iterator::reset(journal_t& journal) } } } +#endif xacts.reset(xact_temps.begin(), xact_temps.end()); diff --git a/src/pool.cc b/src/pool.cc index ba408fc5..67cfe3d1 100644 --- a/src/pool.cc +++ b/src/pool.cc @@ -35,6 +35,7 @@ #include "commodity.h" #include "annotate.h" #include "pool.h" +#include "history.h" #include "quotes.h" namespace ledger { @@ -74,15 +75,15 @@ commodity_t * commodity_pool_t::create(const string& symbol) commodity.get())); assert(result.second); + commodity_price_history.add_commodity(*commodity.get()); + return commodity.release(); } commodity_t * commodity_pool_t::find_or_create(const string& symbol) { DEBUG("pool.commodities", "Find-or-create commodity " << symbol); - - commodity_t * commodity = find(symbol); - if (commodity) + if (commodity_t * commodity = find(symbol)) return commodity; return create(symbol); } @@ -222,6 +223,15 @@ commodity_t * commodity_pool_t::find_or_create(commodity_t& comm, return create(comm, details, name); } +optional +commodity_pool_t::find_price(const commodity_t& source, + const optional& commodity, + const optional& moment, + const optional& oldest) const +{ + return commodity_price_history.find_price(source, commodity, moment, oldest); +} + void commodity_pool_t::exchange(commodity_t& commodity, const amount_t& per_unit_cost, const datetime_t& moment) @@ -382,76 +392,4 @@ commodity_pool_t::parse_price_expression(const std::string& str, return NULL; } -void commodity_pool_t::print_pricemap(std::ostream& out, - const keep_details_t& keep, - const optional& moment) -{ - typedef std::map comm_map_t; - - comm_map_t comm_map; - - foreach (const commodities_map::value_type& comm_pair, commodities) { - commodity_t * comm(&comm_pair.second->strip_annotations(keep)); - comm_map.insert(comm_map_t::value_type(comm, NULL)); - } - - out << "digraph commodities {\n"; - - foreach (const comm_map_t::value_type& comm_pair, comm_map) { - commodity_t * comm(comm_pair.first); - if (comm->has_flags(COMMODITY_BUILTIN)) - continue; - - out << " "; - if (commodity_t::symbol_needs_quotes(comm->symbol())) - out << comm->symbol() << ";\n"; - else - out << "\"" << comm->symbol() << "\";\n"; - - if (! comm->has_flags(COMMODITY_NOMARKET) && - (! commodity_pool_t::current_pool->default_commodity || - comm != commodity_pool_t::current_pool->default_commodity)) { - if (optional vhist = - comm->varied_history()) { - foreach (const commodity_t::history_by_commodity_map::value_type& pair, - vhist->histories) { - datetime_t most_recent; - amount_t most_recent_amt; - foreach (const commodity_t::history_map::value_type& inner_pair, - pair.second.prices) { - if ((most_recent.is_not_a_date_time() || - inner_pair.first > most_recent) && - (! moment || inner_pair.first <= moment)) { - most_recent = inner_pair.first; - most_recent_amt = inner_pair.second; - } - } - - if (! most_recent.is_not_a_date_time()) { - out << " "; - if (commodity_t::symbol_needs_quotes(comm->symbol())) - out << comm->symbol(); - else - out << "\"" << comm->symbol() << "\""; - - out << " -> "; - - if (commodity_t::symbol_needs_quotes(pair.first->symbol())) - out << pair.first->symbol(); - else - out << "\"" << pair.first->symbol() << "\""; - - out << " [label=\"" - << most_recent_amt.number() << "\\n" - << format_date(most_recent.date(), FMT_WRITTEN) - << "\" fontcolor=\"#008e28\"];\n"; - } - } - } - } - } - - out << "}\n"; -} - } // namespace ledger diff --git a/src/pool.h b/src/pool.h index 87b315f9..709f5c71 100644 --- a/src/pool.h +++ b/src/pool.h @@ -46,6 +46,8 @@ #ifndef _POOL_H #define _POOL_H +#include "history.h" + namespace ledger { struct cost_breakdown_t @@ -66,15 +68,16 @@ public: */ typedef std::map commodities_map; - commodities_map commodities; - commodity_t * null_commodity; - commodity_t * default_commodity; + commodities_map commodities; + commodity_history_t commodity_price_history; + commodity_t * null_commodity; + commodity_t * default_commodity; - bool keep_base; // --base + bool keep_base; // --base - optional price_db; // --price-db= - long quote_leeway; // --leeway= - bool get_quotes; // --download + optional price_db; // --price-db= + long quote_leeway; // --leeway= + bool get_quotes; // --download static shared_ptr current_pool; @@ -131,12 +134,6 @@ public: const bool add_prices = true, const optional& moment = none); - // Output the commodity price map for a given date as a DOT file - - void print_pricemap(std::ostream& out, - const keep_details_t& keep, - const optional& moment = none); - #if defined(HAVE_BOOST_SERIALIZATION) private: /** Serialization. */ diff --git a/src/report.cc b/src/report.cc index 647df3d2..689028d0 100644 --- a/src/report.cc +++ b/src/report.cc @@ -878,11 +878,12 @@ value_t report_t::echo_command(call_scope_t& args) value_t report_t::pricemap_command(call_scope_t& args) { std::ostream& out(output_stream); - +#if 0 + // jww (2012-03-04): TODO commodity_pool_t::current_pool->print_pricemap (out, what_to_keep(), args.has(0) ? optional(datetime_t(parse_date(args.get(0)))) : none); - +#endif return true; } @@ -913,6 +914,11 @@ option_t * report_t::lookup_option(const char * p) case 'G': OPT_CH(gain); break; +#if 0 + case 'H': + OPT_CH(historical); + break; +#endif case 'I': OPT_CH(price); break; diff --git a/src/system.hh.in b/src/system.hh.in index 3aa60f71..8f684486 100644 --- a/src/system.hh.in +++ b/src/system.hh.in @@ -138,37 +138,52 @@ typedef std::ostream::pos_type ostream_pos_type; #include #include #include + #include #include #include + #include #include #include #include #include + #if !(defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__) #include #endif #include + +#include +#include +#include +#include + #include + #include #include #define BOOST_IOSTREAMS_USE_DEPRECATED 1 #include + #include #include + #include #include #include #include + #include #include #include #include + #if defined(HAVE_BOOST_REGEX_UNICODE) #include #else #include + #endif // HAVE_BOOST_REGEX_UNICODE #include #include diff --git a/tools/Makefile.am b/tools/Makefile.am index 09021b1f..671db294 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -30,6 +30,7 @@ libledger_util_la_LDFLAGS = -release $(LIBVERSION) libledger_math_la_SOURCES = \ src/balance.cc \ src/quotes.cc \ + src/history.cc \ src/pool.cc \ src/annotate.cc \ src/commodity.cc \ @@ -104,6 +105,7 @@ pkginclude_HEADERS = \ src/amount.h \ src/commodity.h \ src/annotate.h \ + src/history.h \ src/pool.h \ src/quotes.h \ src/balance.h \ -- cgit v1.2.3 From 5d8cb30774cf630cddd26407202c1cad8568bbef Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 4 Mar 2012 05:22:30 -0600 Subject: Implemented first cut at price conversion logic --- src/commodity.cc | 4 +- src/history.cc | 152 ++++++++++++++++++++++++++++----------------- src/history.h | 26 +++++--- src/report.cc | 7 +-- src/system.hh.in | 2 +- test/regress/D943AE0F.test | 2 +- 6 files changed, 119 insertions(+), 74 deletions(-) (limited to 'src/report.cc') diff --git a/src/commodity.cc b/src/commodity.cc index a01847c5..5e55db31 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -96,7 +96,9 @@ commodity_t::find_price(const optional& commodity, target = *pool().default_commodity; optional point = - pool().commodity_price_history.find_price(*this, when, oldest, target); + target ? + pool().commodity_price_history.find_price(*this, *target, when, oldest) : + pool().commodity_price_history.find_price(*this, when, oldest); if (pair) { if (base->price_map.size() > base_t::max_price_map_size) { diff --git a/src/history.cc b/src/history.cc index c92a0102..a3d9139b 100644 --- a/src/history.cc +++ b/src/history.cc @@ -85,19 +85,50 @@ void commodity_history_t::remove_price(const commodity_t& source, } optional -commodity_history_t::find_price(const commodity_t& source, - const datetime_t& moment, - const optional& oldest, - const optional& target) +commodity_history_t::find_price(const commodity_t& source, + const datetime_t& moment, + const optional& oldest) { vertex_descriptor sv = vertex(*source.graph_index(), price_graph); - // jww (2012-03-04): What to do when target is null? In that case, - // should we just return whatever is the most recent price for that - // commodity? - vertex_descriptor tv = vertex(*target->graph_index(), price_graph); // Filter out edges which came into being after the reference time + FGraph fg(price_graph, + recent_edge_weight + (get(edge_weight, price_graph), pricemap, ratiomap, + moment, oldest)); + + datetime_t most_recent = moment; + amount_t price; + + graph_traits::adjacency_iterator f_vi, f_vend; + for (tie(f_vi, f_vend) = adjacent_vertices(sv, fg); f_vi != f_vend; ++f_vi) { + std::pair edgePair = edge(sv, *f_vi, fg); + Graph::edge_descriptor edge = edgePair.first; + + const price_point_t& point(get(pricemap, edge)); + + if (price.is_null() || point.when > most_recent) { + most_recent = point.when; + price = point.price; + } + } + + if (price.is_null()) + return none; + else + return price_point_t(most_recent, price); +} + +optional +commodity_history_t::find_price(const commodity_t& source, + const commodity_t& target, + const datetime_t& moment, + const optional& oldest) +{ + vertex_descriptor sv = vertex(*source.graph_index(), price_graph); + vertex_descriptor tv = vertex(*target.graph_index(), price_graph); + // Filter out edges which came into being after the reference time FGraph fg(price_graph, recent_edge_weight (get(edge_weight, price_graph), pricemap, ratiomap, @@ -118,6 +149,8 @@ commodity_history_t::find_price(const commodity_t& source, datetime_t least_recent = moment; amount_t price; + FNameMap ptrs = get(vertex_name, fg); + vertex_descriptor v = tv; for (vertex_descriptor u = predecessorMap[v]; u != v; @@ -128,70 +161,73 @@ commodity_history_t::find_price(const commodity_t& source, const price_point_t& point(get(pricemap, edge)); + const commodity_t * last_source = &source; + + bool first_run = false; if (price.is_null()) { least_recent = point.when; price = point.price; + first_run = true; } - else if (point.when < least_recent) + else if (point.when < least_recent) { least_recent = point.when; + } - // jww (2012-03-04): TODO - //price *= point.price; - } - - return price_point_t(least_recent, price); -} + DEBUG("history.find", "u commodity = " << get(ptrs, u)->symbol()); + DEBUG("history.find", "v commodity = " << get(ptrs, v)->symbol()); + DEBUG("history.find", "last source = " << last_source->symbol()); -#if 0 - print_vertices(fg, f_commmap); - print_edges(fg, f_commmap); - print_graph(fg, f_commmap); - - graph_traits::vertex_iterator f_vi, f_vend; - for(tie(f_vi, f_vend) = vertices(fg); f_vi != f_vend; ++f_vi) - std::cerr << get(f_commmap, *f_vi) << " is in the filtered graph" - << std::endl; - - for (tie(f_vi, f_vend) = vertices(fg); f_vi != f_vend; ++f_vi) { - std::cerr << "distance(" << get(f_commmap, *f_vi) << ") = " - << distanceMap[*f_vi] << ", "; - std::cerr << "parent(" << get(f_commmap, *f_vi) << ") = " - << get(f_commmap, predecessorMap[*f_vi]) - << std::endl; - } + // Determine which direction we are converting in + amount_t pprice(point.price); + DEBUG("history.find", "pprice = " << pprice); - // Write shortest path - FCommMap f_commmap = get(vertex_comm, fg); + DEBUG("history.find", "price was = " << price); + if (! first_run) { + if (pprice.commodity() == *last_source) + price *= pprice.inverted(); + else + price *= pprice; + } + else if (price.commodity() == *last_source) { + price = price.inverted(); + } + DEBUG("history.find", "price is = " << price); - std::cerr << "Shortest path from CAD to EUR:" << std::endl; - for (PathType::reverse_iterator pathIterator = path.rbegin(); - pathIterator != path.rend(); - ++pathIterator) - { - std::cerr << get(f_commmap, source(*pathIterator, fg)) - << " -> " << get(f_commmap, target(*pathIterator, fg)) - << " = " << get(edge_weight, fg, *pathIterator) - << std::endl; + if (*last_source == *get(ptrs, v)) + last_source = get(ptrs, u); + else + last_source = get(ptrs, v); } - std::cerr << std::endl; - std::cerr << "Distance: " << distanceMap[vd4] << std::endl; -#endif + price.set_commodity(const_cast(target)); + DEBUG("history.find", "final price is = " << price); -#if 0 - #include + if (price.is_null()) + return none; + else + return price_point_t(least_recent, price); +} - // Writing graph to file - { - std::ofstream f("test.dot"); - - dynamic_properties p; - p.property("label", get(edge_weight, g)); - p.property("weight", get(edge_weight, g)); - p.property("node_id", get(vertex_comm, g)); - write_graphviz(f,g,p); - f.close(); +void commodity_history_t::print_map(std::ostream& out, + const optional& moment) +{ +#if 0 + dynamic_properties p; + p.property("label", get(edge_weight, price_graph)); + p.property("weight", get(edge_weight, price_graph)); + p.property("node_id", get(vertex_index, price_graph)); + + if (moment) { + // Filter out edges which came into being after the reference time + FGraph fg(price_graph, + recent_edge_weight + (get(edge_weight, price_graph), pricemap, ratiomap, + *moment)); + write_graphviz(out, fg, p); + } else { + write_graphviz(out, price_graph, p); } #endif +} } // namespace ledger diff --git a/src/history.h b/src/history.h index f94d12c3..70831445 100644 --- a/src/history.h +++ b/src/history.h @@ -83,18 +83,20 @@ public: reftime(_reftime), oldest(_oldest) { } template - bool operator()(const Edge& e) const { + bool operator()(const Edge& e) const + { const price_map_t& prices(get(ratios, e)); + if (prices.empty()) + return false; + price_map_t::const_iterator low = prices.upper_bound(reftime); - if (prices.empty() || - (low != prices.end() && low == prices.begin())) { + if (low != prices.end() && low == prices.begin()) { return false; } else { - if (low == prices.end()) - --low; + --low; assert(((*low).first <= reftime)); - if (oldest && (*low).first <= *oldest) + if (oldest && (*low).first < *oldest) return false; long secs = (reftime - (*low).first).total_seconds(); @@ -175,8 +177,16 @@ public: optional find_price(const commodity_t& source, const datetime_t& moment, - const optional& oldest = none, - const optional& commodity = none); + const optional& oldest = none); + + optional + find_price(const commodity_t& source, + const commodity_t& target, + const datetime_t& moment, + const optional& oldest = none); + + void print_map(std::ostream& out, + const optional& moment = none); }; } // namespace ledger diff --git a/src/report.cc b/src/report.cc index 689028d0..2d825751 100644 --- a/src/report.cc +++ b/src/report.cc @@ -878,12 +878,9 @@ value_t report_t::echo_command(call_scope_t& args) value_t report_t::pricemap_command(call_scope_t& args) { std::ostream& out(output_stream); -#if 0 - // jww (2012-03-04): TODO - commodity_pool_t::current_pool->print_pricemap - (out, what_to_keep(), args.has(0) ? + commodity_pool_t::current_pool->commodity_price_history.print_map + (out, args.has(0) ? optional(datetime_t(parse_date(args.get(0)))) : none); -#endif return true; } diff --git a/src/system.hh.in b/src/system.hh.in index 8f684486..5e5a0c1d 100644 --- a/src/system.hh.in +++ b/src/system.hh.in @@ -157,7 +157,7 @@ typedef std::ostream::pos_type ostream_pos_type; #include #include #include -#include +#include #include diff --git a/test/regress/D943AE0F.test b/test/regress/D943AE0F.test index 960fbe13..10082f75 100644 --- a/test/regress/D943AE0F.test +++ b/test/regress/D943AE0F.test @@ -6,7 +6,7 @@ D 1000.00 EUR P 2008/04/20 00:00:00 CAD 1.20 EUR -test reg -V +test reg -V --now=2008/04/20 08-Apr-15 Paid expenses back .. Exp:Cie-Reimbursements 2200.00 EUR 2200.00 EUR Assets:Checking -2200.00 EUR 0 08-Apr-20 Commodities revalued 200.00 EUR 200.00 EUR -- cgit v1.2.3 From dc9ecc600aa766caa3e7d718b0b8656da4ba1f70 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 5 Mar 2012 15:17:59 -0600 Subject: Guard against double-freeing of report objects --- src/report.cc | 91 +++++++++++++++++++++++++++++++++++++---------------------- src/report.h | 2 +- 2 files changed, 59 insertions(+), 34 deletions(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 2d825751..7789ff80 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1386,8 +1386,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, switch (*p) { case 'a': if (is_eq(p, "accounts")) { - return WRAP_FUNCTOR(reporter<>(new report_accounts(*this), *this, - "#accounts")); + return WRAP_FUNCTOR(reporter<>(post_handler_ptr(new report_accounts(*this)), + *this, "#accounts")); } break; @@ -1395,9 +1395,10 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (*(p + 1) == '\0' || is_eq(p, "bal") || is_eq(p, "balance")) { return expr_t::op_t::wrap_functor (reporter - (new format_accounts(*this, report_format(HANDLER(balance_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t()), + (acct_handler_ptr(new format_accounts + (*this, report_format(HANDLER(balance_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())), *this, "#balance")); } else if (is_eq(p, "budget")) { @@ -1407,11 +1408,24 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (! (budget_flags & ~BUDGET_WRAP_VALUES)) budget_flags |= BUDGET_BUDGETED; +#if 0 +#define POSTS_REPORT(formatter) + return WRAP_FUNCTOR(reporter<>(post_handler_ptr(formatter), *this, + string("#") + p)); + +#define ACCOUNTS_REPORT(formatter) + return WRAP_FUNCTOR(reporter + (acct_handler_ptr(formatter), *this, + string("#") + p)); +#endif + return expr_t::op_t::wrap_functor (reporter - (new format_accounts(*this, report_format(HANDLER(budget_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t()), + (acct_handler_ptr(new format_accounts + (*this, report_format(HANDLER(budget_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())), *this, "#budget")); } break; @@ -1420,9 +1434,10 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (is_eq(p, "csv")) { return WRAP_FUNCTOR (reporter<> - (new format_posts(*this, report_format(HANDLER(csv_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t()), + (post_handler_ptr(new format_posts + (*this, report_format(HANDLER(csv_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())), *this, "#csv")); } else if (is_eq(p, "cleared")) { @@ -1430,31 +1445,35 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, "(amount, cleared ? amount : 0)"); return expr_t::op_t::wrap_functor (reporter - (new format_accounts(*this, report_format(HANDLER(cleared_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t()), + (acct_handler_ptr(new format_accounts + (*this, report_format(HANDLER(cleared_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())), *this, "#cleared")); } else if (is_eq(p, "convert")) { return WRAP_FUNCTOR(convert_command); } else if (is_eq(p, "commodities")) { - return WRAP_FUNCTOR(reporter<>(new report_commodities(*this), *this, - "#commodities")); + return WRAP_FUNCTOR(reporter<> + (post_handler_ptr(new report_commodities(*this)), + *this, "#commodities")); } break; case 'e': if (is_eq(p, "equity")) { HANDLER(generated).on_only(string("#equity")); - return WRAP_FUNCTOR(reporter<>(new print_xacts(*this), *this, "#equity")); + return WRAP_FUNCTOR(reporter<>(post_handler_ptr(new print_xacts(*this)), + *this, "#equity")); } else if (is_eq(p, "entry")) { return WRAP_FUNCTOR(xact_command); } else if (is_eq(p, "emacs")) { return WRAP_FUNCTOR - (reporter<>(new format_emacs_posts(output_stream), *this, "#emacs")); + (reporter<>(post_handler_ptr(new format_emacs_posts(output_stream)), + *this, "#emacs")); } else if (is_eq(p, "echo")) { return MAKE_FUNCTOR(report_t::echo_command); @@ -1465,7 +1484,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (is_eq(p, "org")) { return WRAP_FUNCTOR (reporter<> - (new posts_to_org_table(*this, maybe_format(HANDLER(prepend_format_))), + (post_handler_ptr(new posts_to_org_table + (*this, maybe_format(HANDLER(prepend_format_)))), *this, "#org")); } break; @@ -1473,30 +1493,33 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, case 'p': if (*(p + 1) == '\0' || is_eq(p, "print")) { return WRAP_FUNCTOR - (reporter<>(new print_xacts(*this, HANDLED(raw)), *this, "#print")); + (reporter<>(post_handler_ptr(new print_xacts(*this, HANDLED(raw))), + *this, "#print")); } else if (is_eq(p, "prices")) { return expr_t::op_t::wrap_functor (reporter - (new format_posts(*this, report_format(HANDLER(prices_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t()), + (post_handler_ptr(new format_posts + (*this, report_format(HANDLER(prices_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())), *this, "#prices")); } else if (is_eq(p, "pricedb")) { return expr_t::op_t::wrap_functor (reporter - (new format_posts(*this, report_format(HANDLER(pricedb_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t()), + (post_handler_ptr(new format_posts + (*this, report_format(HANDLER(pricedb_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())), *this, "#pricedb")); } else if (is_eq(p, "pricemap")) { return MAKE_FUNCTOR(report_t::pricemap_command); } else if (is_eq(p, "payees")) { - return WRAP_FUNCTOR(reporter<>(new report_payees(*this), *this, - "#payees")); + return WRAP_FUNCTOR(reporter<>(post_handler_ptr(new report_payees(*this)), + *this, "#payees")); } break; @@ -1504,9 +1527,10 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register")) { return WRAP_FUNCTOR (reporter<> - (new format_posts(*this, report_format(HANDLER(register_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t()), + (post_handler_ptr(new format_posts + (*this, report_format(HANDLER(register_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())), *this, "#register")); } else if (is_eq(p, "reload")) { @@ -1525,7 +1549,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (is_eq(p, "xact")) return WRAP_FUNCTOR(xact_command); else if (is_eq(p, "xml")) - return WRAP_FUNCTOR(reporter<>(new format_xml(*this), *this, "#xml")); + return WRAP_FUNCTOR(reporter<>(post_handler_ptr(new format_xml(*this)), + *this, "#xml")); break; } break; @@ -1550,7 +1575,7 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (is_eq(p, "generate")) { return expr_t::op_t::wrap_functor (reporter - (new print_xacts(*this), *this, "#generate")); + (post_handler_ptr(new print_xacts(*this)), *this, "#generate")); } break; case 'p': diff --git a/src/report.h b/src/report.h index 35d45437..03eee78b 100644 --- a/src/report.h +++ b/src/report.h @@ -1019,7 +1019,7 @@ class reporter string whence; public: - reporter(item_handler * _handler, + reporter(shared_ptr > _handler, report_t& _report, const string& _whence) : handler(_handler), report(_report), whence(_whence) {} -- cgit v1.2.3 From 477a9106e3788b33863a7701466860eb5f9682e3 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 5 Mar 2012 15:52:33 -0600 Subject: Prettified some code in report.cc --- src/report.cc | 139 +++++++++++++++++++++++----------------------------------- 1 file changed, 55 insertions(+), 84 deletions(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 7789ff80..90f482cc 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1382,24 +1382,37 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return MAKE_OPT_HANDLER(report_t, handler); break; +#define POSTS_REPORT(formatter) \ + WRAP_FUNCTOR(reporter<>(post_handler_ptr(formatter), *this, \ + string("#") + p)); + + // Can't use WRAP_FUNCTOR here because the template arguments + // confuse the parser +#define POSTS_REPORT_(method, formatter) \ + expr_t::op_t::wrap_functor \ + (reporter \ + (post_handler_ptr(formatter), *this, string("#") + p)); + +#define ACCOUNTS_REPORT(formatter) \ + expr_t::op_t::wrap_functor(reporter \ + (acct_handler_ptr(formatter), *this, \ + string("#") + p)); + case symbol_t::COMMAND: switch (*p) { case 'a': if (is_eq(p, "accounts")) { - return WRAP_FUNCTOR(reporter<>(post_handler_ptr(new report_accounts(*this)), - *this, "#accounts")); + return POSTS_REPORT(new report_accounts(*this)); } break; case 'b': if (*(p + 1) == '\0' || is_eq(p, "bal") || is_eq(p, "balance")) { - return expr_t::op_t::wrap_functor - (reporter - (acct_handler_ptr(new format_accounts - (*this, report_format(HANDLER(balance_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())), - *this, "#balance")); + return ACCOUNTS_REPORT(new format_accounts + (*this, report_format(HANDLER(balance_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())); } else if (is_eq(p, "budget")) { HANDLER(amount_).set_expr(string("#budget"), "(amount, 0)"); @@ -1408,72 +1421,46 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (! (budget_flags & ~BUDGET_WRAP_VALUES)) budget_flags |= BUDGET_BUDGETED; -#if 0 -#define POSTS_REPORT(formatter) - return WRAP_FUNCTOR(reporter<>(post_handler_ptr(formatter), *this, - string("#") + p)); - -#define ACCOUNTS_REPORT(formatter) - return WRAP_FUNCTOR(reporter - (acct_handler_ptr(formatter), *this, - string("#") + p)); -#endif - - return expr_t::op_t::wrap_functor - (reporter - (acct_handler_ptr(new format_accounts - (*this, report_format(HANDLER(budget_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())), - *this, "#budget")); + return ACCOUNTS_REPORT(new format_accounts + (*this, report_format(HANDLER(budget_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())); } break; case 'c': if (is_eq(p, "csv")) { - return WRAP_FUNCTOR - (reporter<> - (post_handler_ptr(new format_posts - (*this, report_format(HANDLER(csv_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())), - *this, "#csv")); + return POSTS_REPORT(new format_posts + (*this, report_format(HANDLER(csv_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())); } else if (is_eq(p, "cleared")) { HANDLER(amount_).set_expr(string("#cleared"), "(amount, cleared ? amount : 0)"); - return expr_t::op_t::wrap_functor - (reporter - (acct_handler_ptr(new format_accounts - (*this, report_format(HANDLER(cleared_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())), - *this, "#cleared")); + return ACCOUNTS_REPORT(new format_accounts + (*this, report_format(HANDLER(cleared_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())); } else if (is_eq(p, "convert")) { return WRAP_FUNCTOR(convert_command); } else if (is_eq(p, "commodities")) { - return WRAP_FUNCTOR(reporter<> - (post_handler_ptr(new report_commodities(*this)), - *this, "#commodities")); + return POSTS_REPORT(new report_commodities(*this)); } break; case 'e': if (is_eq(p, "equity")) { HANDLER(generated).on_only(string("#equity")); - return WRAP_FUNCTOR(reporter<>(post_handler_ptr(new print_xacts(*this)), - *this, "#equity")); + return POSTS_REPORT(new print_xacts(*this)); } else if (is_eq(p, "entry")) { return WRAP_FUNCTOR(xact_command); } else if (is_eq(p, "emacs")) { - return WRAP_FUNCTOR - (reporter<>(post_handler_ptr(new format_emacs_posts(output_stream)), - *this, "#emacs")); + return POSTS_REPORT(new format_emacs_posts(output_stream)); } else if (is_eq(p, "echo")) { return MAKE_FUNCTOR(report_t::echo_command); @@ -1482,56 +1469,43 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, case 'o': if (is_eq(p, "org")) { - return WRAP_FUNCTOR - (reporter<> - (post_handler_ptr(new posts_to_org_table - (*this, maybe_format(HANDLER(prepend_format_)))), - *this, "#org")); + return POSTS_REPORT(new posts_to_org_table + (*this, maybe_format(HANDLER(prepend_format_)))); } break; case 'p': if (*(p + 1) == '\0' || is_eq(p, "print")) { - return WRAP_FUNCTOR - (reporter<>(post_handler_ptr(new print_xacts(*this, HANDLED(raw))), - *this, "#print")); + return POSTS_REPORT(new print_xacts(*this, HANDLED(raw))); } else if (is_eq(p, "prices")) { - return expr_t::op_t::wrap_functor - (reporter - (post_handler_ptr(new format_posts + return POSTS_REPORT_(&report_t::commodities_report, + new format_posts (*this, report_format(HANDLER(prices_format_)), maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())), - *this, "#prices")); + HANDLER(prepend_width_).value.to_size_t())); } else if (is_eq(p, "pricedb")) { - return expr_t::op_t::wrap_functor - (reporter - (post_handler_ptr(new format_posts + return POSTS_REPORT_(&report_t::commodities_report, + new format_posts (*this, report_format(HANDLER(pricedb_format_)), maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())), - *this, "#pricedb")); + HANDLER(prepend_width_).value.to_size_t())); } else if (is_eq(p, "pricemap")) { return MAKE_FUNCTOR(report_t::pricemap_command); } else if (is_eq(p, "payees")) { - return WRAP_FUNCTOR(reporter<>(post_handler_ptr(new report_payees(*this)), - *this, "#payees")); + return POSTS_REPORT(new report_payees(*this)); } break; case 'r': if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register")) { - return WRAP_FUNCTOR - (reporter<> - (post_handler_ptr(new format_posts - (*this, report_format(HANDLER(register_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())), - *this, "#register")); + return POSTS_REPORT(new format_posts + (*this, report_format(HANDLER(register_format_)), + maybe_format(HANDLER(prepend_format_)), + HANDLER(prepend_width_).value.to_size_t())); } else if (is_eq(p, "reload")) { return MAKE_FUNCTOR(report_t::reload_command); @@ -1549,8 +1523,7 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (is_eq(p, "xact")) return WRAP_FUNCTOR(xact_command); else if (is_eq(p, "xml")) - return WRAP_FUNCTOR(reporter<>(post_handler_ptr(new format_xml(*this)), - *this, "#xml")); + return POSTS_REPORT(new format_xml(*this)); break; } break; @@ -1572,11 +1545,9 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return WRAP_FUNCTOR(format_command); break; case 'g': - if (is_eq(p, "generate")) { - return expr_t::op_t::wrap_functor - (reporter - (post_handler_ptr(new print_xacts(*this)), *this, "#generate")); - } + if (is_eq(p, "generate")) + return POSTS_REPORT_(&report_t::generate_report, + new print_xacts(*this)); break; case 'p': if (is_eq(p, "parse")) -- cgit v1.2.3 From b6adc8f4605befc2e6a91dfa28cc9237fb391fbc Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 5 Mar 2012 17:46:42 -0600 Subject: Use unique_ptr instead of std::auto_ptr --- src/amount.cc | 4 ++-- src/csv.cc | 4 ++-- src/draft.cc | 4 ++-- src/format.cc | 2 +- src/main.cc | 2 +- src/report.cc | 2 +- src/session.h | 4 ++-- src/textual.cc | 10 +++++----- src/timelog.cc | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src/report.cc') diff --git a/src/amount.cc b/src/amount.cc index 9704dd21..3ddb7672 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -1027,12 +1027,12 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags) } // Allocate memory for the amount's quantity value. We have to - // monitor the allocation in an auto_ptr because this function gets + // monitor the allocation in a unique_ptr because this function gets // called sometimes from amount_t's constructor; and if there is an // exeception thrown by any of the function calls after this point, // the destructor will never be called and the memory never freed. - std::auto_ptr new_quantity; + unique_ptr new_quantity; if (quantity) { if (quantity->refc > 1) diff --git a/src/csv.cc b/src/csv.cc index 305db992..1e55129e 100644 --- a/src/csv.cc +++ b/src/csv.cc @@ -139,8 +139,8 @@ xact_t * csv_reader::read_xact(bool rich_data) std::istringstream instr(line); - std::auto_ptr xact(new xact_t); - std::auto_ptr post(new post_t); + unique_ptr xact(new xact_t); + unique_ptr post(new post_t); xact->set_state(item_t::CLEARED); diff --git a/src/draft.cc b/src/draft.cc index 7c95caf7..017c637d 100644 --- a/src/draft.cc +++ b/src/draft.cc @@ -233,7 +233,7 @@ xact_t * draft_t::insert(journal_t& journal) throw std::runtime_error(_("'xact' command requires at least a payee")); xact_t * matching = NULL; - std::auto_ptr added(new xact_t); + unique_ptr added(new xact_t); if (xact_t * xact = lookup_probable_account(tmpl->payee_mask.str(), journal.xacts.rbegin(), @@ -316,7 +316,7 @@ xact_t * draft_t::insert(journal_t& journal) } foreach (xact_template_t::post_template_t& post, tmpl->posts) { - std::auto_ptr new_post; + unique_ptr new_post; commodity_t * found_commodity = NULL; diff --git a/src/format.cc b/src/format.cc index 9824d5f7..d8c03e6a 100644 --- a/src/format.cc +++ b/src/format.cc @@ -125,7 +125,7 @@ namespace { format_t::element_t * format_t::parse_elements(const string& fmt, const optional& tmpl) { - std::auto_ptr result; + unique_ptr result; element_t * current = NULL; diff --git a/src/main.cc b/src/main.cc index aafbdbcb..dd03206f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -80,7 +80,7 @@ int main(int argc, char * argv[], char * envp[]) ::textdomain("ledger"); #endif - std::auto_ptr global_scope; + unique_ptr global_scope; try { // Create the session object, which maintains nearly all state relating to diff --git a/src/report.cc b/src/report.cc index 90f482cc..b86f77eb 100644 --- a/src/report.cc +++ b/src/report.cc @@ -309,7 +309,7 @@ void report_t::posts_report(post_handler_ptr handler) { handler = chain_post_handlers(handler, *this); if (HANDLED(group_by_)) { - std::auto_ptr + unique_ptr splitter(new post_splitter(handler, *this, HANDLER(group_by_).expr)); splitter->set_postflush_func(posts_flusher(handler, *this)); handler = post_handler_ptr(splitter.release()); diff --git a/src/session.h b/src/session.h index 879efeb6..cfeced39 100644 --- a/src/session.h +++ b/src/session.h @@ -59,8 +59,8 @@ class session_t : public symbol_scope_t public: bool flush_on_next_data_file; - std::auto_ptr journal; - parse_context_stack_t parsing_context; + unique_ptr journal; + parse_context_stack_t parsing_context; explicit session_t(); virtual ~session_t() { diff --git a/src/textual.cc b/src/textual.cc index 95635184..2493dc0d 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -527,7 +527,7 @@ void instance_t::automated_xact_directive(char * line) query.parse_args(string_value(skip_ws(line + 1)).to_sequence(), keeper, false, true); - std::auto_ptr ae(new auto_xact_t(predicate_t(expr, keeper))); + unique_ptr ae(new auto_xact_t(predicate_t(expr, keeper))); ae->pos = position_t(); ae->pos->pathname = context.pathname; ae->pos->beg_pos = context.line_beg_pos; @@ -621,7 +621,7 @@ void instance_t::period_xact_directive(char * line) try { - std::auto_ptr pe(new period_xact_t(skip_ws(line + 1))); + unique_ptr pe(new period_xact_t(skip_ws(line + 1))); pe->pos = position_t(); pe->pos->pathname = context.pathname; pe->pos->beg_pos = context.line_beg_pos; @@ -665,7 +665,7 @@ void instance_t::xact_directive(char * line, std::streamsize len) TRACE_START(xacts, 1, "Time spent handling transactions:"); if (xact_t * xact = parse_xact(line, len, top_account())) { - std::auto_ptr manager(xact); + unique_ptr manager(xact); if (context.journal->add_xact(xact)) { manager.release(); // it's owned by the journal now @@ -874,7 +874,7 @@ void instance_t::account_directive(char * line) char * p = skip_ws(line); account_t * account = context.journal->register_account(p, NULL, top_account()); - std::auto_ptr ae; + unique_ptr ae; while (peek_whitespace_line()) { read_line(line); @@ -1287,7 +1287,7 @@ post_t * instance_t::parse_post(char * line, { TRACE_START(post_details, 1, "Time spent parsing postings:"); - std::auto_ptr post(new post_t); + unique_ptr post(new post_t); post->xact = xact; // this could be NULL post->pos = position_t(); diff --git a/src/timelog.cc b/src/timelog.cc index 67ea1015..b46d3922 100644 --- a/src/timelog.cc +++ b/src/timelog.cc @@ -88,7 +88,7 @@ namespace { if (! out_event.note.empty() && event.note.empty()) event.note = out_event.note; - std::auto_ptr curr(new xact_t); + unique_ptr curr(new xact_t); curr->_date = event.checkin.date(); curr->code = out_event.desc; // if it wasn't used above curr->payee = event.desc; -- cgit v1.2.3 From b1107f85ae07a85124e58a0e379ec2d9ab47d119 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 7 Mar 2012 10:32:24 -0600 Subject: Removed value_t::price and balance_t::price --- src/balance.cc | 10 ---------- src/balance.h | 2 -- src/py_balance.cc | 2 -- src/py_value.cc | 3 +-- src/report.cc | 7 ------- src/report.h | 1 - src/value.cc | 12 ------------ src/value.h | 2 -- 8 files changed, 1 insertion(+), 38 deletions(-) (limited to 'src/report.cc') diff --git a/src/balance.cc b/src/balance.cc index 4fba7344..08368dd8 100644 --- a/src/balance.cc +++ b/src/balance.cc @@ -202,16 +202,6 @@ balance_t::value(const optional& moment, return resolved ? temp : optional(); } -balance_t balance_t::price() const -{ - balance_t temp; - - foreach (const amounts_map::value_type& pair, amounts) - temp += pair.second.price(); - - return temp; -} - optional balance_t::commodity_amount(const optional& commodity) const { diff --git a/src/balance.h b/src/balance.h index 57e6ace4..921f87ef 100644 --- a/src/balance.h +++ b/src/balance.h @@ -387,8 +387,6 @@ public: value(const optional& moment = none, const optional& in_terms_of = none) const; - balance_t price() const; - /** * Truth tests. An balance may be truth test in two ways: * diff --git a/src/py_balance.cc b/src/py_balance.cc index 6c9ccb24..38941832 100644 --- a/src/py_balance.cc +++ b/src/py_balance.cc @@ -201,8 +201,6 @@ void export_balance() .def("value", py_value_1, args("in_terms_of")) .def("value", py_value_2, args("in_terms_of", "moment")) - .def("price", &balance_t::price) - .def("__nonzero__", &balance_t::is_nonzero) .def("is_nonzero", &balance_t::is_nonzero) .def("is_zero", &balance_t::is_zero) diff --git a/src/py_value.cc b/src/py_value.cc index 949f2a49..78301acd 100644 --- a/src/py_value.cc +++ b/src/py_value.cc @@ -266,8 +266,7 @@ void export_value() .def("value", py_value_1, args("in_terms_of")) .def("value", py_value_2, args("in_terms_of", "moment")) - .def("value", &value_t::value, value_overloads()) - .def("price", &value_t::price) + //.def("value", &value_t::value, value_overloads()) .def("exchange_commodities", &value_t::exchange_commodities, exchange_commodities_overloads()) diff --git a/src/report.cc b/src/report.cc index b86f77eb..52e8c888 100644 --- a/src/report.cc +++ b/src/report.cc @@ -731,11 +731,6 @@ value_t report_t::fn_percent(call_scope_t& args) (args.get(0) / args.get(1)).number()); } -value_t report_t::fn_price(call_scope_t& args) -{ - return args[0].price(); -} - value_t report_t::fn_commodity(call_scope_t& args) { return string_value(args.get(0).commodity().symbol()); @@ -1278,8 +1273,6 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return WRAP_FUNCTOR(fn_false); else if (is_eq(p, "percent")) return MAKE_FUNCTOR(report_t::fn_percent); - else if (is_eq(p, "price")) - return MAKE_FUNCTOR(report_t::fn_price); else if (is_eq(p, "print")) return MAKE_FUNCTOR(report_t::fn_print); break; diff --git a/src/report.h b/src/report.h index 03eee78b..9541da43 100644 --- a/src/report.h +++ b/src/report.h @@ -169,7 +169,6 @@ public: value_t fn_format_date(call_scope_t& scope); value_t fn_ansify_if(call_scope_t& scope); value_t fn_percent(call_scope_t& scope); - value_t fn_price(call_scope_t& scope); value_t fn_commodity(call_scope_t& scope); value_t fn_lot_date(call_scope_t& scope); value_t fn_lot_price(call_scope_t& scope); diff --git a/src/value.cc b/src/value.cc index 2446c97a..de491e6c 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1427,18 +1427,6 @@ value_t value_t::value(const optional& moment, return NULL_VALUE; } -value_t value_t::price() const -{ - switch (type()) { - case AMOUNT: - return as_amount().price(); - case BALANCE: - return as_balance().price(); - default: - return *this; - } -} - value_t value_t::exchange_commodities(const std::string& commodities, const bool add_prices, const optional& moment) diff --git a/src/value.h b/src/value.h index 1e4d0ce9..df075843 100644 --- a/src/value.h +++ b/src/value.h @@ -480,8 +480,6 @@ public: value_t value(const optional& moment = none, const optional& in_terms_of = none) const; - value_t price() const; - value_t exchange_commodities(const std::string& commodities, const bool add_prices = false, const optional& moment = none); -- cgit v1.2.3 From 21e8b7f6f0a182f67899c5cd3689a5e646d8ed4a Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 8 Mar 2012 00:55:06 -0600 Subject: Added nail_down() for pinning market value exprs --- src/commodity.cc | 9 +++++++++ src/commodity.h | 2 ++ src/report.cc | 20 ++++++++++++++++++++ src/report.h | 1 + 4 files changed, 32 insertions(+) (limited to 'src/report.cc') diff --git a/src/commodity.cc b/src/commodity.cc index 24d54695..dd1b2743 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -217,6 +217,15 @@ commodity_t::check_for_updated_price(const optional& point, return point; } +commodity_t& commodity_t::nail_down(const expr_t& expr) +{ + annotation_t new_details; + new_details.value_expr = expr; + commodity_t * new_comm = + commodity_pool_t::current_pool->find_or_create(symbol(), new_details); + return *new_comm; +} + commodity_t::operator bool() const { return this != pool().null_commodity; diff --git a/src/commodity.h b/src/commodity.h index 3d36e35e..3f493f8b 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -291,6 +291,8 @@ public: const optional& moment, const optional& in_terms_of); + commodity_t& nail_down(const expr_t& expr); + // Methods related to parsing, reading, writing, etc., the commodity // itself. diff --git a/src/report.cc b/src/report.cc index 52e8c888..ba70d1d3 100644 --- a/src/report.cc +++ b/src/report.cc @@ -736,6 +736,24 @@ value_t report_t::fn_commodity(call_scope_t& args) return string_value(args.get(0).commodity().symbol()); } +value_t report_t::fn_nail_down(call_scope_t& args) +{ + value_t arg0(args[0]); + switch (arg0.type()) { + case value_t::AMOUNT: { + amount_t tmp(arg0.as_amount()); + if (tmp.has_commodity()) + tmp.set_commodity(tmp.commodity() + .nail_down(args[1].as_any())); + return tmp; + } + + default: + throw_(std::runtime_error, _("Attempting to nail down %1") + << args[0].label()); + } +} + value_t report_t::fn_lot_date(call_scope_t& args) { if (args[0].has_annotation()) { @@ -1261,6 +1279,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return WRAP_FUNCTOR(fn_null); else if (is_eq(p, "now")) return MAKE_FUNCTOR(report_t::fn_now); + else if (is_eq(p, "nail_down")) + return MAKE_FUNCTOR(report_t::fn_nail_down); break; case 'o': diff --git a/src/report.h b/src/report.h index f50bdc28..515b14c2 100644 --- a/src/report.h +++ b/src/report.h @@ -170,6 +170,7 @@ public: value_t fn_ansify_if(call_scope_t& scope); value_t fn_percent(call_scope_t& scope); value_t fn_commodity(call_scope_t& scope); + value_t fn_nail_down(call_scope_t& scope); value_t fn_lot_date(call_scope_t& scope); value_t fn_lot_price(call_scope_t& scope); value_t fn_lot_tag(call_scope_t& scope); -- cgit v1.2.3 From 113fb0ee6a520dccdcd18a634f7ee73acd8ee488 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 8 Mar 2012 01:00:16 -0600 Subject: Added --historical option --- doc/ledger.1 | 3 +- src/report.cc | 3 +- src/report.h | 8 +++++ test/baseline/opt-historical.test | 61 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 test/baseline/opt-historical.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index 4829034f..2fb074cb 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -1,4 +1,4 @@ -.Dd February 28, 2012 +.Dd March 7, 2012 .Dt ledger 1 .Sh NAME .Nm ledger @@ -163,6 +163,7 @@ Show any gains (or losses) in commodity values over time. Only show the top .Ar number postings. +.It Fl \-historical Pq Fl H .It Fl \-invert Invert the value of amounts shown. .It Fl \-market Pq Fl V diff --git a/src/report.cc b/src/report.cc index ba70d1d3..26e6da0c 100644 --- a/src/report.cc +++ b/src/report.cc @@ -924,11 +924,9 @@ option_t * report_t::lookup_option(const char * p) case 'G': OPT_CH(gain); break; -#if 0 case 'H': OPT_CH(historical); break; -#endif case 'I': OPT_CH(price); break; @@ -1044,6 +1042,7 @@ option_t * report_t::lookup_option(const char * p) break; case 'h': OPT(head_); + else OPT(historical); break; case 'i': OPT(invert); diff --git a/src/report.h b/src/report.h index 515b14c2..d68d1f75 100644 --- a/src/report.h +++ b/src/report.h @@ -645,6 +645,14 @@ public: }); OPTION(report_t, head_); + + OPTION_(report_t, historical, DO() { // -H + parent->HANDLER(amount_) + .set_expr(string("--historical"), + "nail_down(amount_expr, (s,d,t -> market(s,value_date,t)))"); + }); + + OPTION(report_t, inject_); OPTION_(report_t, invert, DO() { diff --git a/test/baseline/opt-historical.test b/test/baseline/opt-historical.test new file mode 100644 index 00000000..1cd141ab --- /dev/null +++ b/test/baseline/opt-historical.test @@ -0,0 +1,61 @@ +2012-03-01 Broker + Assets:Stocks 10 APPL {$1} @ $1 + Equity + +2012-03-02 Broker + Assets:Stocks 10 APPL {$1} @ $2 + Equity + +2012-03-03 Broker + Assets:Stocks 10 APPL {$1} @ $3 + Equity + +2012-03-04 Broker + Assets:Stocks 10 APPL {$1} @ $4 + Equity + +2012-03-05 Broker + Assets:Stocks 10 APPL {$1} @ $5 + Equity + +test reg stocks -O +12-Mar-01 Broker Assets:Stocks 10 APPL 10 APPL +12-Mar-02 Broker Assets:Stocks 10 APPL 20 APPL +12-Mar-03 Broker Assets:Stocks 10 APPL 30 APPL +12-Mar-04 Broker Assets:Stocks 10 APPL 40 APPL +12-Mar-05 Broker Assets:Stocks 10 APPL 50 APPL +end test + +test reg stocks -B +12-Mar-01 Broker Assets:Stocks $10 $10 +12-Mar-02 Broker Assets:Stocks $20 $30 +12-Mar-03 Broker Assets:Stocks $30 $60 +12-Mar-04 Broker Assets:Stocks $40 $100 +12-Mar-05 Broker Assets:Stocks $50 $150 +end test + +test reg stocks -I +12-Mar-01 Broker Assets:Stocks $10 $10 +12-Mar-02 Broker Assets:Stocks $10 $20 +12-Mar-03 Broker Assets:Stocks $10 $30 +12-Mar-04 Broker Assets:Stocks $10 $40 +12-Mar-05 Broker Assets:Stocks $10 $50 +end test + +test reg stocks -O -H +end test + +test reg stocks -B -H +end test + +test reg stocks -I -H +end test + +test reg stocks -O -V +end test + +test reg stocks -B -V +end test + +test reg stocks -I -V +end test -- cgit v1.2.3 From 9f81c798ee0854cab038714670123bff6676a5d5 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 8 Mar 2012 01:08:08 -0600 Subject: fn_market can now accept a commodity name for arg 0 --- src/report.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 26e6da0c..02fd7c18 100644 --- a/src/report.cc +++ b/src/report.cc @@ -517,11 +517,21 @@ value_t report_t::fn_market(call_scope_t& args) args.get(1) : optional()); value_t result; + value_t arg0 = args[0]; + + if (arg0.is_string()) { + amount_t tmp(1L); + commodity_t * commodity = + commodity_pool_t::current_pool->find_or_create(arg0.as_string()); + tmp.set_commodity(*commodity); + arg0 = tmp; + } + if (args.has(2)) - result = args[0].exchange_commodities(args.get(2), - /* add_prices= */ false, moment); + result = arg0.exchange_commodities(args.get(2), + /* add_prices= */ false, moment); else - result = args[0].value(moment); + result = arg0.value(moment); if (! result.is_null()) return result; -- cgit v1.2.3 From 59f5ebe2dfe7cc93e36377f0251691e4de7b83b4 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Fri, 9 Mar 2012 03:51:53 -0600 Subject: Reworked the way that options are handled --- doc/ledger.1 | 3 +- src/chain.cc | 11 +- src/draft.cc | 2 +- src/option.h | 77 ++--- src/print.cc | 17 +- src/pyinterp.h | 4 +- src/report.cc | 240 ++++++++------- src/report.h | 635 ++++++++++++++++++---------------------- src/session.h | 18 +- test/baseline/opt-no-pager.test | 0 10 files changed, 468 insertions(+), 539 deletions(-) create mode 100644 test/baseline/opt-no-pager.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index 2fb074cb..a948d5a6 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -1,4 +1,4 @@ -.Dd March 7, 2012 +.Dd March 9, 2012 .Dt ledger 1 .Sh NAME .Nm ledger @@ -359,6 +359,7 @@ See .It Fl \-meta-width Ar INT .It Fl \-monthly Pq Fl M .It Fl \-no-color +.It Fl \-no-pager .It Fl \-no-rounding .It Fl \-no-titles .It Fl \-no-total diff --git a/src/chain.cc b/src/chain.cc index f8f0aeff..44b3db82 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -88,10 +88,9 @@ post_handler_ptr chain_pre_post_handlers(post_handler_ptr base_handler, predicate_t(report.HANDLER(forecast_while_).str(), report.what_to_keep()), report, - report.HANDLED(forecast_years_) ? - static_cast - (report.HANDLER(forecast_years_).value.to_long()) : - 5UL); + (report.HANDLED(forecast_years_) ? + lexical_cast + (report.HANDLER(forecast_years_).value) : 5UL)); forecast_handler->add_period_xacts(report.session.journal->period_xacts); handler.reset(forecast_handler); @@ -137,9 +136,9 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler, handler.reset (new truncate_xacts(handler, report.HANDLED(head_) ? - report.HANDLER(head_).value.to_int() : 0, + lexical_cast(report.HANDLER(head_).value) : 0, report.HANDLED(tail_) ? - report.HANDLER(tail_).value.to_int() : 0)); + lexical_cast(report.HANDLER(tail_).value) : 0)); // display_filter_posts adds virtual posts to the list to account // for changes in value of commodities, which otherwise would affect diff --git a/src/draft.cc b/src/draft.cc index 9abc769e..74a6f4d2 100644 --- a/src/draft.cc +++ b/src/draft.cc @@ -522,7 +522,7 @@ value_t xact_command(call_scope_t& args) xact_t * new_xact = draft.insert(*report.session.journal.get()); // Only consider actual postings for the "xact" command - report.HANDLER(limit_).on(string("#xact"), "actual"); + report.HANDLER(limit_).on("#xact", "actual"); if (new_xact) report.xact_report(post_handler_ptr(new print_xacts(report)), *new_xact); diff --git a/src/option.h b/src/option.h index 38431f9d..f892b00e 100644 --- a/src/option.h +++ b/src/option.h @@ -61,9 +61,9 @@ protected: option_t& operator=(const option_t&); public: - T * parent; - value_t value; - bool wants_arg; + T * parent; + string value; + bool wants_arg; option_t(const char * _name, const char _ch = '\0') : name(_name), name_len(std::strlen(name)), ch(_ch), @@ -94,7 +94,8 @@ public: out << std::right << desc(); if (wants_arg) { out << " = "; - value.print(out, 42); + out.width(42); + out << value; } else { out.width(45); out << ' '; @@ -123,43 +124,49 @@ public: return handled; } - string& str() { + string str() const { assert(handled); - if (! value) + if (value.empty()) throw_(std::runtime_error, _("No argument provided for %1") << desc()); - return value.as_string_lval(); + return value; } - string str() const { - assert(handled); - if (! value) - throw_(std::runtime_error, _("No argument provided for %1") << desc()); - return value.as_string(); + void on(const char * whence) { + on(string(whence)); } + void on(const optional& whence) { + handler_thunk(whence); - void on_only(const optional& whence) { handled = true; source = whence; } - void on(const optional& whence, const string& str) { - on_with(whence, string_value(str)); + + void on(const char * whence, const string& str) { + on(string(whence), str); } - virtual void on_with(const optional& whence, - const value_t& val) { + void on(const optional& whence, const string& str) { + string before = value; + + handler_thunk(whence, str); + + if (value == before) + value = str; + handled = true; - value = val; source = whence; } void off() { handled = false; - value = value_t(); + value = ""; source = none; } - virtual void handler_thunk(call_scope_t&) {} + virtual void handler_thunk(const optional& whence) {} + virtual void handler_thunk(const optional& whence, + const string& str) {} - virtual void handler(call_scope_t& args) { + value_t handler(call_scope_t& args) { if (wants_arg) { if (args.size() < 2) throw_(std::runtime_error, _("No argument provided for %1") << desc()); @@ -167,7 +174,7 @@ public: throw_(std::runtime_error, _("To many arguments provided for %1") << desc()); else if (! args[0].is_string()) throw_(std::runtime_error, _("Context argument for %1 not a string") << desc()); - on_with(args.get(0), args[1]); + on(args.get(0), args.get(1)); } else if (args.size() < 1) { throw_(std::runtime_error, _("No argument provided for %1") << desc()); @@ -176,27 +183,18 @@ public: throw_(std::runtime_error, _("Context argument for %1 not a string") << desc()); } else { - on_only(args.get(0)); + on(args.get(0)); } - - handler_thunk(args); - } - - virtual value_t handler_wrapper(call_scope_t& args) { - handler(args); return true; } virtual value_t operator()(call_scope_t& args) { if (! args.empty()) { args.push_front(string_value("?expr")); - return handler_wrapper(args); + return handler(args); } else if (wants_arg) { - if (handled) - return value; - else - return NULL_VALUE; + return string_value(value); } else { return handled; @@ -215,15 +213,16 @@ public: vartype var ; \ name ## option_t() : option_t(#name), var value -#define DO() virtual void handler_thunk(call_scope_t&) -#define DO_(var) virtual void handler_thunk(call_scope_t& var) +#define DO() virtual void handler_thunk(const optional& whence) +#define DO_(var) virtual void handler_thunk(const optional& whence, \ + const string& var) #define END(name) name ## handler #define COPY_OPT(name, other) name ## handler(other.name ## handler) #define MAKE_OPT_HANDLER(type, x) \ - expr_t::op_t::wrap_functor(bind(&option_t::handler_wrapper, x, _1)) + expr_t::op_t::wrap_functor(bind(&option_t::handler, x, _1)) #define MAKE_OPT_FUNCTOR(type, x) \ expr_t::op_t::wrap_functor(bind(&option_t::operator(), x, _1)) @@ -284,6 +283,10 @@ inline bool is_eq(const char * p, const char * n) { } \ END(name) +#define OTHER(name) \ + parent->HANDLER(name).parent = parent; \ + parent->HANDLER(name) + bool process_option(const string& whence, const string& name, scope_t& scope, const char * arg, const string& varname); diff --git a/src/print.cc b/src/print.cc index c544c4e0..9e52ce95 100644 --- a/src/print.cc +++ b/src/print.cc @@ -133,7 +133,7 @@ namespace { std::size_t columns = (report.HANDLED(columns_) ? - static_cast(report.HANDLER(columns_).value.to_long()) : 80); + lexical_cast(report.HANDLER(columns_).str()) : 80); if (xact.note) print_note(out, *xact.note, xact.has_flags(ITEM_NOTE_ON_NEXT_LINE), @@ -191,8 +191,8 @@ namespace { unistring name(pbuf.str()); std::size_t account_width = - (report.HANDLER(account_width_).specified ? - static_cast(report.HANDLER(account_width_).value.to_long()) : 36); + (report.HANDLED(account_width_) ? + lexical_cast(report.HANDLER(account_width_).str()) : 36); if (account_width < name.length()) account_width = name.length(); @@ -218,13 +218,14 @@ namespace { // first. } else { - int amount_width = - (report.HANDLER(amount_width_).specified ? - report.HANDLER(amount_width_).value.to_int() : 12); + std::size_t amount_width = + (report.HANDLED(amount_width_) ? + lexical_cast(report.HANDLER(amount_width_).str()) : + 12); std::ostringstream amt_str; - value_t(post->amount).print(amt_str, amount_width, -1, - AMOUNT_PRINT_RIGHT_JUSTIFY | + value_t(post->amount).print(amt_str, static_cast(amount_width), + -1, AMOUNT_PRINT_RIGHT_JUSTIFY | AMOUNT_PRINT_NO_COMPUTED_ANNOTATIONS); amt = amt_str.str(); } diff --git a/src/pyinterp.h b/src/pyinterp.h index 8699f69d..556b1563 100644 --- a/src/pyinterp.h +++ b/src/pyinterp.h @@ -136,8 +136,8 @@ public: virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind, const string& name); - OPTION_(python_interpreter_t, import_, DO_(args) { - parent->import_option(args.get(1)); + OPTION_(python_interpreter_t, import_, DO_(str) { + parent->import_option(str); }); }; diff --git a/src/report.cc b/src/report.cc index 02fd7c18..110d33ee 100644 --- a/src/report.cc +++ b/src/report.cc @@ -59,7 +59,7 @@ void report_t::normalize_options(const string& verb) #ifdef HAVE_ISATTY if (! HANDLED(force_color)) { if (! HANDLED(no_color) && isatty(STDOUT_FILENO)) - HANDLER(color).on_only(string("?normalize")); + HANDLER(color).on("?normalize"); if (HANDLED(color) && ! isatty(STDOUT_FILENO)) HANDLER(color).off(); } @@ -83,7 +83,7 @@ void report_t::normalize_options(const string& verb) if (session.HANDLED(price_exp_)) commodity_pool_t::current_pool->quote_leeway = - session.HANDLER(price_exp_).value.as_long(); + lexical_cast(session.HANDLER(price_exp_).value) * 3600L; if (session.HANDLED(price_db_)) commodity_pool_t::current_pool->price_db = session.HANDLER(price_db_).str(); @@ -106,39 +106,35 @@ void report_t::normalize_options(const string& verb) if (! HANDLED(meta_width_)) { string::size_type i = HANDLER(meta_).str().find(':'); if (i != string::npos) { - HANDLED(meta_width_).on_with - (string("?normalize"), - lexical_cast(string(HANDLER(meta_).str(), i + 1))); - HANDLED(meta_).on(string("?normalize"), + HANDLED(meta_width_).on("?normalize", + string(HANDLER(meta_).str(), i + 1)); + HANDLED(meta_).on("?normalize", string(HANDLER(meta_).str(), 0, i)); } } if (HANDLED(meta_width_)) { - HANDLER(prepend_format_).on - (string("?normalize"), - string("%(justify(truncated(tag(\"") + - HANDLER(meta_).str() + "\"), " + - HANDLED(meta_width_).value.to_string() + " - 1), " + - HANDLED(meta_width_).value.to_string() + "))"); - meta_width = HANDLED(meta_width_).value.to_long(); + HANDLER(prepend_format_) + .on("?normalize", string("%(justify(truncated(tag(\"") + + HANDLER(meta_).str() + "\"), " + + HANDLED(meta_width_).value + " - 1), " + + HANDLED(meta_width_).value + "))"); + meta_width = lexical_cast(HANDLED(meta_width_).value); } else { - HANDLER(prepend_format_).on(string("?normalize"), string("%(tag(\"") + - HANDLER(meta_).str() + "\"))"); + HANDLER(prepend_format_) + .on("?normalize", string("%(tag(\"") + HANDLER(meta_).str() + "\"))"); } } - if (! HANDLED(prepend_width_)) - HANDLER(prepend_width_).on_with(string("?normalize"), static_cast(0)); if (verb == "print" || verb == "xact" || verb == "dump") { - HANDLER(related).on_only(string("?normalize")); - HANDLER(related_all).on_only(string("?normalize")); + HANDLER(related_all).parent = this; + HANDLER(related_all).on("?normalize"); } else if (verb == "equity") { - HANDLER(equity).on_only(string("?normalize")); + HANDLER(equity).on("?normalize"); } if (verb[0] != 'b' && verb[0] != 'r') - HANDLER(base).on_only(string("?normalize")); + HANDLER(base).on("?normalize"); // If a time period was specified with -p, check whether it also gave a // begin and/or end to the report period (though these can be overridden @@ -152,12 +148,10 @@ void report_t::normalize_options(const string& verb) // to avoid option ordering issues were we to have done it during the // initial parsing of the options. if (HANDLED(amount_data)) { - HANDLER(format_) - .on_with(string("?normalize"), HANDLER(plot_amount_format_).value); + HANDLER(format_).on("?normalize", HANDLER(plot_amount_format_).value); } else if (HANDLED(total_data)) { - HANDLER(format_) - .on_with(string("?normalize"), HANDLER(plot_total_format_).value); + HANDLER(format_).on("?normalize", HANDLER(plot_total_format_).value); } // If the --exchange (-X) option was used, parse out any final price @@ -170,7 +164,7 @@ void report_t::normalize_options(const string& verb) long cols = 0; if (HANDLED(columns_)) - cols = HANDLER(columns_).value.to_long(); + cols = lexical_cast(HANDLER(columns_).value); else if (const char * columns = std::getenv("COLUMNS")) cols = lexical_cast(columns); else @@ -182,23 +176,20 @@ void report_t::normalize_options(const string& verb) if (cols > 0) { DEBUG("auto.columns", "cols = " << cols); - if (! HANDLER(date_width_).specified) - HANDLER(date_width_) - .on_with(none, static_cast(format_date(CURRENT_DATE(), - FMT_PRINTED).length())); - - long date_width = HANDLER(date_width_).value.to_long(); - long payee_width = (HANDLER(payee_width_).specified ? - HANDLER(payee_width_).value.to_long() : - int(double(cols) * 0.263157)); - long account_width = (HANDLER(account_width_).specified ? - HANDLER(account_width_).value.to_long() : - int(double(cols) * 0.302631)); - long amount_width = (HANDLER(amount_width_).specified ? - HANDLER(amount_width_).value.to_long() : - int(double(cols) * 0.157894)); - long total_width = (HANDLER(total_width_).specified ? - HANDLER(total_width_).value.to_long() : + long date_width = (HANDLED(date_width_) ? + lexical_cast(HANDLER(date_width_).str()) : + format_date(CURRENT_DATE(),FMT_PRINTED).length()); + long payee_width = (HANDLED(payee_width_) ? + lexical_cast(HANDLER(payee_width_).str()) : + long(double(cols) * 0.263157)); + long account_width = (HANDLED(account_width_) ? + lexical_cast(HANDLER(account_width_).str()) : + long(double(cols) * 0.302631)); + long amount_width = (HANDLED(amount_width_) ? + lexical_cast(HANDLER(amount_width_).str()) : + long(double(cols) * 0.157894)); + long total_width = (HANDLED(total_width_) ? + lexical_cast(HANDLER(total_width_).str()) : amount_width); DEBUG("auto.columns", "date_width = " << date_width); @@ -207,11 +198,11 @@ void report_t::normalize_options(const string& verb) DEBUG("auto.columns", "amount_width = " << amount_width); DEBUG("auto.columns", "total_width = " << total_width); - if (! HANDLER(date_width_).specified && - ! HANDLER(payee_width_).specified && - ! HANDLER(account_width_).specified && - ! HANDLER(amount_width_).specified && - ! HANDLER(total_width_).specified) { + if (! HANDLED(date_width_) && + ! HANDLED(payee_width_) && + ! HANDLED(account_width_) && + ! HANDLED(amount_width_) && + ! HANDLED(total_width_)) { long total = (4 /* the spaces between */ + date_width + payee_width + account_width + amount_width + total_width); if (total > cols) { @@ -222,17 +213,19 @@ void report_t::normalize_options(const string& verb) } if (! HANDLED(meta_width_)) - HANDLER(meta_width_).on_with(string("?normalize"), 0L); - if (! HANDLER(date_width_).specified) - HANDLER(date_width_).on_with(string("?normalize"), date_width); - if (! HANDLER(payee_width_).specified) - HANDLER(payee_width_).on_with(string("?normalize"), payee_width); - if (! HANDLER(account_width_).specified) - HANDLER(account_width_).on_with(string("?normalize"), account_width); - if (! HANDLER(amount_width_).specified) - HANDLER(amount_width_).on_with(string("?normalize"), amount_width); - if (! HANDLER(total_width_).specified) - HANDLER(total_width_).on_with(string("?normalize"), total_width); + HANDLER(meta_width_).value = "0"; + if (! HANDLED(prepend_width_)) + HANDLER(prepend_width_).value = "0"; + if (! HANDLED(date_width_)) + HANDLER(date_width_).value = to_string(date_width); + if (! HANDLED(payee_width_)) + HANDLER(payee_width_).value = to_string(payee_width); + if (! HANDLED(account_width_)) + HANDLER(account_width_).value = to_string(account_width); + if (! HANDLED(amount_width_)) + HANDLER(amount_width_).value = to_string(amount_width); + if (! HANDLED(total_width_)) + HANDLER(total_width_).value = to_string(total_width); } } @@ -255,7 +248,7 @@ void report_t::normalize_period() if (! interval.duration) HANDLER(period_).off(); else if (! HANDLED(sort_all_)) - HANDLER(sort_xacts_).on_only(string("?normalize")); + HANDLER(sort_xacts_).on("?normalize"); } void report_t::parse_query_args(const value_t& args, const string& whence) @@ -278,7 +271,7 @@ void report_t::parse_query_args(const value_t& args, const string& whence) } if (query.has_query(query_t::QUERY_BOLD)) { - HANDLER(bold_if_).set_expr(whence, query.get_query(query_t::QUERY_BOLD)); + HANDLER(bold_if_).on(whence, query.get_query(query_t::QUERY_BOLD)); DEBUG("report.predicate", "Bolding predicate = " << HANDLER(bold_if_).str()); } @@ -329,9 +322,9 @@ void report_t::generate_report(post_handler_ptr handler) generate_posts_iterator walker (session, HANDLED(seed_) ? - static_cast(HANDLER(seed_).value.to_long()) : 0, + lexical_cast(HANDLER(seed_).str()) : 0, HANDLED(head_) ? - static_cast(HANDLER(head_).value.to_long()) : 50); + lexical_cast(HANDLER(head_).str()) : 50); pass_down_posts(handler, walker); } @@ -527,16 +520,17 @@ value_t report_t::fn_market(call_scope_t& args) arg0 = tmp; } + string target_commodity; if (args.has(2)) - result = arg0.exchange_commodities(args.get(2), + target_commodity = args.get(2); + + if (! target_commodity.empty()) + result = arg0.exchange_commodities(target_commodity, /* add_prices= */ false, moment); else result = arg0.value(moment); - if (! result.is_null()) - return result; - - return args[0]; + return ! result.is_null() ? result : arg0; } value_t report_t::fn_get_at(call_scope_t& args) @@ -1245,7 +1239,7 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, else if (is_eq(p, "display_total")) return MAKE_FUNCTOR(report_t::fn_display_total); else if (is_eq(p, "date")) - return MAKE_FUNCTOR(report_t::fn_now); + return MAKE_FUNCTOR(report_t::fn_today); break; case 'f': @@ -1404,85 +1398,98 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return MAKE_OPT_HANDLER(report_t, handler); break; -#define POSTS_REPORT(formatter) \ +#define POSTS_REPORTER(formatter) \ WRAP_FUNCTOR(reporter<>(post_handler_ptr(formatter), *this, \ - string("#") + p)); + string("#") + p)) // Can't use WRAP_FUNCTOR here because the template arguments // confuse the parser -#define POSTS_REPORT_(method, formatter) \ - expr_t::op_t::wrap_functor \ - (reporter \ - (post_handler_ptr(formatter), *this, string("#") + p)); - -#define ACCOUNTS_REPORT(formatter) \ +#define POSTS_REPORTER_(method, formatter) \ + expr_t::op_t::wrap_functor \ + (reporter \ + (post_handler_ptr(formatter), *this, string("#") + p)) + +#define FORMATTED_POSTS_REPORTER(format) \ + POSTS_REPORTER \ + (new format_posts \ + (*this, report_format(HANDLER(format)), \ + maybe_format(HANDLER(prepend_format_)), \ + HANDLED(prepend_width_) ? \ + lexical_cast(HANDLER(prepend_width_).str()) : 0)) + +#define FORMATTED_COMMODITIES_REPORTER(format) \ + POSTS_REPORTER_ \ + (&report_t::commodities_report, \ + new format_posts \ + (*this, report_format(HANDLER(format)), \ + maybe_format(HANDLER(prepend_format_)), \ + HANDLED(prepend_width_) ? \ + lexical_cast(HANDLER(prepend_width_).str()) : 0)) + +#define ACCOUNTS_REPORTER(formatter) \ expr_t::op_t::wrap_functor(reporter \ (acct_handler_ptr(formatter), *this, \ - string("#") + p)); + string("#") + p)) + +#define FORMATTED_ACCOUNTS_REPORTER(format) \ + ACCOUNTS_REPORTER \ + (new format_accounts \ + (*this, report_format(HANDLER(format)), \ + maybe_format(HANDLER(prepend_format_)), \ + HANDLED(prepend_width_) ? \ + lexical_cast(HANDLER(prepend_width_).str()) : 0)) case symbol_t::COMMAND: switch (*p) { case 'a': if (is_eq(p, "accounts")) { - return POSTS_REPORT(new report_accounts(*this)); + return POSTS_REPORTER(new report_accounts(*this)); } break; case 'b': if (*(p + 1) == '\0' || is_eq(p, "bal") || is_eq(p, "balance")) { - return ACCOUNTS_REPORT(new format_accounts - (*this, report_format(HANDLER(balance_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())); + return FORMATTED_ACCOUNTS_REPORTER(balance_format_); } else if (is_eq(p, "budget")) { - HANDLER(amount_).set_expr(string("#budget"), "(amount, 0)"); + HANDLER(amount_).on(string("#budget"), "(amount, 0)"); budget_flags |= BUDGET_WRAP_VALUES; if (! (budget_flags & ~BUDGET_WRAP_VALUES)) budget_flags |= BUDGET_BUDGETED; - return ACCOUNTS_REPORT(new format_accounts - (*this, report_format(HANDLER(budget_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())); + return FORMATTED_ACCOUNTS_REPORTER(budget_format_); } break; case 'c': if (is_eq(p, "csv")) { - return POSTS_REPORT(new format_posts - (*this, report_format(HANDLER(csv_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())); + return FORMATTED_POSTS_REPORTER(csv_format_); } else if (is_eq(p, "cleared")) { - HANDLER(amount_).set_expr(string("#cleared"), - "(amount, cleared ? amount : 0)"); - return ACCOUNTS_REPORT(new format_accounts - (*this, report_format(HANDLER(cleared_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())); + HANDLER(amount_).on(string("#cleared"), + "(amount, cleared ? amount : 0)"); + return FORMATTED_ACCOUNTS_REPORTER(cleared_format_); } else if (is_eq(p, "convert")) { return WRAP_FUNCTOR(convert_command); } else if (is_eq(p, "commodities")) { - return POSTS_REPORT(new report_commodities(*this)); + return POSTS_REPORTER(new report_commodities(*this)); } break; case 'e': if (is_eq(p, "equity")) { - HANDLER(generated).on_only(string("#equity")); - return POSTS_REPORT(new print_xacts(*this)); + HANDLER(generated).on("#equity"); + return POSTS_REPORTER(new print_xacts(*this)); } else if (is_eq(p, "entry")) { return WRAP_FUNCTOR(xact_command); } else if (is_eq(p, "emacs")) { - return POSTS_REPORT(new format_emacs_posts(output_stream)); + return POSTS_REPORTER(new format_emacs_posts(output_stream)); } else if (is_eq(p, "echo")) { return MAKE_FUNCTOR(report_t::echo_command); @@ -1491,43 +1498,32 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, case 'o': if (is_eq(p, "org")) { - return POSTS_REPORT(new posts_to_org_table + return POSTS_REPORTER(new posts_to_org_table (*this, maybe_format(HANDLER(prepend_format_)))); } break; case 'p': if (*(p + 1) == '\0' || is_eq(p, "print")) { - return POSTS_REPORT(new print_xacts(*this, HANDLED(raw))); + return POSTS_REPORTER(new print_xacts(*this, HANDLED(raw))); } else if (is_eq(p, "prices")) { - return POSTS_REPORT_(&report_t::commodities_report, - new format_posts - (*this, report_format(HANDLER(prices_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())); + return FORMATTED_COMMODITIES_REPORTER(prices_format_); } else if (is_eq(p, "pricedb")) { - return POSTS_REPORT_(&report_t::commodities_report, - new format_posts - (*this, report_format(HANDLER(pricedb_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())); + return FORMATTED_COMMODITIES_REPORTER(pricedb_format_); } else if (is_eq(p, "pricemap")) { return MAKE_FUNCTOR(report_t::pricemap_command); } else if (is_eq(p, "payees")) { - return POSTS_REPORT(new report_payees(*this)); + return POSTS_REPORTER(new report_payees(*this)); } break; case 'r': if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register")) { - return POSTS_REPORT(new format_posts - (*this, report_format(HANDLER(register_format_)), - maybe_format(HANDLER(prepend_format_)), - HANDLER(prepend_width_).value.to_size_t())); + return FORMATTED_POSTS_REPORTER(register_format_); } else if (is_eq(p, "reload")) { return MAKE_FUNCTOR(report_t::reload_command); @@ -1545,7 +1541,7 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, if (is_eq(p, "xact")) return WRAP_FUNCTOR(xact_command); else if (is_eq(p, "xml")) - return POSTS_REPORT(new format_xml(*this)); + return POSTS_REPORTER(new format_xml(*this)); break; } break; @@ -1568,8 +1564,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, break; case 'g': if (is_eq(p, "generate")) - return POSTS_REPORT_(&report_t::generate_report, - new print_xacts(*this)); + return POSTS_REPORTER_(&report_t::generate_report, + new print_xacts(*this)); break; case 'p': if (is_eq(p, "parse")) diff --git a/src/report.h b/src/report.h index d68d1f75..2ad53f01 100644 --- a/src/report.h +++ b/src/report.h @@ -353,12 +353,16 @@ public: * Option handlers */ - OPTION__(report_t, abbrev_len_, - CTOR(report_t, abbrev_len_) { on_with(none, 2L); }); + OPTION__ + (report_t, abbrev_len_, + CTOR(report_t, abbrev_len_) { + on(none, "2"); + }); + OPTION(report_t, account_); OPTION_(report_t, actual, DO() { // -L - parent->HANDLER(limit_).on(string("--actual"), "actual"); + OTHER(limit_).on(whence, "actual"); }); OPTION_(report_t, add_budget, DO() { @@ -368,12 +372,8 @@ public: OPTION__ (report_t, amount_, // -t DECL1(report_t, amount_, merged_expr_t, expr, ("amount_expr", "amount")) {} - void set_expr(const optional& whence, const string& str) { + DO_(str) { expr.append(str); - on(whence, str); - } - DO_(args) { - set_expr(args.get(0), args.get(1)); }); OPTION(report_t, amount_data); // -j @@ -381,216 +381,204 @@ public: OPTION(report_t, auto_match); OPTION_(report_t, average, DO() { // -A - parent->HANDLER(display_total_) - .set_expr(string("--average"), "count>0?(display_total/count):0"); + OTHER(display_total_) + .on(whence, "count>0?(display_total/count):0"); }); - OPTION__(report_t, balance_format_, CTOR(report_t, balance_format_) { - on(none, - "%(ansify_if(" - " justify(scrub(display_total), 20, 20 + prepend_width, true, color)," - " bold if should_bold))" - " %(!options.flat ? depth_spacer : \"\")" - "%-(ansify_if(" - " ansify_if(partial_account(options.flat), blue if color)," - " bold if should_bold))\n%/" - "%$1\n%/" - "%(prepend_width ? \" \" * prepend_width : \"\")" - "--------------------\n"); - }); + OPTION__ + (report_t, balance_format_, + CTOR(report_t, balance_format_) { + on(none, + "%(ansify_if(" + " justify(scrub(display_total), 20," + " 20 + int(prepend_width), true, color)," + " bold if should_bold))" + " %(!options.flat ? depth_spacer : \"\")" + "%-(ansify_if(" + " ansify_if(partial_account(options.flat), blue if color)," + " bold if should_bold))\n%/" + "%$1\n%/" + "%(prepend_width ? \" \" * int(prepend_width) : \"\")" + "--------------------\n"); + }); OPTION(report_t, base); OPTION_(report_t, basis, DO() { // -B - parent->HANDLER(revalued).on_only(string("--basis")); - parent->HANDLER(amount_).expr.set_base_expr("rounded(cost)"); + OTHER(revalued).on(whence); + OTHER(amount_).expr.set_base_expr("rounded(cost)"); }); - OPTION_(report_t, begin_, DO_(args) { // -b - date_interval_t interval(args.get(1)); - optional begin = interval.begin(); - if (! begin) + OPTION_(report_t, begin_, DO_(str) { // -b + date_interval_t interval(str); + if (optional begin = interval.begin()) { + string predicate = "date>=[" + to_iso_extended_string(*begin) + "]"; + OTHER(limit_).on(whence, predicate); + } else { throw_(std::invalid_argument, - _("Could not determine beginning of period '%1'") - << args.get(1)); - - string predicate = "date>=[" + to_iso_extended_string(*begin) + "]"; - parent->HANDLER(limit_).on(string("--begin"), predicate); + _("Could not determine beginning of period '%1'") << str); + } }); - OPTION__ + OPTION_ (report_t, bold_if_, expr_t expr; - CTOR(report_t, bold_if_) {} - void set_expr(const optional& whence, const string& str) { + DO_(str) { expr = str; - on(whence, str); - } - DO_(args) { - set_expr(args.get(0), args.get(1)); }); OPTION_(report_t, budget, DO() { parent->budget_flags |= BUDGET_BUDGETED; }); - OPTION__(report_t, budget_format_, CTOR(report_t, budget_format_) { - on(none, - "%(justify(scrub(get_at(display_total, 0)), 12, -1, true, color))" - " %(justify(-scrub(get_at(display_total, 1)), 12, " - " 12 + 1 + 12, true, color))" - " %(justify(scrub(get_at(display_total, 1) + " - " get_at(display_total, 0)), 12, " - " 12 + 1 + 12 + 1 + 12, true, color))" - " %(ansify_if(" - " justify((get_at(display_total, 1) ? " - " (100% * scrub(get_at(display_total, 0))) / " - " -scrub(get_at(display_total, 1)) : 0), " - " 5, -1, true, false)," - " magenta if (color and get_at(display_total, 1) and " - " (abs(quantity(scrub(get_at(display_total, 0))) / " - " quantity(scrub(get_at(display_total, 1)))) >= 1))))" - " %(!options.flat ? depth_spacer : \"\")" - "%-(ansify_if(partial_account(options.flat), blue if color))\n" - "%/%$1 %$2 %$3 %$4\n%/" - "%(prepend_width ? \" \" * prepend_width : \"\")" - "------------ ------------ ------------ -----\n"); - }); + OPTION__ + (report_t, budget_format_, + CTOR(report_t, budget_format_) { + on(none, + "%(justify(scrub(get_at(display_total, 0)), 12, -1, true, color))" + " %(justify(-scrub(get_at(display_total, 1)), 12, " + " 12 + 1 + 12, true, color))" + " %(justify(scrub(get_at(display_total, 1) + " + " get_at(display_total, 0)), 12, " + " 12 + 1 + 12 + 1 + 12, true, color))" + " %(ansify_if(" + " justify((get_at(display_total, 1) ? " + " (100% * scrub(get_at(display_total, 0))) / " + " -scrub(get_at(display_total, 1)) : 0), " + " 5, -1, true, false)," + " magenta if (color and get_at(display_total, 1) and " + " (abs(quantity(scrub(get_at(display_total, 0))) / " + " quantity(scrub(get_at(display_total, 1)))) >= 1))))" + " %(!options.flat ? depth_spacer : \"\")" + "%-(ansify_if(partial_account(options.flat), blue if color))\n" + "%/%$1 %$2 %$3 %$4\n%/" + "%(prepend_width ? \" \" * int(prepend_width) : \"\")" + "------------ ------------ ------------ -----\n"); + }); OPTION(report_t, by_payee); // -P OPTION_(report_t, cleared, DO() { // -C - parent->HANDLER(limit_).on(string("--cleared"), "cleared"); + OTHER(limit_).on(whence, "cleared"); }); - OPTION__(report_t, cleared_format_, CTOR(report_t, cleared_format_) { - on(none, - "%(justify(scrub(get_at(display_total, 0)), 16, 16 + prepend_width, " - " true, color)) %(justify(scrub(get_at(display_total, 1)), 18, " - " 36 + prepend_width, true, color))" - " %(latest_cleared ? format_date(latest_cleared) : \" \")" - " %(!options.flat ? depth_spacer : \"\")" - "%-(ansify_if(partial_account(options.flat), blue if color))\n%/" - "%$1 %$2 %$3\n%/" - "%(prepend_width ? \" \" * prepend_width : \"\")" - "---------------- ---------------- ---------\n"); - }); + OPTION__ + (report_t, cleared_format_, + CTOR(report_t, cleared_format_) { + on(none, + "%(justify(scrub(get_at(display_total, 0)), 16, 16 + int(prepend_width), " + " true, color)) %(justify(scrub(get_at(display_total, 1)), 18, " + " 36 + int(prepend_width), true, color))" + " %(latest_cleared ? format_date(latest_cleared) : \" \")" + " %(!options.flat ? depth_spacer : \"\")" + "%-(ansify_if(partial_account(options.flat), blue if color))\n%/" + "%$1 %$2 %$3\n%/" + "%(prepend_width ? \" \" * int(prepend_width) : \"\")" + "---------------- ---------------- ---------\n"); + }); OPTION(report_t, color); OPTION_(report_t, collapse, DO() { // -n // Make sure that balance reports are collapsed too, but only apply it // to account xacts - parent->HANDLER(display_).on(string("--collapse"), "post|depth<=1"); + OTHER(display_).on(whence, "post|depth<=1"); }); OPTION_(report_t, collapse_if_zero, DO() { - parent->HANDLER(collapse).on_only(string("--collapse-if-zero")); + OTHER(collapse).on(whence); }); OPTION(report_t, columns_); OPTION(report_t, count); - OPTION__(report_t, csv_format_, CTOR(report_t, csv_format_) { - on(none, - "%(quoted(date))," - "%(quoted(code))," - "%(quoted(payee))," - "%(quoted(display_account))," - "%(quoted(commodity))," - "%(quoted(quantity(scrub(display_amount))))," - "%(quoted(cleared ? \"*\" : (pending ? \"!\" : \"\")))," - "%(quoted(join(note | xact.note)))\n"); - }); + OPTION__ + (report_t, csv_format_, + CTOR(report_t, csv_format_) { + on(none, + "%(quoted(date))," + "%(quoted(code))," + "%(quoted(payee))," + "%(quoted(display_account))," + "%(quoted(commodity))," + "%(quoted(quantity(scrub(display_amount))))," + "%(quoted(cleared ? \"*\" : (pending ? \"!\" : \"\")))," + "%(quoted(join(note | xact.note)))\n"); + }); OPTION_(report_t, current, DO() { // -c - parent->HANDLER(limit_).on(string("--current"), "date<=today"); + OTHER(limit_).on(whence, "date<=today"); }); OPTION_(report_t, daily, DO() { // -D - parent->HANDLER(period_).on(string("--daily"), "daily"); + OTHER(period_).on(whence, "daily"); }); OPTION(report_t, date_); OPTION(report_t, date_format_); OPTION(report_t, datetime_format_); - OPTION_(report_t, depth_, DO_(args) { - parent->HANDLER(display_) - .on(string("--depth"), string("depth<=") + args.get(1)); + OPTION_(report_t, depth_, DO_(str) { + OTHER(display_).on(whence, string("depth<=") + str); }); OPTION_(report_t, deviation, DO() { - parent->HANDLER(display_total_) - .set_expr(string("--deviation"), "display_amount-display_total"); + OTHER(display_total_) + .on(whence, "display_amount-display_total"); }); - OPTION__ - (report_t, display_, // -d - CTOR(report_t, display_) {} - virtual void on_with(const optional& whence, const value_t& text) { - if (! handled) - option_t::on_with(whence, text); - else - option_t::on_with(whence, - string_value(string("(") + str() + ")&(" + - text.as_string() + ")")); + OPTION_ + (report_t, display_, + DO_(str) { // -d + if (handled) + value = string("(") + value + ")&(" + str + ")"; }); OPTION__ (report_t, display_amount_, DECL1(report_t, display_amount_, merged_expr_t, expr, ("display_amount", "amount_expr")) {} - void set_expr(const optional& whence, const string& str) { + DO_(str) { expr.append(str); - on(whence, str); - } - DO_(args) { - set_expr(args.get(0), args.get(1)); }); OPTION__ (report_t, display_total_, DECL1(report_t, display_total_, merged_expr_t, expr, ("display_total", "total_expr")) {} - void set_expr(const optional& whence, const string& str) { + DO_(str) { expr.append(str); - on(whence, str); - } - DO_(args) { - set_expr(args.get(0), args.get(1)); }); OPTION(report_t, dow); OPTION(report_t, aux_date); OPTION(report_t, empty); // -E - OPTION_(report_t, end_, DO_(args) { // -e - date_interval_t interval(args.get(1)); + OPTION_(report_t, end_, DO_(str) { // -e // Use begin() here so that if the user says --end=2008, we end on // 2008/01/01 instead of 2009/01/01 (which is what end() would // return). - optional end = interval.begin(); - if (! end) + date_interval_t interval(str); + if (optional end = interval.begin()) { + string predicate = "date<[" + to_iso_extended_string(*end) + "]"; + OTHER(limit_).on(whence, predicate); + + parent->terminus = datetime_t(*end); + } else { throw_(std::invalid_argument, _("Could not determine end of period '%1'") - << args.get(1)); - - string predicate = "date<[" + to_iso_extended_string(*end) + "]"; - parent->HANDLER(limit_).on(string("--end"), predicate); - - parent->terminus = datetime_t(*end); + << str); + } }); OPTION(report_t, equity); OPTION(report_t, exact); - OPTION_(report_t, exchange_, DO_(args) { // -X - on_with(args.get(0), args[1]); - call_scope_t no_args(*parent); - no_args.push_back(args[0]); - parent->HANDLER(market).parent = parent; - parent->HANDLER(market).handler(no_args); + OPTION_(report_t, exchange_, DO_() { // -X + // Using -X implies -V. The main difference is that now + // HANDLER(exchange_) contains the name of a commodity, which + // is accessed via the "exchange" value expression function. + OTHER(market).on(whence); }); OPTION(report_t, flat); @@ -601,74 +589,65 @@ public: OPTION(report_t, format_); // -F OPTION_(report_t, gain, DO() { // -G - parent->HANDLER(revalued).on_only(string("--gain")); + OTHER(revalued).on(whence); - parent->HANDLER(amount_).expr.set_base_expr("(amount, cost)"); - parent->HANDLER(total_).expr.set_base_expr("total"); + OTHER(amount_).expr.set_base_expr("(amount, cost)"); + OTHER(total_).expr.set_base_expr("total"); // Since we are displaying the amounts of revalued postings, they // will end up being composite totals, and hence a pair of pairs. - parent->HANDLER(display_amount_) - .set_expr(string("--gain"), - "use_direct_amount ? amount :" - " (is_seq(get_at(amount_expr, 0)) ?" - " get_at(get_at(amount_expr, 0), 0) :" - " market(get_at(amount_expr, 0), value_date, exchange)" - " - get_at(amount_expr, 1))"); - parent->HANDLER(revalued_total_) - .set_expr(string("--gain"), - "(market(get_at(total_expr, 0), value_date, exchange), " - "get_at(total_expr, 1))"); - parent->HANDLER(display_total_) - .set_expr(string("--gain"), - "use_direct_amount ? total_expr :" - " market(get_at(total_expr, 0), value_date, exchange)" - " - get_at(total_expr, 1)"); + OTHER(display_amount_) + .on(whence, + "use_direct_amount ? amount :" + " (is_seq(get_at(amount_expr, 0)) ?" + " get_at(get_at(amount_expr, 0), 0) :" + " market(get_at(amount_expr, 0), value_date, exchange)" + " - get_at(amount_expr, 1))"); + OTHER(revalued_total_) + .on(whence, + "(market(get_at(total_expr, 0), value_date, exchange), " + "get_at(total_expr, 1))"); + OTHER(display_total_) + .on(whence, + "use_direct_amount ? total_expr :" + " market(get_at(total_expr, 0), value_date, exchange)" + " - get_at(total_expr, 1)"); }); OPTION(report_t, generated); - OPTION__ + OPTION_ (report_t, group_by_, expr_t expr; - CTOR(report_t, group_by_) {} - void set_expr(const optional& whence, const string& str) { + DO_(str) { expr = str; - on(whence, str); - } - DO_(args) { - set_expr(args.get(0), args.get(1)); }); - OPTION__(report_t, group_title_format_, CTOR(report_t, group_title_format_) { - on(none, "%(value)\n"); - }); + OPTION__ + (report_t, group_title_format_, + CTOR(report_t, group_title_format_) { + on(none, "%(value)\n"); + }); OPTION(report_t, head_); OPTION_(report_t, historical, DO() { // -H - parent->HANDLER(amount_) - .set_expr(string("--historical"), - "nail_down(amount_expr, (s,d,t -> market(s,value_date,t)))"); + OTHER(amount_) + .on(whence, "nail_down(amount_expr, " + "market(amount_expr, value_date, exchange))"); }); - OPTION(report_t, inject_); OPTION_(report_t, invert, DO() { - parent->HANDLER(amount_).set_expr(string("--invert"), "-amount"); + OTHER(amount_).on(whence, "-amount"); }); - OPTION__ - (report_t, limit_, // -l - CTOR(report_t, limit_) {} - virtual void on_with(const optional& whence, const value_t& text) { - if (! handled) - option_t::on_with(whence, text); - else - option_t::on_with(whence, - string_value(string("(") + str() + ")&(" + - text.as_string() + ")")); + OPTION_ + (report_t, limit_, + DO_(str) { // -l + if (handled) + value = string("(") + value + ")&(" + str + ")"; }); OPTION(report_t, lot_dates); @@ -678,49 +657,44 @@ public: OPTION(report_t, lots_actual); OPTION_(report_t, market, DO() { // -V - parent->HANDLER(revalued).on_only(string("--market")); - parent->HANDLER(display_amount_) - .set_expr(string("--market"), - "market(display_amount, value_date, exchange)"); - parent->HANDLER(display_total_) - .set_expr(string("--market"), - "market(display_total, value_date, exchange)"); + OTHER(revalued).on(whence); + + OTHER(display_amount_) + .on(whence, "market(display_amount, value_date, exchange)"); + OTHER(display_total_) + .on(whence, "market(display_total, value_date, exchange)"); }); OPTION(report_t, meta_); OPTION_(report_t, monthly, DO() { // -M - parent->HANDLER(period_).on(string("--monthly"), "monthly"); + OTHER(period_).on(whence, "monthly"); }); OPTION_(report_t, no_color, DO() { - parent->HANDLER(color).off(); + OTHER(color).off(); }); OPTION(report_t, no_rounding); OPTION(report_t, no_titles); OPTION(report_t, no_total); - OPTION_(report_t, now_, DO_(args) { - date_interval_t interval(args.get(1)); - optional begin = interval.begin(); - if (! begin) + OPTION_(report_t, now_, DO_(str) { + date_interval_t interval(str); + if (optional begin = interval.begin()) { + ledger::epoch = parent->terminus = datetime_t(*begin); + } else { throw_(std::invalid_argument, _("Could not determine beginning of period '%1'") - << args.get(1)); - ledger::epoch = parent->terminus = datetime_t(*begin); + << str); + } }); - OPTION__ + OPTION_ (report_t, only_, - CTOR(report_t, only_) {} - virtual void on_with(const optional& whence, const value_t& text) { - if (! handled) - option_t::on_with(whence, text); - else - option_t::on_with(whence, - string_value(string("(") + str() + ")&(" + - text.as_string() + ")")); + DO_(str) { + if (handled) + value = string("(") + value + ")&(" + str + ")"; }); OPTION(report_t, output_); // -o @@ -741,178 +715,162 @@ public: setenv("LESS", "-FRSX", 0); // don't overwrite } } - } - virtual void on_with(const optional& whence, const value_t& text) { - string cmd(text.to_string()); - if (cmd == "" || cmd == "false" || cmd == "off" || - cmd == "none" || cmd == "no" || cmd == "disable") - option_t::off(); - else - option_t::on_with(whence, text); }); #else // HAVE_ISATTY - OPTION__ - (report_t, pager_, - CTOR(report_t, pager_) { - } - virtual void on_with(const optional& whence, const value_t& text) { - string cmd(text.to_string()); - if (cmd == "" || cmd == "false" || cmd == "off" || - cmd == "none" || cmd == "no" || cmd == "disable") - option_t::off(); - else - option_t::on_with(whence, text); - }); + OPTION(report_t, pager_); #endif // HAVE_ISATTY + OPTION_(report_t, no_pager, DO() { + OTHER(pager_).off(); + }); + OPTION(report_t, payee_); OPTION_(report_t, pending, DO() { // -C - parent->HANDLER(limit_).on(string("--pending"), "pending"); + OTHER(limit_).on(whence, "pending"); }); OPTION_(report_t, percent, DO() { // -% - parent->HANDLER(total_) - .set_expr(string("--percent"), - "((is_account&parent&parent.total)?" - " percent(scrub(total), scrub(parent.total)):0)"); + OTHER(total_) + .on(whence, + "((is_account&parent&parent.total)?" + " percent(scrub(total), scrub(parent.total)):0)"); }); - OPTION__ - (report_t, period_, // -p - CTOR(report_t, period_) {} - virtual void on_with(const optional& whence, const value_t& text) { - if (! handled) - option_t::on_with(whence, text); - else - option_t::on_with(whence, - string_value(text.as_string() + " " + str())); + OPTION_ + (report_t, period_, + DO_(str) { // -p + if (handled) + value += string(" ") + str; }); OPTION(report_t, pivot_); - OPTION__(report_t, plot_amount_format_, CTOR(report_t, plot_amount_format_) { - on(none, - "%(format_date(date, \"%Y-%m-%d\")) %(quantity(scrub(display_amount)))\n"); - }); + OPTION__ + (report_t, plot_amount_format_, + CTOR(report_t, plot_amount_format_) { + on(none, + "%(format_date(date, \"%Y-%m-%d\")) %(quantity(scrub(display_amount)))\n"); + }); - OPTION__(report_t, plot_total_format_, CTOR(report_t, plot_total_format_) { - on(none, - "%(format_date(date, \"%Y-%m-%d\")) %(quantity(scrub(display_total)))\n"); - }); + OPTION__ + (report_t, plot_total_format_, + CTOR(report_t, plot_total_format_) { + on(none, + "%(format_date(date, \"%Y-%m-%d\")) %(quantity(scrub(display_total)))\n"); + }); OPTION(report_t, prepend_format_); - OPTION_(report_t, prepend_width_, DO_(args) { - value = args.get(1); - }); + OPTION(report_t, prepend_width_); OPTION_(report_t, price, DO() { // -I - parent->HANDLER(amount_).expr.set_base_expr("price"); + OTHER(amount_).expr.set_base_expr("price"); }); - OPTION__(report_t, prices_format_, CTOR(report_t, prices_format_) { - on(none, - "%(date) %-8(display_account) %(justify(scrub(display_amount), 12, " - " 2 + 9 + 8 + 12, true, color))\n"); - }); + OPTION__ + (report_t, prices_format_, + CTOR(report_t, prices_format_) { + on(none, + "%(date) %-8(display_account) %(justify(scrub(display_amount), 12, " + " 2 + 9 + 8 + 12, true, color))\n"); + }); - OPTION__(report_t, pricedb_format_, CTOR(report_t, pricedb_format_) { - on(none, - "P %(datetime) %(display_account) %(scrub(display_amount))\n"); - }); + OPTION__ + (report_t, pricedb_format_, + CTOR(report_t, pricedb_format_) { + on(none, + "P %(datetime) %(display_account) %(scrub(display_amount))\n"); + }); OPTION(report_t, primary_date); OPTION_(report_t, quantity, DO() { // -O - parent->HANDLER(revalued).off(); - parent->HANDLER(amount_).expr.set_base_expr("amount"); - parent->HANDLER(total_).expr.set_base_expr("total"); + OTHER(revalued).off(); + + OTHER(amount_).expr.set_base_expr("amount"); + OTHER(total_).expr.set_base_expr("total"); }); OPTION_(report_t, quarterly, DO() { - parent->HANDLER(period_).on(string("--quarterly"), "quarterly"); + OTHER(period_).on(whence, "quarterly"); }); OPTION(report_t, raw); OPTION_(report_t, real, DO() { // -R - parent->HANDLER(limit_).on(string("--real"), "real"); + OTHER(limit_).on(whence, "real"); }); - OPTION__(report_t, register_format_, CTOR(report_t, register_format_) { - on(none, - "%(ansify_if(" - " ansify_if(justify(format_date(date), date_width)," - " green if color and date > today)," - " bold if should_bold))" - " %(ansify_if(" - " ansify_if(justify(truncated(payee, payee_width), payee_width), " - " bold if color and !cleared and actual)," - " bold if should_bold))" - " %(ansify_if(" - " ansify_if(justify(truncated(display_account, account_width, " - " abbrev_len), account_width)," - " blue if color)," - " bold if should_bold))" - " %(ansify_if(" - " justify(scrub(display_amount), amount_width, " - " 3 + meta_width + date_width + payee_width" - " + account_width + amount_width + prepend_width," - " true, color)," - " bold if should_bold))" - " %(ansify_if(" - " justify(scrub(display_total), total_width, " - " 4 + meta_width + date_width + payee_width" - " + account_width + amount_width + total_width" - " + prepend_width, true, color)," - " bold if should_bold))\n%/" - "%(justify(\" \", date_width))" - " %(ansify_if(" - " justify(truncated(has_tag(\"Payee\") ? payee : \" \", " - " payee_width), payee_width)," - " bold if should_bold))" - " %$3 %$4 %$5\n"); - }); + OPTION__ + (report_t, register_format_, + CTOR(report_t, register_format_) { + on(none, + "%(ansify_if(" + " ansify_if(justify(format_date(date), int(date_width))," + " green if color and date > today)," + " bold if should_bold))" + " %(ansify_if(" + " ansify_if(justify(truncated(payee, int(payee_width)), int(payee_width)), " + " bold if color and !cleared and actual)," + " bold if should_bold))" + " %(ansify_if(" + " ansify_if(justify(truncated(display_account, int(account_width), " + " abbrev_len), int(account_width))," + " blue if color)," + " bold if should_bold))" + " %(ansify_if(" + " justify(scrub(display_amount), int(amount_width), " + " 3 + int(meta_width) + int(date_width) + int(payee_width)" + " + int(account_width) + int(amount_width) + int(prepend_width)," + " true, color)," + " bold if should_bold))" + " %(ansify_if(" + " justify(scrub(display_total), int(total_width), " + " 4 + int(meta_width) + int(date_width) + int(payee_width)" + " + int(account_width) + int(amount_width) + int(total_width)" + " + int(prepend_width), true, color)," + " bold if should_bold))\n%/" + "%(justify(\" \", int(date_width)))" + " %(ansify_if(" + " justify(truncated(has_tag(\"Payee\") ? payee : \" \", " + " int(payee_width)), int(payee_width))," + " bold if should_bold))" + " %$3 %$4 %$5\n"); + }); OPTION(report_t, related); // -r OPTION_(report_t, related_all, DO() { - parent->HANDLER(related).on_only(string("--related-all")); + OTHER(related).on(whence); }); OPTION(report_t, revalued); OPTION(report_t, revalued_only); - OPTION__ + OPTION_ (report_t, revalued_total_, expr_t expr; - CTOR(report_t, revalued_total_) {} - void set_expr(const optional& whence, const string& str) { + DO_(str) { expr = str; - on(whence, str); - } - DO_(args) { - set_expr(args.get(0), args.get(1)); }); OPTION(report_t, rich_data); OPTION(report_t, seed_); - OPTION_(report_t, sort_, DO_(args) { // -S - on_with(args.get(0), args[1]); - parent->HANDLER(sort_xacts_).off(); - parent->HANDLER(sort_all_).off(); + OPTION_(report_t, sort_, DO_(str) { // -S + OTHER(sort_xacts_).off(); + OTHER(sort_all_).off(); }); - OPTION_(report_t, sort_all_, DO_(args) { - parent->HANDLER(sort_).on_with(string("--sort-all"), args[1]); - parent->HANDLER(sort_xacts_).off(); + OPTION_(report_t, sort_all_, DO_(str) { + OTHER(sort_).on(whence, str); + OTHER(sort_xacts_).off(); }); - OPTION_(report_t, sort_xacts_, DO_(args) { - parent->HANDLER(sort_).on_with(string("--sort-xacts"), args[1]); - parent->HANDLER(sort_all_).off(); + OPTION_(report_t, sort_xacts_, DO_(str) { + OTHER(sort_).on(whence, str); + OTHER(sort_all_).off(); }); OPTION(report_t, start_of_week_); @@ -922,18 +880,13 @@ public: OPTION__ (report_t, total_, // -T DECL1(report_t, total_, merged_expr_t, expr, ("total_expr", "total")) {} - void set_expr(const optional& whence, const string& str) { + DO_(str) { expr.append(str); - on(whence, str); - } - DO_(args) { - set_expr(args.get(0), args.get(1)); }); OPTION(report_t, total_data); // -J - OPTION_(report_t, truncate_, DO_(args) { - string style(args.get(1)); + OPTION_(report_t, truncate_, DO_(style) { if (style == "leading") format_t::default_style = format_t::TRUNCATE_LEADING; else if (style == "middle") @@ -951,7 +904,7 @@ public: }); OPTION_(report_t, uncleared, DO() { // -U - parent->HANDLER(limit_).on(string("--uncleared"), "uncleared|pending"); + OTHER(limit_).on(whence, "uncleared|pending"); }); OPTION(report_t, unrealized); @@ -960,48 +913,28 @@ public: OPTION(report_t, unrealized_losses_); OPTION_(report_t, unround, DO() { - parent->HANDLER(amount_) - .set_expr(string("--unround"), "unrounded(amount_expr)"); - parent->HANDLER(total_) - .set_expr(string("--unround"), "unrounded(total_expr)"); + OTHER(amount_).on(whence, "unrounded(amount_expr)"); + OTHER(total_).on(whence, "unrounded(total_expr)"); }); OPTION_(report_t, weekly, DO() { // -W - parent->HANDLER(period_).on(string("--weekly"), "weekly"); + OTHER(period_).on(whence, "weekly"); }); OPTION_(report_t, wide, DO() { // -w - parent->HANDLER(columns_).on_with(string("--wide"), 132L); + OTHER(columns_).on(whence, "132"); }); OPTION_(report_t, yearly, DO() { // -Y - parent->HANDLER(period_).on(string("--yearly"), "yearly"); + OTHER(period_).on(whence, "yearly"); }); - OPTION__(report_t, meta_width_, - bool specified; - CTOR(report_t, meta_width_) { specified = false; } - DO_(args) { value = args.get(1); specified = true; }); - OPTION__(report_t, date_width_, - bool specified; - CTOR(report_t, date_width_) { specified = false; } - DO_(args) { value = args.get(1); specified = true; }); - OPTION__(report_t, payee_width_, - bool specified; - CTOR(report_t, payee_width_) { specified = false; } - DO_(args) { value = args.get(1); specified = true; }); - OPTION__(report_t, account_width_, - bool specified; - CTOR(report_t, account_width_) { specified = false; } - DO_(args) { value = args.get(1); specified = true; }); - OPTION__(report_t, amount_width_, - bool specified; - CTOR(report_t, amount_width_) { specified = false; } - DO_(args) { value = args.get(1); specified = true; }); - OPTION__(report_t, total_width_, - bool specified; - CTOR(report_t, total_width_) { specified = false; } - DO_(args) { value = args.get(1); specified = true; }); + OPTION(report_t, meta_width_); + OPTION(report_t, date_width_); + OPTION(report_t, payee_width_); + OPTION(report_t, account_width_); + OPTION(report_t, amount_width_); + OPTION(report_t, total_width_); }; diff --git a/src/session.h b/src/session.h index b06c4a42..cb981346 100644 --- a/src/session.h +++ b/src/session.h @@ -128,28 +128,24 @@ public: OPTION__ (session_t, price_exp_, // -Z - CTOR(session_t, price_exp_) { value = 24L * 3600L; } - DO_(args) { - value = args.get(1) * 60L; - }); + CTOR(session_t, price_exp_) { value = "24"; }); OPTION__ (session_t, file_, // -f std::list data_files; CTOR(session_t, file_) {} - DO_(args) { - assert(args.size() == 2); + DO_(str) { if (parent->flush_on_next_data_file) { data_files.clear(); parent->flush_on_next_data_file = false; } - data_files.push_back(args.get(1)); + data_files.push_back(str); }); - OPTION_(session_t, input_date_format_, DO_(args) { - // This changes static variables inside times.h, which affects the basic - // date parser. - set_input_date_format(args.get(1).c_str()); + OPTION_(session_t, input_date_format_, DO_(str) { + // This changes static variables inside times.h, which affects the + // basic date parser. + set_input_date_format(str.c_str()); }); OPTION(session_t, explicit); diff --git a/test/baseline/opt-no-pager.test b/test/baseline/opt-no-pager.test new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3 From 318b5f49ff07bdd906eb7c976b5c36c2eeb45872 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Fri, 9 Mar 2012 07:02:53 -0600 Subject: Fixed the behavior of fn_nail_down --- src/report.cc | 14 ++- test/baseline/feat-value-expr.test | 18 ++- test/baseline/opt-historical.test | 243 ++++++++++++++++++++++++++++++++----- 3 files changed, 234 insertions(+), 41 deletions(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 110d33ee..27d8bb2a 100644 --- a/src/report.cc +++ b/src/report.cc @@ -743,12 +743,20 @@ value_t report_t::fn_commodity(call_scope_t& args) value_t report_t::fn_nail_down(call_scope_t& args) { value_t arg0(args[0]); + value_t arg1(args[1]); + switch (arg0.type()) { case value_t::AMOUNT: { amount_t tmp(arg0.as_amount()); - if (tmp.has_commodity()) - tmp.set_commodity(tmp.commodity() - .nail_down(args[1].as_any())); + if (tmp.has_commodity() && ! arg1.is_null()) { + expr_t value_expr(is_expr(arg1) ? + as_expr(arg1) : expr_t::op_t::wrap_value(arg1 / arg0)); + std::ostringstream buf; + value_expr.print(buf); + value_expr.set_text(buf.str()); + + tmp.set_commodity(tmp.commodity().nail_down(value_expr)); + } return tmp; } diff --git a/test/baseline/feat-value-expr.test b/test/baseline/feat-value-expr.test index 690febf9..01f9780b 100644 --- a/test/baseline/feat-value-expr.test +++ b/test/baseline/feat-value-expr.test @@ -89,15 +89,11 @@ account Expenses:Food5 test reg -V food 12-Mar-02 KFC Expenses:Food2 2 EUR 2 EUR -12-Mar-03 KFC -1 EUR 1 EUR - Expenses:Food3 3 EUR 4 EUR -12-Mar-04 KFC -2 EUR 2 EUR - Expenses:Food4 4 EUR 6 EUR -12-Mar-05 KFC -3 EUR 3 EUR - Expenses:Food5 5 EUR 8 EUR -12-Mar-06 KFC -4 EUR 4 EUR - Expenses:Food6 6 EUR 10 EUR -12-Mar-07 KFC Expenses:Food7 7 EUR 17 EUR -12-Mar-08 XACT Expenses:Food8 8 EUR 25 EUR -12-Mar-09 POST (Expenses:Food9) 9 EUR 34 EUR +12-Mar-03 KFC Expenses:Food3 3 EUR 5 EUR +12-Mar-04 KFC Expenses:Food4 4 EUR 9 EUR +12-Mar-05 KFC Expenses:Food5 5 EUR 14 EUR +12-Mar-06 KFC Expenses:Food6 6 EUR 20 EUR +12-Mar-07 KFC Expenses:Food7 7 EUR 27 EUR +12-Mar-08 XACT Expenses:Food8 8 EUR 35 EUR +12-Mar-09 POST (Expenses:Food9) 9 EUR 44 EUR end test diff --git a/test/baseline/opt-historical.test b/test/baseline/opt-historical.test index 1cd141ab..9eb3558b 100644 --- a/test/baseline/opt-historical.test +++ b/test/baseline/opt-historical.test @@ -1,61 +1,250 @@ -2012-03-01 Broker - Assets:Stocks 10 APPL {$1} @ $1 +D EUR 2.000,00 + +P 2011-12-15 $ EUR 2 +P 2011-12-15 AAPL $5.00 + +2012-01-01 Broker + Assets:Stocks 10 AAPL {$1} @ $10 Equity -2012-03-02 Broker - Assets:Stocks 10 APPL {$1} @ $2 +P 2012-01-15 AAPL $15.00 + +2012-02-02 Broker + Assets:Stocks 10 AAPL {$2} @ $20 Equity +P 2012-02-15 AAPL $25.00 + 2012-03-03 Broker - Assets:Stocks 10 APPL {$1} @ $3 + Assets:Stocks 10 AAPL {$3} @ $30 Equity -2012-03-04 Broker - Assets:Stocks 10 APPL {$1} @ $4 +P 2012-03-15 AAPL $35.00 + +2012-04-04 Broker + Assets:Stocks 10 AAPL {$4} @ $40 Equity -2012-03-05 Broker - Assets:Stocks 10 APPL {$1} @ $5 +P 2012-04-15 AAPL $45.00 + +2012-05-05 Broker + Assets:Stocks 10 AAPL {$5} @ $50 Equity +P 2012-5-15 AAPL $55.00 + +test reg stocks +12-Jan-01 Broker Assets:Stocks 10 AAPL 10 AAPL +12-Feb-02 Broker Assets:Stocks 10 AAPL 20 AAPL +12-Mar-03 Broker Assets:Stocks 10 AAPL 30 AAPL +12-Apr-04 Broker Assets:Stocks 10 AAPL 40 AAPL +12-May-05 Broker Assets:Stocks 10 AAPL 50 AAPL +end test + test reg stocks -O -12-Mar-01 Broker Assets:Stocks 10 APPL 10 APPL -12-Mar-02 Broker Assets:Stocks 10 APPL 20 APPL -12-Mar-03 Broker Assets:Stocks 10 APPL 30 APPL -12-Mar-04 Broker Assets:Stocks 10 APPL 40 APPL -12-Mar-05 Broker Assets:Stocks 10 APPL 50 APPL +12-Jan-01 Broker Assets:Stocks 10 AAPL 10 AAPL +12-Feb-02 Broker Assets:Stocks 10 AAPL 20 AAPL +12-Mar-03 Broker Assets:Stocks 10 AAPL 30 AAPL +12-Apr-04 Broker Assets:Stocks 10 AAPL 40 AAPL +12-May-05 Broker Assets:Stocks 10 AAPL 50 AAPL end test test reg stocks -B -12-Mar-01 Broker Assets:Stocks $10 $10 -12-Mar-02 Broker Assets:Stocks $20 $30 -12-Mar-03 Broker Assets:Stocks $30 $60 -12-Mar-04 Broker Assets:Stocks $40 $100 -12-Mar-05 Broker Assets:Stocks $50 $150 +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Feb-02 Broker Assets:Stocks $200 $300 +12-Mar-03 Broker Assets:Stocks $300 $600 +12-Apr-04 Broker Assets:Stocks $400 $1000 +12-May-05 Broker Assets:Stocks $500 $1500 end test test reg stocks -I -12-Mar-01 Broker Assets:Stocks $10 $10 -12-Mar-02 Broker Assets:Stocks $10 $20 -12-Mar-03 Broker Assets:Stocks $10 $30 -12-Mar-04 Broker Assets:Stocks $10 $40 -12-Mar-05 Broker Assets:Stocks $10 $50 +12-Jan-01 Broker Assets:Stocks $10 $10 +12-Feb-02 Broker Assets:Stocks $20 $30 +12-Mar-03 Broker Assets:Stocks $30 $60 +12-Apr-04 Broker Assets:Stocks $40 $100 +12-May-05 Broker Assets:Stocks $50 $150 +end test + +test reg stocks -V +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Jan-15 Commodities revalued $50 $150 +12-Feb-02 Commodities revalued $50 $200 +12-Feb-02 Broker Assets:Stocks $200 $400 +12-Feb-15 Commodities revalued $100 $500 +12-Mar-03 Commodities revalued $100 $600 +12-Mar-03 Broker Assets:Stocks $300 $900 +12-Mar-15 Commodities revalued $150 $1050 +12-Apr-04 Commodities revalued $150 $1200 +12-Apr-04 Broker Assets:Stocks $400 $1600 +12-Apr-15 Commodities revalued $200 $1800 +12-May-05 Commodities revalued $200 $2000 +12-May-05 Broker Assets:Stocks $500 $2500 +end test + +test reg stocks -O -V +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Jan-15 Commodities revalued $50 $150 +12-Feb-02 Commodities revalued $50 $200 +12-Feb-02 Broker Assets:Stocks $200 $400 +12-Feb-15 Commodities revalued $100 $500 +12-Mar-03 Commodities revalued $100 $600 +12-Mar-03 Broker Assets:Stocks $300 $900 +12-Mar-15 Commodities revalued $150 $1050 +12-Apr-04 Commodities revalued $150 $1200 +12-Apr-04 Broker Assets:Stocks $400 $1600 +12-Apr-15 Commodities revalued $200 $1800 +12-May-05 Commodities revalued $200 $2000 +12-May-05 Broker Assets:Stocks $500 $2500 +end test + +test reg stocks -B -V +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Feb-02 Broker Assets:Stocks $200 $300 +12-Mar-03 Broker Assets:Stocks $300 $600 +12-Apr-04 Broker Assets:Stocks $400 $1000 +12-May-05 Broker Assets:Stocks $500 $1500 +end test + +test reg stocks -I -V +12-Jan-01 Broker Assets:Stocks $10 $10 +12-Feb-02 Broker Assets:Stocks $20 $30 +12-Mar-03 Broker Assets:Stocks $30 $60 +12-Apr-04 Broker Assets:Stocks $40 $100 +12-May-05 Broker Assets:Stocks $50 $150 +end test + +test reg stocks -X EUR +12-Jan-01 Broker Assets:Stocks EUR 200,00 EUR 200,00 +12-Feb-02 Commodities revalued EUR 200,00 EUR 400,00 +12-Feb-02 Broker Assets:Stocks EUR 400,00 EUR 800,00 +12-Mar-03 Commodities revalued EUR 400,00 EUR 1.200,00 +12-Mar-03 Broker Assets:Stocks EUR 600,00 EUR 1.800,00 +12-Apr-04 Commodities revalued EUR 600,00 EUR 2.400,00 +12-Apr-04 Broker Assets:Stocks EUR 800,00 EUR 3.200,00 +12-May-05 Commodities revalued EUR 800,00 EUR 4.000,00 +12-May-05 Broker Assets:Stocks EUR 1.000,00 EUR 5.000,00 +end test + +test reg stocks -O -X EUR +12-Jan-01 Broker Assets:Stocks EUR 200,00 EUR 200,00 +12-Feb-02 Commodities revalued EUR 200,00 EUR 400,00 +12-Feb-02 Broker Assets:Stocks EUR 400,00 EUR 800,00 +12-Mar-03 Commodities revalued EUR 400,00 EUR 1.200,00 +12-Mar-03 Broker Assets:Stocks EUR 600,00 EUR 1.800,00 +12-Apr-04 Commodities revalued EUR 600,00 EUR 2.400,00 +12-Apr-04 Broker Assets:Stocks EUR 800,00 EUR 3.200,00 +12-May-05 Commodities revalued EUR 800,00 EUR 4.000,00 +12-May-05 Broker Assets:Stocks EUR 1.000,00 EUR 5.000,00 +end test + +test reg stocks -B -X EUR +12-Jan-01 Broker Assets:Stocks EUR 200,00 EUR 200,00 +12-Feb-02 Broker Assets:Stocks EUR 400,00 EUR 600,00 +12-Mar-03 Broker Assets:Stocks EUR 600,00 EUR 1.200,00 +12-Apr-04 Broker Assets:Stocks EUR 800,00 EUR 2.000,00 +12-May-05 Broker Assets:Stocks EUR 1.000,00 EUR 3.000,00 +end test + +test reg stocks -I -X EUR +12-Jan-01 Broker Assets:Stocks EUR 20,00 EUR 20,00 +12-Feb-02 Broker Assets:Stocks EUR 40,00 EUR 60,00 +12-Mar-03 Broker Assets:Stocks EUR 60,00 EUR 120,00 +12-Apr-04 Broker Assets:Stocks EUR 80,00 EUR 200,00 +12-May-05 Broker Assets:Stocks EUR 100,00 EUR 300,00 +end test + +test reg stocks -H +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Feb-02 Broker Assets:Stocks $200 $300 +12-Mar-03 Broker Assets:Stocks $300 $600 +12-Apr-04 Broker Assets:Stocks $400 $1000 +12-May-05 Broker Assets:Stocks $500 $1500 end test test reg stocks -O -H +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Feb-02 Broker Assets:Stocks $200 $300 +12-Mar-03 Broker Assets:Stocks $300 $600 +12-Apr-04 Broker Assets:Stocks $400 $1000 +12-May-05 Broker Assets:Stocks $500 $1500 end test test reg stocks -B -H +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Feb-02 Broker Assets:Stocks $200 $300 +12-Mar-03 Broker Assets:Stocks $300 $600 +12-Apr-04 Broker Assets:Stocks $400 $1000 +12-May-05 Broker Assets:Stocks $500 $1500 end test test reg stocks -I -H +12-Jan-01 Broker Assets:Stocks $10 $10 +12-Feb-02 Broker Assets:Stocks $20 $30 +12-Mar-03 Broker Assets:Stocks $30 $60 +12-Apr-04 Broker Assets:Stocks $40 $100 +12-May-05 Broker Assets:Stocks $50 $150 end test -test reg stocks -O -V +test reg stocks -H -V +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Feb-02 Broker Assets:Stocks $200 $300 +12-Mar-03 Broker Assets:Stocks $300 $600 +12-Apr-04 Broker Assets:Stocks $400 $1000 +12-May-05 Broker Assets:Stocks $500 $1500 end test -test reg stocks -B -V +test reg stocks -O -H -V +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Feb-02 Broker Assets:Stocks $200 $300 +12-Mar-03 Broker Assets:Stocks $300 $600 +12-Apr-04 Broker Assets:Stocks $400 $1000 +12-May-05 Broker Assets:Stocks $500 $1500 end test -test reg stocks -I -V +test reg stocks -B -H -V +12-Jan-01 Broker Assets:Stocks $100 $100 +12-Feb-02 Broker Assets:Stocks $200 $300 +12-Mar-03 Broker Assets:Stocks $300 $600 +12-Apr-04 Broker Assets:Stocks $400 $1000 +12-May-05 Broker Assets:Stocks $500 $1500 +end test + +test reg stocks -I -H -V +12-Jan-01 Broker Assets:Stocks $10 $10 +12-Feb-02 Broker Assets:Stocks $20 $30 +12-Mar-03 Broker Assets:Stocks $30 $60 +12-Apr-04 Broker Assets:Stocks $40 $100 +12-May-05 Broker Assets:Stocks $50 $150 +end test + +test reg stocks -H -X EUR +12-Jan-01 Broker Assets:Stocks EUR 200,00 EUR 200,00 +12-Feb-02 Broker Assets:Stocks EUR 400,00 EUR 600,00 +12-Mar-03 Broker Assets:Stocks EUR 600,00 EUR 1.200,00 +12-Apr-04 Broker Assets:Stocks EUR 800,00 EUR 2.000,00 +12-May-05 Broker Assets:Stocks EUR 1.000,00 EUR 3.000,00 +end test + +test reg stocks -O -H -X EUR +12-Jan-01 Broker Assets:Stocks EUR 200,00 EUR 200,00 +12-Feb-02 Broker Assets:Stocks EUR 400,00 EUR 600,00 +12-Mar-03 Broker Assets:Stocks EUR 600,00 EUR 1.200,00 +12-Apr-04 Broker Assets:Stocks EUR 800,00 EUR 2.000,00 +12-May-05 Broker Assets:Stocks EUR 1.000,00 EUR 3.000,00 +end test + +test reg stocks -B -H -X EUR +12-Jan-01 Broker Assets:Stocks EUR 200,00 EUR 200,00 +12-Feb-02 Broker Assets:Stocks EUR 400,00 EUR 600,00 +12-Mar-03 Broker Assets:Stocks EUR 600,00 EUR 1.200,00 +12-Apr-04 Broker Assets:Stocks EUR 800,00 EUR 2.000,00 +12-May-05 Broker Assets:Stocks EUR 1.000,00 EUR 3.000,00 +end test + +test reg stocks -I -H -X EUR +12-Jan-01 Broker Assets:Stocks EUR 20,00 EUR 20,00 +12-Feb-02 Broker Assets:Stocks EUR 40,00 EUR 60,00 +12-Mar-03 Broker Assets:Stocks EUR 60,00 EUR 120,00 +12-Apr-04 Broker Assets:Stocks EUR 80,00 EUR 200,00 +12-May-05 Broker Assets:Stocks EUR 100,00 EUR 300,00 end test -- cgit v1.2.3 From 77e9e3bfb9b7342fb367723d18073200c311d420 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Fri, 9 Mar 2012 14:11:13 -0600 Subject: Allow --budget-format to be used --- src/report.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 27d8bb2a..2d37f19f 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1003,6 +1003,7 @@ option_t * report_t::lookup_option(const char * p) else OPT_(begin_); else OPT(bold_if_); else OPT(budget); + else OPT(budget_format_); else OPT(by_payee); break; case 'c': -- cgit v1.2.3 From 50f202c4e8faecf7398fb21ba5b31768ec46c826 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 10 Mar 2012 01:01:18 -0600 Subject: Make --lot-notes a synonym for --lot-tags --- doc/ledger.1 | 3 ++- src/report.cc | 2 +- test/baseline/opt-lot-notes.test | 0 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 test/baseline/opt-lot-notes.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index a8e5dcc4..2879cbe0 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -1,4 +1,4 @@ -.Dd March 9, 2012 +.Dd March 10, 2012 .Dt ledger 1 .Sh NAME .Nm ledger @@ -349,6 +349,7 @@ See .It Fl \-leeway Ar INT Pq Fl Z .It Fl \-limit Ar EXPR Pq Fl l .It Fl \-lot-dates +.It Fl \-lot-notes .It Fl \-lot-prices .It Fl \-lot-tags .It Fl \-lots diff --git a/src/report.cc b/src/report.cc index 2d37f19f..c959e70a 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1068,7 +1068,7 @@ option_t * report_t::lookup_option(const char * p) OPT_(limit_); else OPT(lot_dates); else OPT(lot_prices); - else OPT(lot_tags); + else OPT_ALT(lot_tags, lot_notes); else OPT(lots); else OPT(lots_actual); else OPT_ALT(tail_, last_); diff --git a/test/baseline/opt-lot-notes.test b/test/baseline/opt-lot-notes.test new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3 From 02225a014a6e7b3d41cd6b64632b2dba06681c67 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 10 Mar 2012 21:32:31 -0600 Subject: Give a better error when sequences are mis-indexed --- src/report.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index c959e70a..4dd0bca4 100644 --- a/src/report.cc +++ b/src/report.cc @@ -539,13 +539,20 @@ value_t report_t::fn_get_at(call_scope_t& args) if (index == 0) { if (! args[0].is_sequence()) return args[0]; - } else { - if (! args[0].is_sequence()) - throw_(std::runtime_error, - _("Attempting to get argument at index %1 from %2") - << index << args[0].label()); } - return args[0].as_sequence()[index]; + else if (! args[0].is_sequence()) { + throw_(std::runtime_error, + _("Attempting to get argument at index %1 from %2") + << index << args[0].label()); + } + + value_t::sequence_t& seq(args[0].as_sequence_lval()); + if (index >= seq.size()) + throw_(std::runtime_error, + _("Attempting to get index %1 from %2 with %3 elements") + << index << args[0].label() << seq.size()); + + return seq[index]; } value_t report_t::fn_is_seq(call_scope_t& scope) -- cgit v1.2.3 From 7b45a664f2d188065dadb8506742f718982373eb Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 10 Mar 2012 21:32:48 -0600 Subject: Make --lot-notes the primary name, not --lot-tags --- doc/ledger.1 | 1 - src/report.cc | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index 2879cbe0..20369a78 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -351,7 +351,6 @@ See .It Fl \-lot-dates .It Fl \-lot-notes .It Fl \-lot-prices -.It Fl \-lot-tags .It Fl \-lots .It Fl \-lots-actual .It Fl \-market Pq Fl V diff --git a/src/report.cc b/src/report.cc index 4dd0bca4..36865a75 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1075,7 +1075,7 @@ option_t * report_t::lookup_option(const char * p) OPT_(limit_); else OPT(lot_dates); else OPT(lot_prices); - else OPT_ALT(lot_tags, lot_notes); + else OPT_ALT(lot_notes, lot_tags); else OPT(lots); else OPT(lots_actual); else OPT_ALT(tail_, last_); -- cgit v1.2.3 From 860610fdaf94ca5904ea3e0d3d82126de74c7d80 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 10 Mar 2012 21:34:51 -0600 Subject: Added --dc option, for debit/credit style reports --- doc/ledger.1 | 1 + src/report.cc | 19 +++++++-- src/report.h | 76 ++++++++++++++++++++++++++++++++--- test/baseline/opt-dc.test | 16 ++++++++ test/baseline/opt-meta-width.test | 4 +- test/manual/transaction-codes-1.test | 4 +- test/manual/transaction-notes-1.test | 4 +- test/manual/transaction-notes-2.test | 2 +- test/manual/transaction-notes-3.test | 2 +- test/manual/transaction-status-1.test | 6 +-- test/manual/transaction-status-2.test | 2 +- test/manual/transaction-status-3.test | 4 +- test/manual/transaction-status-4.test | 2 +- 13 files changed, 119 insertions(+), 23 deletions(-) create mode 100644 test/baseline/opt-dc.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index 20369a78..d69d6c22 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -300,6 +300,7 @@ See .It Fl \-date-format Ar DATEFMT Pq Fl y .It Fl \-datetime-format Ar FMT .It Fl \-date-width Ar INT +.It Fl \-dc .It Fl \-debug Ar STR .It Fl \-decimal-comma .It Fl \-depth Ar INT diff --git a/src/report.cc b/src/report.cc index 36865a75..8cfa7a59 100644 --- a/src/report.cc +++ b/src/report.cc @@ -204,10 +204,22 @@ void report_t::normalize_options(const string& verb) ! HANDLED(amount_width_) && ! HANDLED(total_width_)) { long total = (4 /* the spaces between */ + date_width + payee_width + - account_width + amount_width + total_width); - if (total > cols) { + account_width + amount_width + total_width + + (HANDLED(dc) ? 1 + amount_width : 0)); + while (total > cols && account_width > 5 && payee_width > 5) { DEBUG("auto.columns", "adjusting account down"); - account_width -= total - cols; + if (total > cols) { + --account_width; + --total; + if (total > cols) { + --account_width; + --total; + } + } + if (total > cols) { + --payee_width; + --total; + } DEBUG("auto.columns", "account_width now = " << account_width); } } @@ -1029,6 +1041,7 @@ option_t * report_t::lookup_option(const char * p) else OPT(date_); else OPT(date_format_); else OPT(datetime_format_); + else OPT(dc); else OPT(depth_); else OPT(deviation); else OPT_(display_); diff --git a/src/report.h b/src/report.h index ed3aae2e..04fdcd45 100644 --- a/src/report.h +++ b/src/report.h @@ -215,7 +215,7 @@ public: bool lots = HANDLED(lots) || HANDLED(lots_actual); return keep_details_t(lots || HANDLED(lot_prices), lots || HANDLED(lot_dates), - lots || HANDLED(lot_tags), + lots || HANDLED(lot_notes), HANDLED(lots_actual)); } @@ -250,6 +250,7 @@ public: HANDLER(date_).report(out); HANDLER(date_format_).report(out); HANDLER(datetime_format_).report(out); + HANDLER(dc).report(out); HANDLER(depth_).report(out); HANDLER(deviation).report(out); HANDLER(display_).report(out); @@ -277,7 +278,7 @@ public: HANDLER(limit_).report(out); HANDLER(lot_dates).report(out); HANDLER(lot_prices).report(out); - HANDLER(lot_tags).report(out); + HANDLER(lot_notes).report(out); HANDLER(lots).report(out); HANDLER(lots_actual).report(out); HANDLER(market).report(out); @@ -518,6 +519,73 @@ public: OPTION(report_t, date_format_); OPTION(report_t, datetime_format_); + OPTION_(report_t, dc, DO() { + OTHER(amount_).expr.set_base_expr + ("(amount > 0 ? amount : 0, amount < 0 ? amount : 0)"); + + OTHER(register_format_) + .on(none, + "%(ansify_if(" + " ansify_if(justify(format_date(date), int(date_width))," + " green if color and date > today)," + " bold if should_bold))" + " %(ansify_if(" + " ansify_if(justify(truncated(payee, int(payee_width)), int(payee_width)), " + " bold if color and !cleared and actual)," + " bold if should_bold))" + " %(ansify_if(" + " ansify_if(justify(truncated(display_account, int(account_width), " + " abbrev_len), int(account_width))," + " blue if color)," + " bold if should_bold))" + " %(ansify_if(" + " justify(scrub(abs(get_at(display_amount, 0))), int(amount_width), " + " 3 + int(meta_width) + int(date_width) + int(payee_width)" + " + int(account_width) + int(amount_width) + int(prepend_width)," + " true, color)," + " bold if should_bold))" + " %(ansify_if(" + " justify(scrub(abs(get_at(display_amount, 1))), int(amount_width), " + " 4 + int(meta_width) + int(date_width) + int(payee_width)" + " + int(account_width) + int(amount_width) + int(amount_width) + int(prepend_width)," + " true, color)," + " bold if should_bold))" + " %(ansify_if(" + " justify(scrub(get_at(display_total, 0) + get_at(display_total, 1)), int(total_width), " + " 5 + int(meta_width) + int(date_width) + int(payee_width)" + " + int(account_width) + int(amount_width) + int(amount_width) + int(total_width)" + " + int(prepend_width), true, color)," + " bold if should_bold))\n%/" + "%(justify(\" \", int(date_width)))" + " %(ansify_if(" + " justify(truncated(has_tag(\"Payee\") ? payee : \" \", " + " int(payee_width)), int(payee_width))," + " bold if should_bold))" + " %$3 %$4 %$5 %$6\n"); + + OTHER(balance_format_) + .on(none, + "%(ansify_if(" + " justify(scrub(abs(get_at(display_total, 0))), 14," + " 14 + int(prepend_width), true, color)," + " bold if should_bold)) " + "%(ansify_if(" + " justify(scrub(abs(get_at(display_total, 1))), 14," + " 14 + 1 + int(prepend_width) + int(total_width), true, color)," + " bold if should_bold)) " + "%(ansify_if(" + " justify(scrub(get_at(display_total, 0) + get_at(display_total, 1)), 14," + " 14 + 2 + int(prepend_width) + int(total_width) + int(total_width), true, color)," + " bold if should_bold))" + " %(!options.flat ? depth_spacer : \"\")" + "%-(ansify_if(" + " ansify_if(partial_account(options.flat), blue if color)," + " bold if should_bold))\n%/" + "%$1 %$2 %$3\n%/" + "%(prepend_width ? \" \" * int(prepend_width) : \"\")" + "--------------------------------------------\n"); + }); + OPTION_(report_t, depth_, DO_(str) { OTHER(display_).on(whence, string("depth<=") + str); }); @@ -590,9 +658,7 @@ public: OPTION_(report_t, gain, DO() { // -G OTHER(revalued).on(whence); - OTHER(amount_).expr.set_base_expr("(amount, cost)"); - OTHER(total_).expr.set_base_expr("total"); // Since we are displaying the amounts of revalued postings, they // will end up being composite totals, and hence a pair of pairs. @@ -653,7 +719,7 @@ public: OPTION(report_t, lot_dates); OPTION(report_t, lot_prices); - OPTION(report_t, lot_tags); + OPTION(report_t, lot_notes); OPTION(report_t, lots); OPTION(report_t, lots_actual); diff --git a/test/baseline/opt-dc.test b/test/baseline/opt-dc.test new file mode 100644 index 00000000..24a564dd --- /dev/null +++ b/test/baseline/opt-dc.test @@ -0,0 +1,16 @@ +2012-03-10 Employer + Assets:Cash $100 + Income:Employer + +2012-03-10 KFC + Expenses:Food $20 + Assets:Cash + +2012-03-10 KFC - Rebate + Assets:Cash + Expenses:Food $-5 + +2012-03-10 KFC - Food & Rebate + Expenses:Food $20 + Expenses:Food $-5 + Assets:Cash diff --git a/test/baseline/opt-meta-width.test b/test/baseline/opt-meta-width.test index ce751e24..893e175b 100644 --- a/test/baseline/opt-meta-width.test +++ b/test/baseline/opt-meta-width.test @@ -9,6 +9,6 @@ ; :AnotherTag: test reg --meta Sample --meta-width=15 -Another Value 04-May-27 Credit card com.. Liab:MasterCard $20.00 $20.00 -Value As:Ban:Checking $-20.00 0 +Another Value 04-May-27 Credit card co.. Liabi:MasterCard $20.00 $20.00 +Value As:Bank:Checking $-20.00 0 end test diff --git a/test/manual/transaction-codes-1.test b/test/manual/transaction-codes-1.test index 7a05b349..ff68e0ec 100644 --- a/test/manual/transaction-codes-1.test +++ b/test/manual/transaction-codes-1.test @@ -15,6 +15,6 @@ Liabilities:Credit Card test reg --columns=60 food and code xfer -09-Oct-29 Panera Bread Expenses:Food $4.50 $4.50 -09-Oct-30 Panera Bread Expenses:Food $4.50 $9.00 +09-Oct-29 Panera Bread Expenses:Food $4.50 $4.50 +09-Oct-30 Panera Bread Expenses:Food $4.50 $9.00 end test diff --git a/test/manual/transaction-notes-1.test b/test/manual/transaction-notes-1.test index 7c3d7200..05ab3412 100644 --- a/test/manual/transaction-notes-1.test +++ b/test/manual/transaction-notes-1.test @@ -17,6 +17,6 @@ Assets:Checking test reg --columns=60 food and note eat -09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 -09-Nov-01 Panera Bread Expenses:Food $4.50 $9.00 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +09-Nov-01 Panera Bread Expenses:Food $4.50 $9.00 end test diff --git a/test/manual/transaction-notes-2.test b/test/manual/transaction-notes-2.test index 603fcbe1..a29eda6e 100644 --- a/test/manual/transaction-notes-2.test +++ b/test/manual/transaction-notes-2.test @@ -17,5 +17,5 @@ Assets:Checking test reg --columns=60 food and tag eating -09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 end test diff --git a/test/manual/transaction-notes-3.test b/test/manual/transaction-notes-3.test index 9b05334c..b83322b0 100644 --- a/test/manual/transaction-notes-3.test +++ b/test/manual/transaction-notes-3.test @@ -17,5 +17,5 @@ Assets:Checking test reg --columns=60 food and tag type=dining -09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 end test diff --git a/test/manual/transaction-status-1.test b/test/manual/transaction-status-1.test index 1f7ad095..8bfdd6d9 100644 --- a/test/manual/transaction-status-1.test +++ b/test/manual/transaction-status-1.test @@ -11,7 +11,7 @@ Assets test reg --columns=60 food -09-Oct-31 Panera Bread Expenses:Food $4.50 $4.50 -09-Nov-01 Panera Bread Expenses:Food $4.50 $9.00 -09-Nov-02 Panera Bread Expenses:Food $4.50 $13.50 +09-Oct-31 Panera Bread Expenses:Food $4.50 $4.50 +09-Nov-01 Panera Bread Expenses:Food $4.50 $9.00 +09-Nov-02 Panera Bread Expenses:Food $4.50 $13.50 end test diff --git a/test/manual/transaction-status-2.test b/test/manual/transaction-status-2.test index 6c6d4b8c..94c42a65 100644 --- a/test/manual/transaction-status-2.test +++ b/test/manual/transaction-status-2.test @@ -11,5 +11,5 @@ Assets test reg --columns=60 food --cleared -09-Oct-31 Panera Bread Expenses:Food $4.50 $4.50 +09-Oct-31 Panera Bread Expenses:Food $4.50 $4.50 end test diff --git a/test/manual/transaction-status-3.test b/test/manual/transaction-status-3.test index f50ea23c..f11cd0f7 100644 --- a/test/manual/transaction-status-3.test +++ b/test/manual/transaction-status-3.test @@ -11,6 +11,6 @@ Assets test reg --columns=60 food --uncleared -09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 -09-Nov-02 Panera Bread Expenses:Food $4.50 $9.00 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +09-Nov-02 Panera Bread Expenses:Food $4.50 $9.00 end test diff --git a/test/manual/transaction-status-4.test b/test/manual/transaction-status-4.test index 2ae03c3e..c6f0419b 100644 --- a/test/manual/transaction-status-4.test +++ b/test/manual/transaction-status-4.test @@ -11,5 +11,5 @@ Assets test reg --columns=60 food --pending -09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 end test -- cgit v1.2.3 From 2a4d7e1af0ac18693b0c1ffa39daa4ad51e1492f Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 10 Mar 2012 21:58:28 -0600 Subject: Added --immediate option --- doc/ledger.1 | 1 + src/report.cc | 6 ++++++ src/report.h | 2 ++ test/baseline/opt-immediate.test | 0 4 files changed, 9 insertions(+) create mode 100644 test/baseline/opt-immediate.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index d69d6c22..8076c7c4 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -339,6 +339,7 @@ See .It Fl \-help-calc .It Fl \-help-comm .It Fl \-help-disp +.It Fl \-immediate .It Fl \-import Ar STR .It Fl \-init-file Ar FILE .It Fl \-inject Ar STR diff --git a/src/report.cc b/src/report.cc index 8cfa7a59..bd2df046 100644 --- a/src/report.cc +++ b/src/report.cc @@ -162,6 +162,11 @@ void report_t::normalize_options(const string& verb) terminus); } + if (HANDLED(immediate) && HANDLED(market)) { + HANDLER(amount_) + .on("?normalize", "market(amount_expr, value_date, exchange)"); + } + long cols = 0; if (HANDLED(columns_)) cols = lexical_cast(HANDLER(columns_).value); @@ -1080,6 +1085,7 @@ option_t * report_t::lookup_option(const char * p) case 'i': OPT(invert); else OPT(inject_); + else OPT(immediate); break; case 'j': OPT_CH(amount_data); diff --git a/src/report.h b/src/report.h index 04fdcd45..a3825335 100644 --- a/src/report.h +++ b/src/report.h @@ -273,6 +273,7 @@ public: HANDLER(group_by_).report(out); HANDLER(group_title_format_).report(out); HANDLER(head_).report(out); + HANDLER(immediate).report(out); HANDLER(inject_).report(out); HANDLER(invert).report(out); HANDLER(limit_).report(out); @@ -704,6 +705,7 @@ public: "market(amount_expr, value_date, exchange))"); }); + OPTION(report_t, immediate); OPTION(report_t, inject_); OPTION_(report_t, invert, DO() { diff --git a/test/baseline/opt-immediate.test b/test/baseline/opt-immediate.test new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3 From 6ddd935e4a140d77b9f94beeed1c76286c9cc1ca Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 10 Mar 2012 21:58:43 -0600 Subject: --percent now plays well with -X and -V --- src/report.cc | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index bd2df046..2b07efcb 100644 --- a/src/report.cc +++ b/src/report.cc @@ -162,6 +162,15 @@ void report_t::normalize_options(const string& verb) terminus); } + if (HANDLED(percent) && HANDLED(market)) { + HANDLER(total_) + .on("?normalize", + "(__tmp = market(parent.total, value_date, exchange);" + " ((is_account & parent & __tmp) ?" + " percent(scrub(market(total, value_date, exchange)), " + " scrub(__tmp)) : 0))"); + } + if (HANDLED(immediate) && HANDLED(market)) { HANDLER(amount_) .on("?normalize", "market(amount_expr, value_date, exchange)"); -- cgit v1.2.3 From 0d9d8453387e0f49f0dd4ea4b5f090da91c283bd Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 11 Mar 2012 03:06:03 -0500 Subject: Corrected a rounding error in nail_down Fixes #678 --- src/report.cc | 3 ++- test/regress/889BB167.test | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 test/regress/889BB167.test (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 2b07efcb..fb585ce1 100644 --- a/src/report.cc +++ b/src/report.cc @@ -783,7 +783,8 @@ value_t report_t::fn_nail_down(call_scope_t& args) amount_t tmp(arg0.as_amount()); if (tmp.has_commodity() && ! arg1.is_null()) { expr_t value_expr(is_expr(arg1) ? - as_expr(arg1) : expr_t::op_t::wrap_value(arg1 / arg0)); + as_expr(arg1) : + expr_t::op_t::wrap_value(arg1.unrounded() / arg0)); std::ostringstream buf; value_expr.print(buf); value_expr.set_text(buf.str()); diff --git a/test/regress/889BB167.test b/test/regress/889BB167.test new file mode 100644 index 00000000..02e25ab6 --- /dev/null +++ b/test/regress/889BB167.test @@ -0,0 +1,17 @@ +D 1000.00 GBP + +P 2011-01-01 EUR 0.8604 GBP +P 2011-02-01 EUR 0.8576 GBP + +2011-01-31 * AdSense earnings + Assets:Receivable:AdSense 11.00 EUR + Income:AdSense + +2011-02-28 * AdSense earnings + Assets:Receivable:AdSense 10.00 EUR + Income:AdSense + +test reg income:adse -X GBP -H +11-Jan-31 AdSense earnings Income:AdSense -9.46 GBP -9.46 GBP +11-Feb-28 AdSense earnings Income:AdSense -8.58 GBP -18.04 GBP +end test -- cgit v1.2.3 From 2303aa993cf41ad5bde8f8f5722bd265c11e3aa7 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 11 Mar 2012 03:06:50 -0500 Subject: Allow balances to be passed to nail_down Fixes #679 --- src/report.cc | 23 +++++++++++++++++++++++ src/value.cc | 2 +- test/regress/14DB77E7.test | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 test/regress/14DB77E7.test (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index fb585ce1..8205c1dd 100644 --- a/src/report.cc +++ b/src/report.cc @@ -794,6 +794,29 @@ value_t report_t::fn_nail_down(call_scope_t& args) return tmp; } + case value_t::BALANCE: { + balance_t tmp; + foreach (const balance_t::amounts_map::value_type& pair, + arg0.as_balance_lval().amounts) { + call_scope_t inner_args(*args.parent); + inner_args.push_back(pair.second); + inner_args.push_back(arg1); + tmp += fn_nail_down(inner_args).as_amount(); + } + return tmp; + } + + case value_t::SEQUENCE: { + value_t tmp; + foreach (value_t& value, arg0.as_sequence_lval()) { + call_scope_t inner_args(*args.parent); + inner_args.push_back(value); + inner_args.push_back(arg1); + tmp.push_back(fn_nail_down(inner_args)); + } + return tmp; + } + default: throw_(std::runtime_error, _("Attempting to nail down %1") << args[0].label()); diff --git a/src/value.cc b/src/value.cc index 97328c37..c4e7170d 100644 --- a/src/value.cc +++ b/src/value.cc @@ -724,7 +724,7 @@ value_t& value_t::operator/=(const value_t& val) return *this; case AMOUNT: if (as_balance().single_amount()) { - in_place_simplify(); + in_place_cast(AMOUNT); as_amount_lval() /= val.as_amount(); return *this; } diff --git a/test/regress/14DB77E7.test b/test/regress/14DB77E7.test new file mode 100644 index 00000000..ee155afb --- /dev/null +++ b/test/regress/14DB77E7.test @@ -0,0 +1,18 @@ +D 1000.00 GBP + +;P 2011-01-01 EUR 0.8604 GBP +P 2011-02-01 EUR 0.8576 GBP + +2011-01-31 * AdSense earnings + Assets:Receivable:AdSense 11.00 EUR + Income:AdSense + +2011-02-28 * AdSense earnings + Assets:Receivable:AdSense 10.00 EUR + Income:AdSense + +test reg income:adse -X GBP -H +11-Jan-31 AdSense earnings Income:AdSense -11.00 EUR -11.00 EUR +11-Feb-01 Commodities revalued -9.43 GBP -9.43 GBP +11-Feb-28 AdSense earnings Income:AdSense -8.58 GBP -18.01 GBP +end test -- cgit v1.2.3 From 363670d35bf451ff8ce636c071da73a0d93c514a Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 11 Mar 2012 03:55:25 -0500 Subject: Tighten up argument passing related to fn_market() --- src/amount.cc | 19 +++++------ src/amount.h | 8 +++-- src/annotate.cc | 16 +++++----- src/annotate.h | 6 ++-- src/balance.cc | 4 +-- src/balance.h | 4 +-- src/commodity.cc | 78 ++++++++++++++++++++++------------------------ src/commodity.h | 22 ++++++------- src/history.cc | 55 ++++++++++++++++---------------- src/history.h | 23 +++++++------- src/pool.h | 3 +- src/py_amount.cc | 6 ++-- src/py_balance.cc | 6 ++-- src/py_value.cc | 6 ++-- src/quotes.cc | 2 +- src/quotes.h | 2 +- src/report.cc | 9 +++--- src/value.cc | 16 +++++----- src/value.h | 10 +++--- test/regress/25A099C9.test | 12 +++---- test/unit/t_commodity.cc | 6 ++-- 21 files changed, 153 insertions(+), 160 deletions(-) (limited to 'src/report.cc') diff --git a/src/amount.cc b/src/amount.cc index 46eb5531..5fa58528 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -728,16 +728,16 @@ void amount_t::in_place_unreduce() } optional -amount_t::value(const optional& moment, - const optional& in_terms_of) const +amount_t::value(const datetime_t& moment, + const commodity_t * in_terms_of) const { if (quantity) { #if defined(DEBUG_ON) DEBUG("commodity.price.find", "amount_t::value of " << commodity().symbol()); - if (moment) + if (! moment.is_not_a_date_time()) DEBUG("commodity.price.find", - "amount_t::value: moment = " << *moment); + "amount_t::value: moment = " << moment); if (in_terms_of) DEBUG("commodity.price.find", "amount_t::value: in_terms_of = " << in_terms_of->symbol()); @@ -745,7 +745,7 @@ amount_t::value(const optional& moment, if (has_commodity() && (in_terms_of || ! commodity().has_flags(COMMODITY_PRIMARY))) { optional point; - optional comm(in_terms_of); + const commodity_t * comm(in_terms_of); if (has_annotation() && annotation().price) { if (annotation().has_flags(ANNOTATION_PRICE_FIXATED)) { @@ -755,7 +755,7 @@ amount_t::value(const optional& moment, "amount_t::value: fixated price = " << point->price); } else if (! comm) { - comm = annotation().price->commodity(); + comm = annotation().price->commodity_ptr(); } } @@ -869,15 +869,10 @@ bool amount_t::fits_in_long() const commodity_t * amount_t::commodity_ptr() const { - return (has_commodity() ? + return (commodity_ ? commodity_ : commodity_pool_t::current_pool->null_commodity); } -commodity_t& amount_t::commodity() const -{ - return *commodity_ptr(); -} - bool amount_t::has_commodity() const { return commodity_ && commodity_ != commodity_->pool().null_commodity; diff --git a/src/amount.h b/src/amount.h index 7bf4fe51..903a01cd 100644 --- a/src/amount.h +++ b/src/amount.h @@ -404,8 +404,8 @@ public: $100.00. */ optional - value(const optional& moment = none, - const optional& in_terms_of = none) const; + value(const datetime_t& moment = datetime_t(), + const commodity_t * in_terms_of = NULL) const; optional price() const; @@ -534,7 +534,9 @@ public: useful for accessing just the numeric portion of an amount. */ commodity_t * commodity_ptr() const; - commodity_t& commodity() const; + commodity_t& commodity() const { + return *commodity_ptr(); + } bool has_commodity() const; void set_commodity(commodity_t& comm) { diff --git a/src/annotate.cc b/src/annotate.cc index d2c7f983..2b118e76 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -241,16 +241,16 @@ bool annotated_commodity_t::operator==(const commodity_t& comm) const } optional -annotated_commodity_t::find_price(const optional& commodity, - const optional& moment, - const optional& oldest) const +annotated_commodity_t::find_price(const commodity_t * commodity, + const datetime_t& moment, + const datetime_t& oldest) const { DEBUG("commodity.price.find", "annotated_commodity_t::find_price(" << symbol() << ")"); datetime_t when; - if (moment) - when = *moment; + if (! moment.is_not_a_date_time()) + when = moment; else if (epoch) when = *epoch; else @@ -258,7 +258,7 @@ annotated_commodity_t::find_price(const optional& commodity, DEBUG("commodity.price.find", "reference time: " << when); - optional target; + const commodity_t * target = NULL; if (commodity) target = commodity; @@ -272,7 +272,7 @@ annotated_commodity_t::find_price(const optional& commodity, } else if (! target) { DEBUG("commodity.price.find", "setting target commodity from price"); - target = details.price->commodity(); + target = details.price->commodity_ptr(); } } @@ -285,7 +285,7 @@ annotated_commodity_t::find_price(const optional& commodity, return find_price_from_expr(const_cast(*details.value_expr), commodity, when); - return commodity_t::find_price(commodity, moment, oldest); + return commodity_t::find_price(target, moment, oldest); } commodity_t& diff --git a/src/annotate.h b/src/annotate.h index 606c6a60..044ebc4d 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -256,9 +256,9 @@ public: } optional - virtual find_price(const optional& commodity = none, - const optional& moment = none, - const optional& oldest = none) const; + virtual find_price(const commodity_t * commodity = NULL, + const datetime_t& moment = datetime_t(), + const datetime_t& oldest = datetime_t()) const; virtual commodity_t& strip_annotations(const keep_details_t& what_to_keep); virtual void write_annotations(std::ostream& out, diff --git a/src/balance.cc b/src/balance.cc index 08368dd8..f87e8bbd 100644 --- a/src/balance.cc +++ b/src/balance.cc @@ -185,8 +185,8 @@ balance_t& balance_t::operator/=(const amount_t& amt) } optional -balance_t::value(const optional& moment, - const optional& in_terms_of) const +balance_t::value(const datetime_t& moment, + const commodity_t * in_terms_of) const { balance_t temp; bool resolved = false; diff --git a/src/balance.h b/src/balance.h index 921f87ef..5f0d52ed 100644 --- a/src/balance.h +++ b/src/balance.h @@ -384,8 +384,8 @@ public: } optional - value(const optional& moment = none, - const optional& in_terms_of = none) const; + value(const datetime_t& moment = datetime_t(), + const commodity_t * in_terms_of = NULL) const; /** * Truth tests. An balance may be truth test in two ways: diff --git a/src/commodity.cc b/src/commodity.cc index 963fb646..8f0dc100 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -71,12 +71,12 @@ void commodity_t::remove_price(const datetime_t& date, commodity_t& commodity) } void commodity_t::map_prices(function fn, - const optional& moment, - const optional& _oldest) + const datetime_t& moment, + const datetime_t& _oldest) { datetime_t when; - if (moment) - when = *moment; + if (! moment.is_not_a_date_time()) + when = moment; else if (epoch) when = *epoch; else @@ -86,8 +86,7 @@ void commodity_t::map_prices(function fn, } optional -commodity_t::find_price_from_expr(expr_t& expr, - const optional& commodity, +commodity_t::find_price_from_expr(expr_t& expr, const commodity_t * commodity, const datetime_t& moment) const { #if defined(DEBUG_ON) @@ -114,31 +113,30 @@ commodity_t::find_price_from_expr(expr_t& expr, } optional -commodity_t::find_price(const optional& commodity, - const optional& moment, - const optional& oldest) const +commodity_t::find_price(const commodity_t * commodity, + const datetime_t& moment, + const datetime_t& oldest) const { DEBUG("commodity.price.find", "commodity_t::find_price(" << symbol() << ")"); - optional target; + const commodity_t * target = NULL; if (commodity) target = commodity; else if (pool().default_commodity) - target = *pool().default_commodity; + target = &*pool().default_commodity; - if (target && *this == *target) + if (target && this == target) return none; - optional - entry(base_t::memoized_price_entry(moment, oldest, - commodity ? &(*commodity) : NULL)); + base_t::memoized_price_entry entry(moment, oldest, + commodity ? commodity : NULL); DEBUG("commodity.price.find", "looking for memoized args: " - << (moment ? format_datetime(*moment) : "NONE") << ", " - << (oldest ? format_datetime(*oldest) : "NONE") << ", " + << (! moment.is_not_a_date_time() ? format_datetime(moment) : "NONE") << ", " + << (! oldest.is_not_a_date_time() ? format_datetime(oldest) : "NONE") << ", " << (commodity ? commodity->symbol() : "NONE")); { - base_t::memoized_price_map::iterator i = base->price_map.find(*entry); + base_t::memoized_price_map::iterator i = base->price_map.find(entry); if (i != base->price_map.end()) { DEBUG("commodity.price.find", "found! returning: " << ((*i).second ? (*i).second->price : amount_t(0L))); @@ -147,8 +145,8 @@ commodity_t::find_price(const optional& commodity, } datetime_t when; - if (moment) - when = *moment; + if (! moment.is_not_a_date_time()) + when = moment; else if (epoch) when = *epoch; else @@ -157,40 +155,40 @@ commodity_t::find_price(const optional& commodity, if (base->value_expr) return find_price_from_expr(*base->value_expr, commodity, when); - optional point = - target ? - pool().commodity_price_history.find_price(*this, *target, when, oldest) : - pool().commodity_price_history.find_price(*this, when, oldest); - - if (entry) { - if (base->price_map.size() > base_t::max_price_map_size) { - DEBUG("history.find", - "price map has grown too large, clearing it by half"); - for (std::size_t i = 0; i < base_t::max_price_map_size >> 1; i++) - base->price_map.erase(base->price_map.begin()); - } + optional + point(target ? + pool().commodity_price_history.find_price(*this, *target, + when, oldest) : + pool().commodity_price_history.find_price(*this, when, oldest)); + // Record this price point in the memoization map + if (base->price_map.size() > base_t::max_price_map_size) { DEBUG("history.find", - "remembered: " << (point ? point->price : amount_t(0L))); - base->price_map.insert(base_t::memoized_price_map::value_type(*entry, point)); + "price map has grown too large, clearing it by half"); + for (std::size_t i = 0; i < base_t::max_price_map_size >> 1; i++) + base->price_map.erase(base->price_map.begin()); } + DEBUG("history.find", + "remembered: " << (point ? point->price : amount_t(0L))); + base->price_map.insert(base_t::memoized_price_map::value_type(entry, point)); + return point; } optional commodity_t::check_for_updated_price(const optional& point, - const optional& moment, - const optional& in_terms_of) + const datetime_t& moment, + const commodity_t* in_terms_of) { if (pool().get_quotes && ! has_flags(COMMODITY_NOMARKET)) { bool exceeds_leeway = true; if (point) { time_duration_t::sec_type seconds_diff; - if (moment) { - seconds_diff = (*moment - point->when).total_seconds(); - DEBUG("commodity.download", "moment = " << *moment); + if (! moment.is_not_a_date_time()) { + seconds_diff = (moment - point->when).total_seconds(); + DEBUG("commodity.download", "moment = " << moment); DEBUG("commodity.download", "slip.moment = " << seconds_diff); } else { seconds_diff = (TRUE_CURRENT_TIME() - point->when).total_seconds(); @@ -209,7 +207,7 @@ commodity_t::check_for_updated_price(const optional& point, pool().get_commodity_quote(*this, in_terms_of)) { if (! in_terms_of || (quote->price.has_commodity() && - quote->price.commodity() == *in_terms_of)) + quote->price.commodity_ptr() == in_terms_of)) return quote; } } diff --git a/src/commodity.h b/src/commodity.h index 1358966e..bd1aedb9 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -117,12 +117,12 @@ protected: optional larger; optional value_expr; - typedef tuple, - optional, commodity_t *> memoized_price_entry; + typedef tuple memoized_price_entry; typedef std::map > memoized_price_map; - static const std::size_t max_price_map_size = 16; + static const std::size_t max_price_map_size = 8; mutable memoized_price_map price_map; public: @@ -272,22 +272,22 @@ public: void remove_price(const datetime_t& date, commodity_t& commodity); void map_prices(function fn, - const optional& moment = none, - const optional& _oldest = none); + const datetime_t& moment = datetime_t(), + const datetime_t& _oldest = datetime_t()); optional - find_price_from_expr(expr_t& expr, const optional& commodity, + find_price_from_expr(expr_t& expr, const commodity_t * commodity, const datetime_t& moment) const; optional - virtual find_price(const optional& commodity = none, - const optional& moment = none, - const optional& oldest = none) const; + virtual find_price(const commodity_t * commodity = NULL, + const datetime_t& moment = datetime_t(), + const datetime_t& oldest = datetime_t()) const; optional check_for_updated_price(const optional& point, - const optional& moment, - const optional& in_terms_of); + const datetime_t& moment, + const commodity_t * in_terms_of); commodity_t& nail_down(const expr_t& expr); diff --git a/src/history.cc b/src/history.cc index 83326728..22ac4494 100644 --- a/src/history.cc +++ b/src/history.cc @@ -52,15 +52,15 @@ public: PricePointMap price_point; PriceRatioMap ratios; - datetime_t reftime; - optional oldest; + datetime_t reftime; + datetime_t oldest; recent_edge_weight() { } - recent_edge_weight(EdgeWeightMap _weight, - PricePointMap _price_point, - PriceRatioMap _ratios, - datetime_t _reftime, - const optional& _oldest = none) + recent_edge_weight(EdgeWeightMap _weight, + PricePointMap _price_point, + PriceRatioMap _ratios, + const datetime_t& _reftime, + const datetime_t& _oldest = datetime_t()) : weight(_weight), price_point(_price_point), ratios(_ratios), reftime(_reftime), oldest(_oldest) { } @@ -69,8 +69,8 @@ public: { #if defined(DEBUG_ON) DEBUG("history.find", " reftime = " << reftime); - if (oldest) { - DEBUG("history.find", " oldest = " << *oldest); + if (! oldest.is_not_a_date_time()) { + DEBUG("history.find", " oldest = " << oldest); } #endif @@ -88,7 +88,7 @@ public: --low; assert(((*low).first <= reftime)); - if (oldest && (*low).first < *oldest) { + if (! oldest.is_not_a_date_time() && (*low).first < oldest) { DEBUG("history.find", " edge is out of range"); return false; } @@ -170,9 +170,9 @@ void commodity_history_t::remove_price(const commodity_t& source, void commodity_history_t::map_prices(function fn, - const commodity_t& source, - const datetime_t& moment, - const optional& oldest) + const commodity_t& source, + const datetime_t& moment, + const datetime_t& oldest) { vertex_descriptor sv = vertex(*source.graph_index(), price_graph); @@ -193,7 +193,7 @@ void commodity_history_t::map_prices(function= *oldest) && when <= moment) { + if ((oldest.is_not_a_date_time() || when >= oldest) && when <= moment) { if (pair.second.commodity() == source) { amount_t price(pair.second); price.in_place_invert(); @@ -209,9 +209,9 @@ void commodity_history_t::map_prices(function -commodity_history_t::find_price(const commodity_t& source, - const datetime_t& moment, - const optional& oldest) +commodity_history_t::find_price(const commodity_t& source, + const datetime_t& moment, + const datetime_t& oldest) { vertex_descriptor sv = vertex(*source.graph_index(), price_graph); @@ -270,10 +270,10 @@ commodity_history_t::find_price(const commodity_t& source, } optional -commodity_history_t::find_price(const commodity_t& source, - const commodity_t& target, - const datetime_t& moment, - const optional& oldest) +commodity_history_t::find_price(const commodity_t& source, + const commodity_t& target, + const datetime_t& moment, + const datetime_t& oldest) { vertex_descriptor sv = vertex(*source.graph_index(), price_graph); vertex_descriptor tv = vertex(*target.graph_index(), price_graph); @@ -402,17 +402,16 @@ private: Name name; }; -void commodity_history_t::print_map(std::ostream& out, - const optional& moment) +void commodity_history_t::print_map(std::ostream& out, const datetime_t& moment) { - if (moment) { + if (moment.is_not_a_date_time()) { + write_graphviz(out, price_graph, + label_writer(get(vertex_name, price_graph))); + } else { FGraph fg(price_graph, recent_edge_weight - (get(edge_weight, price_graph), pricemap, ratiomap, *moment)); + (get(edge_weight, price_graph), pricemap, ratiomap, moment)); write_graphviz(out, fg, label_writer(get(vertex_name, fg))); - } else { - write_graphviz(out, price_graph, - label_writer(get(vertex_name, price_graph))); } } diff --git a/src/history.h b/src/history.h index 920feec6..71cbad0c 100644 --- a/src/history.h +++ b/src/history.h @@ -111,23 +111,22 @@ public: const datetime_t& date); void map_prices(function fn, - const commodity_t& source, - const datetime_t& moment, - const optional& _oldest = none); + const commodity_t& source, + const datetime_t& moment, + const datetime_t& _oldest = datetime_t()); optional - find_price(const commodity_t& source, - const datetime_t& moment, - const optional& oldest = none); + find_price(const commodity_t& source, + const datetime_t& moment, + const datetime_t& oldest = datetime_t()); optional - find_price(const commodity_t& source, - const commodity_t& target, - const datetime_t& moment, - const optional& oldest = none); + find_price(const commodity_t& source, + const commodity_t& target, + const datetime_t& moment, + const datetime_t& oldest = datetime_t()); - void print_map(std::ostream& out, - const optional& moment = none); + void print_map(std::ostream& out, const datetime_t& moment = datetime_t()); }; } // namespace ledger diff --git a/src/pool.h b/src/pool.h index b7921f59..eb630781 100644 --- a/src/pool.h +++ b/src/pool.h @@ -83,13 +83,12 @@ public: bool get_quotes; // --download function - (commodity_t& commodity, const optional& in_terms_of)> + (commodity_t& commodity, const commodity_t * in_terms_of)> get_commodity_quote; static shared_ptr current_pool; explicit commodity_pool_t(); - virtual ~commodity_pool_t() { TRACE_DTOR(commodity_pool_t); } diff --git a/src/py_amount.cc b/src/py_amount.cc index 25ec8e26..ea69dec5 100644 --- a/src/py_amount.cc +++ b/src/py_amount.cc @@ -48,12 +48,12 @@ namespace { return amount.value(CURRENT_TIME()); } boost::optional py_value_1(const amount_t& amount, - commodity_t& in_terms_of) { + const commodity_t * in_terms_of) { return amount.value(CURRENT_TIME(), in_terms_of); } boost::optional py_value_2(const amount_t& amount, - commodity_t& in_terms_of, - datetime_t& moment) { + const commodity_t * in_terms_of, + const datetime_t& moment) { return amount.value(moment, in_terms_of); } diff --git a/src/py_balance.cc b/src/py_balance.cc index 38941832..2ae546f1 100644 --- a/src/py_balance.cc +++ b/src/py_balance.cc @@ -48,12 +48,12 @@ namespace { return balance.value(CURRENT_TIME()); } boost::optional py_value_1(const balance_t& balance, - commodity_t& in_terms_of) { + const commodity_t * in_terms_of) { return balance.value(CURRENT_TIME(), in_terms_of); } boost::optional py_value_2(const balance_t& balance, - commodity_t& in_terms_of, - datetime_t& moment) { + const commodity_t * in_terms_of, + const datetime_t& moment) { return balance.value(moment, in_terms_of); } diff --git a/src/py_value.cc b/src/py_value.cc index 78301acd..efeb4340 100644 --- a/src/py_value.cc +++ b/src/py_value.cc @@ -51,12 +51,12 @@ namespace { return value.value(CURRENT_TIME()); } boost::optional py_value_1(const value_t& value, - commodity_t& in_terms_of) { + const commodity_t * in_terms_of) { return value.value(CURRENT_TIME(), in_terms_of); } boost::optional py_value_2(const value_t& value, - commodity_t& in_terms_of, - datetime_t& moment) { + const commodity_t * in_terms_of, + const datetime_t& moment) { return value.value(moment, in_terms_of); } diff --git a/src/quotes.cc b/src/quotes.cc index b29eb8bd..c33e0826 100644 --- a/src/quotes.cc +++ b/src/quotes.cc @@ -40,7 +40,7 @@ namespace ledger { optional commodity_quote_from_script(commodity_t& commodity, - const optional& exchange_commodity) + const commodity_t * exchange_commodity) { DEBUG("commodity.download", "downloading quote for symbol " << commodity.symbol()); #if defined(DEBUG_ON) diff --git a/src/quotes.h b/src/quotes.h index 52092fbc..56740e47 100644 --- a/src/quotes.h +++ b/src/quotes.h @@ -46,7 +46,7 @@ namespace ledger { optional commodity_quote_from_script(commodity_t& commodity, - const optional& exchange_commodity); + const commodity_t * exchange_commodity); } // namespace ledger diff --git a/src/report.cc b/src/report.cc index 8205c1dd..a3abcb98 100644 --- a/src/report.cc +++ b/src/report.cc @@ -532,12 +532,13 @@ value_t report_t::fn_should_bold(call_scope_t& scope) value_t report_t::fn_market(call_scope_t& args) { - optional moment = (args.has(1) ? - args.get(1) : - optional()); value_t result; value_t arg0 = args[0]; + datetime_t moment; + if (args.has(1)) + moment = args.get(1); + if (arg0.is_string()) { amount_t tmp(1L); commodity_t * commodity = @@ -962,7 +963,7 @@ value_t report_t::pricemap_command(call_scope_t& args) std::ostream& out(output_stream); commodity_pool_t::current_pool->commodity_price_history.print_map (out, args.has(0) ? - optional(datetime_t(parse_date(args.get(0)))) : none); + datetime_t(parse_date(args.get(0))) : datetime_t()); return true; } diff --git a/src/value.cc b/src/value.cc index c4e7170d..cae2a356 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1399,8 +1399,8 @@ bool value_t::is_zero() const return false; } -value_t value_t::value(const optional& moment, - const optional& in_terms_of) const +value_t value_t::value(const datetime_t& moment, + const commodity_t * in_terms_of) const { switch (type()) { case INTEGER: @@ -1432,9 +1432,9 @@ value_t value_t::value(const optional& moment, return NULL_VALUE; } -value_t value_t::exchange_commodities(const std::string& commodities, - const bool add_prices, - const optional& moment) +value_t value_t::exchange_commodities(const std::string& commodities, + const bool add_prices, + const datetime_t& moment) { if (type() == SEQUENCE) { value_t temp; @@ -1447,7 +1447,7 @@ value_t value_t::exchange_commodities(const std::string& commodities, // expression, skip the expensive logic below. if (commodities.find(',') == string::npos && commodities.find('=') == string::npos) - return value(moment, *commodity_pool_t::current_pool->find_or_create(commodities)); + return value(moment, commodity_pool_t::current_pool->find_or_create(commodities)); std::vector comms; std::vector force; @@ -1479,7 +1479,7 @@ value_t value_t::exchange_commodities(const std::string& commodities, break; DEBUG("commodity.exchange", "Referent doesn't match, pricing..."); - if (optional val = as_amount_lval().value(moment, *comm)) { + if (optional val = as_amount_lval().value(moment, comm)) { DEBUG("commodity.exchange", "Re-priced amount is: " << *val); return *val; } @@ -1502,7 +1502,7 @@ value_t value_t::exchange_commodities(const std::string& commodities, temp += pair.second; } else { DEBUG("commodity.exchange", "Referent doesn't match, pricing..."); - if (optional val = pair.second.value(moment, *comm)) { + if (optional val = pair.second.value(moment, comm)) { DEBUG("commodity.exchange", "Re-priced member amount is: " << *val); temp += *val; repriced = true; diff --git a/src/value.h b/src/value.h index df075843..a95968c2 100644 --- a/src/value.h +++ b/src/value.h @@ -477,12 +477,12 @@ public: void in_place_unreduce(); // exists for efficiency's sake // Return the "market value" of a given value at a specific time. - value_t value(const optional& moment = none, - const optional& in_terms_of = none) const; + value_t value(const datetime_t& moment = datetime_t(), + const commodity_t * in_terms_of = NULL) const; - value_t exchange_commodities(const std::string& commodities, - const bool add_prices = false, - const optional& moment = none); + value_t exchange_commodities(const std::string& commodities, + const bool add_prices = false, + const datetime_t& moment = datetime_t()); /** * Truth tests. diff --git a/test/regress/25A099C9.test b/test/regress/25A099C9.test index c43deb21..418b77c8 100644 --- a/test/regress/25A099C9.test +++ b/test/regress/25A099C9.test @@ -2,16 +2,16 @@ test -f $sourcepath/src/amount.h reg -> 7 __ERROR__ While parsing file "$sourcepath/src/amount.h", line 66: Error: No quantity specified for amount -While parsing file "$sourcepath/src/amount.h", line 732: +While parsing file "$sourcepath/src/amount.h", line 734: Error: Invalid date/time: line amount_t amoun -While parsing file "$sourcepath/src/amount.h", line 738: +While parsing file "$sourcepath/src/amount.h", line 740: Error: Invalid date/time: line string amount_ -While parsing file "$sourcepath/src/amount.h", line 744: +While parsing file "$sourcepath/src/amount.h", line 746: Error: Invalid date/time: line string amount_ -While parsing file "$sourcepath/src/amount.h", line 750: +While parsing file "$sourcepath/src/amount.h", line 752: Error: Invalid date/time: line string amount_ -While parsing file "$sourcepath/src/amount.h", line 756: +While parsing file "$sourcepath/src/amount.h", line 758: Error: Invalid date/time: line std::ostream& -While parsing file "$sourcepath/src/amount.h", line 763: +While parsing file "$sourcepath/src/amount.h", line 765: Error: Invalid date/time: line std::istream& end test diff --git a/test/unit/t_commodity.cc b/test/unit/t_commodity.cc index 6a6f27aa..8caeb694 100644 --- a/test/unit/t_commodity.cc +++ b/test/unit/t_commodity.cc @@ -92,18 +92,18 @@ BOOST_AUTO_TEST_CASE(testPriceHistory) BOOST_CHECK_EQUAL(string("$2124.122"), amt->to_fullstring()); #endif - amt = x1.value(CURRENT_TIME(), euro); + amt = x1.value(CURRENT_TIME(), &euro); BOOST_CHECK(amt); BOOST_CHECK_EQUAL(string("EUR 1787.50"), amt->rounded().to_string()); // Add a newer Euro pricing aapl.add_price(jan17_07, amount_t("EUR 23.00")); - amt = x1.value(CURRENT_TIME(), euro); + amt = x1.value(CURRENT_TIME(), &euro); BOOST_CHECK(amt); BOOST_CHECK_EQUAL(string("EUR 2302.30"), amt->to_string()); - amt = x1.value(CURRENT_TIME(), cad); + amt = x1.value(CURRENT_TIME(), &cad); BOOST_CHECK(amt); BOOST_CHECK_EQUAL(string("CAD 3223.22"), amt->to_string()); #endif // NOT_FOR_PYTHON -- cgit v1.2.3 From fad24d40f7826b4c4ea840f0c068ac43ed50947d Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 11 Mar 2012 04:02:52 -0500 Subject: When --percent is used, disable --decimal-comma after parsing Fixes #674 --- src/report.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index a3abcb98..3151b211 100644 --- a/src/report.cc +++ b/src/report.cc @@ -162,13 +162,16 @@ void report_t::normalize_options(const string& verb) terminus); } - if (HANDLED(percent) && HANDLED(market)) { - HANDLER(total_) - .on("?normalize", - "(__tmp = market(parent.total, value_date, exchange);" - " ((is_account & parent & __tmp) ?" - " percent(scrub(market(total, value_date, exchange)), " - " scrub(__tmp)) : 0))"); + if (HANDLED(percent)) { + commodity_t::decimal_comma_by_default = false; + if (HANDLED(market)) { + HANDLER(total_) + .on("?normalize", + "(__tmp = market(parent.total, value_date, exchange);" + " ((is_account & parent & __tmp) ?" + " percent(scrub(market(total, value_date, exchange)), " + " scrub(__tmp)) : 0))"); + } } if (HANDLED(immediate) && HANDLED(market)) { -- cgit v1.2.3 From 62c04deb8719444d1f958d40fe6442b714bb7e50 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 11 Mar 2012 05:08:55 -0500 Subject: Quieted several compiler warnings from Clang --- acprep | 1 + src/option.h | 5 ++--- src/report.cc | 4 +++- src/value.cc | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src/report.cc') diff --git a/acprep b/acprep index 06087572..d3639f54 100755 --- a/acprep +++ b/acprep @@ -1211,6 +1211,7 @@ class PrepareBuild(CommandLineApp): self.CXXFLAGS.append('-Wno-missing-prototypes') self.CXXFLAGS.append('-Wno-missing-noreturn') self.CXXFLAGS.append('-Wno-disabled-macro-expansion') + self.CXXFLAGS.append('-Wno-unused-parameter') self.CXXFLAGS.append('-fno-limit-debug-info') #self.CXXFLAGS.append('-Wold-style-cast') diff --git a/src/option.h b/src/option.h index f892b00e..36dba3a4 100644 --- a/src/option.h +++ b/src/option.h @@ -162,9 +162,8 @@ public: source = none; } - virtual void handler_thunk(const optional& whence) {} - virtual void handler_thunk(const optional& whence, - const string& str) {} + virtual void handler_thunk(const optional&) {} + virtual void handler_thunk(const optional&, const string&) {} value_t handler(call_scope_t& args) { if (wants_arg) { diff --git a/src/report.cc b/src/report.cc index 3151b211..1adbe9d0 100644 --- a/src/report.cc +++ b/src/report.cc @@ -195,7 +195,8 @@ void report_t::normalize_options(const string& verb) long date_width = (HANDLED(date_width_) ? lexical_cast(HANDLER(date_width_).str()) : - format_date(CURRENT_DATE(),FMT_PRINTED).length()); + static_cast + (format_date(CURRENT_DATE(),FMT_PRINTED).length())); long payee_width = (HANDLED(payee_width_) ? lexical_cast(HANDLER(payee_width_).str()) : long(double(cols) * 0.263157)); @@ -825,6 +826,7 @@ value_t report_t::fn_nail_down(call_scope_t& args) throw_(std::runtime_error, _("Attempting to nail down %1") << args[0].label()); } + return arg0; } value_t report_t::fn_lot_date(call_scope_t& args) diff --git a/src/value.cc b/src/value.cc index cae2a356..c14a7104 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1468,7 +1468,7 @@ value_t value_t::exchange_commodities(const std::string& commodities, } } - int index = 0; + std::size_t index = 0; foreach (commodity_t * comm, comms) { switch (type()) { case AMOUNT: -- cgit v1.2.3 From cf67fcbd0628e03ac2f788da6f2c082121faf21f Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 12 Mar 2012 05:47:32 -0500 Subject: Resolved a huge performance issue with 'pricedb' --- src/report.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 1adbe9d0..c4f916d7 100644 --- a/src/report.cc +++ b/src/report.cc @@ -469,8 +469,20 @@ void report_t::commodities_report(post_handler_ptr handler) { handler = chain_handlers(handler, *this); - posts_commodities_iterator walker(*session.journal.get()); - pass_down_posts(handler, walker); + posts_commodities_iterator * walker(new posts_commodities_iterator(*session.journal.get())); + try { + pass_down_posts(handler, *walker); + } + catch (...) { +#if defined(VERIFY_ON) + IF_VERIFY() { + // If --verify was used, clean up the posts_commodities_iterator. + // Otherwise, just leak like a sieve. + checked_delete(walker); + } +#endif + throw; + } session.journal->clear_xdata(); } -- cgit v1.2.3 From cb317f9d395f44b2c2fc48f02869c3ed0f5ebcd0 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 13 Mar 2012 03:40:16 -0500 Subject: Added format_datetime valexpr function --- src/report.cc | 11 +++++++++++ src/report.h | 1 + 2 files changed, 12 insertions(+) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index c4f916d7..cf227fe6 100644 --- a/src/report.cc +++ b/src/report.cc @@ -756,6 +756,15 @@ value_t report_t::fn_format_date(call_scope_t& args) return string_value(format_date(args.get(0), FMT_PRINTED)); } +value_t report_t::fn_format_datetime(call_scope_t& args) +{ + if (args.has(1)) + return string_value(format_datetime(args.get(0), FMT_CUSTOM, + args.get(1).c_str())); + else + return string_value(format_datetime(args.get(0), FMT_PRINTED)); +} + value_t report_t::fn_ansify_if(call_scope_t& args) { if (args.has(1)) { @@ -1331,6 +1340,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, case 'f': if (is_eq(p, "format_date")) return MAKE_FUNCTOR(report_t::fn_format_date); + else if (is_eq(p, "format_datetime")) + return MAKE_FUNCTOR(report_t::fn_format_datetime); else if (is_eq(p, "format")) return MAKE_FUNCTOR(report_t::fn_format); else if (is_eq(p, "floor")) diff --git a/src/report.h b/src/report.h index a3825335..6322aeb8 100644 --- a/src/report.h +++ b/src/report.h @@ -167,6 +167,7 @@ public: value_t fn_quoted(call_scope_t& scope); value_t fn_join(call_scope_t& scope); value_t fn_format_date(call_scope_t& scope); + value_t fn_format_datetime(call_scope_t& scope); value_t fn_ansify_if(call_scope_t& scope); value_t fn_percent(call_scope_t& scope); value_t fn_commodity(call_scope_t& scope); -- cgit v1.2.3 From c8dd3d28e3ed39ca93f9aac71a127f15c8d65e4b Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 13 Mar 2012 03:43:51 -0500 Subject: Added --time-report option This is a rather basic option at the moment which only affects the balance report. I use it as follows, for entering contractor hours into a project planning application, where $1 is the contractor's timelog file, and $2 is the date after which new entries appear in the file: ledger -f $1 balance \ --account=payee \ --time-report \ -d "latest > [$2]" \ --datetime-format='%m/%d/%y %I:%M %p' --- doc/ledger.1 | 3 ++- src/report.cc | 1 + src/report.h | 20 ++++++++++++++++++++ test/baseline/opt-time-report.test | 0 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 test/baseline/opt-time-report.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index 8076c7c4..63017452 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -1,4 +1,4 @@ -.Dd March 10, 2012 +.Dd March 13, 2012 .Dt ledger 1 .Sh NAME .Nm ledger @@ -415,6 +415,7 @@ appeared in the original journal file. .It Fl \-strict .It Fl \-subtotal Pq Fl s .It Fl \-tail Ar INT +.It Fl \-time-report .It Fl \-total Ar EXPR .It Fl \-total-data Pq Fl J .It Fl \-total-width Ar INT diff --git a/src/report.cc b/src/report.cc index cf227fe6..e93bd6fd 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1224,6 +1224,7 @@ option_t * report_t::lookup_option(const char * p) else OPT(total_data); else OPT(truncate_); else OPT(total_width_); + else OPT(time_report); break; case 'u': OPT(unbudgeted); diff --git a/src/report.h b/src/report.h index 6322aeb8..c0398d4c 100644 --- a/src/report.h +++ b/src/report.h @@ -324,6 +324,7 @@ public: HANDLER(start_of_week_).report(out); HANDLER(subtotal).report(out); HANDLER(tail_).report(out); + HANDLER(time_report).report(out); HANDLER(total_).report(out); HANDLER(total_data).report(out); HANDLER(truncate_).report(out); @@ -947,6 +948,25 @@ public: OPTION(report_t, subtotal); // -s OPTION(report_t, tail_); + OPTION_(report_t, time_report, DO() { + OTHER(balance_format_) + .on(none, + "%(justify(earliest_checkin ? " + " format_datetime(earliest_checkin) : \"\", 19, -1, true)) " + "%(justify(latest_checkout ? " + " format_datetime(latest_checkout) : \"\", 19, -1, true)) " + "%(ansify_if(" + " justify(scrub(display_total), 8," + " 8 + 4 + 19 * 2, true, color), bold if should_bold))" + " %(!options.flat ? depth_spacer : \"\")" + "%-(ansify_if(" + " ansify_if(partial_account(options.flat), blue if color)," + " bold if should_bold))\n%/" + "%$1 %$2 %$3\n%/" + "%(prepend_width ? \" \" * int(prepend_width) : \"\")" + "--------------------------------------------------\n"); + }); + OPTION__ (report_t, total_, // -T DECL1(report_t, total_, merged_expr_t, expr, ("total_expr", "total")) {} diff --git a/test/baseline/opt-time-report.test b/test/baseline/opt-time-report.test new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3 From 37347bad56646f3f3e7e10ee0303e6429c29bbba Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 13 Mar 2012 10:35:08 -0500 Subject: Add experimental support for select queries --- src/report.cc | 3 + src/select.cc | 441 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/select.h | 55 +++++++ tools/Makefile.am | 2 + 4 files changed, 501 insertions(+) create mode 100644 src/select.cc create mode 100644 src/select.h (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index e93bd6fd..91de2eb5 100644 --- a/src/report.cc +++ b/src/report.cc @@ -41,6 +41,7 @@ #include "iterators.h" #include "filters.h" #include "precmd.h" +#include "select.h" #include "stats.h" #include "generate.h" #include "draft.h" @@ -1633,6 +1634,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return WRAP_FUNCTOR(report_statistics); else if (is_eq(p, "source")) return WRAP_FUNCTOR(source_command); + else if (is_eq(p, "select")) + return WRAP_FUNCTOR(select_command); break; case 'x': diff --git a/src/select.cc b/src/select.cc new file mode 100644 index 00000000..56bd3f2d --- /dev/null +++ b/src/select.cc @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "select.h" +#include "journal.h" +#include "account.h" +#include "report.h" +#include "output.h" +#include "print.h" +#include "chain.h" +#include "filters.h" +#include "scope.h" +#include "op.h" + +namespace ledger { + +namespace { + bool get_principal_identifiers(expr_t::ptr_op_t expr, string& ident, + bool do_transforms = false) + { + bool result = true; + + if (expr->is_ident()) { + string name(expr->as_ident()); + if (name == "date" || name == "aux_date" || name == "payee") { + if (! ident.empty() && + ! (name == "date" || name == "aux_date" || name == "payee")) + result = false; + ident = name; + } + else if (name == "account") { + if (! ident.empty() && ! (name == "account")) + result = false; + ident = name; + if (do_transforms) + expr->set_ident("display_account"); + } + else if (name == "amount") { + if (! ident.empty() && ! (name == "amount")) + result = false; + ident = name; + if (do_transforms) + expr->set_ident("display_amount"); + } + else if (name == "total") { + if (! ident.empty() && ! (name == "total")) + result = false; + ident = name; + if (do_transforms) + expr->set_ident("display_total"); + } + } + + if (expr->kind > expr_t::op_t::TERMINALS || expr->is_scope()) { + if (expr->left()) { + if (! get_principal_identifiers(expr->left(), ident, do_transforms)) + result = false; + if (expr->kind > expr_t::op_t::UNARY_OPERATORS && expr->has_right()) + if (! get_principal_identifiers(expr->right(), ident, do_transforms)) + result = false; + } + } + + return result; + } +} + +value_t select_command(call_scope_t& args) +{ + string text = "select " + join_args(args); + if (text.empty()) + throw std::logic_error(_("Usage: select TEXT")); + + report_t& report(find_scope(args)); + + // Our first step is to divide the select statement into its principal + // parts: + // + // SELECT + // FROM + // WHERE + // DISPLAY + // COLLECT + // GROUP BY + // STYLE + + boost::regex select_re + ("(select|from|where|display|collect|group\\s+by|style)\\s+" + "(.+?)" + "(?=(\\s+(from|where|display|collect|group\\s+by|style)\\s+|$))", + boost::regex::perl | boost::regex::icase); + + boost::regex from_accounts_re("from\\s+accounts\\>"); + bool accounts_report = boost::regex_search(text, from_accounts_re); + + boost::sregex_iterator m1(text.begin(), text.end(), select_re); + boost::sregex_iterator m2; + + expr_t::ptr_op_t report_functor; + std::ostringstream formatter; + + while (m1 != m2) { + const boost::match_results& match(*m1); + + string keyword(match[1]); + string arg(match[2]); + + DEBUG("select.parse", "keyword: " << keyword); + DEBUG("select.parse", "arg: " << arg); + + if (keyword == "select") { + expr_t args_expr(arg); + value_t columns(split_cons_expr(args_expr.get_op())); + bool first = true; + string thus_far = ""; + + std::size_t cols = 0; + if (report.HANDLED(columns_)) + cols = lexical_cast(report.HANDLER(columns_).value); + else if (const char * columns_env = std::getenv("COLUMNS")) + cols = lexical_cast(columns_env); + else + cols = 80; + + std::size_t date_width = + (report.HANDLED(date_width_) ? + lexical_cast(report.HANDLER(date_width_).str()) : + static_cast + (format_date(CURRENT_DATE(),FMT_PRINTED).length())); + std::size_t payee_width = + (report.HANDLED(payee_width_) ? + lexical_cast(report.HANDLER(payee_width_).str()) : + std::size_t(double(cols) * 0.263157)); + std::size_t account_width = + (report.HANDLED(account_width_) ? + lexical_cast(report.HANDLER(account_width_).str()) : + std::size_t(double(cols) * 0.302631)); + std::size_t amount_width = + (report.HANDLED(amount_width_) ? + lexical_cast(report.HANDLER(amount_width_).str()) : + std::size_t(double(cols) * 0.157894)); + std::size_t total_width = + (report.HANDLED(total_width_) ? + lexical_cast(report.HANDLER(total_width_).str()) : + amount_width); + std::size_t meta_width = + (report.HANDLED(meta_width_) ? + lexical_cast(report.HANDLER(meta_width_).str()) : + 10); + + bool saw_date = false; + bool saw_payee = false; + bool saw_account = false; + bool saw_amount = false; + bool saw_total = false; + bool saw_meta = false; + + std::size_t cols_needed = 0; + foreach (const value_t& column, columns.to_sequence()) { + string ident; + if (get_principal_identifiers(as_expr(column), ident)) { + if (ident == "date" || ident == "aux_date") { + cols_needed += date_width + 1; + saw_date = true; + } + else if (ident == "payee") { + cols_needed += payee_width + 1; + saw_payee = true; + } + else if (ident == "account") { + cols_needed += account_width + 1; + saw_account = true; + } + else if (ident == "amount") { + cols_needed += amount_width + 1; + saw_amount = true; + } + else if (ident == "total") { + cols_needed += total_width + 1; + saw_total = true; + } + else { + cols_needed += meta_width + 1; + saw_meta = true; + } + } + } + + while ((saw_account || saw_payee) && cols_needed < cols) { + if (saw_account && cols_needed < cols) { + ++account_width; + ++cols_needed; + if (cols_needed < cols) { + ++account_width; + ++cols_needed; + } + } + if (saw_payee && cols_needed < cols) { + ++payee_width; + ++cols_needed; + } + } + + while ((saw_account || saw_payee) && cols_needed > cols && + account_width > 5 && payee_width > 5) { + DEBUG("auto.columns", "adjusting account down"); + if (saw_account && cols_needed > cols) { + --account_width; + --cols_needed; + if (cols_needed > cols) { + --account_width; + --cols_needed; + } + } + if (saw_payee && cols_needed > cols) { + --payee_width; + --cols_needed; + } + DEBUG("auto.columns", "account_width now = " << account_width); + } + + if (! report.HANDLED(date_width_)) + report.HANDLER(date_width_).value = to_string(date_width); + if (! report.HANDLED(payee_width_)) + report.HANDLER(payee_width_).value = to_string(payee_width); + if (! report.HANDLED(account_width_)) + report.HANDLER(account_width_).value = to_string(account_width); + if (! report.HANDLED(amount_width_)) + report.HANDLER(amount_width_).value = to_string(amount_width); + if (! report.HANDLED(total_width_)) + report.HANDLER(total_width_).value = to_string(total_width); + + foreach (const value_t& column, columns.to_sequence()) { + if (first) + first = false; + else + formatter << ' '; + + formatter << "%("; + + string ident; + if (get_principal_identifiers(as_expr(column), ident, true)) { + if (ident == "date" || ident == "aux_date") { + formatter << "ansify_if(" + << "ansify_if(justify(format_date("; + + as_expr(column)->print(formatter); + + formatter << "), int(date_width)),"; + formatter << "green if color and date > today)," + << "bold if should_bold)"; + + if (! thus_far.empty()) + thus_far += " + "; + thus_far += "int(date_width) + 1"; + } + else if (ident == "payee") { + formatter << "ansify_if(" + << "ansify_if(justify(truncated("; + + as_expr(column)->print(formatter); + + formatter << ", int(payee_width)), int(payee_width)),"; + formatter << "bold if color and !cleared and actual)," + << "bold if should_bold)"; + + if (! thus_far.empty()) + thus_far += " + "; + thus_far += "int(payee_width) + 1"; + } + else if (ident == "account") { + formatter << "ansify_if(" + << "ansify_if("; + + if (accounts_report) { + formatter << "partial_account(options.flat), blue if color),"; + } else { + formatter << "justify(truncated("; + as_expr(column)->print(formatter); + formatter << ", int(account_width), int(abbrev_len))," + << "int(account_width)),"; + formatter << "true, color),"; + + if (! thus_far.empty()) + thus_far += " + "; + thus_far += "int(account_width) + 1"; + } + + formatter << " bold if should_bold)"; + } + else if (ident == "amount" || ident == "total") { + formatter << "ansify_if(" + << "justify(scrub("; + + as_expr(column)->print(formatter); + + formatter << "), "; + + if (ident == "amount") + formatter << "int(amount_width),"; + else + formatter << "int(total_width),"; + + if (! thus_far.empty()) + thus_far += " + "; + + if (ident == "amount") + thus_far += "int(amount_width)"; + else + thus_far += "int(total_width)"; + + if (thus_far.empty()) + formatter << "-1"; + else + formatter << thus_far; + + formatter << ", true, color)," + << " bold if should_bold)"; + + thus_far += " + 1"; + } + else { + formatter << "ansify_if(" + << "justify(truncated("; + + as_expr(column)->print(formatter); + + formatter << ", int(meta_width or 10)), int(meta_width) or 10),"; + formatter << "bold if should_bold)"; + + if (! thus_far.empty()) + thus_far += " + "; + thus_far += "(int(meta_width) or 10) + 1"; + } + } + formatter << ")"; + } + formatter << "\\n"; + } + else if (keyword == "from") { + DEBUG("select.parse", "formatter: " << formatter.str()); + + if (arg == "xacts" || arg == "txns" || arg == "transactions") { + report_functor = expr_t::op_t::wrap_functor + (reporter<>(post_handler_ptr(new print_xacts(report, + report.HANDLED(raw))), + report, string("#select"))); + } + else if (arg == "posts" || arg == "postings") { + report_functor = expr_t::op_t::wrap_functor + (reporter<>(post_handler_ptr(new format_posts(report, formatter.str())), + report, string("#select"))); + } + else if (arg == "accounts") { + report_functor = expr_t::op_t::wrap_functor + (reporter + (acct_handler_ptr(new format_accounts(report, formatter.str())), + report, string("#select"))); + } + else if (arg == "commodities") { + report_functor = expr_t::op_t::wrap_functor + (reporter + (post_handler_ptr(new format_posts(report, formatter.str())), + report, string("#select"))); + } + } + else if (keyword == "where") { +#if 0 + query_t query; + keep_details_t keeper(true, true, true); + expr_t::ptr_op_t expr = + query.parse_args(string_value(arg).to_sequence(), keeper, false, true); + report.HANDLER(limit_).on("#select", query.get_query(query_t::QUERY_LIMIT)); +#else + report.HANDLER(limit_).on("#select", arg); +#endif + } + else if (keyword == "display") { + report.HANDLER(display_).on("#select", arg); + } + else if (keyword == "collect") { + report.HANDLER(amount_).on("#select", arg); + } + else if (keyword == "group by") { + report.HANDLER(group_by_).on("#select", arg); + } + else if (keyword == "style") { + if (arg == "csv") { + } + else if (arg == "xml") { + } + else if (arg == "emacs") { + } + else if (arg == "org") { + } + } + + ++m1; + } + + if (! report_functor) { + report_functor = expr_t::op_t::wrap_functor + (reporter<>(post_handler_ptr(new format_posts(report, formatter.str())), + report, string("#select"))); + } + + call_scope_t call_args(report); + return report_functor->as_function()(call_args); +} + +} // namespace ledger diff --git a/src/select.h b/src/select.h new file mode 100644 index 00000000..54883d22 --- /dev/null +++ b/src/select.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup select + */ + +/** + * @file select.h + * @author John Wiegley + * + * @ingroup select + */ +#ifndef _SELECT_H +#define _SELECT_H + +#include "utils.h" +#include "value.h" + +namespace ledger { + +class call_scope_t; +value_t select_command(call_scope_t& args); + +} // namespace ledger + +#endif // _SELECT_H diff --git a/tools/Makefile.am b/tools/Makefile.am index c6295aad..5d299b05 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -79,6 +79,7 @@ libledger_report_la_SOURCES = \ src/chain.cc \ src/filters.cc \ src/report.cc \ + src/select.cc \ src/session.cc libledger_report_la_CPPFLAGS = $(lib_cppflags) @@ -128,6 +129,7 @@ pkginclude_HEADERS = \ src/lookup.h \ \ src/session.h \ + src/select.h \ src/report.h \ src/filters.h \ src/chain.h \ -- cgit v1.2.3 From f96a205c03c177a474db3040e4eb27d482271b8f Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 17 Mar 2012 05:55:11 -0500 Subject: Make --days-of-week an alias for --dow --- src/report.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 91de2eb5..bff068b8 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1113,7 +1113,7 @@ option_t * report_t::lookup_option(const char * p) else OPT_(display_); else OPT(display_amount_); else OPT(display_total_); - else OPT_ALT(dow, days-of-week); + else OPT_ALT(dow, days_of_week); else OPT(date_width_); break; case 'e': -- cgit v1.2.3 From f9088f88360019bb4be8743dd8091036502adb9c Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 18 Mar 2012 01:01:30 -0500 Subject: Added --verify-memory and missing TRACE_[CD]TOR calls --- doc/ledger.1 | 3 +- src/account.h | 11 +++- src/accum.h | 11 +++- src/commodity.h | 4 +- src/csv.h | 4 ++ src/draft.h | 16 ++++- src/global.cc | 21 +++++-- src/global.h | 1 + src/history.cc | 7 ++- src/iterators.cc | 8 ++- src/iterators.h | 103 ++++++++++++++++++++++++++++---- src/main.cc | 1 + src/pstream.h | 5 ++ src/py_journal.cc | 5 +- src/report.cc | 7 ++- src/report.h | 23 +++++++- src/scope.h | 14 ++++- src/temps.h | 4 ++ src/utils.cc | 110 ++++++++++++++++++++++++++--------- test/baseline/opt-verify-memory.test | 0 20 files changed, 299 insertions(+), 59 deletions(-) create mode 100644 test/baseline/opt-verify-memory.test (limited to 'src/report.cc') diff --git a/doc/ledger.1 b/doc/ledger.1 index cd76d5b0..9cfa41c0 100644 --- a/doc/ledger.1 +++ b/doc/ledger.1 @@ -1,4 +1,4 @@ -.Dd March 17, 2012 +.Dd March 18, 2012 .Dt ledger 1 .Sh NAME .Nm ledger @@ -431,6 +431,7 @@ appeared in the original journal file. .It Fl \-value-expr Ar EXPR .It Fl \-verbose .It Fl \-verify +.It Fl \-verify-memory .It Fl \-version .It Fl \-weekly Pq Fl W .It Fl \-wide Pq Fl w diff --git a/src/account.h b/src/account.h index 4ddd85e7..fee12595 100644 --- a/src/account.h +++ b/src/account.h @@ -189,7 +189,16 @@ public: posts_cleared_count(0), posts_last_7_count(0), posts_last_30_count(0), - posts_this_month_count(0) {} + posts_this_month_count(0) { + TRACE_CTOR(account_t::xdata_t::details_t, ""); + } + // A copy copies nothing + details_t(const details_t&) { + TRACE_CTOR(account_t::xdata_t::details_t, "copy"); + } + ~details_t() throw() { + TRACE_DTOR(account_t::xdata_t::details_t); + } details_t& operator+=(const details_t& other); diff --git a/src/accum.h b/src/accum.h index dde93c30..628a6b36 100644 --- a/src/accum.h +++ b/src/accum.h @@ -51,7 +51,12 @@ protected: std::string::size_type index; public: - straccbuf() : index(0) {} + straccbuf() : index(0) { + TRACE_CTOR(straccbuf, ""); + } + ~straccbuf() throw() { + TRACE_DTOR(straccbuf); + } protected: virtual std::streamsize xsputn(const char * s, std::streamsize num); @@ -66,8 +71,12 @@ protected: public: straccstream() : std::ostream(0) { + TRACE_CTOR(straccstream, ""); rdbuf(&buf); } + ~straccstream() throw() { + TRACE_DTOR(straccstream); + } void clear() { std::ostream::clear(); diff --git a/src/commodity.h b/src/commodity.h index 148a3636..ba47a572 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -132,10 +132,10 @@ protected: static_cast(COMMODITY_STYLE_DECIMAL_COMMA) : static_cast(COMMODITY_STYLE_DEFAULTS)), symbol(_symbol), precision(0) { - TRACE_CTOR(base_t, "const string&"); + TRACE_CTOR(commodity_t::base_t, "const string&"); } virtual ~base_t() { - TRACE_DTOR(base_t); + TRACE_DTOR(commodity_t::base_t); } #if defined(HAVE_BOOST_SERIALIZATION) diff --git a/src/csv.h b/src/csv.h index 24ea9121..d98c0567 100644 --- a/src/csv.h +++ b/src/csv.h @@ -91,8 +91,12 @@ public: cost_mask("cost"), total_mask("total"), note_mask("note") { + TRACE_CTOR(csv_reader, "parse_context_t&"); read_index(*context.stream.get()); } + ~csv_reader() { + TRACE_DTOR(csv_reader); + } void read_index(std::istream& in); string read_field(std::istream& in); diff --git a/src/draft.h b/src/draft.h index 41485731..e5d29134 100644 --- a/src/draft.h +++ b/src/draft.h @@ -68,12 +68,22 @@ class draft_t : public expr_base_t optional cost_operator; optional cost; - post_template_t() : from(false) {} + post_template_t() : from(false) { + TRACE_CTOR(post_template_t, ""); + } + ~post_template_t() throw() { + TRACE_DTOR(post_template_t); + } }; std::list posts; - xact_template_t() {} + xact_template_t() { + TRACE_CTOR(xact_template_t, ""); + } + ~xact_template_t() throw() { + TRACE_DTOR(xact_template_t); + } void dump(std::ostream& out) const; }; @@ -86,7 +96,7 @@ public: if (! args.empty()) parse_args(args); } - virtual ~draft_t() { + virtual ~draft_t() throw() { TRACE_DTOR(draft_t); } diff --git a/src/global.cc b/src/global.cc index d7742161..b5ceb614 100644 --- a/src/global.cc +++ b/src/global.cc @@ -272,6 +272,7 @@ void global_scope_t::report_options(report_t& report, std::ostream& out) HANDLER(trace_).report(out); HANDLER(verbose).report(out); HANDLER(verify).report(out); + HANDLER(verify_memory).report(out); out << std::endl << "[Session scope options]" << std::endl; report.session.report_options(out); @@ -315,6 +316,7 @@ option_t * global_scope_t::lookup_option(const char * p) case 'v': OPT_(verbose); else OPT(verify); + else OPT(verify_memory); else OPT(version); break; } @@ -452,29 +454,36 @@ void handle_debug_options(int argc, char * argv[]) if (std::strcmp(argv[i], "--args-only") == 0) { args_only = true; } + else if (std::strcmp(argv[i], "--verify-memory") == 0) { +#if defined(VERIFY_ON) + verify_enabled = true; + + _log_level = LOG_DEBUG; + _log_category = "memory\\.counts"; +#endif + } else if (std::strcmp(argv[i], "--verify") == 0) { #if defined(VERIFY_ON) - verify_enabled = true; // global in utils.h + verify_enabled = true; #endif } else if (std::strcmp(argv[i], "--verbose") == 0 || std::strcmp(argv[i], "-v") == 0) { #if defined(LOGGING_ON) - _log_level = LOG_INFO; // global in utils.h + _log_level = LOG_INFO; #endif } else if (i + 1 < argc && std::strcmp(argv[i], "--debug") == 0) { #if defined(DEBUG_ON) - _log_level = LOG_DEBUG; // global in utils.h - _log_category = argv[i + 1]; // global in utils.h + _log_level = LOG_DEBUG; + _log_category = argv[i + 1]; i++; #endif } else if (i + 1 < argc && std::strcmp(argv[i], "--trace") == 0) { #if defined(TRACING_ON) - _log_level = LOG_TRACE; // global in utils.h + _log_level = LOG_TRACE; try { - // global in utils.h _trace_level = boost::lexical_cast(argv[i + 1]); } catch (const boost::bad_lexical_cast&) { diff --git a/src/global.h b/src/global.h index 0c11e025..5786bb89 100644 --- a/src/global.h +++ b/src/global.h @@ -158,6 +158,7 @@ See LICENSE file included with the distribution for details and disclaimer."); OPTION(global_scope_t, trace_); OPTION(global_scope_t, verbose); OPTION(global_scope_t, verify); + OPTION(global_scope_t, verify_memory); OPTION_(global_scope_t, version, DO() { // -v parent->show_version_info(std::cout); diff --git a/src/history.cc b/src/history.cc index f1e88401..d94ec647 100644 --- a/src/history.cc +++ b/src/history.cc @@ -423,7 +423,12 @@ commodity_history_t::find_price(const commodity_t& source, template class label_writer { public: - label_writer(Name _name) : name(_name) {} + label_writer(Name _name) : name(_name) { + TRACE_CTOR(label_writer, "Name"); + } + ~label_writer() throw() { + TRACE_DTOR(label_writer); + } template void operator()(std::ostream& out, const VertexOrEdge& v) const { diff --git a/src/iterators.cc b/src/iterators.cc index acbb581f..7cc1291a 100644 --- a/src/iterators.cc +++ b/src/iterators.cc @@ -88,7 +88,13 @@ namespace { create_price_xact(journal_t& _journal, account_t * _account, temporaries_t& _temps, xacts_list& _xact_temps) : journal(_journal), account(_account), temps(_temps), - xact_temps(_xact_temps) {} + xact_temps(_xact_temps) { + TRACE_CTOR(create_price_xact, + "journal_t&, account_t *, temporaries_t&, xacts_list&"); + } + ~create_price_xact() throw() { + TRACE_DTOR(create_price_xact); + } void operator()(datetime_t& date, const amount_t& price) { xact_t * xact; diff --git a/src/iterators.h b/src/iterators.h index 5bb9de6f..922ebccd 100644 --- a/src/iterators.h +++ b/src/iterators.h @@ -58,7 +58,15 @@ class iterator_facade_base typedef Value node_base; public: - iterator_facade_base() : m_node(NULL) {} + iterator_facade_base() : m_node(NULL) { + TRACE_CTOR(iterator_facade_base, ""); + } + iterator_facade_base(const iterator_facade_base& i) : m_node(i.m_node) { + TRACE_CTOR(iterator_facade_base, "copy"); + } + ~iterator_facade_base() throw() { + TRACE_DTOR(iterator_facade_base); + } explicit iterator_facade_base(node_base p) : m_node(p) {} @@ -87,12 +95,24 @@ class xact_posts_iterator bool posts_uninitialized; public: - xact_posts_iterator() : posts_uninitialized(true) {} + xact_posts_iterator() : posts_uninitialized(true) { + TRACE_CTOR(xact_posts_iterator, ""); + } xact_posts_iterator(xact_t& xact) : posts_uninitialized(true) { + TRACE_CTOR(xact_posts_iterator, "xact_t&"); reset(xact); } - ~xact_posts_iterator() throw() {} + xact_posts_iterator(const xact_posts_iterator& i) + : iterator_facade_base(i), + posts_i(i.posts_i), posts_end(i.posts_end), + posts_uninitialized(i.posts_uninitialized) { + TRACE_CTOR(xact_posts_iterator, "copy"); + } + ~xact_posts_iterator() throw() { + TRACE_DTOR(xact_posts_iterator); + } void reset(xact_t& xact) { posts_i = xact.posts.begin(); @@ -121,15 +141,28 @@ public: bool xacts_uninitialized; - xacts_iterator() : xacts_uninitialized(true) {} + xacts_iterator() : xacts_uninitialized(true) { + TRACE_CTOR(xacts_iterator, ""); + } xacts_iterator(journal_t& journal) : xacts_uninitialized(false) { + TRACE_CTOR(xacts_iterator, "journal_t&"); reset(journal); } xacts_iterator(xacts_list::iterator beg, xacts_list::iterator end) : xacts_uninitialized(false) { + TRACE_CTOR(xacts_iterator, "xacts_list::iterator, xacts_list::iterator"); reset(beg, end); } - ~xacts_iterator() throw() {} + xacts_iterator(const xacts_iterator& i) + : iterator_facade_base(i), + xacts_i(i.xacts_i), xacts_end(i.xacts_end), + xacts_uninitialized(i.xacts_uninitialized) { + TRACE_CTOR(xacts_iterator, "copy"); + } + ~xacts_iterator() throw() { + TRACE_DTOR(xacts_iterator); + } void reset(journal_t& journal); @@ -150,11 +183,22 @@ class journal_posts_iterator xact_posts_iterator posts; public: - journal_posts_iterator() {} + journal_posts_iterator() { + TRACE_CTOR(journal_posts_iterator, ""); + } journal_posts_iterator(journal_t& journal) { + TRACE_CTOR(journal_posts_iterator, "journal_t&"); reset(journal); } - ~journal_posts_iterator() throw() {} + journal_posts_iterator(const journal_posts_iterator& i) + : iterator_facade_base(i), + xacts(i.xacts), posts(i.posts) { + TRACE_CTOR(journal_posts_iterator, "copy"); + } + ~journal_posts_iterator() throw() { + TRACE_DTOR(journal_posts_iterator); + } void reset(journal_t& journal); @@ -173,11 +217,23 @@ protected: temporaries_t temps; public: - posts_commodities_iterator() {} + posts_commodities_iterator() { + TRACE_CTOR(posts_commodities_iterator, ""); + } posts_commodities_iterator(journal_t& journal) { + TRACE_CTOR(posts_commodities_iterator, "journal_t&"); reset(journal); } - ~posts_commodities_iterator() throw() {} + posts_commodities_iterator(const posts_commodities_iterator& i) + : iterator_facade_base(i), + journal_posts(i.journal_posts), xacts(i.xacts), posts(i.posts), + xact_temps(i.xact_temps), temps(i.temps) { + TRACE_CTOR(posts_commodities_iterator, "copy"); + } + ~posts_commodities_iterator() throw() { + TRACE_DTOR(posts_commodities_iterator); + } void reset(journal_t& journal); @@ -192,12 +248,23 @@ class basic_accounts_iterator std::list accounts_end; public: - basic_accounts_iterator() {} + basic_accounts_iterator() { + TRACE_CTOR(basic_accounts_iterator, ""); + } basic_accounts_iterator(account_t& account) { + TRACE_CTOR(basic_accounts_iterator, "account_t&"); push_back(account); increment(); } - ~basic_accounts_iterator() throw() {} + basic_accounts_iterator(const basic_accounts_iterator& i) + : iterator_facade_base(i), + accounts_i(i.accounts_i), accounts_end(i.accounts_end) { + TRACE_CTOR(basic_accounts_iterator, "copy"); + } + ~basic_accounts_iterator() throw() { + TRACE_DTOR(basic_accounts_iterator); + } void increment(); @@ -225,10 +292,22 @@ public: sorted_accounts_iterator(account_t& account, const expr_t& _sort_cmp, bool _flatten_all) : sort_cmp(_sort_cmp), flatten_all(_flatten_all) { + TRACE_CTOR(sorted_accounts_iterator, "account_t&, expr_t, bool"); push_back(account); increment(); } - ~sorted_accounts_iterator() throw() {} + sorted_accounts_iterator(const sorted_accounts_iterator& i) + : iterator_facade_base(i), + sort_cmp(i.sort_cmp), flatten_all(i.flatten_all), + accounts_list(i.accounts_list), + sorted_accounts_i(i.sorted_accounts_i), + sorted_accounts_end(i.sorted_accounts_end) { + TRACE_CTOR(sorted_accounts_iterator, "copy"); + } + ~sorted_accounts_iterator() throw() { + TRACE_DTOR(sorted_accounts_iterator); + } void increment(); diff --git a/src/main.cc b/src/main.cc index 9d2ba311..0130d5c6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -58,6 +58,7 @@ int main(int argc, char * argv[], char * envp[]) // --verbose ; turns on logging // --debug CATEGORY ; turns on debug logging // --trace LEVEL ; turns on trace logging + // --memory ; turns on memory usage tracing handle_debug_options(argc, argv); #if defined(VERIFY_ON) IF_VERIFY() initialize_memory_tracing(); diff --git a/src/pstream.h b/src/pstream.h index a894325d..dfb27056 100644 --- a/src/pstream.h +++ b/src/pstream.h @@ -58,6 +58,8 @@ class ptristream : public std::istream public: ptrinbuf(char * _ptr, std::size_t _len) : ptr(_ptr), len(_len) { + TRACE_CTOR(ptrinbuf, "char *, std::size_t"); + if (*ptr && len == 0) len = std::strlen(ptr); @@ -65,6 +67,9 @@ class ptristream : public std::istream ptr, // read position ptr+len); // end position } + ~ptrinbuf() throw() { + TRACE_DTOR(ptrinbuf); + } protected: virtual int_type underflow() { diff --git a/src/py_journal.cc b/src/py_journal.cc index 550fb14e..50a52be9 100644 --- a/src/py_journal.cc +++ b/src/py_journal.cc @@ -151,8 +151,11 @@ namespace { collector_wrapper(journal_t& _journal, report_t& base) : journal(_journal), report(base), - posts_collector(new collect_posts) {} + posts_collector(new collect_posts) { + TRACE_CTOR(collector_wrapper, "journal_t&, report_t&"); + } ~collector_wrapper() { + TRACE_DTOR(collector_wrapper); journal.clear_xdata(); } diff --git a/src/report.cc b/src/report.cc index bff068b8..28836d0f 100644 --- a/src/report.cc +++ b/src/report.cc @@ -321,7 +321,12 @@ namespace { report_t& report; posts_flusher(post_handler_ptr _handler, report_t& _report) - : handler(_handler), report(_report) {} + : handler(_handler), report(_report) { + TRACE_CTOR(posts_flusher, "post_handler_ptr, report_t&"); + } + ~posts_flusher() throw() { + TRACE_DTOR(posts_flusher); + } void operator()(const value_t&) { report.session.journal->clear_xdata(); diff --git a/src/report.h b/src/report.h index aca4f466..37123377 100644 --- a/src/report.h +++ b/src/report.h @@ -119,9 +119,19 @@ public: explicit report_t(session_t& _session) : session(_session), terminus(CURRENT_TIME()), - budget_flags(BUDGET_NO_BUDGET) {} + budget_flags(BUDGET_NO_BUDGET) { + TRACE_CTOR(report_t, "session_t&"); + } + report_t(const report_t& report) + : session(report.session), + output_stream(report.output_stream), + terminus(report.terminus), + budget_flags(report.budget_flags) { + TRACE_CTOR(report_t, "copy"); + } virtual ~report_t() { + TRACE_DTOR(report_t); output_stream.close(); } @@ -1045,7 +1055,16 @@ class reporter public: reporter(shared_ptr > _handler, report_t& _report, const string& _whence) - : handler(_handler), report(_report), whence(_whence) {} + : handler(_handler), report(_report), whence(_whence) { + TRACE_CTOR(reporter, "item_handler, report_t&, string"); + } + reporter(const reporter& other) + : handler(other.handler), report(other.report), whence(other.whence) { + TRACE_CTOR(reporter, "copy"); + } + ~reporter() throw() { + TRACE_DTOR(reporter); + } value_t operator()(call_scope_t& args) { diff --git a/src/scope.h b/src/scope.h index 134babb2..9318fc5c 100644 --- a/src/scope.h +++ b/src/scope.h @@ -142,6 +142,13 @@ private: class empty_scope_t : public scope_t { public: + empty_scope_t() { + TRACE_CTOR(empty_scope_t, ""); + } + ~empty_scope_t() throw() { + TRACE_DTOR(empty_scope_t); + } + virtual string description() { return _(""); } @@ -683,7 +690,12 @@ class value_scope_t : public child_scope_t public: value_scope_t(scope_t& _parent, const value_t& _value) - : child_scope_t(_parent), value(_value) {} + : child_scope_t(_parent), value(_value) { + TRACE_CTOR(value_scope_t, "scope_t&, value_t"); + } + ~value_scope_t() throw() { + TRACE_DTOR(value_scope_t); + } virtual string description() { return parent->description(); diff --git a/src/temps.h b/src/temps.h index ad4e5672..f41c487c 100644 --- a/src/temps.h +++ b/src/temps.h @@ -51,7 +51,11 @@ class temporaries_t optional > acct_temps; public: + temporaries_t() { + TRACE_CTOR(temporaries_t, ""); + } ~temporaries_t() { + TRACE_DTOR(temporaries_t); clear(); } diff --git a/src/utils.cc b/src/utils.cc index 628fb158..5a364008 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -270,13 +270,79 @@ void operator delete[](void * ptr, const std::nothrow_t&) throw() { namespace ledger { -inline void report_count_map(std::ostream& out, object_count_map& the_map) -{ - foreach (object_count_map::value_type& pair, the_map) - out << " " << std::right << std::setw(12) << pair.second.first - << " " << std::right << std::setw(7) << pair.second.second - << " " << std::left << pair.first - << std::endl; +namespace { + void stream_commified_number(std::ostream& out, std::size_t num) + { + std::ostringstream buf; + std::ostringstream obuf; + + buf << num; + + int integer_digits = 0; + // Count the number of integer digits + for (const char * p = buf.str().c_str(); *p; p++) { + if (*p == '.') + break; + else if (*p != '-') + integer_digits++; + } + + for (const char * p = buf.str().c_str(); *p; p++) { + if (*p == '.') { + obuf << *p; + assert(integer_digits <= 3); + } + else if (*p == '-') { + obuf << *p; + } + else { + obuf << *p; + + if (integer_digits > 3 && --integer_digits % 3 == 0) + obuf << ','; + } + } + + out << obuf.str(); + } + + void stream_memory_size(std::ostream& out, std::size_t size) + { + std::ostringstream obuf; + + if (size > 10 * 1024 * 1024) + obuf << "\033[1m"; + if (size > 100 * 1024 * 1024) + obuf << "\033[31m"; + + obuf << std::setw(7); + + if (size < 1024) + obuf << size << 'b'; + else if (size < (1024 * 1024)) + obuf << int(double(size) / 1024.0) << 'K'; + else if (size < (1024 * 1024 * 1024)) + obuf << int(double(size) / (1024.0 * 1024.0)) << 'M'; + else + obuf << int(double(size) / (1024.0 * 1024.0 * 1024.0)) << 'G'; + + if (size > 10 * 1024 * 1024) + obuf << "\033[0m"; + + out << obuf.str(); + } + + void report_count_map(std::ostream& out, object_count_map& the_map) + { + foreach (object_count_map::value_type& pair, the_map) { + out << " " << std::right << std::setw(12); + stream_commified_number(out, pair.second.first); + out << " " << std::right << std::setw(7); + stream_memory_size(out, pair.second.second); + out << " " << std::left << pair.first + << std::endl; + } + } } std::size_t current_objects_size() @@ -354,7 +420,7 @@ void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size) void report_memory(std::ostream& out, bool report_all) { - if (! live_memory || ! memory_tracing_active) return; + if (! live_memory) return; if (live_memory_count->size() > 0) { out << "NOTE: There may be memory held by Boost " @@ -366,11 +432,13 @@ void report_memory(std::ostream& out, bool report_all) if (live_memory->size() > 0) { out << "Live memory:" << std::endl; - foreach (const memory_map::value_type& pair, *live_memory) + foreach (const memory_map::value_type& pair, *live_memory) { out << " " << std::right << std::setw(12) << pair.first - << " " << std::right << std::setw(7) << pair.second.second - << " " << std::left << pair.second.first + << " " << std::right << std::setw(7); + stream_memory_size(out, pair.second.second); + out << " " << std::left << pair.second.first << std::endl; + } } if (report_all && total_memory_count->size() > 0) { @@ -386,11 +454,13 @@ void report_memory(std::ostream& out, bool report_all) if (live_objects->size() > 0) { out << "Live objects:" << std::endl; - foreach (const objects_map::value_type& pair, *live_objects) + foreach (const objects_map::value_type& pair, *live_objects) { out << " " << std::right << std::setw(12) << pair.first - << " " << std::right << std::setw(7) << pair.second.second - << " " << std::left << pair.second.first + << " " << std::right << std::setw(7); + stream_memory_size(out, pair.second.second); + out << " " << std::left << pair.second.first << std::endl; + } } if (report_all) { @@ -529,18 +599,6 @@ std::ostringstream _log_buffer; uint8_t _trace_level; #endif -static inline void stream_memory_size(std::ostream& out, std::size_t size) -{ - if (size < 1024) - out << size << 'b'; - else if (size < (1024 * 1024)) - out << (double(size) / 1024.0) << 'K'; - else if (size < (1024 * 1024 * 1024)) - out << (double(size) / (1024.0 * 1024.0)) << 'M'; - else - out << (double(size) / (1024.0 * 1024.0 * 1024.0)) << 'G'; -} - static bool logger_has_run = false; static ptime logger_start; diff --git a/test/baseline/opt-verify-memory.test b/test/baseline/opt-verify-memory.test new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3 From cd50fe054794d89253fce26daa685e2043428873 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 19 Mar 2012 00:41:32 -0500 Subject: More improvements to nail_down; fixes #715 --- src/report.cc | 6 ++++-- test/regress/BFD3FBE1.test | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 test/regress/BFD3FBE1.test (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 28836d0f..21fc9c1b 100644 --- a/src/report.cc +++ b/src/report.cc @@ -813,10 +813,12 @@ value_t report_t::fn_nail_down(call_scope_t& args) switch (arg0.type()) { case value_t::AMOUNT: { amount_t tmp(arg0.as_amount()); - if (tmp.has_commodity() && ! arg1.is_null()) { + if (tmp.has_commodity() && ! tmp.is_null() && ! tmp.is_realzero()) { + arg1 = arg1.strip_annotations(keep_details_t()).to_amount(); expr_t value_expr(is_expr(arg1) ? as_expr(arg1) : - expr_t::op_t::wrap_value(arg1.unrounded() / arg0)); + expr_t::op_t::wrap_value(arg1.unrounded() / + arg0.number())); std::ostringstream buf; value_expr.print(buf); value_expr.set_text(buf.str()); diff --git a/test/regress/BFD3FBE1.test b/test/regress/BFD3FBE1.test new file mode 100644 index 00000000..5b2f8b42 --- /dev/null +++ b/test/regress/BFD3FBE1.test @@ -0,0 +1,17 @@ +2011-01-01 * Opening balance + Assets:Investment 100 "AAA" @ 16.58900489 EUR + Assets:Investments 5 "BBB" @ 24.79900855 EUR + Equity:Opening balance + +2011-02-10 * Reimbursement: Taxi / Subway / Bus / Train + Assets:A 1.59 GBP + Assets:B -1.80 EUR @ 0.884955752212389381 GBP + +test reg -X EUR -H +11-Jan-01 Opening balance Assets:Investment 1658.90 EUR 1658.90 EUR + Assets:Investments 124.00 EUR 1782.90 EUR + Equity:Opening balance -1782.90 EUR 0 +11-Feb-10 Reimbursement: Taxi.. -0.01 EUR -0.01 EUR + Assets:A 1.80 EUR 1.80 EUR + Assets:B -1.80 EUR 0 +end test -- cgit v1.2.3 From a47625be3571262f0c36324d6793c55645172dc1 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Sun, 25 Mar 2012 11:50:16 +0100 Subject: Make pricesdb an alias for pricedb for backwards compatibility with ledger 2 ledger 2.2 introduced the pricesdb command. This was renamed to pricedb in ledger 3. Allow pricesdb as an alternative to pricedb to provide backwards compatibility. Fixes bug #728 --- src/report.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 21fc9c1b..97d2df02 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1616,7 +1616,7 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, else if (is_eq(p, "prices")) { return FORMATTED_COMMODITIES_REPORTER(prices_format_); } - else if (is_eq(p, "pricedb")) { + else if (is_eq(p, "pricedb") || is_eq(p, "pricesdb")) { return FORMATTED_COMMODITIES_REPORTER(pricedb_format_); } else if (is_eq(p, "pricemap")) { -- cgit v1.2.3 From 6a5360e2b570d21b321f901ca5584780a6111121 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 12 Apr 2012 02:39:04 -0500 Subject: Make --detail a synonym for --rich-data --- src/report.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 97d2df02..c7559cf7 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1215,7 +1215,7 @@ option_t * report_t::lookup_option(const char * p) else OPT(revalued); else OPT(revalued_only); else OPT(revalued_total_); - else OPT(rich_data); + else OPT_ALT(rich_data, detail); break; case 's': OPT(sort_); -- cgit v1.2.3