diff options
author | John Wiegley <johnw@newartisans.com> | 2010-06-14 17:14:56 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2010-06-14 17:14:56 -0400 |
commit | f3bedb88b24ae8b2047ad86e57b161265c2812f5 (patch) | |
tree | e6e5954f40a09e7fd002f242523c1eb0f318b397 /src | |
parent | 0c699e4d57fe91fa04c4c2f23f9c2f2a6a5da582 (diff) | |
parent | 63b4bdaecff5a865bff22e8e7914bef6ab46fa6b (diff) | |
download | fork-ledger-f3bedb88b24ae8b2047ad86e57b161265c2812f5.tar.gz fork-ledger-f3bedb88b24ae8b2047ad86e57b161265c2812f5.tar.bz2 fork-ledger-f3bedb88b24ae8b2047ad86e57b161265c2812f5.zip |
Merge branch 'next'
Diffstat (limited to 'src')
-rw-r--r-- | src/account.cc | 4 | ||||
-rw-r--r-- | src/commodity.cc | 10 | ||||
-rw-r--r-- | src/filters.cc | 54 | ||||
-rw-r--r-- | src/format.cc | 155 | ||||
-rw-r--r-- | src/global.cc | 2 | ||||
-rw-r--r-- | src/item.cc | 20 | ||||
-rw-r--r-- | src/item.h | 14 | ||||
-rw-r--r-- | src/journal.cc | 10 | ||||
-rw-r--r-- | src/journal.h | 6 | ||||
-rw-r--r-- | src/op.cc | 6 | ||||
-rw-r--r-- | src/post.cc | 12 | ||||
-rw-r--r-- | src/precmd.cc | 2 | ||||
-rw-r--r-- | src/report.cc | 4 | ||||
-rw-r--r-- | src/report.h | 10 | ||||
-rw-r--r-- | src/scope.cc | 2 | ||||
-rw-r--r-- | src/scope.h | 16 | ||||
-rw-r--r-- | src/session.cc | 55 | ||||
-rw-r--r-- | src/session.h | 8 | ||||
-rw-r--r-- | src/textual.cc | 65 | ||||
-rw-r--r-- | src/times.cc | 159 | ||||
-rw-r--r-- | src/times.h | 68 | ||||
-rw-r--r-- | src/xact.cc | 23 | ||||
-rw-r--r-- | src/xact.h | 6 |
23 files changed, 462 insertions, 249 deletions
diff --git a/src/account.cc b/src/account.cc index 809b6e46..ceeb1c12 100644 --- a/src/account.cc +++ b/src/account.cc @@ -295,7 +295,7 @@ namespace { foreach (post_t * p, account.posts) { bind_scope_t bound_scope(args, *p); - if (expr->calc(bound_scope).to_boolean()) + if (expr->calc(bound_scope, args.locus, args.depth).to_boolean()) return true; } return false; @@ -308,7 +308,7 @@ namespace { foreach (post_t * p, account.posts) { bind_scope_t bound_scope(args, *p); - if (! expr->calc(bound_scope).to_boolean()) + if (! expr->calc(bound_scope, args.locus, args.depth).to_boolean()) return false; } return true; diff --git a/src/commodity.cc b/src/commodity.cc index 230113e8..179bbc05 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -646,9 +646,13 @@ void commodity_t::print(std::ostream& out, bool elide_quotes) const { string sym = symbol(); if (elide_quotes && has_flags(COMMODITY_STYLE_SEPARATED) && - ! sym.empty() && sym[0] == '"' && ! std::strchr(sym.c_str(), ' ')) { - DEBUG("foo", "contracting " << sym << " to " << string(sym, 1, sym.length() - 2)); - out << string(sym, 1, sym.length() - 2); + ! sym.empty() && sym[0] == '"' && + ! std::strchr(sym.c_str(), ' ')) { + string subsym(sym, 1, sym.length() - 2); + if (! all(subsym, is_digit())) + out << subsym; + else + out << sym; } else out << sym; } diff --git a/src/filters.cc b/src/filters.cc index 86386f58..69183991 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -501,26 +501,15 @@ void related_posts::flush() { if (posts.size() > 0) { foreach (post_t * post, posts) { - if (post->xact) { - foreach (post_t * r_post, post->xact->posts) { - post_t::xdata_t& xdata(r_post->xdata()); - if (! xdata.has_flags(POST_EXT_HANDLED) && - (! xdata.has_flags(POST_EXT_RECEIVED) ? - ! r_post->has_flags(ITEM_GENERATED | POST_VIRTUAL) : - also_matching)) { - xdata.add_flags(POST_EXT_HANDLED); - item_handler<post_t>::operator()(*r_post); - } - } - } else { - // This code should only be reachable from the "output" - // command, since that is the only command which attempts to - // output auto or period xacts. - post_t::xdata_t& xdata(post->xdata()); + assert(post->xact); + foreach (post_t * r_post, post->xact->posts) { + post_t::xdata_t& xdata(r_post->xdata()); if (! xdata.has_flags(POST_EXT_HANDLED) && - ! post->has_flags(ITEM_GENERATED)) { + (! xdata.has_flags(POST_EXT_RECEIVED) ? + ! r_post->has_flags(ITEM_GENERATED | POST_VIRTUAL) : + also_matching)) { xdata.add_flags(POST_EXT_HANDLED); - item_handler<post_t>::operator()(*post); + item_handler<post_t>::operator()(*r_post); } } } @@ -1228,18 +1217,16 @@ void budget_posts::operator()(post_t& post) void forecast_posts::add_post(const date_interval_t& period, post_t& post) { - generate_posts::add_post(period, post); + date_interval_t i(period); + if (! i.start && ! i.find_period(CURRENT_DATE())) + return; - // Advance the period's interval until it is at or beyond the current date. - date_interval_t& i = pending_posts.back().first; - if (! i.start) { - if (! i.find_period(CURRENT_DATE())) - throw_(std::runtime_error, _("Something odd has happened")); + generate_posts::add_post(i, post); + + // Advance the period's interval until it is at or beyond the current + // date. + while (*i.start < CURRENT_DATE()) ++i; - } else { - while (*i.start < CURRENT_DATE()) - ++i; - } } void forecast_posts::flush() @@ -1281,6 +1268,8 @@ void forecast_posts::flush() for (pending_posts_list::iterator i = ++pending_posts.begin(); i != pending_posts.end(); i++) { + assert((*i).first.start); + assert((*least).first.start); if (*(*i).first.start < *(*least).first.start) least = i; } @@ -1307,7 +1296,6 @@ void forecast_posts::flush() } begin = next; - ++(*least).first; // `post' refers to the posting defined in the period transaction. We // make a copy of it within a temporary transaction with the payee @@ -1337,6 +1325,14 @@ void forecast_posts::flush() continue; } } + + // Increment the 'least', but remove it from pending_posts if it + // exceeds its own boundaries. + ++(*least).first; + if (! (*least).first.start) { + pending_posts.erase(least); + continue; + } } item_handler<post_t>::flush(); diff --git a/src/format.cc b/src/format.cc index ae40e1c3..946dcf80 100644 --- a/src/format.cc +++ b/src/format.cc @@ -432,6 +432,23 @@ string format_t::truncate(const unistring& ustr, case ABBREVIATE: if (account_abbrev_length > 0) { + // The algorithm here is complex, but aims to preserve the most + // information in the most useful places. + // + // Consider: You have an account name like + // 'Assets:Banking:Check:Register'. This account name, which is + // 29 characters long, must be shortened to fit in 20. How would + // you shorten it? + // + // The approach taken below is to compute the difference, or 9 + // characters, and then distribute this difference semi-evenly + // among first three segments of the account name, by taking + // characters until the difference is gone. Further, earlier + // segments will give up more of their share of letters than later + // segments, since the later segments usually contain more useful + // information. + + // First, chop up the Unicode string into individual segments. std::list<string> parts; string::size_type beg = 0; string strcopy(ustr.extract()); @@ -441,34 +458,140 @@ string format_t::truncate(const unistring& ustr, parts.push_back(string(strcopy, beg, pos - beg)); parts.push_back(string(strcopy, beg)); - std::ostringstream result; - - std::size_t newlen = len; + DEBUG("format.abbrev", "Account name: " << strcopy); + DEBUG("format.abbrev", + "Must fit a " << len << " char string in " << width << " chars"); + + // Figure out the lengths of all the parts. The last part is + // always displayed in full, while the former parts are + // distributed, with the latter parts being longer than the + // former, but with none shorter than account_abbrev_length. + std::list<std::size_t> lens; +#if defined(DEBUG_ON) + int index = 0; +#endif for (std::list<string>::iterator i = parts.begin(); i != parts.end(); i++) { - // Don't contract the last element + std::size_t l = unistring(*i).length(); + DEBUG("format.abbrev", + "Segment " << ++index << " is " << l << " chars wide"); + lens.push_back(l); + } + + // Determine the "overflow", or how many chars in excess we are. + + std::size_t overflow = len - width; + DEBUG("format.abbrev", + "There are " << overflow << " chars of overflow"); + + // Walk through the first n-1 segments, and start subtracting + // letters to decrease the overflow. This is done in multiple + // passes until the overflow is gone, or we cannot reduce any + // further. The calculation to find the amount to remove is: + // + // overflow * (((len(segment) + counter) * iteration) / + // (len(string) - len(last_segment) - counter)) + // + // Where: + // overflow - the amount that needs to be removed + // counter - starts at n-1 for the first segment, then + // decreases by one until it reaches 0 for the + // last segment (which is never shortened). + // This value is used to weight the shrinkage + // so that earlier segments shrink faster. + // iteration - starts at 1, increase by 1 for every + // iteration of the loop + // + // In the example above, we have this account name: + // + // Assets:Banking:Check:Register + // + // Therefore, the amount to be removed from Assets is calculated as: + // + // 9 * (((6 + 3) * 1) / (29 - 8 - 3)) = ceil(4.5) = 5 + // + // However, since removing 5 chars would make the length of the + // segment shorter than the default minimum of 2, we can only + // remove 4 chars from Assets to reduce the overflow. And on it + // goes. + // + // The final result will be: As:Ban:Chec:Register + + std::size_t iteration = 1; + std::size_t len_minus_last = len - lens.back(); + while (overflow > 0) { + std::size_t overflow_at_start = overflow; + DEBUG("format.abbrev", + "Overflow starting at " << overflow << " chars"); +#if defined(DEBUG_ON) + index = 0; +#endif + std::size_t counter = lens.size(); + for (std::list<std::size_t>::iterator i = lens.begin(); + i != lens.end(); + i++) { + if (--counter == 0 || overflow == 0) + break; + DEBUG("format.abbrev", "Overflow is " << overflow << " chars"); + std::size_t adjust; + if (overflow == 1) + adjust = 1; + else + adjust = std::size_t + (std::ceil(double(overflow) * + ((double(*i + counter) * double(iteration)) / + (double(len_minus_last) - double(counter))))); + DEBUG("format.abbrev", "Weight calc: (" << overflow + << " * (((" << *i << " + " << counter << ") * " + << iteration << ") / (" << len_minus_last + << " - " << counter << ")))"); + if (adjust == 0) + adjust = 1; + else if (adjust > overflow) + adjust = overflow; + DEBUG("format.abbrev", "The weighted part is " << adjust << " chars"); + std::size_t slack = *i - std::min(*i, account_abbrev_length); + if (adjust > slack) + adjust = slack; + if (adjust > 0) { + DEBUG("format.abbrev", + "Reducing segment " << ++index << " by " << adjust << " chars"); + (*i) -= adjust; + DEBUG("format.abbrev", + "Segment " << index << " is now " << *i << " chars wide"); + overflow -= adjust; + DEBUG("format.abbrev", "Overflow is now " << overflow << " chars"); + } + } + DEBUG("format.abbrev", + "Overflow ending this time at " << overflow << " chars"); + if (overflow == overflow_at_start) + break; + iteration++; + } + + assert(parts.size() == lens.size()); + + std::list<string>::iterator i = parts.begin(); + std::list<std::size_t>::iterator l = lens.begin(); + std::ostringstream result; + + for (; i != parts.end() && l != lens.end(); i++, l++) { std::list<string>::iterator x = i; if (++x == parts.end()) { result << *i; break; } - if (newlen > width) { - unistring temp(*i); - if (temp.length() > account_abbrev_length) { - result << temp.extract(0, account_abbrev_length) << ":"; - newlen -= temp.length() - account_abbrev_length; - } else { - result << temp.extract() << ":"; - newlen -= temp.length(); - } - } else { + unistring temp(*i); + if (temp.length() > *l) + result << temp.extract(0, *l) << ":"; + else result << *i << ":"; - } } - if (newlen > width) { + if (overflow > 0) { // Even abbreviated its too big to show the last account, so // abbreviate all but the last and truncate at the beginning. unistring temp(result.str()); diff --git a/src/global.cc b/src/global.cc index eb138f25..b1466cae 100644 --- a/src/global.cc +++ b/src/global.cc @@ -49,6 +49,8 @@ global_scope_t::global_scope_t(char ** envp) { TRACE_CTOR(global_scope_t, ""); + epoch = CURRENT_TIME(); + #if defined(HAVE_BOOST_PYTHON) if (! python_session.get()) { python_session.reset(new ledger::python_interpreter_t); diff --git a/src/item.cc b/src/item.cc index f0273e59..63f0f3a9 100644 --- a/src/item.cc +++ b/src/item.cc @@ -134,10 +134,9 @@ item_t::set_tag(const string& tag, } } -void item_t::parse_tags(const char * p, - scope_t& scope, - bool overwrite_existing, - optional<date_t::year_type> current_year) +void item_t::parse_tags(const char * p, + scope_t& scope, + bool overwrite_existing) { if (const char * b = std::strchr(p, '[')) { if (*(b + 1) != '\0' && @@ -149,10 +148,10 @@ void item_t::parse_tags(const char * p, if (char * p = std::strchr(buf, '=')) { *p++ = '\0'; - _date_eff = parse_date(p, current_year); + _date_eff = parse_date(p); } if (buf[0]) - _date = parse_date(buf, current_year); + _date = parse_date(buf); } } } @@ -202,10 +201,9 @@ void item_t::parse_tags(const char * p, } } -void item_t::append_note(const char * p, - scope_t& scope, - bool overwrite_existing, - optional<date_t::year_type> current_year) +void item_t::append_note(const char * p, + scope_t& scope, + bool overwrite_existing) { if (note) { *note += '\n'; @@ -214,7 +212,7 @@ void item_t::append_note(const char * p, note = p; } - parse_tags(p, scope, overwrite_existing, current_year); + parse_tags(p, scope, overwrite_existing); } namespace { @@ -162,14 +162,12 @@ public: const optional<value_t>& value = none, const bool overwrite_existing = true); - virtual void parse_tags(const char * p, - scope_t& scope, - bool overwrite_existing = true, - optional<date_t::year_type> current_year = none); - virtual void append_note(const char * p, - scope_t& scope, - bool overwrite_existing = true, - optional<date_t::year_type> current_year = none); + virtual void parse_tags(const char * p, + scope_t& scope, + bool overwrite_existing = true); + virtual void append_note(const char * p, + scope_t& scope, + bool overwrite_existing = true); static bool use_effective_date; diff --git a/src/journal.cc b/src/journal.cc index ed1e26be..fd6d3eac 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -105,8 +105,7 @@ account_t * journal_t::find_account_re(const string& regexp) return master->find_account_re(regexp); } -bool journal_t::add_xact(xact_t * xact, - optional<date_t::year_type> current_year) +bool journal_t::add_xact(xact_t * xact) { xact->journal = this; @@ -115,17 +114,16 @@ bool journal_t::add_xact(xact_t * xact, return false; } - extend_xact(xact, current_year); + extend_xact(xact); xacts.push_back(xact); return true; } -void journal_t::extend_xact(xact_base_t * xact, - optional<date_t::year_type> current_year) +void journal_t::extend_xact(xact_base_t * xact) { foreach (auto_xact_t * auto_xact, auto_xacts) - auto_xact->extend_xact(*xact, current_year); + auto_xact->extend_xact(*xact); } bool journal_t::remove_xact(xact_t * xact) diff --git a/src/journal.h b/src/journal.h index 183d074d..ca6b6e4f 100644 --- a/src/journal.h +++ b/src/journal.h @@ -140,10 +140,8 @@ public: account_t * find_account(const string& name, bool auto_create = true); account_t * find_account_re(const string& regexp); - bool add_xact(xact_t * xact, - optional<date_t::year_type> current_year = none); - void extend_xact(xact_base_t * xact, - optional<date_t::year_type> current_year = none); + bool add_xact(xact_t * xact); + void extend_xact(xact_base_t * xact); bool remove_xact(xact_t * xact); xacts_list::iterator xacts_begin() { @@ -157,7 +157,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) // Evaluating an identifier is the same as calling its definition // directly, so we create an empty call_scope_t to reflect the scope for // this implicit call. - call_scope_t call_args(scope, scope.type_context(), scope.type_required()); + call_scope_t call_args(scope, locus, depth); result = left()->compile(call_args, depth + 1) ->calc(call_args, locus, depth + 1); check_type_context(scope, result); @@ -168,7 +168,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) // Evaluating a FUNCTION is the same as calling it directly; this happens // when certain functions-that-look-like-variables (such as "amount") are // resolved. - call_scope_t call_args(scope, scope.type_context(), scope.type_required()); + call_scope_t call_args(scope, locus, depth); result = as_function()(call_args); check_type_context(scope, result); #if defined(DEBUG_ON) @@ -235,7 +235,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) } case O_CALL: { - call_scope_t call_args(scope, scope.type_context(), scope.type_required()); + call_scope_t call_args(scope, locus, depth); if (has_right()) call_args.set_args(split_cons_expr(right()->kind == O_SEQ ? right()->left() : right())); diff --git a/src/post.cc b/src/post.cc index bbf43227..675749fc 100644 --- a/src/post.cc +++ b/src/post.cc @@ -353,12 +353,14 @@ namespace { foreach (post_t * p, post.xact->posts) { bind_scope_t bound_scope(args, *p); if (p == &post && args.has<expr_t::ptr_op_t>(1) && - ! args.get<expr_t::ptr_op_t>(1)->calc(bound_scope).to_boolean()) { + ! args.get<expr_t::ptr_op_t>(1) + ->calc(bound_scope, args.locus, args.depth).to_boolean()) { // If the user specifies any(EXPR, false), and the context is a // posting, then that posting isn't considered by the test. ; // skip it } - else if (expr->calc(bound_scope).to_boolean()) { + else if (expr->calc(bound_scope, args.locus, + args.depth).to_boolean()) { return true; } } @@ -373,12 +375,14 @@ namespace { foreach (post_t * p, post.xact->posts) { bind_scope_t bound_scope(args, *p); if (p == &post && args.has<expr_t::ptr_op_t>(1) && - ! args.get<expr_t::ptr_op_t>(1)->calc(bound_scope).to_boolean()) { + ! args.get<expr_t::ptr_op_t>(1) + ->calc(bound_scope, args.locus, args.depth).to_boolean()) { // If the user specifies any(EXPR, false), and the context is a // posting, then that posting isn't considered by the test. ; // skip it } - else if (! expr->calc(bound_scope).to_boolean()) { + else if (! expr->calc(bound_scope, args.locus, + args.depth).to_boolean()) { return false; } } diff --git a/src/precmd.cc b/src/precmd.cc index 4c916608..95f3e875 100644 --- a/src/precmd.cc +++ b/src/precmd.cc @@ -186,7 +186,7 @@ value_t period_command(call_scope_t& args) out << std::endl; date_interval_t interval(arg); - interval.dump(out, report.session.current_year); + interval.dump(out); return NULL_VALUE; } diff --git a/src/report.cc b/src/report.cc index 6b52c52e..f7455440 100644 --- a/src/report.cc +++ b/src/report.cc @@ -148,8 +148,8 @@ void report_t::normalize_options(const string& verb) if (HANDLED(period_)) { date_interval_t interval(HANDLER(period_).str()); - optional<date_t> begin = interval.begin(session.current_year); - optional<date_t> end = interval.end(session.current_year); + optional<date_t> begin = interval.begin(); + optional<date_t> end = interval.end(); if (! HANDLED(begin_) && begin) { string predicate = "date>=[" + to_iso_extended_string(*begin) + "]"; diff --git a/src/report.h b/src/report.h index 44aed03b..6176c19b 100644 --- a/src/report.h +++ b/src/report.h @@ -393,7 +393,7 @@ public: OPTION_(report_t, begin_, DO_(args) { // -b date_interval_t interval(args.get<string>(1)); - optional<date_t> begin = interval.begin(parent->session.current_year); + optional<date_t> begin = interval.begin(); if (! begin) throw_(std::invalid_argument, _("Could not determine beginning of period '%1'") @@ -543,8 +543,9 @@ public: OPTION_(report_t, end_, DO_(args) { // -e date_interval_t interval(args.get<string>(1)); // 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<date_t> end = interval.begin(parent->session.current_year); + // 2008/01/01 instead of 2009/01/01 (which is what end() would + // return). + optional<date_t> end = interval.begin(); if (! end) throw_(std::invalid_argument, _("Could not determine end of period '%1'") @@ -665,13 +666,12 @@ public: OPTION_(report_t, now_, DO_(args) { date_interval_t interval(args.get<string>(1)); - optional<date_t> begin = interval.begin(parent->session.current_year); + optional<date_t> begin = interval.begin(); if (! begin) throw_(std::invalid_argument, _("Could not determine beginning of period '%1'") << args.get<string>(1)); ledger::epoch = parent->terminus = datetime_t(*begin); - parent->session.current_year = ledger::epoch->date().year(); }); OPTION__ diff --git a/src/scope.cc b/src/scope.cc index 52cf6a90..e18b5a0a 100644 --- a/src/scope.cc +++ b/src/scope.cc @@ -81,7 +81,7 @@ value_t& call_scope_t::resolve(const std::size_t index, value_t& value(args[index]); if (value.is_any()) { context_scope_t scope(*this, context, required); - value = as_expr(value)->calc(scope); + value = as_expr(value)->calc(scope, locus, depth); if (required && ! value.is_type(context)) throw_(calc_error, _("Expected %1 for argument %2, but received %3") << value.label(context) << index diff --git a/src/scope.h b/src/scope.h index 98b0ee02..07b6bebe 100644 --- a/src/scope.h +++ b/src/scope.h @@ -335,11 +335,17 @@ class call_scope_t : public context_scope_t const bool required = false); public: - explicit call_scope_t(scope_t& _parent, - value_t::type_t _type_context = value_t::VOID, - const bool _required = true) - : context_scope_t(_parent, _type_context, _required), ptr(NULL) { - TRACE_CTOR(call_scope_t, "scope_t&, value_t::type_t, bool"); + expr_t::ptr_op_t * locus; + const int depth; + + explicit call_scope_t(scope_t& _parent, + expr_t::ptr_op_t * _locus = NULL, + const int _depth = 0) + : context_scope_t(_parent, _parent.type_context(), + _parent.type_required()), + ptr(NULL), locus(_locus), depth(_depth) { + TRACE_CTOR(call_scope_t, + "scope_t&, value_t::type_t, bool, expr_t::ptr_op_t *, int"); } virtual ~call_scope_t() { TRACE_DTOR(call_scope_t); diff --git a/src/session.cc b/src/session.cc index df6eaf7d..85b5fab2 100644 --- a/src/session.cc +++ b/src/session.cc @@ -60,9 +60,7 @@ void set_session_context(session_t * session) } session_t::session_t() - : flush_on_next_data_file(false), - current_year(CURRENT_DATE().year()), - journal(new journal_t) + : flush_on_next_data_file(false), journal(new journal_t) { TRACE_CTOR(session_t, ""); @@ -192,6 +190,40 @@ value_t session_t::fn_account(call_scope_t& args) return NULL_VALUE; } +value_t session_t::fn_min(call_scope_t& args) +{ + return args[1] < args[0] ? args[1] : args[0]; +} +value_t session_t::fn_max(call_scope_t& args) +{ + return args[1] > args[0] ? args[1] : args[0]; +} + +value_t session_t::fn_lot_price(call_scope_t& args) +{ + amount_t amt(args.get<amount_t>(1, false)); + if (amt.has_annotation() && amt.annotation().price) + return *amt.annotation().price; + else + return NULL_VALUE; +} +value_t session_t::fn_lot_date(call_scope_t& args) +{ + amount_t amt(args.get<amount_t>(1, false)); + if (amt.has_annotation() && amt.annotation().date) + return *amt.annotation().date; + else + return NULL_VALUE; +} +value_t session_t::fn_lot_tag(call_scope_t& args) +{ + amount_t amt(args.get<amount_t>(1, false)); + if (amt.has_annotation() && amt.annotation().tag) + return string_value(*amt.annotation().tag); + else + return NULL_VALUE; +} + option_t<session_t> * session_t::lookup_option(const char * p) { switch (*p) { @@ -243,6 +275,23 @@ expr_t::ptr_op_t session_t::lookup(const symbol_t::kind_t kind, if (is_eq(p, "account")) return MAKE_FUNCTOR(session_t::fn_account); break; + + case 'l': + if (is_eq(p, "lot_price")) + return MAKE_FUNCTOR(session_t::fn_lot_price); + else if (is_eq(p, "lot_date")) + return MAKE_FUNCTOR(session_t::fn_lot_date); + else if (is_eq(p, "lot_tag")) + return MAKE_FUNCTOR(session_t::fn_lot_tag); + break; + + case 'm': + if (is_eq(p, "min")) + return MAKE_FUNCTOR(session_t::fn_min); + else if (is_eq(p, "max")) + return MAKE_FUNCTOR(session_t::fn_max); + break; + default: break; } diff --git a/src/session.h b/src/session.h index 597268ee..6de4b2dd 100644 --- a/src/session.h +++ b/src/session.h @@ -56,8 +56,7 @@ class session_t : public symbol_scope_t friend void set_session_context(session_t * session); public: - bool flush_on_next_data_file; - date_t::year_type current_year; + bool flush_on_next_data_file; std::auto_ptr<journal_t> journal; explicit session_t(); @@ -75,6 +74,11 @@ public: void close_journal_files(); value_t fn_account(call_scope_t& scope); + value_t fn_min(call_scope_t& scope); + value_t fn_max(call_scope_t& scope); + value_t fn_lot_price(call_scope_t& scope); + value_t fn_lot_date(call_scope_t& scope); + value_t fn_lot_tag(call_scope_t& scope); void report_options(std::ostream& out) { diff --git a/src/textual.cc b/src/textual.cc index 113bafe8..800d0c4e 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -93,18 +93,17 @@ namespace { static const std::size_t MAX_LINE = 1024; public: - parse_context_t& context; - instance_t * parent; - accounts_map account_aliases; - const path * original_file; - path pathname; - std::istream& in; - char linebuf[MAX_LINE + 1]; - std::size_t linenum; - istream_pos_type line_beg_pos; - istream_pos_type curr_pos; - - optional<date_t::year_type> current_year; + parse_context_t& context; + instance_t * parent; + accounts_map account_aliases; + const path * original_file; + path pathname; + std::istream& in; + char linebuf[MAX_LINE + 1]; + std::size_t linenum; + istream_pos_type line_beg_pos; + istream_pos_type curr_pos; + optional<datetime_t> prev_epoch; instance_t(parse_context_t& _context, std::istream& _in, @@ -207,11 +206,15 @@ instance_t::instance_t(parse_context_t& _context, pathname(original_file ? *original_file : "/dev/stdin"), in(_in) { TRACE_CTOR(instance_t, "..."); + DEBUG("times.epoch", "Saving epoch " << epoch); + prev_epoch = epoch; // declared in times.h } instance_t::~instance_t() { TRACE_DTOR(instance_t); + epoch = prev_epoch; + DEBUG("times.epoch", "Restored epoch to " << epoch); } void instance_t::parse() @@ -420,7 +423,7 @@ void instance_t::clock_in_directive(char * line, bool /*capitalized*/) position.end_line = linenum; position.sequence = context.sequence++; - time_xact_t event(position, parse_datetime(datetime, current_year), + time_xact_t event(position, parse_datetime(datetime), p ? context.top_account()->find_account(p) : NULL, n ? n : "", end ? end : ""); @@ -449,7 +452,7 @@ void instance_t::clock_out_directive(char * line, bool /*capitalized*/) position.end_line = linenum; position.sequence = context.sequence++; - time_xact_t event(position, parse_datetime(datetime, current_year), + time_xact_t event(position, parse_datetime(datetime), p ? context.top_account()->find_account(p) : NULL, n ? n : "", end ? end : ""); @@ -503,7 +506,12 @@ void instance_t::nomarket_directive(char * line) void instance_t::year_directive(char * line) { - current_year = lexical_cast<unsigned short>(skip_ws(line + 1)); + unsigned short year(lexical_cast<unsigned short>(skip_ws(line + 1))); + DEBUG("times.epoch", "Setting current year to " << year); + // This must be set to the last day of the year, otherwise partial + // dates like "11/01" will refer to last year's november, not the + // current year. + epoch = datetime_t(date_t(year, 12, 31)); } void instance_t::option_directive(char * line) @@ -554,7 +562,7 @@ void instance_t::automated_xact_directive(char * line) item = ae.get(); // This is a trailing note, and possibly a metadata info tag - item->append_note(p + 1, context.scope, true, current_year); + item->append_note(p + 1, context.scope, true); item->pos->end_pos = curr_pos; item->pos->end_line++; @@ -634,7 +642,7 @@ void instance_t::period_xact_directive(char * line) pe->journal = &context.journal; if (pe->finalize()) { - context.journal.extend_xact(pe.get(), current_year); + context.journal.extend_xact(pe.get()); context.journal.period_xacts.push_back(pe.get()); pe->pos->end_pos = curr_pos; @@ -885,14 +893,14 @@ void instance_t::assert_directive(char * line) { expr_t expr(line); if (! expr.calc(context.scope).to_boolean()) - throw_(parse_error, _("Assertion failed: %1" << line)); + throw_(parse_error, _("Assertion failed: %1") << line); } void instance_t::check_directive(char * line) { expr_t expr(line); if (! expr.calc(context.scope).to_boolean()) - warning_(_("Check failed: %1" << line)); + warning_(_("Check failed: %1") << line); } void instance_t::expr_directive(char * line) @@ -1324,7 +1332,7 @@ post_t * instance_t::parse_post(char * line, // Parse the optional note if (next && *next == ';') { - post->append_note(++next, context.scope, true, current_year); + post->append_note(++next, context.scope, true); next = line + len; DEBUG("textual.parse", "line " << linenum << ": " << "Parsed a posting note"); @@ -1343,8 +1351,7 @@ post_t * instance_t::parse_post(char * line, if (! context.state_stack.empty()) { foreach (const state_t& state, context.state_stack) if (state.type() == typeid(string)) - post->parse_tags(boost::get<string>(state).c_str(), context.scope, - true, current_year); + post->parse_tags(boost::get<string>(state).c_str(), context.scope, true); } TRACE_STOP(post_details, 1); @@ -1407,9 +1414,9 @@ xact_t * instance_t::parse_xact(char * line, if (char * p = std::strchr(line, '=')) { *p++ = '\0'; - xact->_date_eff = parse_date(p, current_year); + xact->_date_eff = parse_date(p); } - xact->_date = parse_date(line, current_year); + xact->_date = parse_date(line); // Parse the optional cleared flag: * @@ -1456,7 +1463,7 @@ xact_t * instance_t::parse_xact(char * line, // Parse the xact note if (next && *next == ';') - xact->append_note(++next, context.scope, false, current_year); + xact->append_note(++next, context.scope, false); TRACE_STOP(xact_text, 1); @@ -1483,7 +1490,7 @@ xact_t * instance_t::parse_xact(char * line, if (*p == ';') { // This is a trailing note, and possibly a metadata info tag - item->append_note(p + 1, context.scope, true, current_year); + item->append_note(p + 1, context.scope, true); item->pos->end_pos = curr_pos; item->pos->end_line++; } @@ -1502,9 +1509,9 @@ xact_t * instance_t::parse_xact(char * line, } else if (! expr.calc(bound_scope).to_boolean()) { if (c == 'a') { - throw_(parse_error, _("Transaction assertion failed: %1" << p)); + throw_(parse_error, _("Transaction assertion failed: %1") << p); } else { - warning_(_("Transaction check failed: %1" << p)); + warning_(_("Transaction check failed: %1") << p); } } } @@ -1542,7 +1549,7 @@ xact_t * instance_t::parse_xact(char * line, foreach (const state_t& state, context.state_stack) if (state.type() == typeid(string)) xact->parse_tags(boost::get<string>(state).c_str(), context.scope, - false, current_year); + false); } TRACE_STOP(xact_details, 1); diff --git a/src/times.cc b/src/times.cc index a9768f4f..31367e34 100644 --- a/src/times.cc +++ b/src/times.cc @@ -194,7 +194,6 @@ namespace { std::deque<shared_ptr<date_io_t> > readers; date_t parse_date_mask_routine(const char * date_str, date_io_t& io, - optional_year year, date_traits_t * traits = NULL) { VERIFY(std::strlen(date_str) < 127); @@ -229,29 +228,26 @@ namespace { *traits = io.traits; if (! io.traits.has_year) { - when = date_t(year ? *year : CURRENT_DATE().year(), - when.month(), when.day()); + when = date_t(CURRENT_DATE().year(), when.month(), when.day()); - if (! year && when.month() > CURRENT_DATE().month()) + if (when.month() > CURRENT_DATE().month()) when -= gregorian::years(1); } } return when; } - date_t parse_date_mask(const char * date_str, optional_year year, - date_traits_t * traits = NULL) + date_t parse_date_mask(const char * date_str, date_traits_t * traits = NULL) { if (input_date_io.get()) { date_t when = parse_date_mask_routine(date_str, *input_date_io.get(), - year, traits); + traits); if (! when.is_not_a_date()) return when; } foreach (shared_ptr<date_io_t>& reader, readers) { - date_t when = parse_date_mask_routine(date_str, *reader.get(), - year, traits); + date_t when = parse_date_mask_routine(date_str, *reader.get(), traits); if (! when.is_not_a_date()) return when; } @@ -312,7 +308,7 @@ string_to_month_of_year(const std::string& str) return none; } -datetime_t parse_datetime(const char * str, optional_year) +datetime_t parse_datetime(const char * str) { datetime_t when = input_datetime_io->parse(str); if (when.is_not_a_date_time()) @@ -320,18 +316,16 @@ datetime_t parse_datetime(const char * str, optional_year) return when; } -date_t parse_date(const char * str, optional_year current_year) +date_t parse_date(const char * str) { - return parse_date_mask(str, current_year); + return parse_date_mask(str); } -date_t date_specifier_t::begin(const optional_year& current_year) const +date_t date_specifier_t::begin() const { - assert(year || current_year); - - year_type the_year = year ? *year : static_cast<year_type>(*current_year); + year_type the_year = year ? *year : year_type(CURRENT_DATE().year()); month_type the_month = month ? *month : date_t::month_type(1); - day_type the_day = day ? *day : date_t::day_type(1); + day_type the_day = day ? *day : date_t::day_type(1); #if !defined(NO_ASSERTS) if (day) @@ -348,14 +342,14 @@ date_t date_specifier_t::begin(const optional_year& current_year) const static_cast<date_t::day_type>(the_day)); } -date_t date_specifier_t::end(const optional_year& current_year) const +date_t date_specifier_t::end() const { if (day || wday) - return begin(current_year) + gregorian::days(1); + return begin() + gregorian::days(1); else if (month) - return begin(current_year) + gregorian::months(1); + return begin() + gregorian::months(1); else if (year) - return begin(current_year) + gregorian::years(1); + return begin() + gregorian::years(1); else { assert(false); return date_t(); @@ -667,6 +661,16 @@ void date_parser_t::determine_when(date_parser_t::lexer_t::token_t& tok, (boost::get<date_time::weekdays>(*tok.value)); break; + case lexer_t::token_t::TOK_TODAY: + specifier = date_specifier_t(CURRENT_DATE()); + break; + case lexer_t::token_t::TOK_TOMORROW: + specifier = date_specifier_t(CURRENT_DATE() + gregorian::days(1)); + break; + case lexer_t::token_t::TOK_YESTERDAY: + specifier = date_specifier_t(CURRENT_DATE() - gregorian::days(1)); + break; + default: tok.unexpected(); break; @@ -687,14 +691,6 @@ date_interval_t date_parser_t::parse() tok.kind != lexer_t::token_t::END_REACHED; tok = lexer.next_token()) { switch (tok.kind) { -#if 0 - case lexer_t::token_t::TOK_INT: - // jww (2009-11-18): NYI - assert(! "Need to allow for expressions like \"4 months ago\""); - tok.unexpected(); - break; -#endif - case lexer_t::token_t::TOK_DATE: if (! inclusion_specifier) inclusion_specifier = date_specifier_t(); @@ -782,11 +778,44 @@ date_interval_t date_parser_t::parse() tok = lexer.next_token(); switch (tok.kind) { - case lexer_t::token_t::TOK_INT: - // jww (2009-11-18): Allow things like "last 5 weeks" - assert(! "Need to allow for expressions like \"last 5 weeks\""); - tok.unexpected(); + case lexer_t::token_t::TOK_INT: { + unsigned short amount = boost::get<unsigned short>(*tok.value); + + date_t base(today); + date_t end(today); + + tok = lexer.next_token(); + switch (tok.kind) { + case lexer_t::token_t::TOK_YEARS: + base += gregorian::years(amount * adjust); + break; + case lexer_t::token_t::TOK_QUARTERS: + base += gregorian::months(amount * adjust * 3); + break; + case lexer_t::token_t::TOK_MONTHS: + base += gregorian::months(amount * adjust); + break; + case lexer_t::token_t::TOK_WEEKS: + base += gregorian::weeks(amount * adjust); + break; + case lexer_t::token_t::TOK_DAYS: + base += gregorian::days(amount * adjust); + break; + default: + tok.unexpected(); + break; + } + + if (adjust >= 0) { + date_t temp = base; + base = end; + end = temp; + } + + since_specifier = date_specifier_t(base); + until_specifier = date_specifier_t(end); break; + } case lexer_t::token_t::TOK_A_MONTH: { inclusion_specifier = date_specifier_t(); @@ -822,26 +851,40 @@ date_interval_t date_parser_t::parse() } case lexer_t::token_t::TOK_QUARTER: { - date_t temp = + date_t base = date_duration_t::find_nearest(today, date_duration_t::QUARTERS); - temp += gregorian::months(3 * adjust); - inclusion_specifier = - date_specifier_t(static_cast<date_specifier_t::year_type>(temp.year()), - temp.month()); -#if 0 - period.duration = date_duration_t(date_duration_t::QUARTERS, 1); -#endif + date_t temp; + if (adjust < 0) { + temp = base + gregorian::months(3 * adjust); + } + else if (adjust == 0) { + temp = base + gregorian::months(3); + } + else if (adjust > 0) { + base += gregorian::months(3 * adjust); + temp = base + gregorian::months(3 * adjust); + } + since_specifier = date_specifier_t(adjust < 0 ? temp : base); + until_specifier = date_specifier_t(adjust < 0 ? base : temp); break; } case lexer_t::token_t::TOK_WEEK: { - date_t temp = + date_t base = date_duration_t::find_nearest(today, date_duration_t::WEEKS); - temp += gregorian::days(7 * adjust); - inclusion_specifier = date_specifier_t(today); -#if 0 - period.duration = date_duration_t(date_duration_t::WEEKS, 1); -#endif + date_t temp; + if (adjust < 0) { + temp = base + gregorian::days(7 * adjust); + } + else if (adjust == 0) { + temp = base + gregorian::days(7); + } + else if (adjust > 0) { + base += gregorian::days(7 * adjust); + temp = base + gregorian::days(7 * adjust); + } + since_specifier = date_specifier_t(adjust < 0 ? temp : base); + until_specifier = date_specifier_t(adjust < 0 ? base : temp); break; } @@ -862,6 +905,7 @@ date_interval_t date_parser_t::parse() break; } } + break; } case lexer_t::token_t::TOK_TODAY: @@ -876,7 +920,7 @@ date_interval_t date_parser_t::parse() case lexer_t::token_t::TOK_EVERY: tok = lexer.next_token(); - if (tok == lexer_t::token_t::TOK_INT) { + if (tok.kind == lexer_t::token_t::TOK_INT) { int quantity = boost::get<unsigned short>(*tok.value); tok = lexer.next_token(); switch (tok.kind) { @@ -1052,8 +1096,8 @@ void date_interval_t::stabilize(const optional<date_t>& date) // want a date early enough that the range will be correct, but late // enough that we don't spend hundreds of thousands of loops skipping // through time. - optional<date_t> initial_start = start ? start : begin(date->year()); - optional<date_t> initial_finish = finish ? finish : end(date->year()); + optional<date_t> initial_start = start ? start : begin(); + optional<date_t> initial_finish = finish ? finish : end(); #if defined(DEBUG_ON) if (initial_start) @@ -1116,13 +1160,8 @@ void date_interval_t::stabilize(const optional<date_t>& date) #endif } else if (range) { - if (date) { - start = range->begin(date->year()); - finish = range->end(date->year()); - } else { - start = range->begin(); - finish = range->end(); - } + start = range->begin(); + finish = range->end(); } aligned = true; } @@ -1228,7 +1267,7 @@ date_interval_t& date_interval_t::operator++() return *this; } -void date_interval_t::dump(std::ostream& out, optional_year current_year) +void date_interval_t::dump(std::ostream& out) { out << _("--- Before stabilization ---") << std::endl; @@ -1242,7 +1281,7 @@ void date_interval_t::dump(std::ostream& out, optional_year current_year) if (duration) out << _("duration: ") << duration->to_string() << std::endl; - stabilize(begin(current_year)); + stabilize(begin()); out << std::endl << _("--- After stabilization ---") << std::endl; @@ -1317,7 +1356,7 @@ date_parser_t::lexer_t::token_t date_parser_t::lexer_t::next_token() try { date_traits_t traits; - date_t when = parse_date_mask(possible_date.c_str(), none, &traits); + date_t when = parse_date_mask(possible_date.c_str(), &traits); if (! when.is_not_a_date()) { begin = i; return token_t(token_t::TOK_DATE, diff --git a/src/times.h b/src/times.h index 02b39ef7..ac96669d 100644 --- a/src/times.h +++ b/src/times.h @@ -77,27 +77,23 @@ extern optional<datetime_t> epoch; #define CURRENT_DATE() \ (epoch ? epoch->date() : boost::gregorian::day_clock::universal_day()) -extern date_time::weekdays start_of_week; +extern date_time::weekdays start_of_week; optional<date_time::weekdays> string_to_day_of_week(const std::string& str); optional<date_time::months_of_year> string_to_month_of_year(const std::string& str); -typedef optional<date_t::year_type> optional_year; +datetime_t parse_datetime(const char * str); -datetime_t parse_datetime(const char * str, optional_year current_year = none); - -inline datetime_t parse_datetime(const std::string& str, - optional_year current_year = none) { - return parse_datetime(str.c_str(), current_year); +inline datetime_t parse_datetime(const std::string& str) { + return parse_datetime(str.c_str()); } -date_t parse_date(const char * str, optional_year current_year = none); +date_t parse_date(const char * str); -inline date_t parse_date(const std::string& str, - optional_year current_year = none) { - return parse_date(str.c_str(), current_year); +inline date_t parse_date(const std::string& str) { + return parse_date(str.c_str()); } enum format_type_t { @@ -329,12 +325,11 @@ public: TRACE_DTOR(date_specifier_t); } - date_t begin(const optional_year& current_year = none) const; - date_t end(const optional_year& current_year = none) const; + date_t begin() const; + date_t end() const; - bool is_within(const date_t& date, - const optional_year& current_year = none) const { - return date >= begin(current_year) && date < end(current_year); + bool is_within(const date_t& date) const { + return date >= begin() && date < end(); } optional<date_duration_t> implied_duration() const { @@ -404,27 +399,26 @@ public: TRACE_DTOR(date_range_t); } - optional<date_t> begin(const optional_year& current_year = none) const { + optional<date_t> begin() const { if (range_begin) - return range_begin->begin(current_year); + return range_begin->begin(); else return none; } - optional<date_t> end(const optional_year& current_year = none) const { + optional<date_t> end() const { if (range_end) { if (end_inclusive) - return range_end->end(current_year); + return range_end->end(); else - return range_end->begin(current_year); + return range_end->begin(); } else { return none; } } - bool is_within(const date_t& date, - const optional_year& current_year = none) const { - optional<date_t> b = begin(current_year); - optional<date_t> e = end(current_year); + bool is_within(const date_t& date) const { + optional<date_t> b = begin(); + optional<date_t> e = end(); bool after_begin = b ? date >= *b : true; bool before_end = e ? date < *e : true; return after_begin && before_end; @@ -482,19 +476,19 @@ public: TRACE_DTOR(date_specifier_or_range_t); } - optional<date_t> begin(const optional_year& current_year = none) const { + optional<date_t> begin() const { if (specifier_or_range.type() == typeid(date_specifier_t)) - return boost::get<date_specifier_t>(specifier_or_range).begin(current_year); + return boost::get<date_specifier_t>(specifier_or_range).begin(); else if (specifier_or_range.type() == typeid(date_range_t)) - return boost::get<date_range_t>(specifier_or_range).begin(current_year); + return boost::get<date_range_t>(specifier_or_range).begin(); else return none; } - optional<date_t> end(const optional_year& current_year = none) const { + optional<date_t> end() const { if (specifier_or_range.type() == typeid(date_specifier_t)) - return boost::get<date_specifier_t>(specifier_or_range).end(current_year); + return boost::get<date_specifier_t>(specifier_or_range).end(); else if (specifier_or_range.type() == typeid(date_range_t)) - return boost::get<date_range_t>(specifier_or_range).end(current_year); + return boost::get<date_range_t>(specifier_or_range).end(); else return none; } @@ -571,11 +565,11 @@ public: return is_valid(); } - optional<date_t> begin(const optional_year& current_year = none) const { - return start ? start : (range ? range->begin(current_year) : none); + optional<date_t> begin() const { + return start ? start : (range ? range->begin() : none); } - optional<date_t> end(const optional_year& current_year = none) const { - return finish ? finish : (range ? range->end(current_year) : none); + optional<date_t> end() const { + return finish ? finish : (range ? range->end() : none); } void parse(const string& str); @@ -590,7 +584,7 @@ public: /** Find the current or next period containing date. Returns true if the date_interval_t object has been altered to reflect the interval containing date, or false if no such period can be found. */ - bool find_period(const date_t& date); + bool find_period(const date_t& date = CURRENT_DATE()); optional<date_t> inclusive_end() const { if (end_of_duration) @@ -601,7 +595,7 @@ public: date_interval_t& operator++(); - void dump(std::ostream& out, optional_year current_year = none); + void dump(std::ostream& out); #if defined(HAVE_BOOST_SERIALIZATION) private: diff --git a/src/xact.cc b/src/xact.cc index 1188fd0f..d8ed3f8b 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -509,7 +509,7 @@ namespace { foreach (post_t * p, post.xact->posts) { bind_scope_t bound_scope(args, *p); - if (expr->calc(bound_scope).to_boolean()) + if (expr->calc(bound_scope, args.locus, args.depth).to_boolean()) return true; } return false; @@ -522,7 +522,7 @@ namespace { foreach (post_t * p, post.xact->posts) { bind_scope_t bound_scope(args, *p); - if (! expr->calc(bound_scope).to_boolean()) + if (! expr->calc(bound_scope, args.locus, args.depth).to_boolean()) return false; } return true; @@ -629,8 +629,7 @@ namespace { } // unnamed namespace -void auto_xact_t::extend_xact(xact_base_t& xact, - optional<date_t::year_type> current_year) +void auto_xact_t::extend_xact(xact_base_t& xact) { posts_list initial_posts(xact.posts.begin(), xact.posts.end()); @@ -680,10 +679,8 @@ void auto_xact_t::extend_xact(xact_base_t& xact, if (deferred_notes) { foreach (deferred_tag_data_t& data, *deferred_notes) { if (data.apply_to_post == NULL) - initial_post->parse_tags(data.tag_data.c_str(), - bound_scope, - data.overwrite_existing, - current_year); + initial_post->parse_tags(data.tag_data.c_str(), bound_scope, + data.overwrite_existing); } } if (check_exprs) { @@ -694,9 +691,9 @@ void auto_xact_t::extend_xact(xact_base_t& xact, else if (! pair.first.calc(bound_scope).to_boolean()) { if (pair.second == auto_xact_t::EXPR_ASSERTION) { throw_(parse_error, - _("Transaction assertion failed: %1" << pair.first)); + _("Transaction assertion failed: %1") << pair.first); } else { - warning_(_("Transaction check failed: %1" << pair.first)); + warning_(_("Transaction check failed: %1") << pair.first); } } } @@ -778,10 +775,8 @@ void auto_xact_t::extend_xact(xact_base_t& xact, if (deferred_notes) { foreach (deferred_tag_data_t& data, *deferred_notes) { if (data.apply_to_post == post) - new_post->parse_tags(data.tag_data.c_str(), - bound_scope, - data.overwrite_existing, - current_year); + new_post->parse_tags(data.tag_data.c_str(), bound_scope, + data.overwrite_existing); } } } @@ -196,15 +196,13 @@ public: virtual void parse_tags(const char * p, scope_t&, - bool overwrite_existing = true, - optional<date_t::year_type> = none) { + bool overwrite_existing = true) { if (! deferred_notes) deferred_notes = deferred_notes_list(); deferred_notes->push_back(deferred_tag_data_t(p, overwrite_existing)); } - virtual void extend_xact(xact_base_t& xact, - optional<date_t::year_type> current_year); + virtual void extend_xact(xact_base_t& xact); #if defined(HAVE_BOOST_SERIALIZATION) private: |