diff options
author | John Wiegley <johnw@newartisans.com> | 2009-02-19 22:36:08 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2009-02-19 22:36:08 -0400 |
commit | f2f52066d2a9c82619ffea0f3972e48417a90b5b (patch) | |
tree | 3390b046e383309c4845be29dcf1d44c258c6d56 /src | |
parent | 2694335e54316606ab169e957034ba71e8274144 (diff) | |
download | fork-ledger-f2f52066d2a9c82619ffea0f3972e48417a90b5b.tar.gz fork-ledger-f2f52066d2a9c82619ffea0f3972e48417a90b5b.tar.bz2 fork-ledger-f2f52066d2a9c82619ffea0f3972e48417a90b5b.zip |
Added a --strict session option
When enabled, if any accounts or commodities are seen in an uncleared
transaction, which were not seen previously in a cleared or pending
transaction or a textual directive dealing with accounts or commodities,
a warning is generated about the unknown item.
Diffstat (limited to 'src')
-rw-r--r-- | src/account.h | 5 | ||||
-rw-r--r-- | src/commodity.h | 1 | ||||
-rw-r--r-- | src/journal.h | 5 | ||||
-rw-r--r-- | src/precmd.cc | 2 | ||||
-rw-r--r-- | src/session.cc | 6 | ||||
-rw-r--r-- | src/session.h | 1 | ||||
-rw-r--r-- | src/textual.cc | 48 |
7 files changed, 54 insertions, 14 deletions
diff --git a/src/account.h b/src/account.h index f9fd2f52..8b485ec2 100644 --- a/src/account.h +++ b/src/account.h @@ -69,6 +69,7 @@ class account_t : public scope_t optional<string> note; unsigned short depth; accounts_map accounts; + bool known; mutable void * data; mutable string _fullname; @@ -77,7 +78,8 @@ class account_t : public scope_t const string& _name = "", const optional<string>& _note = none) : scope_t(), parent(_parent), name(_name), note(_note), - depth(parent ? parent->depth + 1 : 0), data(NULL) { + depth(parent ? parent->depth + 1 : 0), + known(false), data(NULL) { TRACE_CTOR(account_t, "account_t *, const string&, const string&"); } account_t(const account_t& other) @@ -87,6 +89,7 @@ class account_t : public scope_t note(other.note), depth(other.depth), accounts(other.accounts), + known(other.known), data(NULL) { TRACE_CTOR(account_t, "copy"); assert(other.data == NULL); diff --git a/src/commodity.h b/src/commodity.h index 92bacb25..b6ce0c85 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -150,6 +150,7 @@ public: #define COMMODITY_NOMARKET 0x10 #define COMMODITY_BUILTIN 0x20 #define COMMODITY_WALKED 0x40 +#define COMMODITY_KNOWN 0x80 string symbol; amount_t::precision_t precision; diff --git a/src/journal.h b/src/journal.h index 8c72becc..b0d61c98 100644 --- a/src/journal.h +++ b/src/journal.h @@ -97,8 +97,9 @@ public: std::size_t parse(std::istream& in, scope_t& session_scope, - account_t * master, - const path * original_file); + account_t * master = NULL, + const path * original_file = NULL, + bool strict = false); bool valid() const; }; diff --git a/src/precmd.cc b/src/precmd.cc index 6e6ea9cd..c02be263 100644 --- a/src/precmd.cc +++ b/src/precmd.cc @@ -55,7 +55,7 @@ namespace { << std::endl << str << std::endl; { std::istringstream in(str); - report.session.journal->parse(in, report.session, NULL, NULL); + report.session.journal->parse(in, report.session); report.session.clean_accounts(); } } diff --git a/src/session.cc b/src/session.cc index 1e2dfb64..7a3ecf19 100644 --- a/src/session.cc +++ b/src/session.cc @@ -84,7 +84,8 @@ std::size_t session_t::read_journal(std::istream& in, { if (! master) master = journal->master; - std::size_t count = journal->parse(in, *this, master, &pathname); + std::size_t count = journal->parse(in, *this, master, &pathname, + HANDLED(strict)); clean_accounts(); // remove calculated totals return count; } @@ -220,6 +221,9 @@ option_t<session_t> * session_t::lookup_option(const char * p) case 'p': OPT(price_db_); break; + case 's': + OPT(strict); + break; case 'Q': OPT_CH(download); // -Q break; diff --git a/src/session.h b/src/session.h index 2b657125..d2320bb7 100644 --- a/src/session.h +++ b/src/session.h @@ -131,6 +131,7 @@ public: OPTION(session_t, input_date_format_); OPTION(session_t, price_db_); + OPTION(session_t, strict); }; /** diff --git a/src/textual.cc b/src/textual.cc index ce945fdf..eec3be61 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -58,6 +58,7 @@ namespace { const path * original_file; accounts_map account_aliases; int current_year; + bool strict; path pathname; char linebuf[MAX_LINE + 1]; @@ -78,6 +79,7 @@ namespace { journal_t& _journal, account_t * _master = NULL, const path * _original_file = NULL, + bool _strict = false, instance_t * _parent = NULL); ~instance_t(); @@ -115,7 +117,8 @@ namespace { xact_t * parse_xact(char * line, std::streamsize len, account_t * account, - entry_t * entry); + entry_t * entry, + bool honor_strict = true); bool parse_xacts(account_t * account, entry_base_t& entry); @@ -168,13 +171,15 @@ instance_t::instance_t(std::list<account_t *>& _account_stack, journal_t& _journal, account_t * _master, const path * _original_file, + bool _strict, instance_t * _parent) : account_stack(_account_stack), #if defined(TIMELOG_SUPPORT) timelog(_timelog), #endif parent(_parent), in(_in), session_scope(_session_scope), - journal(_journal), master(_master), original_file(_original_file) + journal(_journal), master(_master), + original_file(_original_file), strict(_strict) { TRACE_CTOR(instance_t, "..."); @@ -418,11 +423,13 @@ void instance_t::default_commodity_directive(char * line) amount_t amt(skip_ws(line + 1)); assert(amt.valid()); amount_t::current_pool->default_commodity = &amt.commodity(); + amt.commodity().add_flags(COMMODITY_KNOWN); } void instance_t::default_account_directive(char * line) { journal.basket = account_stack.front()->find_account(skip_ws(line + 1)); + journal.basket->known = true; } void instance_t::price_conversion_directive(char * line) @@ -484,8 +491,12 @@ void instance_t::price_entry_directive(char * line) assert(price.valid()); if (commodity_t * commodity = - amount_t::current_pool->find_or_create(symbol)) + amount_t::current_pool->find_or_create(symbol)) { commodity->add_price(datetime, price); + commodity->add_flags(COMMODITY_KNOWN); + } else { + assert(false); + } } void instance_t::nomarket_directive(char * line) @@ -496,7 +507,7 @@ void instance_t::nomarket_directive(char * line) if (commodity_t * commodity = amount_t::current_pool->find_or_create(symbol)) - commodity->add_flags(COMMODITY_NOMARKET); + commodity->add_flags(COMMODITY_NOMARKET | COMMODITY_KNOWN); } void instance_t::year_directive(char * line) @@ -616,7 +627,7 @@ void instance_t::include_directive(char * line) timelog, #endif stream, session_scope, journal, master, - &filename, this); + &filename, strict, this); instance.parse(); errors += instance.errors; @@ -722,7 +733,8 @@ void instance_t::general_directive(char * line) xact_t * instance_t::parse_xact(char * line, std::streamsize len, account_t * account, - entry_t * entry) + entry_t * entry, + bool honor_strict) { TRACE_START(xact_details, 1, "Time spent parsing transactions:"); @@ -800,6 +812,14 @@ xact_t * instance_t::parse_xact(char * line, if (! xact->account) xact->account = account->find_account(name); + if (honor_strict && strict && ! xact->account->known) { + if (xact->_state == item_t::UNCLEARED) + std::cerr << "Warning: \"" << pathname << "\", line " << linenum + << ": Unknown account '" << xact->account->fullname() + << "'" << std::endl; + xact->account->known = true; + } + // Parse the optional amount bool saw_amount = false; @@ -817,6 +837,15 @@ xact_t * instance_t::parse_xact(char * line, static_cast<uint_least8_t>(expr_t::PARSE_NO_REDUCE) | static_cast<uint_least8_t>(expr_t::PARSE_NO_ASSIGN)); + if (! xact->amount.is_null() && honor_strict && strict && + xact->amount.has_commodity() && + ! xact->amount.commodity().has_flags(COMMODITY_KNOWN)) { + if (xact->_state == item_t::UNCLEARED) + std::cerr << "Warning: \"" << pathname << "\", line " << linenum + << ": Unknown commodity '" << xact->amount.commodity() + << "'" << std::endl; + xact->amount.commodity().add_flags(COMMODITY_KNOWN); + } #if 0 // jww (2009-02-12): This isn't quite working yet; it causes cost computes // to skyrocket, since the per-unit price isn't also being reduced by the @@ -1022,7 +1051,7 @@ bool instance_t::parse_xacts(account_t * account, std::streamsize len = read_line(line); assert(len > 0); - if (xact_t * xact = parse_xact(line, len, account, NULL)) { + if (xact_t * xact = parse_xact(line, len, account, NULL, false)) { entry.add_xact(xact); added = true; } @@ -1144,7 +1173,8 @@ expr_t::ptr_op_t instance_t::lookup(const string& name) std::size_t journal_t::parse(std::istream& in, scope_t& session_scope, account_t * master, - const path * original_file) + const path * original_file, + bool strict) { TRACE_START(parsing_total, 1, "Total time spent parsing text:"); @@ -1158,7 +1188,7 @@ std::size_t journal_t::parse(std::istream& in, timelog, #endif in, session_scope, *this, master, - original_file); + original_file, strict); parsing_instance.parse(); TRACE_STOP(parsing_total, 1); |