diff options
62 files changed, 1227 insertions, 569 deletions
@@ -1337,8 +1337,6 @@ class PrepareBuild(CommandLineApp): def phase_proof(self, *args): self.log.info('Executing phase: proof') - self.phase_makeall(reset=False, *args) - self.log.info('=== Copying source tree ===') self.phase_rsync() self.phase_makeall(reset=True, *args) diff --git a/src/account.cc b/src/account.cc index 52a6b436..23761049 100644 --- a/src/account.cc +++ b/src/account.cc @@ -42,10 +42,9 @@ account_t::~account_t() { TRACE_DTOR(account_t); - foreach (accounts_map::value_type& pair, accounts) { - assert(! pair.second->has_flags(ACCOUNT_TEMP)); - checked_delete(pair.second); - } + foreach (accounts_map::value_type& pair, accounts) + if (! pair.second->has_flags(ACCOUNT_TEMP)) + checked_delete(pair.second); } account_t * account_t::find_account(const string& name, @@ -55,7 +54,7 @@ account_t * account_t::find_account(const string& name, if (i != accounts.end()) return (*i).second; - char buf[256]; + char buf[8192]; string::size_type sep = name.find(':'); assert(sep < 256|| sep == string::npos); @@ -398,6 +397,21 @@ value_t account_t::amount(const optional<expr_t&>& expr) const xdata_->self_details.last_post = i; } + if (xdata_->self_details.last_reported_post) + i = *xdata_->self_details.last_reported_post; + else + i = xdata_->reported_posts.begin(); + + for (; i != xdata_->reported_posts.end(); i++) { + if ((*i)->xdata().has_flags(POST_EXT_VISITED)) { + if (! (*i)->xdata().has_flags(POST_EXT_CONSIDERED)) { + (*i)->add_to_value(xdata_->self_details.total, expr); + (*i)->xdata().add_flags(POST_EXT_CONSIDERED); + } + } + xdata_->self_details.last_reported_post = i; + } + return xdata_->self_details.total; } else { return NULL_VALUE; diff --git a/src/account.h b/src/account.h index ce0a7a66..4ac69532 100644 --- a/src/account.h +++ b/src/account.h @@ -159,6 +159,7 @@ public: std::set<string> payees_referenced; optional<posts_list::const_iterator> last_post; + optional<posts_list::const_iterator> last_reported_post; details_t() : calculated(false), @@ -176,8 +177,9 @@ public: void update(post_t& post, bool gather_all = false); }; - details_t self_details; - details_t family_details; + details_t self_details; + details_t family_details; + posts_list reported_posts; std::list<sort_value_t> sort_values; @@ -193,7 +195,6 @@ public: { TRACE_CTOR(account_t::xdata_t, "copy"); } - ~xdata_t() throw() { TRACE_DTOR(account_t::xdata_t); } diff --git a/src/amount.cc b/src/amount.cc index 3ac47c59..435cdea4 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -783,7 +783,7 @@ void amount_t::annotate(const annotation_t& details) else if (! has_commodity()) return; // ignore attempt to annotate a "bare commodity - if (commodity().annotated) { + if (commodity().is_annotated()) { this_ann = &as_annotated_commodity(commodity()); this_base = &this_ann->referent(); } else { @@ -811,9 +811,9 @@ bool amount_t::is_annotated() const throw_(amount_error, _("Cannot determine if an uninitialized amount's commodity is annotated")); - assert(! has_commodity() || ! commodity().annotated || + assert(! has_commodity() || ! commodity().is_annotated() || as_annotated_commodity(commodity()).details); - return has_commodity() && commodity().annotated; + return has_commodity() && commodity().is_annotated(); } annotation_t& amount_t::annotation() diff --git a/src/annotate.cc b/src/annotate.cc index c6084f7f..9c676086 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -135,13 +135,13 @@ void annotation_t::print(std::ostream& out, bool keep_base) const bool keep_details_t::keep_all(const commodity_t& comm) const { - return (! comm.annotated || + return (! comm.is_annotated() || (keep_price && keep_date && keep_tag && ! only_actuals)); } bool keep_details_t::keep_any(const commodity_t& comm) const { - return comm.annotated && (keep_price || keep_date || keep_tag); + return comm.is_annotated() && (keep_price || keep_date || keep_tag); } bool annotated_commodity_t::operator==(const commodity_t& comm) const diff --git a/src/annotate.h b/src/annotate.h index 77dd9372..cb2a1161 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -185,9 +185,10 @@ class annotated_commodity_t equality_comparable2<annotated_commodity_t, commodity_t, noncopyable> > { -public: +protected: + friend class commodity_pool_t; + commodity_t * ptr; - annotation_t details; explicit annotated_commodity_t(commodity_t * _ptr, const annotation_t& _details) @@ -195,6 +196,10 @@ public: TRACE_CTOR(annotated_commodity_t, "commodity_t *, annotation_t"); annotated = true; } + +public: + annotation_t details; + virtual ~annotated_commodity_t() { TRACE_DTOR(annotated_commodity_t); } diff --git a/src/archive.cc b/src/archive.cc index b3aff7d7..d54b1179 100644 --- a/src/archive.cc +++ b/src/archive.cc @@ -43,7 +43,7 @@ #include "xact.h" #define LEDGER_MAGIC 0x4c454447 -#define ARCHIVE_VERSION 0x03000002 +#define ARCHIVE_VERSION 0x03000003 //BOOST_IS_ABSTRACT(ledger::scope_t) BOOST_CLASS_EXPORT(ledger::scope_t) diff --git a/src/balance.h b/src/balance.h index 5452510b..ad340aa5 100644 --- a/src/balance.h +++ b/src/balance.h @@ -207,7 +207,7 @@ public: template <typename T> bool operator==(const T& val) const { - return *this == balance_t(val); + return *this == amount_t(val); } /** @@ -217,11 +217,29 @@ public: */ balance_t& operator+=(const balance_t& bal); balance_t& operator+=(const amount_t& amt); + balance_t& operator+=(const double val) { + return *this += amount_t(val); + } + balance_t& operator+=(const unsigned long val) { + return *this += amount_t(val); + } + balance_t& operator+=(const long val) { + return *this += amount_t(val); + } + balance_t& operator-=(const balance_t& bal); balance_t& operator-=(const amount_t& amt); + balance_t& operator-=(const double val) { + return *this -= amount_t(val); + } + balance_t& operator-=(const unsigned long val) { + return *this -= amount_t(val); + } + balance_t& operator-=(const long val) { + return *this -= amount_t(val); + } balance_t& operator*=(const amount_t& amt); - balance_t& operator*=(const double val) { return *this *= amount_t(val); } @@ -233,7 +251,6 @@ public: } balance_t& operator/=(const amount_t& amt); - balance_t& operator/=(const double val) { return *this /= amount_t(val); } @@ -278,7 +295,7 @@ public: * in_place_reduce() * in_place_unreduce() */ - balance_t negate() const { + balance_t negated() const { balance_t temp(*this); temp.in_place_negate(); return temp; @@ -288,7 +305,7 @@ public: pair.second.in_place_negate(); } balance_t operator-() const { - return negate(); + return negated(); } balance_t abs() const { @@ -388,6 +405,13 @@ public: * it. */ operator bool() const { + return is_nonzero(); + } + + bool is_nonzero() const { + if (is_empty()) + return false; + foreach (const amounts_map::value_type& pair, amounts) if (pair.second.is_nonzero()) return true; @@ -433,6 +457,7 @@ public: else throw_(balance_error, _("Cannot convert a balance with multiple commodities to an amount")); + return amount_t(); } /** diff --git a/src/chain.cc b/src/chain.cc index db52269c..defa2e97 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -159,6 +159,17 @@ post_handler_ptr chain_post_handlers(report_t& report, handler.reset(new sort_posts(handler, "date")); } + if (report.HANDLED(set_reported_account_)) + handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT, + report.session.journal->master, + report.HANDLER(set_reported_account_).str(), + report)); + else if (report.HANDLED(set_reported_payee_)) + handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE, + report.session.journal->master, + report.HANDLER(set_reported_payee_).str(), + report)); + // related_posts will pass along all posts related to the post received. If // the `related_all' handler is on, then all the xact's posts are passed; // meaning that if one post of an xact is to be printed, all the post for diff --git a/src/commodity.cc b/src/commodity.cc index de529ac4..d896572f 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -38,10 +38,12 @@ namespace ledger { -void commodity_t::base_t::history_t::add_price(commodity_t& source, - const datetime_t& date, - const amount_t& price, - const bool reflexive) +bool commodity_t::european_by_default = false; + +void commodity_t::history_t::add_price(commodity_t& source, + const datetime_t& date, + const amount_t& price, + const bool reflexive) { DEBUG("commodity.prices.add", "add_price to " << source << (reflexive ? " (secondary)" : " (primary)") @@ -67,7 +69,7 @@ void commodity_t::base_t::history_t::add_price(commodity_t& source, } } -bool commodity_t::base_t::history_t::remove_price(const datetime_t& date) +bool commodity_t::history_t::remove_price(const datetime_t& date) { DEBUG("commodity.prices.add", "remove_price: " << date); @@ -77,7 +79,7 @@ bool commodity_t::base_t::history_t::remove_price(const datetime_t& date) return false; } -void commodity_t::base_t::varied_history_t:: +void commodity_t::varied_history_t:: add_price(commodity_t& source, const datetime_t& date, const amount_t& price, @@ -97,9 +99,8 @@ void commodity_t::base_t::varied_history_t:: hist->add_price(source, date, price, reflexive); } -bool commodity_t::base_t::varied_history_t:: - remove_price(const datetime_t& date, - commodity_t& comm) +bool commodity_t::varied_history_t::remove_price(const datetime_t& date, + commodity_t& comm) { DEBUG("commodity.prices.add", "varied_remove_price: " << date << ", " << comm); @@ -109,13 +110,12 @@ bool commodity_t::base_t::varied_history_t:: } optional<price_point_t> - commodity_t::base_t::history_t:: - find_price(const optional<datetime_t>& moment, - const optional<datetime_t>& oldest +commodity_t::history_t::find_price(const optional<datetime_t>& moment, + const optional<datetime_t>& oldest #if defined(DEBUG_ON) - , const int indent + , const int indent #endif - ) const + ) const { price_point_t point; bool found = false; @@ -220,15 +220,14 @@ optional<price_point_t> } optional<price_point_t> - commodity_t::base_t::varied_history_t:: - find_price(const commodity_t& source, - const optional<commodity_t&>& commodity, - const optional<datetime_t>& moment, - const optional<datetime_t>& oldest +commodity_t::varied_history_t::find_price(const commodity_t& source, + const optional<commodity_t&>& commodity, + const optional<datetime_t>& moment, + const optional<datetime_t>& oldest #if defined(DEBUG_ON) - , const int indent + , const int indent #endif - ) const + ) const { optional<price_point_t> point; optional<datetime_t> limit = oldest; @@ -352,9 +351,8 @@ optional<price_point_t> return none; } -optional<commodity_t::base_t::history_t&> - commodity_t::base_t::varied_history_t:: - history(const optional<commodity_t&>& commodity) +optional<commodity_t::history_t&> +commodity_t::varied_history_t::history(const optional<commodity_t&>& commodity) { commodity_t * comm = NULL; if (! commodity) { @@ -602,11 +600,11 @@ bool compare_amount_commodities::operator()(const amount_t * left, if (cmp != 0) return cmp < 0; - if (! leftcomm.annotated) { - return rightcomm.annotated; + if (! leftcomm.is_annotated()) { + return rightcomm.is_annotated(); } - else if (! rightcomm.annotated) { - return ! leftcomm.annotated; + else if (! rightcomm.is_annotated()) { + return ! leftcomm.is_annotated(); } else { annotated_commodity_t& aleftcomm(static_cast<annotated_commodity_t&>(leftcomm)); diff --git a/src/commodity.h b/src/commodity.h index 1df1ab18..25397131 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -86,87 +86,85 @@ class commodity_t : public delegates_flags<uint_least16_t>, public equality_comparable1<commodity_t, noncopyable> { - friend class commodity_pool_t; - public: - class base_t : public noncopyable, public supports_flags<uint_least16_t> - { - base_t() { - TRACE_CTOR(base_t, ""); - } - - public: - typedef std::map<const datetime_t, amount_t> history_map; + typedef std::map<const datetime_t, amount_t> history_map; - struct history_t - { - history_map prices; + 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); + 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<price_point_t> - find_price(const optional<datetime_t>& moment = none, - const optional<datetime_t>& oldest = none + optional<price_point_t> + find_price(const optional<datetime_t>& moment = none, + const optional<datetime_t>& oldest = none #if defined(DEBUG_ON) - , const int indent = 0 + , const int indent = 0 #endif - ) const; + ) const; #if defined(HAVE_BOOST_SERIALIZATION) - private: - /** Serialization. */ + private: + /** Serialization. */ - friend class boost::serialization::access; + friend class boost::serialization::access; - template<class Archive> - void serialize(Archive & ar, const unsigned int /* version */) { - ar & prices; - } + template<class Archive> + void serialize(Archive & ar, const unsigned int /* version */) { + ar & prices; + } #endif // HAVE_BOOST_SERIALIZATION - }; - - typedef std::map<commodity_t *, history_t> 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); + typedef std::map<commodity_t *, history_t> history_by_commodity_map; - optional<price_point_t> - find_price(const commodity_t& source, - const optional<commodity_t&>& commodity = none, - const optional<datetime_t>& moment = none, - const optional<datetime_t>& oldest = none + 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<price_point_t> + find_price(const commodity_t& source, + const optional<commodity_t&>& commodity = none, + const optional<datetime_t>& moment = none, + const optional<datetime_t>& oldest = none #if defined(DEBUG_ON) - , const int indent = 0 + , const int indent = 0 #endif - ) const; + ) const; - optional<history_t&> - history(const optional<commodity_t&>& commodity = none); + optional<history_t&> + history(const optional<commodity_t&>& commodity = none); #if defined(HAVE_BOOST_SERIALIZATION) - private: - /** Serialization. */ + private: + /** Serialization. */ - friend class boost::serialization::access; + friend class boost::serialization::access; - template<class Archive> - void serialize(Archive & ar, const unsigned int /* version */) { - ar & histories; - } + template<class Archive> + 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; + class base_t : public noncopyable, public supports_flags<uint_least16_t> + { + public: #define COMMODITY_STYLE_DEFAULTS 0x000 #define COMMODITY_STYLE_SUFFIXED 0x001 #define COMMODITY_STYLE_SEPARATED 0x002 @@ -190,7 +188,9 @@ public: public: explicit base_t(const string& _symbol) - : supports_flags<uint_least16_t>(COMMODITY_STYLE_DEFAULTS), + : supports_flags<uint_least16_t>(commodity_t::european_by_default ? + COMMODITY_STYLE_EUROPEAN : + COMMODITY_STYLE_DEFAULTS), symbol(_symbol), precision(0), searched(false) { TRACE_CTOR(base_t, "const string&"); } @@ -199,33 +199,31 @@ public: } #if defined(HAVE_BOOST_SERIALIZATION) - private: - /** Serialization. */ - - friend class boost::serialization::access; - - template<class Archive> - void serialize(Archive & ar, const unsigned int /* version */) { - ar & boost::serialization::base_object<supports_flags<uint_least16_t> >(*this); - ar & symbol; - ar & precision; - ar & name; - ar & note; - ar & varied_history; - ar & smaller; - ar & larger; - } + private: + base_t() { + TRACE_CTOR(base_t, ""); + } + + /** Serialization. */ + + friend class boost::serialization::access; + + template<class Archive> + void serialize(Archive & ar, const unsigned int /* version */) { + ar & boost::serialization::base_object<supports_flags<uint_least16_t> >(*this); + ar & symbol; + ar & precision; + ar & name; + ar & note; + ar & varied_history; + ar & smaller; + ar & larger; + } #endif // HAVE_BOOST_SERIALIZATION }; -public: static bool symbol_needs_quotes(const string& symbol); - typedef base_t::history_t history_t; - typedef base_t::history_map history_map; - typedef base_t::varied_history_t varied_history_t; - typedef base_t::history_by_commodity_map history_by_commodity_map; - shared_ptr<base_t> base; commodity_pool_t * parent_; @@ -233,13 +231,16 @@ public: optional<string> mapping_key_; bool annotated; -public: explicit commodity_t(commodity_pool_t * _parent, const shared_ptr<base_t>& _base) : delegates_flags<uint_least16_t>(*_base.get()), base(_base), parent_(_parent), annotated(false) { TRACE_CTOR(commodity_t, "commodity_pool_t *, shared_ptr<base_t>"); } + +public: + static bool european_by_default; + virtual ~commodity_t() { TRACE_DTOR(commodity_t); } diff --git a/src/filters.cc b/src/filters.cc index da9e39ae..00e495dd 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -133,6 +133,40 @@ void sort_posts::post_accumulated_posts() posts.clear(); } +namespace { + void split_string(const string& str, const char ch, + std::list<string>& strings) + { + const char * b = str.c_str(); + for (const char * p = b; *p; p++) { + if (*p == ch) { + strings.push_back(string(b, p - b)); + b = p + 1; + } + } + strings.push_back(string(b)); + } + + account_t * create_temp_account_from_path(std::list<string>& account_names, + temporaries_t& temps, + account_t * master) + { + account_t * new_account = NULL; + foreach (const string& name, account_names) { + if (new_account) { + new_account = new_account->find_account(name); + } else { + new_account = master->find_account(name, false); + if (! new_account) + new_account = &temps.create_account(name, master); + } + } + + assert(new_account != NULL); + return new_account; + } +} + void anonymize_posts::operator()(post_t& post) { SHA1 sha; @@ -158,27 +192,19 @@ void anonymize_posts::operator()(post_t& post) } std::list<string> account_names; - account_t * new_account = NULL; for (account_t * acct = post.account; acct; acct = acct->parent) { - if (! acct->parent) { - new_account = acct; - break; - } - sha.Reset(); sha << acct->name.c_str(); sha.Result(message_digest); account_names.push_front(to_hex(message_digest)); } - assert(new_account); - - foreach (const string& name, account_names) - new_account = new_account->find_account(name); + account_t * new_account = + create_temp_account_from_path(account_names, temps, xact.journal->master); post_t& temp = temps.copy_post(post, xact, new_account); temp.note = none; @@ -685,11 +711,15 @@ void transfer_details::operator()(post_t& post) case SET_PAYEE: xact.payee = expr.calc(bound_scope).to_string(); break; - case SET_ACCOUNT: + case SET_ACCOUNT: { + std::list<string> account_names; temp.account->remove_post(&temp); - temp.account = master->find_account(expr.calc(bound_scope).to_string()); + split_string(expr.calc(bound_scope).to_string(), ':', account_names); + temp.account = create_temp_account_from_path(account_names, temps, + xact.journal->master); temp.account->add_post(&temp); break; + } default: assert(false); break; @@ -739,11 +769,11 @@ void budget_posts::report_budget_items(const date_t& date) } assert(begin); - if (*begin < date && + if (*begin <= date && (! pair.first.end || *begin < *pair.first.end)) { post_t& post = *pair.second; - DEBUG("ledger.walk.budget", "Reporting budget for " + DEBUG("budget.generate", "Reporting budget for " << post.reported_account()->fullname()); xact_t& xact = temps.create_xact(); @@ -785,7 +815,7 @@ void budget_posts::operator()(post_t& post) post_in_budget = true; // Report the post as if it had occurred in the parent account. if (post.reported_account() != acct) - post.xdata().account = acct; + post.set_reported_account(acct); goto handle; } } diff --git a/src/filters.h b/src/filters.h index 7c1f169c..0dcf5e41 100644 --- a/src/filters.h +++ b/src/filters.h @@ -288,8 +288,7 @@ public: class anonymize_posts : public item_handler<post_t> { temporaries_t temps; - - xact_t * last_xact; + xact_t * last_xact; anonymize_posts(); diff --git a/src/item.cc b/src/item.cc index debda7a3..37e19a82 100644 --- a/src/item.cc +++ b/src/item.cc @@ -237,7 +237,7 @@ namespace { in_context_t<item_t> env(scope, "s"); if (optional<string> value = env->get_tag(env.get<string>(0))) return string_value(*value); - return false; + return string_value(empty_string); } value_t get_pathname(item_t& item) { @@ -143,6 +143,7 @@ public: _date_eff = item._date_eff; note = item.note; pos = item.pos; + metadata = item.metadata; } virtual bool operator==(const item_t& xact) { @@ -206,8 +207,8 @@ private: ar & _date; ar & _date_eff; ar & note; - ar & metadata; ar & pos; + ar & metadata; } #endif // HAVE_BOOST_SERIALIZATION }; diff --git a/src/iterators.cc b/src/iterators.cc index 50c67ade..540ba8ae 100644 --- a/src/iterators.cc +++ b/src/iterators.cc @@ -94,9 +94,9 @@ void posts_commodities_iterator::reset(journal_t& journal) comm->varied_history()) { account_t * account = journal.master->find_account(comm->symbol()); - foreach (commodity_t::base_t::history_by_commodity_map::value_type pair, + foreach (commodity_t::history_by_commodity_map::value_type pair, history->histories) { - foreach (commodity_t::base_t::history_map::value_type hpair, + foreach (commodity_t::history_map::value_type hpair, pair.second.prices) { xact_t * xact; string symbol = hpair.second.commodity().symbol(); @@ -232,13 +232,13 @@ public: private: void acquire() const { - DEBUG("ledger.xpath.memory", + DEBUG("op.memory", "Acquiring " << this << ", refc now " << refc + 1); assert(refc >= 0); refc++; } void release() const { - DEBUG("ledger.xpath.memory", + DEBUG("op.memory", "Releasing " << this << ", refc now " << refc - 1); assert(refc > 0); if (--refc == 0) diff --git a/src/pool.cc b/src/pool.cc index 68ba3ed7..06a4706c 100644 --- a/src/pool.cc +++ b/src/pool.cc @@ -108,25 +108,23 @@ commodity_pool_t::create(const string& symbol, const annotation_t& details) return new_comm; } -namespace { - string make_qualified_name(const commodity_t& comm, - const annotation_t& details) - { - assert(details); +string commodity_pool_t::make_qualified_name(const commodity_t& comm, + const annotation_t& details) +{ + assert(details); - if (details.price && details.price->sign() < 0) - throw_(amount_error, _("A commodity's price may not be negative")); + if (details.price && details.price->sign() < 0) + throw_(amount_error, _("A commodity's price may not be negative")); - std::ostringstream name; - comm.print(name); - details.print(name, comm.parent().keep_base); + std::ostringstream name; + comm.print(name); + details.print(name, comm.parent().keep_base); - DEBUG("amounts.commodities", "make_qualified_name for " - << *comm.qualified_symbol << std::endl << details); - DEBUG("amounts.commodities", "qualified_name is " << name.str()); + DEBUG("amounts.commodities", "make_qualified_name for " + << *comm.qualified_symbol << std::endl << details); + DEBUG("amounts.commodities", "qualified_name is " << name.str()); - return name.str(); - } + return name.str(); } commodity_t * @@ -98,6 +98,9 @@ public: checked_delete(pair.second); } + string make_qualified_name(const commodity_t& comm, + const annotation_t& details); + commodity_t * create(const string& symbol); commodity_t * find(const string& name); commodity_t * find_or_create(const string& symbol); diff --git a/src/post.cc b/src/post.cc index 7b5e5325..2a1663cb 100644 --- a/src/post.cc +++ b/src/post.cc @@ -141,6 +141,12 @@ namespace { return string_value(post.xact->payee); } + value_t get_note(post_t& post) { + string note = post.note ? *post.note : empty_string; + note += post.xact->note ? *post.xact->note : empty_string; + return string_value(note); + } + value_t get_magnitude(post_t& post) { return post.xact->magnitude(); } @@ -318,6 +324,11 @@ expr_t::ptr_op_t post_t::lookup(const string& name) return WRAP_FUNCTOR(get_wrapper<&get_magnitude>); break; + case 'n': + if (name == "note") + return WRAP_FUNCTOR(get_wrapper<&get_note>); + break; + case 'p': if (name == "post") return WRAP_FUNCTOR(get_wrapper<&get_this>); @@ -425,4 +436,10 @@ void post_t::add_to_value(value_t& value, const optional<expr_t&>& expr) const } } +void post_t::set_reported_account(account_t * account) +{ + xdata().account = account; + account->xdata().reported_posts.push_back(this); +} + } // namespace ledger @@ -193,6 +193,8 @@ public: void add_to_value(value_t& value, const optional<expr_t&>& expr = none) const; + void set_reported_account(account_t * account); + account_t * reported_account() { if (xdata_) if (account_t * acct = xdata_->account) diff --git a/src/precmd.cc b/src/precmd.cc index 590d2553..a08fd2d6 100644 --- a/src/precmd.cc +++ b/src/precmd.cc @@ -42,7 +42,7 @@ namespace ledger { namespace { - post_t * get_sample_post(report_t& report) + post_t * get_sample_xact(report_t& report) { { string str; @@ -50,7 +50,11 @@ namespace { std::ostringstream buf; buf << "2004/05/27 Book Store\n" + << " ; This note applies to all postings. :SecondTag:\n" << " Expenses:Books 20 BOOK @ $10\n" + << " ; Metadata: Some Value\n" + << " ; :ExampleTag:\n" + << " ; Here follows a note describing the posting.\n" << " Liabilities:MasterCard $-200.00\n"; str = buf.str(); @@ -82,7 +86,7 @@ value_t parse_command(call_scope_t& args) report_t& report(find_scope<report_t>(args)); std::ostream& out(report.output_stream); - post_t * post = get_sample_post(report); + post_t * post = get_sample_xact(report); out << _("--- Input expression ---") << std::endl; out << arg << std::endl; @@ -131,7 +135,7 @@ value_t format_command(call_scope_t& args) report_t& report(find_scope<report_t>(args)); std::ostream& out(report.output_stream); - post_t * post = get_sample_post(report); + post_t * post = get_sample_xact(report); out << _("--- Input format string ---") << std::endl; out << arg << std::endl << std::endl; diff --git a/src/predicate.cc b/src/predicate.cc index b3926116..d5b41362 100644 --- a/src/predicate.cc +++ b/src/predicate.cc @@ -156,7 +156,7 @@ query_lexer_t::token_t query_lexer_t::next_token() else if (ident == "code") return token_t(token_t::TOK_CODE); else if (ident == "note") - return token_t(token_t::TOK_NOT); + return token_t(token_t::TOK_NOTE); else if (ident == "tag") return token_t(token_t::TOK_META); else if (ident == "meta") @@ -242,7 +242,39 @@ query_parser_t::parse_query_term(query_lexer_t::token_t::kind_t tok_context) case query_lexer_t::token_t::TERM: assert(tok.value); if (tok_context == query_lexer_t::token_t::TOK_META) { - assert(0); + node = new expr_t::op_t(expr_t::op_t::O_CALL); + + expr_t::ptr_op_t ident; + ident = new expr_t::op_t(expr_t::op_t::IDENT); + ident->set_ident("has_tag"); + node->set_left(ident); + + expr_t::ptr_op_t arg1; + arg1 = new expr_t::op_t(expr_t::op_t::VALUE); + arg1->set_value(mask_t(*tok.value)); + + tok = lexer.peek_token(); + if (tok.kind == query_lexer_t::token_t::TOK_EQ) { + tok = lexer.next_token(); + tok = lexer.next_token(); + if (tok.kind != query_lexer_t::token_t::TERM) + throw_(parse_error, + _("Metadata equality operator not followed by term")); + + expr_t::ptr_op_t cons; + cons = new expr_t::op_t(expr_t::op_t::O_CONS); + + expr_t::ptr_op_t arg2; + arg2 = new expr_t::op_t(expr_t::op_t::VALUE); + assert(tok.value); + arg2->set_value(mask_t(*tok.value)); + + cons->set_left(arg1); + cons->set_right(arg2); + node->set_right(cons); + } else { + node->set_right(arg1); + } } else { node = new expr_t::op_t(expr_t::op_t::O_MATCH); diff --git a/src/py_amount.cc b/src/py_amount.cc index 7fe12674..efae7514 100644 --- a/src/py_amount.cc +++ b/src/py_amount.cc @@ -42,59 +42,66 @@ namespace ledger { using namespace boost::python; -boost::optional<amount_t> py_value_0(const amount_t& amount) { - return amount.value(); -} -boost::optional<amount_t> py_value_1(const amount_t& amount, - const bool primary_only) { - return amount.value(primary_only); -} -boost::optional<amount_t> py_value_2(const amount_t& amount, - const bool primary_only, - const boost::optional<datetime_t>& moment) { - return amount.value(primary_only, moment); -} -boost::optional<amount_t> py_value_3(const amount_t& amount, - const bool primary_only, - const boost::optional<datetime_t>& moment, - const boost::optional<commodity_t&>& in_terms_of) { - return amount.value(primary_only, moment, in_terms_of); -} +namespace { -void py_parse_2(amount_t& amount, object in, unsigned char flags) { - if (PyFile_Check(in.ptr())) { - pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr())); - amount.parse(instr, flags); - } else { - PyErr_SetString(PyExc_IOError, - _("Argument to amount.parse(file) is not a file object")); + boost::optional<amount_t> py_value_0(const amount_t& amount) { + return amount.value(); + } + boost::optional<amount_t> py_value_1(const amount_t& amount, + const bool primary_only) { + return amount.value(primary_only); } -} -void py_parse_1(amount_t& amount, object in) { - py_parse_2(amount, in, 0); -} -void py_parse_str_1(amount_t& amount, const string& str) { - amount.parse(str); -} -void py_parse_str_2(amount_t& amount, const string& str, unsigned char flags) { - amount.parse(str, flags); -} + boost::optional<amount_t> + py_value_2(const amount_t& amount, + const bool primary_only, + const boost::optional<datetime_t>& moment) { + return amount.value(primary_only, moment); + } -void py_print(amount_t& amount, object out) -{ - if (PyFile_Check(out.ptr())) { - pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr())); - amount.print(outstr); - } else { - PyErr_SetString(PyExc_IOError, - _("Argument to amount.print_(file) is not a file object")); + boost::optional<amount_t> + py_value_3(const amount_t& amount, + const bool primary_only, + const boost::optional<datetime_t>& moment, + const boost::optional<commodity_t&>& in_terms_of) { + return amount.value(primary_only, moment, in_terms_of); } -} -void py_amount_initialize() { - amount_t::initialize(); -} + void py_parse_2(amount_t& amount, object in, unsigned char flags) { + if (PyFile_Check(in.ptr())) { + pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr())); + amount.parse(instr, flags); + } else { + PyErr_SetString(PyExc_IOError, + _("Argument to amount.parse(file) is not a file object")); + } + } + void py_parse_1(amount_t& amount, object in) { + py_parse_2(amount, in, 0); + } + + void py_parse_str_1(amount_t& amount, const string& str) { + amount.parse(str); + } + void py_parse_str_2(amount_t& amount, const string& str, unsigned char flags) { + amount.parse(str, flags); + } + + void py_print(amount_t& amount, object out) { + if (PyFile_Check(out.ptr())) { + pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr())); + amount.print(outstr); + } else { + PyErr_SetString(PyExc_IOError, + _("Argument to amount.print_(file) is not a file object")); + } + } + + void py_amount_initialize() { + amount_t::initialize(); + } + +} // unnamed namespace #define EXC_TRANSLATOR(type) \ void exc_translate_ ## type(const type& err) { \ @@ -106,15 +113,18 @@ EXC_TRANSLATOR(amount_error) void export_amount() { class_< amount_t > ("Amount") + .add_static_property("current_pool", + make_getter(&amount_t::current_pool, + return_value_policy<reference_existing_object>())) + .def("initialize", py_amount_initialize) // only for the PyUnitTests .staticmethod("initialize") .def("shutdown", &amount_t::shutdown) .staticmethod("shutdown") - .add_static_property("current_pool", - make_getter(&amount_t::current_pool, - return_value_policy<reference_existing_object>())) - + .add_static_property("is_initialized", + make_getter(&amount_t::is_initialized), + make_setter(&amount_t::is_initialized)) .add_static_property("stream_fullstrings", make_getter(&amount_t::stream_fullstrings), make_setter(&amount_t::stream_fullstrings)) @@ -129,7 +139,8 @@ internal precision.")) .def(init<amount_t>()) - .def("compare", &amount_t::compare) + .def("compare", &amount_t::compare, args("amount"), + _("Compare two amounts for equality, returning <0, 0 or >0.")) .def(self == self) .def(self == long()) @@ -186,6 +197,10 @@ internal precision.")) .def(long() / self) .def("precision", &amount_t::precision) + .def("keep_precision", &amount_t::keep_precision) + .def("set_keep_precision", &amount_t::set_keep_precision, args("keep"), + _("Set whether an amount should always display at full precision.")) + .def("display_precision", &amount_t::display_precision) .def("negated", &amount_t::negated) .def("in_place_negate", &amount_t::in_place_negate, @@ -195,8 +210,19 @@ internal precision.")) .def("abs", &amount_t::abs) .def("__abs__", &amount_t::abs) + .def("inverted", &amount_t::inverted) + .def("rounded", &amount_t::rounded) + .def("in_place_round", &amount_t::in_place_round, + return_value_policy<reference_existing_object>()) + + .def("truncated", &amount_t::truncated) + .def("in_place_truncate", &amount_t::in_place_truncate, + return_value_policy<reference_existing_object>()) + .def("unrounded", &amount_t::unrounded) + .def("in_place_unround", &amount_t::in_place_unround, + return_value_policy<reference_existing_object>()) .def("reduced", &amount_t::reduced) .def("in_place_reduce", &amount_t::in_place_reduce, @@ -207,9 +233,11 @@ internal precision.")) return_value_policy<reference_existing_object>()) .def("value", py_value_0) - .def("value", py_value_1) - .def("value", py_value_2) - .def("value", py_value_3) + .def("value", py_value_1, args("primary_only")) + .def("value", py_value_2, args("primary_only", "moment")) + .def("value", py_value_3, args("primary_only", "moment", "in_terms_of")) + + .def("price", &amount_t::price) .def("sign", &amount_t::sign) .def("__nonzero__", &amount_t::is_nonzero) @@ -222,22 +250,21 @@ internal precision.")) .def("__float__", &amount_t::to_double) .def("to_long", &amount_t::to_long) .def("__int__", &amount_t::to_long) + .def("fits_in_long", &amount_t::fits_in_long) + .def("to_string", &amount_t::to_string) .def("__str__", &amount_t::to_string) .def("to_fullstring", &amount_t::to_fullstring) .def("__repr__", &amount_t::to_fullstring) - - .def("fits_in_long", &amount_t::fits_in_long) - .def("quantity_string", &amount_t::quantity_string) .def("commodity", &amount_t::commodity, return_value_policy<reference_existing_object>()) + .def("has_commodity", &amount_t::has_commodity) .def("set_commodity", &amount_t::set_commodity, with_custodian_and_ward<1, 2>()) - - .def("has_commodity", &amount_t::has_commodity) .def("clear_commodity", &amount_t::clear_commodity) + .def("number", &amount_t::number) .def("annotate", &amount_t::annotate) @@ -256,7 +283,6 @@ internal precision.")) .staticmethod("parse_conversion") .def("print_", py_print) - .def("dump", &amount_t::dump) .def("valid", &amount_t::valid) diff --git a/src/py_balance.cc b/src/py_balance.cc index 086b7b12..2d940876 100644 --- a/src/py_balance.cc +++ b/src/py_balance.cc @@ -32,69 +32,90 @@ #include <system.hh> #include "pyinterp.h" +#include "pyutils.h" +#include "pyfstream.h" +#include "commodity.h" +#include "annotate.h" +#include "balance.h" namespace ledger { using namespace boost::python; -#define EXC_TRANSLATOR(type) \ - void exc_translate_ ## type(const type& err) { \ - PyErr_SetString(PyExc_ArithmeticError, err.what()); \ +namespace { + + boost::optional<balance_t> py_value_0(const balance_t& balance) { + return balance.value(); + } + boost::optional<balance_t> py_value_1(const balance_t& balance, + const bool primary_only) { + return balance.value(primary_only); } -EXC_TRANSLATOR(balance_error) + boost::optional<balance_t> + py_value_2(const balance_t& balance, + const bool primary_only, + const boost::optional<datetime_t>& moment) { + return balance.value(primary_only, moment); + } -void export_balance() -{ -#if 0 - class_< balance_t > ("Balance") - ; -#endif + boost::optional<balance_t> + py_value_3(const balance_t& balance, + const bool primary_only, + const boost::optional<datetime_t>& moment, + const boost::optional<commodity_t&>& in_terms_of) { + return balance.value(primary_only, moment, in_terms_of); + } - //register_optional_to_python<amount_t>(); + boost::optional<amount_t> + py_commodity_amount_0(const balance_t& balance) { + return balance.commodity_amount(); + } - //implicitly_convertible<string, amount_t>(); + boost::optional<amount_t> + py_commodity_amount_1(const balance_t& balance, + const boost::optional<const commodity_t&>& commodity) { + return balance.commodity_amount(commodity); + } -#define EXC_TRANSLATE(type) \ - register_exception_translator<type>(&exc_translate_ ## type); + void py_print(balance_t& balance, object out) { + if (PyFile_Check(out.ptr())) { + pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr())); + balance.print(outstr); + } else { + PyErr_SetString(PyExc_IOError, + _("Argument to balance.print_(file) is not a file object")); + } + } - //EXC_TRANSLATE(balance_error); -} + long balance_len(balance_t& bal) { + return bal.amounts.size(); + } -} // namespace ledger + amount_t balance_getitem(balance_t& bal, long i) { + long len = bal.amounts.size(); -#if 0 -unsigned int balance_len(balance_t& bal) -{ - return bal.amounts.size(); -} + if (labs(i) >= len) { + PyErr_SetString(PyExc_IndexError, _("Index out of range")); + throw_error_already_set(); + } -amount_t balance_getitem(balance_t& bal, int i) -{ - std::size_t len = bal.amounts.size(); + long x = i < 0 ? len + i : i; + balance_t::amounts_map::iterator elem = bal.amounts.begin(); + while (--x >= 0) + elem++; - if (abs(i) >= len) { - PyErr_SetString(PyExc_IndexError, _("Index out of range")); - throw_error_already_set(); + return (*elem).second; } - int x = i < 0 ? len + i : i; - balance_t::amounts_map::iterator elem = bal.amounts.begin(); - while (--x >= 0) - elem++; +} // unnamed namespace - return (*elem).second; -} - -unsigned int balance_pair_len(balance_pair_t& bal_pair) -{ - return balance_len(bal_pair.quantity); -} +#define EXC_TRANSLATOR(type) \ + void exc_translate_ ## type(const type& err) { \ + PyErr_SetString(PyExc_ArithmeticError, err.what()); \ + } -amount_t balance_pair_getitem(balance_pair_t& bal_pair, int i) -{ - return balance_getitem(bal_pair.quantity, i); -} +EXC_TRANSLATOR(balance_error) void export_balance() { @@ -102,8 +123,7 @@ void export_balance() .def(init<balance_t>()) .def(init<amount_t>()) .def(init<long>()) - .def(init<unsigned long>()) - .def(init<double>()) + .def(init<string>()) .def(self += self) .def(self += other<amount_t>()) @@ -117,32 +137,16 @@ void export_balance() .def(self - self) .def(self - other<amount_t>()) .def(self - long()) - .def(self *= self) .def(self *= other<amount_t>()) .def(self *= long()) - .def(self * self) .def(self * other<amount_t>()) .def(self * long()) - .def(self /= self) .def(self /= other<amount_t>()) .def(self /= long()) - .def(self / self) .def(self / other<amount_t>()) .def(self / long()) .def(- self) - .def(self < self) - .def(self < other<amount_t>()) - .def(self < long()) - .def(self <= self) - .def(self <= other<amount_t>()) - .def(self <= long()) - .def(self > self) - .def(self > other<amount_t>()) - .def(self > long()) - .def(self >= self) - .def(self >= other<amount_t>()) - .def(self >= long()) .def(self == self) .def(self == other<amount_t>()) .def(self == long()) @@ -153,114 +157,70 @@ void export_balance() .def(self_ns::str(self)) + .def("negated", &balance_t::negated) + .def("in_place_negate", &balance_t::in_place_negate, + return_value_policy<reference_existing_object>()) + .def(- self) + + .def("abs", &balance_t::abs) .def("__abs__", &balance_t::abs) + .def("__len__", balance_len) .def("__getitem__", balance_getitem) - .def("valid", &balance_t::valid) + .def("rounded", &balance_t::rounded) + .def("in_place_round", &balance_t::in_place_round, + return_value_policy<reference_existing_object>()) - .def("realzero", &balance_t::realzero) - .def("amount", &balance_t::amount) - .def("value", &balance_t::value) - .def("price", &balance_t::price) - .def("date", &balance_t::date) - .def("strip_annotations", &balance_t::strip_annotations) - .def("write", &balance_t::write) - .def("round", &balance_t::round) - .def("negate", &balance_t::negate) - .def("negated", &balance_t::negated) - ; + .def("truncated", &balance_t::truncated) + .def("in_place_truncate", &balance_t::in_place_truncate, + return_value_policy<reference_existing_object>()) - class_< balance_pair_t > ("BalancePair") - .def(init<balance_pair_t>()) - .def(init<balance_t>()) - .def(init<amount_t>()) - .def(init<long>()) - .def(init<unsigned long>()) - .def(init<double>()) + .def("unrounded", &balance_t::unrounded) + .def("in_place_unround", &balance_t::in_place_unround, + return_value_policy<reference_existing_object>()) - .def(self += self) - .def(self += other<balance_t>()) - .def(self += other<amount_t>()) - .def(self += long()) - .def(self + self) - .def(self + other<balance_t>()) - .def(self + other<amount_t>()) - .def(self + long()) - .def(self -= self) - .def(self -= other<balance_t>()) - .def(self -= other<amount_t>()) - .def(self -= long()) - .def(self - self) - .def(self - other<balance_t>()) - .def(self - other<amount_t>()) - .def(self - long()) - .def(self *= self) - .def(self *= other<balance_t>()) - .def(self *= other<amount_t>()) - .def(self *= long()) - .def(self * self) - .def(self * other<balance_t>()) - .def(self * other<amount_t>()) - .def(self * long()) - .def(self /= self) - .def(self /= other<balance_t>()) - .def(self /= other<amount_t>()) - .def(self /= long()) - .def(self / self) - .def(self / other<balance_t>()) - .def(self / other<amount_t>()) - .def(self / long()) - .def(- self) + .def("reduced", &balance_t::reduced) + .def("in_place_reduce", &balance_t::in_place_reduce, + return_value_policy<reference_existing_object>()) - .def(self < self) - .def(self < other<balance_t>()) - .def(self < other<amount_t>()) - .def(self < long()) - .def(self <= self) - .def(self <= other<balance_t>()) - .def(self <= other<amount_t>()) - .def(self <= long()) - .def(self > self) - .def(self > other<balance_t>()) - .def(self > other<amount_t>()) - .def(self > long()) - .def(self >= self) - .def(self >= other<balance_t>()) - .def(self >= other<amount_t>()) - .def(self >= long()) - .def(self == self) - .def(self == other<balance_t>()) - .def(self == other<amount_t>()) - .def(self == long()) - .def(self != self) - .def(self != other<balance_t>()) - .def(self != other<amount_t>()) - .def(self != long()) - .def(! self) + .def("unreduced", &balance_t::unreduced) + .def("in_place_unreduce", &balance_t::in_place_unreduce, + return_value_policy<reference_existing_object>()) - .def(self_ns::str(self)) + .def("value", py_value_0) + .def("value", py_value_1, args("primary_only")) + .def("value", py_value_2, args("primary_only", "moment")) + .def("value", py_value_3, args("primary_only", "moment", "in_terms_of")) + + .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) + .def("is_realzero", &balance_t::is_realzero) + + .def("is_empty", &balance_t::is_empty) + .def("single_amount", &balance_t::single_amount) + + .def("to_amount", &balance_t::to_amount) - .def("__abs__", &balance_pair_t::abs) - .def("__len__", balance_pair_len) - .def("__getitem__", balance_pair_getitem) - - .def("valid", &balance_pair_t::valid) - - .def("realzero", &balance_pair_t::realzero) - .def("amount", &balance_pair_t::amount) - .def("value", &balance_pair_t::value) - .def("price", &balance_pair_t::price) - .def("date", &balance_pair_t::date) - .def("strip_annotations", &balance_pair_t::strip_annotations) - .def("write", &balance_pair_t::write) - .def("round", &balance_pair_t::round) - .def("negate", &balance_pair_t::negate) - .def("negated", &balance_pair_t::negated) - - .add_property("cost", - make_getter(&balance_pair_t::cost, - return_value_policy<reference_existing_object>())) + .def("commodity_count", &balance_t::commodity_count) + .def("commodity_amount", py_commodity_amount_0) + .def("commodity_amount", py_commodity_amount_1) + + .def("strip_annotations", &balance_t::strip_annotations) + + .def("print_", py_print) + .def("dump", &balance_t::dump) + + .def("valid", &balance_t::valid) ; + +#define EXC_TRANSLATE(type) \ + register_exception_translator<type>(&exc_translate_ ## type); + + EXC_TRANSLATE(balance_error); } -#endif + +} // namespace ledger diff --git a/src/pyinterp.cc b/src/pyinterp.cc index f5b1a543..9ad9a906 100644 --- a/src/pyinterp.cc +++ b/src/pyinterp.cc @@ -83,7 +83,7 @@ void initialize_for_python() export_value(); export_xact(); - scope().attr("session") = python_session; + scope().attr("current_session") = python_session; } struct python_run diff --git a/src/report.cc b/src/report.cc index 9f15a2d5..60f6955c 100644 --- a/src/report.cc +++ b/src/report.cc @@ -664,6 +664,8 @@ option_t<report_t> * report_t::lookup_option(const char * p) case 's': OPT(set_account_); else OPT(set_payee_); + else OPT(set_reported_account_); + else OPT(set_reported_payee_); else OPT(sort_); else OPT(sort_all_); else OPT(sort_xacts_); diff --git a/src/report.h b/src/report.h index 0fe7d05b..e00c6460 100644 --- a/src/report.h +++ b/src/report.h @@ -284,6 +284,8 @@ public: HANDLER(seed_).report(out); HANDLER(set_account_).report(out); HANDLER(set_payee_).report(out); + HANDLER(set_reported_account_).report(out); + HANDLER(set_reported_payee_).report(out); HANDLER(sort_).report(out); HANDLER(sort_all_).report(out); HANDLER(sort_xacts_).report(out); @@ -652,7 +654,7 @@ public: if (have_less) { on(none, "less"); - setenv("LESS", "--quit-if-one-screen -R", 0); + setenv("LESS", "-FRSX", 0); // don't overwrite } } } @@ -805,6 +807,8 @@ public: OPTION(report_t, seed_); OPTION(report_t, set_account_); OPTION(report_t, set_payee_); + OPTION(report_t, set_reported_account_); + OPTION(report_t, set_reported_payee_); OPTION_(report_t, sort_, DO_(args) { // -S on_with(args[0].as_string(), args[1]); diff --git a/src/session.cc b/src/session.cc index 3f29716d..33c27165 100644 --- a/src/session.cc +++ b/src/session.cc @@ -264,6 +264,9 @@ option_t<session_t> * session_t::lookup_option(const char * p) case 'd': OPT(download); // -Q break; + case 'e': + OPT(european); + break; case 'f': OPT_(file_); // -f break; diff --git a/src/session.h b/src/session.h index c1e0243b..58e33f6b 100644 --- a/src/session.h +++ b/src/session.h @@ -50,6 +50,7 @@ #include "account.h" #include "journal.h" #include "option.h" +#include "commodity.h" namespace ledger { @@ -105,6 +106,7 @@ public: HANDLER(account_).report(out); HANDLER(cache_).report(out); HANDLER(download).report(out); + HANDLER(european).report(out); HANDLER(file_).report(out); HANDLER(input_date_format_).report(out); HANDLER(price_db_).report(out); @@ -124,6 +126,10 @@ public: OPTION(session_t, cache_); OPTION(session_t, download); // -Q + OPTION_(session_t, european, DO() { + commodity_t::european_by_default = true; + }); + OPTION__ (session_t, price_exp_, // -Z CTOR(session_t, price_exp_) { value = 24L * 3600L; } diff --git a/src/temps.cc b/src/temps.cc index f2dee159..012a573b 100644 --- a/src/temps.cc +++ b/src/temps.cc @@ -49,6 +49,13 @@ temporaries_t::~temporaries_t() post.account->remove_post(&post); } } + + if (acct_temps) { + foreach (account_t& acct, *acct_temps) { + if (acct.parent && ! acct.parent->has_flags(ACCOUNT_TEMP)) + acct.parent->remove_account(&acct); + } + } } xact_t& temporaries_t::copy_xact(xact_t& origin) @@ -120,6 +127,9 @@ account_t& temporaries_t::create_account(const string& name, acct_temps->push_back(account_t(parent, name)); account_t& temp(acct_temps->back()); + if (parent) + parent->add_account(&temp); + temp.add_flags(ACCOUNT_TEMP); return temp; } diff --git a/src/temps.h b/src/temps.h index 646f4dcd..34494ba8 100644 --- a/src/temps.h +++ b/src/temps.h @@ -68,7 +68,7 @@ public: post_t& last_post() { return post_temps->back(); } - account_t& create_account(const string& name, + account_t& create_account(const string& name = "", account_t * parent = NULL); account_t& last_account() { return acct_temps->back(); diff --git a/src/times.cc b/src/times.cc index 667f65a3..b737b2a0 100644 --- a/src/times.cc +++ b/src/times.cc @@ -55,12 +55,13 @@ namespace { #endif // USE_BOOST_FACETS public: - bool has_year; - bool input; + bool has_year; + bool has_day; + bool input; temporal_io_t(const char * _fmt_str, bool _input) : fmt_str(_fmt_str), has_year(icontains(fmt_str, "%y")), - input(_input) { + has_day(icontains(fmt_str, "%d")), input(_input) { #if defined(USE_BOOST_FACETS) if (input) { input_facet = new InputFacetType(fmt_str); @@ -75,6 +76,7 @@ namespace { void set_format(const char * fmt) { fmt_str = fmt; has_year = icontains(fmt_str, "%y"); + has_day = icontains(fmt_str, "%d"); #if defined(USE_BOOST_FACETS) if (input) @@ -190,7 +192,7 @@ namespace { date_t parse_date_mask_routine(const char * date_str, date_io_t& io, optional<date_t::year_type> year, - bool& saw_year) + bool& saw_year, bool& saw_day) { date_t when; @@ -220,26 +222,30 @@ namespace { if (when.month() > CURRENT_DATE().month()) when -= gregorian::years(1); - } else { + } + else { saw_year = true; } + + saw_day = io.has_day; } return when; } date_t parse_date_mask(const char * date_str, - optional<date_t::year_type> year, bool& saw_year) + optional<date_t::year_type> year, + bool& saw_year, bool& saw_day) { if (input_date_io.get()) { date_t when = parse_date_mask_routine(date_str, *input_date_io.get(), - year, saw_year); + year, saw_year, saw_day); 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, saw_year); + year, saw_year, saw_day); if (! when.is_not_a_date()) return when; } @@ -311,7 +317,8 @@ datetime_t parse_datetime(const char * str, optional<date_t::year_type>) date_t parse_date(const char * str, optional<date_t::year_type> current_year) { bool saw_year; - return parse_date_mask(str, current_year, saw_year); + bool saw_day; + return parse_date_mask(str, current_year, saw_year, saw_day); } std::ostream& operator<<(std::ostream& out, @@ -549,7 +556,8 @@ namespace { date_t * end) { bool saw_year = true; - date_t when = parse_date_mask(word.c_str(), none, saw_year); + bool saw_day = true; + date_t when = parse_date_mask(word.c_str(), none, saw_year, saw_day); if (when.is_not_a_date()) throw_(date_error, _("Could not parse date mask: %1") << word); @@ -558,8 +566,8 @@ namespace { *begin = when; if (end) { - if (saw_year) - *end = *begin + gregorian::years(1); + if (saw_day) + *end = *begin + gregorian::days(1); else *end = *begin + gregorian::months(1); } @@ -728,17 +736,17 @@ void date_interval_t::parse(std::istream& in) if (wday) { while (start->day_of_week() != *wday) - *start = duration_t(duration_t::DAYS, 1).subtract(*start); + *start -= gregorian::days(1); if (! end) - end = duration_t(duration_t::DAYS, 1).add(*start); + end = *start + gregorian::days(1); } else { bool overwrite_end = false; if (year) { start = date_t(*year, 1, 1); if (! end) { - end = duration_t(duration_t::YEARS, 1).add(*start); + end = *start + gregorian::years(1); overwrite_end = true; } } @@ -746,7 +754,7 @@ void date_interval_t::parse(std::istream& in) if (mon) { start = date_t(start->year(), *mon, 1); if (! end || overwrite_end) - end = duration_t(duration_t::MONTHS, 1).add(*start); + end = *start + gregorian::months(1); } } } diff --git a/src/xact.cc b/src/xact.cc index 3670cb94..3291c5be 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -39,8 +39,8 @@ namespace ledger { -xact_base_t::xact_base_t(const xact_base_t&) - : item_t(), journal(NULL) +xact_base_t::xact_base_t(const xact_base_t& xact_base) + : item_t(xact_base), journal(xact_base.journal) { TRACE_CTOR(xact_base_t, "copy"); } @@ -65,7 +65,6 @@ class xact_base_t : public item_t { public: journal_t * journal; - posts_list posts; xact_base_t() : item_t(), journal(NULL) { diff --git a/test/ConfirmTests.py b/test/ConfirmTests.py index 0b3d4897..901ae7cd 100755 --- a/test/ConfirmTests.py +++ b/test/ConfirmTests.py @@ -10,7 +10,7 @@ import re from LedgerHarness import LedgerHarness harness = LedgerHarness(sys.argv) -tests = sys.argv[2] +tests = sys.argv[3] if not os.path.isdir(tests) and not os.path.isfile(tests): sys.exit(1) diff --git a/test/GenerateTests.py b/test/GenerateTests.py index aa36737d..d60e0581 100755 --- a/test/GenerateTests.py +++ b/test/GenerateTests.py @@ -104,9 +104,9 @@ def generation_test(seed): beg_range = 1 end_range = 20 -if len(sys.argv) > 3: - beg_range = int(sys.argv[2]) - end_range = int(sys.argv[3]) +if len(sys.argv) > 4: + beg_range = int(sys.argv[3]) + end_range = int(sys.argv[4]) for i in range(beg_range, end_range): if generation_test(i): diff --git a/test/LedgerHarness.py b/test/LedgerHarness.py index cf65f590..8a5af123 100755 --- a/test/LedgerHarness.py +++ b/test/LedgerHarness.py @@ -7,22 +7,27 @@ import re from subprocess import Popen, PIPE class LedgerHarness: - ledger = None - succeeded = 0 - failed = 0 - verify = False - gmalloc = False + ledger = None + sourcepath = None + succeeded = 0 + failed = 0 + verify = False + gmalloc = False def __init__(self, argv): if not os.path.isfile(argv[1]): print "Cannot find ledger at '%s'" % argv[1] sys.exit(1) + if not os.path.isdir(argv[2]): + print "Cannot find source path at '%s'" % argv[2] + sys.exit(1) - self.ledger = argv[1] - self.succeeded = 0 - self.failed = 0 - self.verify = '--verify' in argv - self.gmalloc = '--gmalloc' in argv + self.ledger = argv[1] + self.sourcepath = argv[2] + self.succeeded = 0 + self.failed = 0 + self.verify = '--verify' in argv + self.gmalloc = '--gmalloc' in argv def run(self, command, verify=None, gmalloc=None, columns=True): env = os.environ.copy() @@ -48,10 +53,8 @@ class LedgerHarness: if columns: insert += ' --columns=80' - command = re.sub('\$ledger', '%s%s %s %s %s %s' % \ - (self.ledger, insert, '--args-only', - '--no-color', '--pager=none', - '--date-format=%y-%b-%d'), command) + command = re.sub('\$ledger', '%s%s %s' % \ + (self.ledger, insert, '--args-only'), command) return Popen(command, shell=True, close_fds=True, env=env, stdin=PIPE, stdout=PIPE, stderr=PIPE) diff --git a/test/RegressTests.py b/test/RegressTests.py index 4d23f6b5..13a0a113 100755 --- a/test/RegressTests.py +++ b/test/RegressTests.py @@ -11,7 +11,7 @@ from difflib import unified_diff from LedgerHarness import LedgerHarness harness = LedgerHarness(sys.argv) -tests = sys.argv[2] +tests = sys.argv[3] if not os.path.isdir(tests) and not os.path.isfile(tests): sys.exit(1) @@ -27,11 +27,15 @@ class RegressFile: line == ">>>2\n" or \ line.startswith("===") + def transform_line(self, line): + line = re.sub('\$sourcepath', harness.sourcepath, line) + return line + def read_section(self): lines = [] line = self.fd.readline() while not self.is_directive(line): - lines.append(line) + lines.append(self.transform_line(line)) line = self.fd.readline() return (lines, line) @@ -60,7 +64,7 @@ class RegressFile: test['exitcode'] = int(match.group(1)) return test else: - test['command'] = line + test['command'] = self.transform_line(line) line = self.fd.readline() return None diff --git a/test/baseline/opt-add-budget.test b/test/baseline/opt-add-budget.test index 20dfd320..535335d3 100644 --- a/test/baseline/opt-add-budget.test +++ b/test/baseline/opt-add-budget.test @@ -244,124 +244,124 @@ reg --add-budget books cards Liabilities:Cards $120.00 Assets:Cash >>>1 -08-Jan-01 January Expenses:Books $10.00 $10.00 - Liabilities:Cards $10.00 $20.00 -08-Jan-01 Budget transaction Expenses:Books $-10.00 $10.00 +08-Jan-01 Budget transaction Expenses:Books $-10.00 $-10.00 +08-Jan-01 January Expenses:Books $10.00 0 + Liabilities:Cards $10.00 $10.00 08-Jan-31 End of January Expenses:Books $10.00 $20.00 Liabilities:Cards $10.00 $30.00 -08-Feb-01 February Expenses:Books $20.00 $50.00 - Liabilities:Cards $20.00 $70.00 -08-Feb-01 Budget transaction Expenses:Books $-10.00 $60.00 +08-Feb-01 Budget transaction Expenses:Books $-10.00 $20.00 +08-Feb-01 February Expenses:Books $20.00 $40.00 + Liabilities:Cards $20.00 $60.00 08-Feb-28 End of February Expenses:Books $20.00 $80.00 Liabilities:Cards $20.00 $100.00 -08-Mar-01 March Expenses:Books $30.00 $130.00 - Liabilities:Cards $30.00 $160.00 -08-Mar-01 Budget transaction Expenses:Books $-10.00 $150.00 +08-Mar-01 Budget transaction Expenses:Books $-10.00 $90.00 +08-Mar-01 March Expenses:Books $30.00 $120.00 + Liabilities:Cards $30.00 $150.00 08-Mar-31 End of March Expenses:Books $30.00 $180.00 Liabilities:Cards $30.00 $210.00 -08-Apr-01 April Expenses:Books $40.00 $250.00 - Liabilities:Cards $40.00 $290.00 -08-Apr-01 Budget transaction Expenses:Books $-10.00 $280.00 +08-Apr-01 Budget transaction Expenses:Books $-10.00 $200.00 +08-Apr-01 April Expenses:Books $40.00 $240.00 + Liabilities:Cards $40.00 $280.00 08-Apr-30 End of April Expenses:Books $40.00 $320.00 Liabilities:Cards $40.00 $360.00 -08-May-01 May Expenses:Books $50.00 $410.00 - Liabilities:Cards $50.00 $460.00 -08-May-01 Budget transaction Expenses:Books $-10.00 $450.00 +08-May-01 Budget transaction Expenses:Books $-10.00 $350.00 +08-May-01 May Expenses:Books $50.00 $400.00 + Liabilities:Cards $50.00 $450.00 08-May-31 End of May Expenses:Books $50.00 $500.00 Liabilities:Cards $50.00 $550.00 -08-Jun-01 June Expenses:Books $60.00 $610.00 - Liabilities:Cards $60.00 $670.00 -08-Jun-01 Budget transaction Expenses:Books $-10.00 $660.00 +08-Jun-01 Budget transaction Expenses:Books $-10.00 $540.00 +08-Jun-01 June Expenses:Books $60.00 $600.00 + Liabilities:Cards $60.00 $660.00 08-Jun-30 End of June Expenses:Books $60.00 $720.00 Liabilities:Cards $60.00 $780.00 -08-Jul-01 July Expenses:Books $70.00 $850.00 - Liabilities:Cards $70.00 $920.00 -08-Jul-01 Budget transaction Expenses:Books $-10.00 $910.00 +08-Jul-01 Budget transaction Expenses:Books $-10.00 $770.00 +08-Jul-01 July Expenses:Books $70.00 $840.00 + Liabilities:Cards $70.00 $910.00 08-Jul-31 End of July Expenses:Books $70.00 $980.00 Liabilities:Cards $70.00 $1050.00 -08-Aug-01 August Expenses:Books $80.00 $1130.00 - Liabilities:Cards $80.00 $1210.00 -08-Aug-01 Budget transaction Expenses:Books $-10.00 $1200.00 +08-Aug-01 Budget transaction Expenses:Books $-10.00 $1040.00 +08-Aug-01 August Expenses:Books $80.00 $1120.00 + Liabilities:Cards $80.00 $1200.00 08-Aug-31 End of August Expenses:Books $80.00 $1280.00 Liabilities:Cards $80.00 $1360.00 -08-Sep-01 September Expenses:Books $90.00 $1450.00 - Liabilities:Cards $90.00 $1540.00 -08-Sep-01 Budget transaction Expenses:Books $-10.00 $1530.00 +08-Sep-01 Budget transaction Expenses:Books $-10.00 $1350.00 +08-Sep-01 September Expenses:Books $90.00 $1440.00 + Liabilities:Cards $90.00 $1530.00 08-Sep-30 End of September Expenses:Books $90.00 $1620.00 Liabilities:Cards $90.00 $1710.00 -08-Oct-01 October Expenses:Books $100.00 $1810.00 - Liabilities:Cards $100.00 $1910.00 -08-Oct-01 Budget transaction Expenses:Books $-10.00 $1900.00 +08-Oct-01 Budget transaction Expenses:Books $-10.00 $1700.00 +08-Oct-01 October Expenses:Books $100.00 $1800.00 + Liabilities:Cards $100.00 $1900.00 08-Oct-31 End of October Expenses:Books $100.00 $2000.00 Liabilities:Cards $100.00 $2100.00 -08-Nov-01 November Expenses:Books $110.00 $2210.00 - Liabilities:Cards $110.00 $2320.00 -08-Nov-01 Budget transaction Expenses:Books $-10.00 $2310.00 +08-Nov-01 Budget transaction Expenses:Books $-10.00 $2090.00 +08-Nov-01 November Expenses:Books $110.00 $2200.00 + Liabilities:Cards $110.00 $2310.00 08-Nov-30 End of November Expenses:Books $110.00 $2420.00 Liabilities:Cards $110.00 $2530.00 -08-Dec-01 December Expenses:Books $120.00 $2650.00 - Liabilities:Cards $120.00 $2770.00 -08-Dec-01 Budget transaction Expenses:Books $-10.00 $2760.00 +08-Dec-01 Budget transaction Expenses:Books $-10.00 $2520.00 +08-Dec-01 December Expenses:Books $120.00 $2640.00 + Liabilities:Cards $120.00 $2760.00 08-Dec-31 End of December Expenses:Books $120.00 $2880.00 Liabilities:Cards $120.00 $3000.00 -09-Jan-01 January Expenses:Books $10.00 $3010.00 - Liabilities:Cards $10.00 $3020.00 -09-Jan-01 Budget transaction Expenses:Books $-10.00 $3010.00 +09-Jan-01 Budget transaction Expenses:Books $-10.00 $2990.00 +09-Jan-01 January Expenses:Books $10.00 $3000.00 + Liabilities:Cards $10.00 $3010.00 09-Jan-31 End of January Expenses:Books $10.00 $3020.00 Liabilities:Cards $10.00 $3030.00 -09-Feb-01 February Expenses:Books $20.00 $3050.00 - Liabilities:Cards $20.00 $3070.00 -09-Feb-01 Budget transaction Expenses:Books $-10.00 $3060.00 +09-Feb-01 Budget transaction Expenses:Books $-10.00 $3020.00 +09-Feb-01 February Expenses:Books $20.00 $3040.00 + Liabilities:Cards $20.00 $3060.00 09-Feb-28 End of February Expenses:Books $20.00 $3080.00 Liabilities:Cards $20.00 $3100.00 -09-Mar-01 March Expenses:Books $30.00 $3130.00 - Liabilities:Cards $30.00 $3160.00 -09-Mar-01 Budget transaction Expenses:Books $-10.00 $3150.00 +09-Mar-01 Budget transaction Expenses:Books $-10.00 $3090.00 +09-Mar-01 March Expenses:Books $30.00 $3120.00 + Liabilities:Cards $30.00 $3150.00 09-Mar-31 End of March Expenses:Books $30.00 $3180.00 Liabilities:Cards $30.00 $3210.00 -09-Apr-01 April Expenses:Books $40.00 $3250.00 - Liabilities:Cards $40.00 $3290.00 -09-Apr-01 Budget transaction Expenses:Books $-10.00 $3280.00 +09-Apr-01 Budget transaction Expenses:Books $-10.00 $3200.00 +09-Apr-01 April Expenses:Books $40.00 $3240.00 + Liabilities:Cards $40.00 $3280.00 09-Apr-30 End of April Expenses:Books $40.00 $3320.00 Liabilities:Cards $40.00 $3360.00 -09-May-01 May Expenses:Books $50.00 $3410.00 - Liabilities:Cards $50.00 $3460.00 -09-May-01 Budget transaction Expenses:Books $-10.00 $3450.00 +09-May-01 Budget transaction Expenses:Books $-10.00 $3350.00 +09-May-01 May Expenses:Books $50.00 $3400.00 + Liabilities:Cards $50.00 $3450.00 09-May-31 End of May Expenses:Books $50.00 $3500.00 Liabilities:Cards $50.00 $3550.00 -09-Jun-01 June Expenses:Books $60.00 $3610.00 - Liabilities:Cards $60.00 $3670.00 -09-Jun-01 Budget transaction Expenses:Books $-10.00 $3660.00 +09-Jun-01 Budget transaction Expenses:Books $-10.00 $3540.00 +09-Jun-01 June Expenses:Books $60.00 $3600.00 + Liabilities:Cards $60.00 $3660.00 09-Jun-30 End of June Expenses:Books $60.00 $3720.00 Liabilities:Cards $60.00 $3780.00 -09-Jul-01 July Expenses:Books $70.00 $3850.00 - Liabilities:Cards $70.00 $3920.00 -09-Jul-01 Budget transaction Expenses:Books $-10.00 $3910.00 +09-Jul-01 Budget transaction Expenses:Books $-10.00 $3770.00 +09-Jul-01 July Expenses:Books $70.00 $3840.00 + Liabilities:Cards $70.00 $3910.00 09-Jul-31 End of July Expenses:Books $70.00 $3980.00 Liabilities:Cards $70.00 $4050.00 -09-Aug-01 August Expenses:Books $80.00 $4130.00 - Liabilities:Cards $80.00 $4210.00 -09-Aug-01 Budget transaction Expenses:Books $-10.00 $4200.00 +09-Aug-01 Budget transaction Expenses:Books $-10.00 $4040.00 +09-Aug-01 August Expenses:Books $80.00 $4120.00 + Liabilities:Cards $80.00 $4200.00 09-Aug-31 End of August Expenses:Books $80.00 $4280.00 Liabilities:Cards $80.00 $4360.00 -09-Sep-01 September Expenses:Books $90.00 $4450.00 - Liabilities:Cards $90.00 $4540.00 -09-Sep-01 Budget transaction Expenses:Books $-10.00 $4530.00 +09-Sep-01 Budget transaction Expenses:Books $-10.00 $4350.00 +09-Sep-01 September Expenses:Books $90.00 $4440.00 + Liabilities:Cards $90.00 $4530.00 09-Sep-30 End of September Expenses:Books $90.00 $4620.00 Liabilities:Cards $90.00 $4710.00 -09-Oct-01 October Expenses:Books $100.00 $4810.00 - Liabilities:Cards $100.00 $4910.00 -09-Oct-01 Budget transaction Expenses:Books $-10.00 $4900.00 +09-Oct-01 Budget transaction Expenses:Books $-10.00 $4700.00 +09-Oct-01 October Expenses:Books $100.00 $4800.00 + Liabilities:Cards $100.00 $4900.00 09-Oct-31 End of October Expenses:Books $100.00 $5000.00 Liabilities:Cards $100.00 $5100.00 -09-Nov-01 November Expenses:Books $110.00 $5210.00 - Liabilities:Cards $110.00 $5320.00 -09-Nov-01 Budget transaction Expenses:Books $-10.00 $5310.00 +09-Nov-01 Budget transaction Expenses:Books $-10.00 $5090.00 +09-Nov-01 November Expenses:Books $110.00 $5200.00 + Liabilities:Cards $110.00 $5310.00 09-Nov-30 End of November Expenses:Books $110.00 $5420.00 Liabilities:Cards $110.00 $5530.00 -09-Dec-01 December Expenses:Books $120.00 $5650.00 - Liabilities:Cards $120.00 $5770.00 -09-Dec-01 Budget transaction Expenses:Books $-10.00 $5760.00 +09-Dec-01 Budget transaction Expenses:Books $-10.00 $5520.00 +09-Dec-01 December Expenses:Books $120.00 $5640.00 + Liabilities:Cards $120.00 $5760.00 09-Dec-31 End of December Expenses:Books $120.00 $5880.00 Liabilities:Cards $120.00 $6000.00 >>>2 diff --git a/test/baseline/opt-anon.test b/test/baseline/opt-anon.test index f9244451..6fe6b75f 100644 --- a/test/baseline/opt-anon.test +++ b/test/baseline/opt-anon.test @@ -4,8 +4,8 @@ reg --anon Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00 Income:Dividends:Vanguard:VMMXX $-0.35 >>>1 -07-Feb-02 6a93dcb3 20:5d:27:988a9c3a 0.350 VMMXX 0.350 VMMXX - 1c:b6:27:988a9c3a $-0.35 $-0.35 +07-Feb-02 6a93dcb3 da:20:5d:27:988a9c3a 0.350 VMMXX 0.350 VMMXX + da:1c:b6:27:988a9c3a $-0.35 $-0.35 0.350 VMMXX >>>2 === 0 diff --git a/test/baseline/opt-budget.test b/test/baseline/opt-budget.test index 097d19d8..eb2ade9d 100644 --- a/test/baseline/opt-budget.test +++ b/test/baseline/opt-budget.test @@ -245,77 +245,77 @@ reg --budget books Liabilities:Cards $120.00 Assets:Cash >>>1 -08-Jan-01 January Expenses:Books $10.00 $10.00 -08-Jan-01 Budget transaction Expenses:Books $-10.00 0 +08-Jan-01 Budget transaction Expenses:Books $-10.00 $-10.00 +08-Jan-01 January Expenses:Books $10.00 0 08-Jan-31 End of January Expenses:Books $10.00 $10.00 -08-Feb-01 February Expenses:Books $20.00 $30.00 -08-Feb-01 Budget transaction Expenses:Books $-10.00 $20.00 +08-Feb-01 Budget transaction Expenses:Books $-10.00 0 +08-Feb-01 February Expenses:Books $20.00 $20.00 08-Feb-28 End of February Expenses:Books $20.00 $40.00 -08-Mar-01 March Expenses:Books $30.00 $70.00 -08-Mar-01 Budget transaction Expenses:Books $-10.00 $60.00 +08-Mar-01 Budget transaction Expenses:Books $-10.00 $30.00 +08-Mar-01 March Expenses:Books $30.00 $60.00 08-Mar-31 End of March Expenses:Books $30.00 $90.00 -08-Apr-01 April Expenses:Books $40.00 $130.00 -08-Apr-01 Budget transaction Expenses:Books $-10.00 $120.00 +08-Apr-01 Budget transaction Expenses:Books $-10.00 $80.00 +08-Apr-01 April Expenses:Books $40.00 $120.00 08-Apr-30 End of April Expenses:Books $40.00 $160.00 -08-May-01 May Expenses:Books $50.00 $210.00 -08-May-01 Budget transaction Expenses:Books $-10.00 $200.00 +08-May-01 Budget transaction Expenses:Books $-10.00 $150.00 +08-May-01 May Expenses:Books $50.00 $200.00 08-May-31 End of May Expenses:Books $50.00 $250.00 -08-Jun-01 June Expenses:Books $60.00 $310.00 -08-Jun-01 Budget transaction Expenses:Books $-10.00 $300.00 +08-Jun-01 Budget transaction Expenses:Books $-10.00 $240.00 +08-Jun-01 June Expenses:Books $60.00 $300.00 08-Jun-30 End of June Expenses:Books $60.00 $360.00 -08-Jul-01 July Expenses:Books $70.00 $430.00 -08-Jul-01 Budget transaction Expenses:Books $-10.00 $420.00 +08-Jul-01 Budget transaction Expenses:Books $-10.00 $350.00 +08-Jul-01 July Expenses:Books $70.00 $420.00 08-Jul-31 End of July Expenses:Books $70.00 $490.00 -08-Aug-01 August Expenses:Books $80.00 $570.00 -08-Aug-01 Budget transaction Expenses:Books $-10.00 $560.00 +08-Aug-01 Budget transaction Expenses:Books $-10.00 $480.00 +08-Aug-01 August Expenses:Books $80.00 $560.00 08-Aug-31 End of August Expenses:Books $80.00 $640.00 -08-Sep-01 September Expenses:Books $90.00 $730.00 -08-Sep-01 Budget transaction Expenses:Books $-10.00 $720.00 +08-Sep-01 Budget transaction Expenses:Books $-10.00 $630.00 +08-Sep-01 September Expenses:Books $90.00 $720.00 08-Sep-30 End of September Expenses:Books $90.00 $810.00 -08-Oct-01 October Expenses:Books $100.00 $910.00 -08-Oct-01 Budget transaction Expenses:Books $-10.00 $900.00 +08-Oct-01 Budget transaction Expenses:Books $-10.00 $800.00 +08-Oct-01 October Expenses:Books $100.00 $900.00 08-Oct-31 End of October Expenses:Books $100.00 $1000.00 -08-Nov-01 November Expenses:Books $110.00 $1110.00 -08-Nov-01 Budget transaction Expenses:Books $-10.00 $1100.00 +08-Nov-01 Budget transaction Expenses:Books $-10.00 $990.00 +08-Nov-01 November Expenses:Books $110.00 $1100.00 08-Nov-30 End of November Expenses:Books $110.00 $1210.00 -08-Dec-01 December Expenses:Books $120.00 $1330.00 -08-Dec-01 Budget transaction Expenses:Books $-10.00 $1320.00 +08-Dec-01 Budget transaction Expenses:Books $-10.00 $1200.00 +08-Dec-01 December Expenses:Books $120.00 $1320.00 08-Dec-31 End of December Expenses:Books $120.00 $1440.00 -09-Jan-01 January Expenses:Books $10.00 $1450.00 -09-Jan-01 Budget transaction Expenses:Books $-10.00 $1440.00 +09-Jan-01 Budget transaction Expenses:Books $-10.00 $1430.00 +09-Jan-01 January Expenses:Books $10.00 $1440.00 09-Jan-31 End of January Expenses:Books $10.00 $1450.00 -09-Feb-01 February Expenses:Books $20.00 $1470.00 -09-Feb-01 Budget transaction Expenses:Books $-10.00 $1460.00 +09-Feb-01 Budget transaction Expenses:Books $-10.00 $1440.00 +09-Feb-01 February Expenses:Books $20.00 $1460.00 09-Feb-28 End of February Expenses:Books $20.00 $1480.00 -09-Mar-01 March Expenses:Books $30.00 $1510.00 -09-Mar-01 Budget transaction Expenses:Books $-10.00 $1500.00 +09-Mar-01 Budget transaction Expenses:Books $-10.00 $1470.00 +09-Mar-01 March Expenses:Books $30.00 $1500.00 09-Mar-31 End of March Expenses:Books $30.00 $1530.00 -09-Apr-01 April Expenses:Books $40.00 $1570.00 -09-Apr-01 Budget transaction Expenses:Books $-10.00 $1560.00 +09-Apr-01 Budget transaction Expenses:Books $-10.00 $1520.00 +09-Apr-01 April Expenses:Books $40.00 $1560.00 09-Apr-30 End of April Expenses:Books $40.00 $1600.00 -09-May-01 May Expenses:Books $50.00 $1650.00 -09-May-01 Budget transaction Expenses:Books $-10.00 $1640.00 +09-May-01 Budget transaction Expenses:Books $-10.00 $1590.00 +09-May-01 May Expenses:Books $50.00 $1640.00 09-May-31 End of May Expenses:Books $50.00 $1690.00 -09-Jun-01 June Expenses:Books $60.00 $1750.00 -09-Jun-01 Budget transaction Expenses:Books $-10.00 $1740.00 +09-Jun-01 Budget transaction Expenses:Books $-10.00 $1680.00 +09-Jun-01 June Expenses:Books $60.00 $1740.00 09-Jun-30 End of June Expenses:Books $60.00 $1800.00 -09-Jul-01 July Expenses:Books $70.00 $1870.00 -09-Jul-01 Budget transaction Expenses:Books $-10.00 $1860.00 +09-Jul-01 Budget transaction Expenses:Books $-10.00 $1790.00 +09-Jul-01 July Expenses:Books $70.00 $1860.00 09-Jul-31 End of July Expenses:Books $70.00 $1930.00 -09-Aug-01 August Expenses:Books $80.00 $2010.00 -09-Aug-01 Budget transaction Expenses:Books $-10.00 $2000.00 +09-Aug-01 Budget transaction Expenses:Books $-10.00 $1920.00 +09-Aug-01 August Expenses:Books $80.00 $2000.00 09-Aug-31 End of August Expenses:Books $80.00 $2080.00 -09-Sep-01 September Expenses:Books $90.00 $2170.00 -09-Sep-01 Budget transaction Expenses:Books $-10.00 $2160.00 +09-Sep-01 Budget transaction Expenses:Books $-10.00 $2070.00 +09-Sep-01 September Expenses:Books $90.00 $2160.00 09-Sep-30 End of September Expenses:Books $90.00 $2250.00 -09-Oct-01 October Expenses:Books $100.00 $2350.00 -09-Oct-01 Budget transaction Expenses:Books $-10.00 $2340.00 +09-Oct-01 Budget transaction Expenses:Books $-10.00 $2240.00 +09-Oct-01 October Expenses:Books $100.00 $2340.00 09-Oct-31 End of October Expenses:Books $100.00 $2440.00 -09-Nov-01 November Expenses:Books $110.00 $2550.00 -09-Nov-01 Budget transaction Expenses:Books $-10.00 $2540.00 +09-Nov-01 Budget transaction Expenses:Books $-10.00 $2430.00 +09-Nov-01 November Expenses:Books $110.00 $2540.00 09-Nov-30 End of November Expenses:Books $110.00 $2650.00 -09-Dec-01 December Expenses:Books $120.00 $2770.00 -09-Dec-01 Budget transaction Expenses:Books $-10.00 $2760.00 +09-Dec-01 Budget transaction Expenses:Books $-10.00 $2640.00 +09-Dec-01 December Expenses:Books $120.00 $2760.00 09-Dec-31 End of December Expenses:Books $120.00 $2880.00 >>>2 === 0 diff --git a/test/manual/transaction-codes-1.test b/test/manual/transaction-codes-1.test new file mode 100644 index 00000000..878c5cac --- /dev/null +++ b/test/manual/transaction-codes-1.test @@ -0,0 +1,22 @@ +reg --columns=60 food and code xfer +<<< +2009/10/29 (XFER) Panera Bread + Expenses:Food $4.50 + Assets:Checking + +2009/10/30 (DEP) Pay day! + Assets:Checking $20.00 + Income + +2009/10/30 (XFER) Panera Bread + Expenses:Food $4.50 + Assets:Checking + +2009/10/31 (559385768438A8D7) Panera Bread + Expenses:Food $4.50 + Liabilities:Credit Card +>>>1 +09-Oct-29 Panera Bread Expenses:Food $4.50 $4.50 +09-Oct-30 Panera Bread Expenses:Food $4.50 $9.00 +>>>2 +=== 0 diff --git a/test/manual/transaction-codes-2.test b/test/manual/transaction-codes-2.test new file mode 100644 index 00000000..4e4c76cf --- /dev/null +++ b/test/manual/transaction-codes-2.test @@ -0,0 +1,24 @@ +bal checking --set-reported-account=code +<<< +2009/10/29 (XFER) Panera Bread + Expenses:Food $4.50 + Assets:Checking + +2009/10/30 (DEP) Pay day! + Assets:Checking $20.00 + Income + +2009/10/30 (XFER) Panera Bread + Expenses:Food $4.50 + Assets:Checking + +2009/10/31 (559385768438A8D7) Panera Bread + Expenses:Food $4.50 + Liabilities:Credit Card +>>>1 + $20.00 DEP + $-9.00 XFER +-------------------- + $11.00 +>>>2 +=== 0 diff --git a/test/manual/transaction-notes-1.test b/test/manual/transaction-notes-1.test new file mode 100644 index 00000000..d3fab3b6 --- /dev/null +++ b/test/manual/transaction-notes-1.test @@ -0,0 +1,24 @@ +reg --columns=60 food and note eat +<<< +2009/11/01 Panera Bread ; Got something to eat + Expenses:Food $4.50 + Assets:Checking + +2009/11/01 Panera Bread + ; Type: Coffee + ; Let’s see, I ate a whole bunch of stuff, drank some coffee, + ; pondered a bagel, then decided against the donut. + Expenses:Food $4.50 + Assets:Checking + +2009/11/01 Panera Bread + ; Type: Dining + ; :Eating: + ; This is another long note, after the metadata. + Expenses:Food $4.50 + Assets:Checking +>>>1 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +09-Nov-01 Panera Bread Expenses:Food $4.50 $9.00 +>>>2 +=== 0 diff --git a/test/manual/transaction-notes-2.test b/test/manual/transaction-notes-2.test new file mode 100644 index 00000000..b7a258e0 --- /dev/null +++ b/test/manual/transaction-notes-2.test @@ -0,0 +1,23 @@ +reg --columns=60 food and tag eating +<<< +2009/11/01 Panera Bread ; Got something to eat + Expenses:Food $4.50 + Assets:Checking + +2009/11/01 Panera Bread + ; Type: Coffee + ; Let’s see, I ate a whole bunch of stuff, drank some coffee, + ; pondered a bagel, then decided against the donut. + Expenses:Food $4.50 + Assets:Checking + +2009/11/01 Panera Bread + ; Type: Dining + ; :Eating: + ; This is another long note, after the metadata. + Expenses:Food $4.50 + Assets:Checking +>>>1 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +>>>2 +=== 0 diff --git a/test/manual/transaction-notes-3.test b/test/manual/transaction-notes-3.test new file mode 100644 index 00000000..9d532d5f --- /dev/null +++ b/test/manual/transaction-notes-3.test @@ -0,0 +1,23 @@ +reg --columns=60 food and tag type=dining +<<< +2009/11/01 Panera Bread ; Got something to eat + Expenses:Food $4.50 + Assets:Checking + +2009/11/01 Panera Bread + ; Type: Coffee + ; Let’s see, I ate a whole bunch of stuff, drank some coffee, + ; pondered a bagel, then decided against the donut. + Expenses:Food $4.50 + Assets:Checking + +2009/11/01 Panera Bread + ; Type: Dining + ; :Eating: + ; This is another long note, after the metadata. + Expenses:Food $4.50 + Assets:Checking +>>>1 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +>>>2 +=== 0 diff --git a/test/manual/transaction-notes-4.test b/test/manual/transaction-notes-4.test new file mode 100644 index 00000000..516094c7 --- /dev/null +++ b/test/manual/transaction-notes-4.test @@ -0,0 +1,27 @@ +bal food and tag type --set-reported-account='"Tags:" + tag("Type")' +<<< +2009/11/01 Panera Bread ; Got something to eat + Expenses:Food $4.50 + Assets:Checking + +2009/11/01 Panera Bread + ; Type: Coffee + ; Let’s see, I ate a whole bunch of stuff, drank some coffee, + ; pondered a bagel, then decided against the donut. + Expenses:Food $4.50 + Assets:Checking + +2009/11/01 Panera Bread + ; Type: Dining + ; :Eating: + ; This is another long note, after the metadata. + Expenses:Food $4.50 + Assets:Checking +>>>1 + $9.00 Tags + $4.50 Coffee + $4.50 Dining +-------------------- + $9.00 +>>>2 +=== 0 diff --git a/test/manual/transaction-status-1.test b/test/manual/transaction-status-1.test new file mode 100644 index 00000000..4bdf893a --- /dev/null +++ b/test/manual/transaction-status-1.test @@ -0,0 +1,19 @@ +reg --columns=60 food +<<< +2009/10/31 * Panera Bread + Expenses:Food $4.50 + Assets + +2009/11/01 ! Panera Bread + Expenses:Food $4.50 + Assets + +2009/11/02 Panera Bread + Expenses:Food $4.50 + Assets +>>>1 +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 +>>>2 +=== 0 diff --git a/test/manual/transaction-status-2.test b/test/manual/transaction-status-2.test new file mode 100644 index 00000000..dbbb04ae --- /dev/null +++ b/test/manual/transaction-status-2.test @@ -0,0 +1,17 @@ +reg --columns=60 food --cleared +<<< +2009/10/31 * Panera Bread + Expenses:Food $4.50 + Assets + +2009/11/01 ! Panera Bread + Expenses:Food $4.50 + Assets + +2009/11/02 Panera Bread + Expenses:Food $4.50 + Assets +>>>1 +09-Oct-31 Panera Bread Expenses:Food $4.50 $4.50 +>>>2 +=== 0 diff --git a/test/manual/transaction-status-3.test b/test/manual/transaction-status-3.test new file mode 100644 index 00000000..1e6467ef --- /dev/null +++ b/test/manual/transaction-status-3.test @@ -0,0 +1,18 @@ +reg --columns=60 food --uncleared +<<< +2009/10/31 * Panera Bread + Expenses:Food $4.50 + Assets + +2009/11/01 ! Panera Bread + Expenses:Food $4.50 + Assets + +2009/11/02 Panera Bread + Expenses:Food $4.50 + Assets +>>>1 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +09-Nov-02 Panera Bread Expenses:Food $4.50 $9.00 +>>>2 +=== 0 diff --git a/test/manual/transaction-status-4.test b/test/manual/transaction-status-4.test new file mode 100644 index 00000000..5275eec3 --- /dev/null +++ b/test/manual/transaction-status-4.test @@ -0,0 +1,17 @@ +reg --columns=60 food --pending +<<< +2009/10/31 * Panera Bread + Expenses:Food $4.50 + Assets + +2009/11/01 ! Panera Bread + Expenses:Food $4.50 + Assets + +2009/11/02 Panera Bread + Expenses:Food $4.50 + Assets +>>>1 +09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50 +>>>2 +=== 0 diff --git a/test/regress/25A099C9.test b/test/regress/25A099C9.test new file mode 100644 index 00000000..fb5613e2 --- /dev/null +++ b/test/regress/25A099C9.test @@ -0,0 +1,19 @@ +-f $sourcepath/src/amount.h reg +<<< +>>>1 +>>>2 +While parsing file "$sourcepath/src/amount.h", line 67: +Error: No quantity specified for amount +While parsing file "$sourcepath/src/amount.h", line 707: +Error: Invalid date/time: line amount_t amoun +While parsing file "$sourcepath/src/amount.h", line 713: +Error: Invalid date/time: line string amount_ +While parsing file "$sourcepath/src/amount.h", line 719: +Error: Invalid date/time: line string amount_ +While parsing file "$sourcepath/src/amount.h", line 725: +Error: Invalid date/time: line string amount_ +While parsing file "$sourcepath/src/amount.h", line 731: +Error: Invalid date/time: line std::ostream& +While parsing file "$sourcepath/src/amount.h", line 738: +Error: Invalid date/time: line std::istream& +=== 7 diff --git a/test/regress/373540CC.test b/test/regress/373540CC.test new file mode 100644 index 00000000..5c589ec9 --- /dev/null +++ b/test/regress/373540CC.test @@ -0,0 +1,9 @@ +bal --sort total --flat -X '$' not '(Income|Liabilities)' +<<< +2004/05/27 Book Store + Expenses:Books 20 BOOK @ $10 + Liabilities:MasterCard $-200.00 +>>>1 + $200.00 Expenses:Books +>>>2 +=== 0 diff --git a/test/regress/5F1BAF17.test b/test/regress/5F1BAF17.test new file mode 100644 index 00000000..f52ffb86 --- /dev/null +++ b/test/regress/5F1BAF17.test @@ -0,0 +1,130 @@ +bal da39 --flat --sort amount --display-total amount +<<< +2006/02/16 b5f40e96 + da39a3ee:8d437dbf:ee2bf9bd:f61e33bf $713.35 + Assets + +2006/03/27 c7ab1f2d + da39a3ee:8d437dbf:ee2bf9bd:9b69a35a $139.62 + Assets + +2006/03/30 f32ea1dc + da39a3ee:8d437dbf:ee2bf9bd:d219c681 $1,600.00 + Assets + +2006/04/21 d449d51e + da39a3ee:8d437dbf:ee2bf9bd:75b04b88 $698.10 + Assets + +2006/05/02 b02f8323 + da39a3ee:8d437dbf:ee2bf9bd $42.22 + Assets + +2006/05/05 2a6f6850 + da39a3ee:8d437dbf:ee2bf9bd:75b04b88:b3850e04 $2,468.00 + Assets + +2006/05/09 59f92263 + da39a3ee:8d437dbf:ee2bf9bd:071c929a $132.82 + Assets + +2006/05/18 f78a7a51 + da39a3ee:8d437dbf:ee2bf9bd:e97de844 $368.05 + Assets + +2006/05/19 f35c594c + da39a3ee:8d437dbf:ee2bf9bd:d4e7d7d3 $386.62 + Assets + +2006/05/22 0233a991 + da39a3ee:8d437dbf:ee2bf9bd:9c6e5a3f $141.98 + Assets + +2006/05/23 56ccae7f + da39a3ee:8d437dbf:ee2bf9bd:d31d367b $81.78 + Assets + +2006/05/24 d449d51e + da39a3ee:8d437dbf:ee2bf9bd:75b04b88 $65.00 + Assets + +2006/05/25 dc833c91 + da39a3ee:8d437dbf:ee2bf9bd:d31d367b $34.37 + Assets + +2006/05/31 6822b496 + da39a3ee:8d437dbf:ee2bf9bd:e97de844 $41.78 + Assets + +2006/06/02 dff8ccb2 + da39a3ee:8d437dbf:ee2bf9bd:14e351e1 $67.36 + Assets + +2006/06/02 e1eb3f4b + da39a3ee:8d437dbf:ee2bf9bd:2c7a078f $14.00 + Assets + +2006/06/04 feec73ea + da39a3ee:8d437dbf:ee2bf9bd:131260cb $144.99 + Assets + +2006/06/04 e8f65e0a + da39a3ee:8d437dbf:ee2bf9bd:d219c681 $75.00 + Assets + +2006/06/04 3fd43f7b + da39a3ee:8d437dbf:ee2bf9bd:9c4ba7d0 $239.59 + Assets + +2006/06/06 754be754 + da39a3ee:8d437dbf:ee2bf9bd:35b25929 $1,160.14 + Assets + +2006/06/06 00c16d44 + da39a3ee:8d437dbf:ee2bf9bd:e97de844 $78.45 + Assets + +2006/06/08 e7b0b317 + da39a3ee:8d437dbf:ee2bf9bd $443.00 + Assets + +2006/07/17 a30c4c31 + da39a3ee:8d437dbf:ee2bf9bd $880.80 + Assets + +2006/08/08 e31a0cf9 + da39a3ee:8d437dbf:ee2bf9bd $104.53 + Assets + +2006/08/10 f0c0c688 + da39a3ee:8d437dbf:ee2bf9bd $196.70 + Assets + +2006/09/12 1bc59c63 + da39a3ee:8d437dbf:ee2bf9bd $217.79 + Assets + +2007/07/16 557e3a00 + da39a3ee:8d437dbf:ee2bf9bd:f61e33bf $117.80 + Assets +>>>1 + $14.00 da39a3ee:8d437dbf:ee2bf9bd:2c7a078f + $67.36 da39a3ee:8d437dbf:ee2bf9bd:14e351e1 + $116.15 da39a3ee:8d437dbf:ee2bf9bd:d31d367b + $132.82 da39a3ee:8d437dbf:ee2bf9bd:071c929a + $139.62 da39a3ee:8d437dbf:ee2bf9bd:9b69a35a + $141.98 da39a3ee:8d437dbf:ee2bf9bd:9c6e5a3f + $144.99 da39a3ee:8d437dbf:ee2bf9bd:131260cb + $239.59 da39a3ee:8d437dbf:ee2bf9bd:9c4ba7d0 + $386.62 da39a3ee:8d437dbf:ee2bf9bd:d4e7d7d3 + $488.28 da39a3ee:8d437dbf:ee2bf9bd:e97de844 + $763.10 da39a3ee:8d437dbf:ee2bf9bd:75b04b88 + $831.15 da39a3ee:8d437dbf:ee2bf9bd:f61e33bf + $1,160.14 da39a3ee:8d437dbf:ee2bf9bd:35b25929 + $1,675.00 da39a3ee:8d437dbf:ee2bf9bd:d219c681 + $1,885.04 da39a3ee:8d437dbf:ee2bf9bd + $2,468.00 da39a3ee:8d437dbf:ee2bf9bd:75b04b88:b3850e04 +-------------------- + 0 +>>>2 +=== 0 diff --git a/test/regress/7F3650FD.test b/test/regress/7F3650FD.test new file mode 100644 index 00000000..0eb3a96f --- /dev/null +++ b/test/regress/7F3650FD.test @@ -0,0 +1,50 @@ +period --now=2010/11/01 12/01 +<<< +>>>1 +global details => + + start: 09-Dec-01 + end: 09-Dec-02 + factor: 1 +>>>2 +=== 0 +period --now=2010/11/01 10/01 +<<< +>>>1 +global details => + + start: 10-Oct-01 + end: 10-Oct-02 + factor: 1 +>>>2 +=== 0 +period --now=2010/11/01 2009/10 +<<< +>>>1 +global details => + + start: 09-Oct-01 + end: 09-Nov-01 + factor: 1 +>>>2 +=== 0 +period --now=2010/11/01 2009/10/01 +<<< +>>>1 +global details => + + start: 09-Oct-01 + end: 09-Oct-02 + factor: 1 +>>>2 +=== 0 +period --now=2010/11/01 2009 +<<< +>>>1 +global details => + + start: 09-Jan-01 + end: 10-Jan-01 + factor: 1 +>>>2 +=== 0 diff --git a/test/regress/8254755E.test b/test/regress/8254755E.test new file mode 100644 index 00000000..26baf52d --- /dev/null +++ b/test/regress/8254755E.test @@ -0,0 +1,20 @@ +bal --flat food:out +<<< +~ Monthly + Expenses:Auto:Fuel $120.00 + Expenses:Food:Out $100.00 + Expenses:Food:Groceries $350.00 + Assets + +2009/11/01 + Expenses:Food:Out $50.00 + Assets +>>>1 + $50.00 Expenses:Food:Out +>>>2 +=== 0 +bal --flat --budget food:out +>>>1 + $-50.00 Expenses:Food:Out +>>>2 +=== 0 diff --git a/test/regress/D060256A.test b/test/regress/D060256A.test new file mode 100644 index 00000000..26c30351 --- /dev/null +++ b/test/regress/D060256A.test @@ -0,0 +1,16 @@ +budget --now=2009/11/01 --end=2009/11/30 +<<< +~ Monthly + Expenses:Food $500.00 + Assets + +2009/11/01 Sample + Expenses:Food:Dining $20.00 + Assets +>>>1 + $-20.00 $-500.00 $480.00 4% Assets + $20.00 $500.00 $-480.00 4% Expenses:Food +------------ ------------ ------------ ----- + 0 0 0 0 +>>>2 +=== 0 diff --git a/test/regress/E627C594.test b/test/regress/E627C594.test new file mode 100644 index 00000000..0dfbf778 --- /dev/null +++ b/test/regress/E627C594.test @@ -0,0 +1,18 @@ +reg --forecast-while="d<[2010/03/01]" --now=2009/11/01 +<<< +~ Monthly + Expenses:Food $500.00 + Assets + +2009/11/01 Sample + Expenses:Food:Dining $20.00 + Assets +>>>1 +09-Nov-01 Sample Expenses:Food:Dining $20.00 $20.00 + Assets $-20.00 0 +10-Jan-01 Forecast transaction Expenses:Food $500.00 $500.00 +10-Jan-01 Forecast transaction Assets $-500.00 0 +10-Feb-01 Forecast transaction Expenses:Food $500.00 $500.00 +10-Feb-01 Forecast transaction Assets $-500.00 0 +>>>2 +=== 0 diff --git a/test/regress/F559EC12.test b/test/regress/F559EC12.test index 7900b60d..c8b686db 100644 --- a/test/regress/F559EC12.test +++ b/test/regress/F559EC12.test @@ -3,7 +3,11 @@ format "%-12(scrub(amount))" >>>1 --- Context is first posting of the following transaction --- 2004/05/27 Book Store + ; This note applies to all postings. :SecondTag: Expenses:Books 20 BOOK @ $10 + ; Metadata: Some Value + ; :ExampleTag: + ; Here follows a note describing the posting. Liabilities:MasterCard $-200.00 --- Input format string --- @@ -20,7 +24,11 @@ format "%12(scrub(amount))" >>>1 --- Context is first posting of the following transaction --- 2004/05/27 Book Store + ; This note applies to all postings. :SecondTag: Expenses:Books 20 BOOK @ $10 + ; Metadata: Some Value + ; :ExampleTag: + ; Here follows a note describing the posting. Liabilities:MasterCard $-200.00 --- Input format string --- diff --git a/tools/Makefile.am b/tools/Makefile.am index 13ea4e7f..4dd4a871 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -247,7 +247,7 @@ endif TESTS = if HAVE_PYTHON -TESTS += RegressTests BaselineTests ConfirmTests GenerateTests +TESTS += RegressTests BaselineTests ManualTests ConfirmTests GenerateTests endif if HAVE_CPPUNIT @@ -370,7 +370,7 @@ RegressTests_SOURCES = test/RegressTests.py EXTRA_DIST += test/regress test/convert.py test/LedgerHarness.py RegressTests: $(srcdir)/test/RegressTests.py - echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir)/test/regress \"\$$@\"" > $@ + echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/regress \"\$$@\"" > $@ chmod 755 $@ BaselineTests_SOURCES = test/RegressTests.py @@ -378,7 +378,15 @@ BaselineTests_SOURCES = test/RegressTests.py EXTRA_DIST += test/baseline BaselineTests: $(srcdir)/test/RegressTests.py - echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir)/test/baseline \"\$$@\"" > $@ + echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/baseline \"\$$@\"" > $@ + chmod 755 $@ + +ManualTests_SOURCES = test/RegressTests.py + +EXTRA_DIST += test/manual + +ManualTests: $(srcdir)/test/RegressTests.py + echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/manual \"\$$@\"" > $@ chmod 755 $@ ConfirmTests_SOURCES = test/ConfirmTests.py @@ -393,13 +401,13 @@ test/input/mondo.dat: test/input/standard.dat done ConfirmTests: $(srcdir)/test/ConfirmTests.py - echo "$(PYTHON) $(srcdir)/test/ConfirmTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir)/test/input \"\$$@\"" > $@ + echo "$(PYTHON) $(srcdir)/test/ConfirmTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/input \"\$$@\"" > $@ chmod 755 $@ GenerateTests_SOURCES = test/GenerateTests.py GenerateTests: $(srcdir)/test/GenerateTests.py - echo "$(PYTHON) $(srcdir)/test/GenerateTests.py $(top_builddir)/ledger$(EXEEXT) 1 20 \"\$$@\"" > $@ + echo "$(PYTHON) $(srcdir)/test/GenerateTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) 1 20 \"\$$@\"" > $@ chmod 755 $@ FULLCHECK=$(srcdir)/test/fullcheck.sh @@ -424,10 +432,12 @@ endif fullcheck: cppunittests @$(top_builddir)/RegressTests --verify @$(top_builddir)/BaselineTests --verify + @$(top_builddir)/ManualTests --verify @$(top_builddir)/ConfirmTests --verify @$(top_builddir)/GenerateTests --verify @$(top_builddir)/RegressTests --gmalloc @$(top_builddir)/BaselineTests --gmalloc + @$(top_builddir)/ManualTests --gmalloc # @$(top_builddir)/ConfirmTests --gmalloc # @$(top_builddir)/GenerateTests --gmalloc diff --git a/tools/proof b/tools/proof index ede22558..7c5a16f2 100755 --- a/tools/proof +++ b/tools/proof @@ -14,7 +14,7 @@ fi rm -fr ~/Products/ledger* -./acprep -j16 --warn proof 2>&1 | tee ~/Desktop/proof.log +time ./acprep -j16 --warn proof 2>&1 | tee ~/Desktop/proof.log if egrep -q '(ERROR|CRITICAL)' ~/Desktop/proof.log; then if [[ "$1" = "--alert" ]]; then |