diff options
author | John Wiegley <johnw@newartisans.com> | 2012-02-27 02:29:42 -0600 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2012-02-27 02:31:09 -0600 |
commit | 61bc7362ca974543c9b851f8fc81fe981569ad6c (patch) | |
tree | f5a5420a6b4fa3cacc4ee3c2a9bddb2ebd6c632b /src | |
parent | 30e8c0bc65a94819d8375c9359d6ce77d908dcfc (diff) | |
download | fork-ledger-61bc7362ca974543c9b851f8fc81fe981569ad6c.tar.gz fork-ledger-61bc7362ca974543c9b851f8fc81fe981569ad6c.tar.bz2 fork-ledger-61bc7362ca974543c9b851f8fc81fe981569ad6c.zip |
Added new account/payee/commodity directives
Also added supporting options: --explicit, --permissive, --pedantic, as
well as new behavior for --strict.
Diffstat (limited to 'src')
-rw-r--r-- | src/journal.cc | 164 | ||||
-rw-r--r-- | src/journal.h | 45 | ||||
-rw-r--r-- | src/session.cc | 13 | ||||
-rw-r--r-- | src/session.h | 6 | ||||
-rw-r--r-- | src/textual.cc | 379 |
5 files changed, 405 insertions, 202 deletions
diff --git a/src/journal.cc b/src/journal.cc index 01cff2dc..43f6df77 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -36,6 +36,7 @@ #include "commodity.h" #include "pool.h" #include "xact.h" +#include "post.h" #include "account.h" namespace ledger { @@ -80,9 +81,15 @@ journal_t::~journal_t() void journal_t::initialize() { - master = new account_t; - bucket = NULL; - was_loaded = false; + master = new account_t; + bucket = NULL; + fixed_accounts = false; + fixed_payees = false; + fixed_commodities = false; + fixed_metadata = false; + was_loaded = false; + force_checking = false; + checking_style = CHECK_PERMISSIVE; } void journal_t::add_account(account_t * acct) @@ -105,19 +112,147 @@ account_t * journal_t::find_account_re(const string& regexp) return master->find_account_re(regexp); } -bool journal_t::add_xact(xact_t * xact) +account_t * journal_t::register_account(const string& name, post_t * post, + const string& location, + account_t * master_account) { - if (optional<value_t> ref = xact->get_tag(_("SHA1"))) { - std::pair<checksum_map_t::iterator, bool> result - = checksum_map.insert(checksum_map_t::value_type(ref->to_string(), xact)); - if (! result.second) { - throw_(std::runtime_error, - _("Found duplicated transaction with SHA1: ") - << ref->to_string()); - return false; + account_t * result = NULL; + + if (account_aliases.size() > 0) { + accounts_map::const_iterator i = account_aliases.find(name); + if (i != account_aliases.end()) + result = (*i).second; + } + + if (! result) + result = master_account->find_account(name); + + if (! result->has_flags(ACCOUNT_KNOWN)) { + if (! post) { + if (force_checking) + fixed_accounts = true; + result->add_flags(ACCOUNT_KNOWN); + } + else if (! fixed_accounts && post->_state != item_t::UNCLEARED) { + result->add_flags(ACCOUNT_KNOWN); + } + else if (checking_style == CHECK_WARNING) { + warning_(_("%1Unknown account '%2'") << location + << result->fullname()); + } + else if (checking_style == CHECK_ERROR) { + throw_(parse_error, _("Unknown account '%1'") << result->fullname()); + } + } + + if (result->name == _("Unknown")) { + foreach (account_mapping_t& value, payees_for_unknown_accounts) { + if (value.first.match(post->xact->payee)) { + result = value.second; + break; + } } } + return result; +} + +string journal_t::register_payee(const string& name, xact_t * xact, + const string& location) +{ +#if 0 + std::set<string>::iterator i = known_payees.find(name); + + if (i == known_payees.end()) { + if (! xact) { + if (force_checking) + fixed_payees = true; + known_payees.insert(name); + } + else if (! fixed_payees && xact->_state != item_t::UNCLEARED) { + known_payees.insert(name); + } + else if (checking_style == CHECK_WARNING) { + warning_(_("%1Unknown payee '%2'") << location << name); + } + else if (checking_style == CHECK_ERROR) { + throw_(parse_error, _("Unknown payee '%1'") << name); + } + } +#endif + +#if 0 + foreach (payee_mapping_t& value, context.journal.payee_mappings) { + if (value.first.match(next)) { + xact->payee = value.second; + break; + } + } + if (xact->payee.empty()) + xact->payee = next; +#else + return name; +#endif +} + +void journal_t::register_commodity(commodity_t& comm, + variant<int, xact_t *, post_t *> context, + const string& location) +{ + if (! comm.has_flags(COMMODITY_KNOWN)) { + if (context.which() == 0) { + if (force_checking) + fixed_commodities = true; + comm.add_flags(COMMODITY_KNOWN); + } + else if (! fixed_commodities && + ((context.which() == 1 && + boost::get<xact_t *>(context)->_state != item_t::UNCLEARED) || + (context.which() == 2 && + boost::get<post_t *>(context)->_state != item_t::UNCLEARED))) { + comm.add_flags(COMMODITY_KNOWN); + } + else if (checking_style == CHECK_WARNING) { + warning_(_("%1Unknown commodity '%2'") << location << comm); + } + else if (checking_style == CHECK_ERROR) { + throw_(parse_error, _("Unknown commodity '%1'") << comm); + } + } +} + +#if 0 +void journal_t::register_metadata(const string& key, const string& value, + variant<int, xact_t *, post_t *> context, + const string& location) +{ + std::set<string>::iterator i = known_tags.find(key); + + if (i == known_tags.end()) { + if (context.which() == 0) { + if (force_checking) + fixed_metadata = true; + known_tags.insert(key); + } + else if (! fixed_metadata && + ((context.which() == 1 && + boost::get<xact_t *>(context)->_state != item_t::UNCLEARED) || + (context.which() == 2 && + boost::get<post_t *>(context)->_state != item_t::UNCLEARED))) { + known_tags.insert(key); + } + else if (checking_style == CHECK_WARNING) { + warning_(_("%1Unknown metadata tag '%2'") << location << key); + } + else if (checking_style == CHECK_ERROR) { + throw_(parse_error, _("Unknown metadata tag '%1'") << key); + } + } +} +#endif + +bool journal_t::add_xact(xact_t * xact) +{ xact->journal = this; if (! xact->finalize()) { @@ -187,10 +322,7 @@ std::size_t journal_t::read(std::istream& in, _("No default scope in which to read journal file '%1'") << pathname); - value_t strict = expr_t("strict").calc(*scope); - - count = parse(in, *scope, master_alt ? master_alt : master, - &pathname, strict.to_boolean()); + count = parse(in, *scope, master_alt ? master_alt : master, &pathname); } catch (...) { clear_xdata(); diff --git a/src/journal.h b/src/journal.h index 49a6292b..7411aaf6 100644 --- a/src/journal.h +++ b/src/journal.h @@ -48,10 +48,12 @@ namespace ledger { +class commodity_t; class xact_base_t; class xact_t; class auto_xact_t; class period_xact_t; +class post_t; class account_t; class scope_t; @@ -59,11 +61,12 @@ typedef std::list<xact_t *> xacts_list; typedef std::list<auto_xact_t *> auto_xacts_list; typedef std::list<period_xact_t *> period_xacts_list; -typedef std::pair<mask_t, string> payee_mapping_t; -typedef std::list<payee_mapping_t> payee_mappings_t; -typedef std::pair<mask_t, account_t *> account_mapping_t; -typedef std::list<account_mapping_t> account_mappings_t; -typedef std::map<string, xact_t *> checksum_map_t; +typedef std::pair<mask_t, string> payee_mapping_t; +typedef std::list<payee_mapping_t> payee_mappings_t; +typedef std::pair<mask_t, account_t *> account_mapping_t; +typedef std::list<account_mapping_t> account_mappings_t; +typedef std::map<const string, account_t *> accounts_map; +typedef std::map<string, xact_t *> checksum_map_t; class journal_t : public noncopyable { @@ -116,10 +119,25 @@ public: auto_xacts_list auto_xacts; period_xacts_list period_xacts; std::list<fileinfo_t> sources; + std::set<string> known_payees; + std::set<string> known_tags; + bool fixed_accounts; + bool fixed_payees; + bool fixed_commodities; + bool fixed_metadata; payee_mappings_t payee_mappings; account_mappings_t account_mappings; + accounts_map account_aliases; + account_mappings_t payees_for_unknown_accounts; checksum_map_t checksum_map; bool was_loaded; + bool force_checking; + + enum checking_style_t { + CHECK_PERMISSIVE, + CHECK_WARNING, + CHECK_ERROR + } checking_style; journal_t(); journal_t(const path& pathname); @@ -142,6 +160,20 @@ public: account_t * find_account(const string& name, bool auto_create = true); account_t * find_account_re(const string& regexp); + account_t * register_account(const string& name, post_t * post, + const string& location, + account_t * master = NULL); + string register_payee(const string& name, xact_t * xact, + const string& location); + void register_commodity(commodity_t& comm, + variant<int, xact_t *, post_t *> context, + const string& location); +#if 0 + void register_metadata(const string& key, const string& value, + variant<int, xact_t *, post_t *> context, + const string& location); +#endif + bool add_xact(xact_t * xact); void extend_xact(xact_base_t * xact); bool remove_xact(xact_t * xact); @@ -176,8 +208,7 @@ public: std::size_t parse(std::istream& in, scope_t& session_scope, account_t * master = NULL, - const path * original_file = NULL, - bool strict = false); + const path * original_file = NULL); bool has_xdata(); void clear_xdata(); diff --git a/src/session.cc b/src/session.cc index 72e29895..cc069efe 100644 --- a/src/session.cc +++ b/src/session.cc @@ -97,6 +97,16 @@ std::size_t session_t::read_data(const string& master_account) if (HANDLED(price_db_)) price_db_path = resolve_path(HANDLER(price_db_).str()); + if (HANDLED(explicit)) + journal->force_checking = true; + + if (HANDLED(permissive)) + journal->checking_style = journal_t::CHECK_PERMISSIVE; + else if (HANDLED(pedantic)) + journal->checking_style = journal_t::CHECK_ERROR; + else if (HANDLED(strict)) + journal->checking_style = journal_t::CHECK_WARNING; + #if defined(HAVE_BOOST_SERIALIZATION) optional<archive_t> cache; if (HANDLED(cache_) && master_account.empty()) @@ -251,6 +261,7 @@ option_t<session_t> * session_t::lookup_option(const char * p) break; case 'l': OPT_ALT(price_exp_, leeway_); + else OPT(explicit); break; case 'm': OPT(master_account_); @@ -258,6 +269,8 @@ option_t<session_t> * session_t::lookup_option(const char * p) case 'p': OPT(price_db_); else OPT(price_exp_); + else OPT(pedantic); + else OPT(permissive); break; case 's': OPT(strict); diff --git a/src/session.h b/src/session.h index b8fd52f2..5d6d4bed 100644 --- a/src/session.h +++ b/src/session.h @@ -91,7 +91,10 @@ public: HANDLER(decimal_comma).report(out); HANDLER(file_).report(out); HANDLER(input_date_format_).report(out); + HANDLER(explicit).report(out); HANDLER(master_account_).report(out); + HANDLER(pedantic).report(out); + HANDLER(permissive).report(out); HANDLER(price_db_).report(out); HANDLER(price_exp_).report(out); HANDLER(strict).report(out); @@ -139,7 +142,10 @@ public: set_input_date_format(args.get<string>(1).c_str()); }); + OPTION(session_t, explicit); OPTION(session_t, master_account_); + OPTION(session_t, pedantic); + OPTION(session_t, permissive); OPTION(session_t, price_db_); OPTION(session_t, strict); }; diff --git a/src/textual.cc b/src/textual.cc index 13032236..8a1968fc 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -49,43 +49,45 @@ namespace ledger { namespace { - typedef std::pair<commodity_t *, amount_t> fixed_rate_t; - typedef variant<account_t *, string, fixed_rate_t> state_t; + typedef std::pair<commodity_t *, amount_t> fixed_rate_t; + + struct application_t + { + string label; + variant<account_t *, string, fixed_rate_t> value; + + application_t(string _label, account_t * acct) + : label(_label), value(acct) {} + application_t(string _label, string tag) + : label(_label), value(tag) {} + application_t(string _label, fixed_rate_t rate) + : label(_label), value(rate) {} + }; class parse_context_t : public noncopyable { public: - journal_t& journal; - scope_t& scope; - std::list<state_t> state_stack; + std::list<application_t> apply_stack; + + journal_t& journal; + scope_t& scope; #if defined(TIMELOG_SUPPORT) - time_log_t timelog; + time_log_t timelog; #endif - bool strict; - std::size_t count; - std::size_t errors; - std::size_t sequence; + std::size_t count; + std::size_t errors; + std::size_t sequence; parse_context_t(journal_t& _journal, scope_t& _scope) : journal(_journal), scope(_scope), timelog(journal, scope), - strict(false), count(0), errors(0), sequence(1) { + count(0), errors(0), sequence(1) { timelog.context_count = &count; } - bool front_is_account() { - return state_stack.front().type() == typeid(account_t *); - } - bool front_is_string() { - return state_stack.front().type() == typeid(string); - } - bool front_is_fixed_rate() { - return state_stack.front().type() == typeid(fixed_rate_t); - } - account_t * top_account() { - foreach (state_t& state, state_stack) - if (state.type() == typeid(account_t *)) - return boost::get<account_t *>(state); + foreach (application_t& state, apply_stack) + if (state.value.type() == typeid(account_t *)) + return boost::get<account_t *>(state.value); return NULL; } @@ -101,7 +103,6 @@ namespace { public: parse_context_t& context; instance_t * parent; - accounts_map account_aliases; const path * original_file; path pathname; std::istream& in; @@ -136,36 +137,52 @@ namespace { void clock_out_directive(char * line, bool capitalized); #endif - void default_commodity_directive(char * line); - void default_account_directive(char * line); - void price_conversion_directive(char * line); + bool general_directive(char * line); + + void account_directive(char * line); + void account_alias_directive(char * line); + void account_payee_directive(char * line); + + void payee_directive(char * line); + void payee_alias_directive(char * line); + + void commodity_directive(char * line); +#if 0 + void commodity_alias_directive(char * line); + void commodity_format_directive(char * line); + void commodity_nomarket_directive(char * line); +#endif + + void apply_directive(char * line); + void apply_account_directive(char * line); + void apply_tag_directive(char * line); + void apply_rate_directive(char * line); + void apply_year_directive(char * line); + void end_apply_directive(char * line); + + void xact_directive(char * line, std::streamsize len); + void period_xact_directive(char * line); + void automated_xact_directive(char * line); void price_xact_directive(char * line); + void price_conversion_directive(char * line); void nomarket_directive(char * line); - void year_directive(char * line); - void option_directive(char * line); - void automated_xact_directive(char * line); - void period_xact_directive(char * line); - void xact_directive(char * line, std::streamsize len); + + void default_account_directive(char * line); + void default_commodity_directive(char * line); + void include_directive(char * line); - void master_account_directive(char * line); - void end_directive(char * line); - void alias_directive(char * line); - void fixed_directive(char * line); - void payee_mapping_directive(char * line); - void account_mapping_directive(char * line); - void tag_directive(char * line); + void option_directive(char * line); void define_directive(char * line); + void expr_directive(char * line); void assert_directive(char * line); void check_directive(char * line); void comment_directive(char * line); - void expr_directive(char * line); - bool general_directive(char * line); post_t * parse_post(char * line, std::streamsize len, account_t * account, xact_t * xact, - bool defer_expr = false); + bool defer_expr = false); bool parse_posts(account_t * account, xact_base_t& xact, @@ -402,7 +419,7 @@ void instance_t::read_next_directive() price_xact_directive(line); break; case 'Y': // set the current year - year_directive(line); + apply_year_directive(line); break; } } @@ -514,16 +531,6 @@ void instance_t::nomarket_directive(char * line) commodity->add_flags(COMMODITY_NOMARKET | COMMODITY_KNOWN); } -void instance_t::year_directive(char * line) -{ - unsigned short year(lexical_cast<unsigned short>(skip_ws(line + 1))); - DEBUG("times.epoch", "Setting current year to " << year); - // This must be set to the last day of the year, otherwise partial - // dates like "11/01" will refer to last year's november, not the - // current year. - epoch = datetime_t(date_t(year, 12, 31)); -} - void instance_t::option_directive(char * line) { char * p = next_element(line); @@ -774,44 +781,97 @@ void instance_t::include_directive(char * line) if (! files_found) throw_(std::runtime_error, - _("File to include was not found: '%1'") << filename); + _("File to include was not found: %1") << filename); } -void instance_t::master_account_directive(char * line) +void instance_t::apply_directive(char * line) +{ + char * b = next_element(line); + string keyword(line); + if (keyword == "account") + apply_account_directive(b); + else if (keyword == "tag") + apply_tag_directive(b); + else if (keyword == "fixed" || keyword == "rate") + apply_rate_directive(b); + else if (keyword == "year") + apply_year_directive(b); +} + +void instance_t::apply_account_directive(char * line) { if (account_t * acct = context.top_account()->find_account(line)) - context.state_stack.push_front(acct); + context.apply_stack.push_front(application_t("account", acct)); #if !defined(NO_ASSERTS) else assert("Failed to create account" == NULL); #endif } -void instance_t::end_directive(char * kind) +void instance_t::apply_tag_directive(char * line) { - string name(kind ? kind : ""); + string tag(trim_ws(line)); - if ((name.empty() || name == "account") && ! context.front_is_account()) - throw_(std::runtime_error, - _("'end account' directive does not match open directive")); - else if (name == "tag" && ! context.front_is_string()) - throw_(std::runtime_error, - _("'end tag' directive does not match open directive")); - else if (name == "fixed" && ! context.front_is_fixed_rate()) + if (tag.find(':') == string::npos) + tag = string(":") + tag + ":"; + + context.apply_stack.push_front(application_t("tag", tag)); +} + +void instance_t::apply_rate_directive(char * line) +{ + if (optional<std::pair<commodity_t *, price_point_t> > price_point = + commodity_pool_t::current_pool->parse_price_directive(trim_ws(line), true)) { + context.apply_stack.push_front + (application_t("fixed", fixed_rate_t(price_point->first, + price_point->second.price))); + } else { + throw_(std::runtime_error, _("Error in fixed directive")); + } +} + +void instance_t::apply_year_directive(char * line) +{ + unsigned short year(lexical_cast<unsigned short>(skip_ws(line + 1))); + DEBUG("times.epoch", "Setting current year to " << year); + // This must be set to the last day of the year, otherwise partial + // dates like "11/01" will refer to last year's november, not the + // current year. + epoch = datetime_t(date_t(year, 12, 31)); +} + +void instance_t::end_apply_directive(char * kind) +{ + char * b = next_element(kind); + string name(b ? b : "account"); + + if (context.apply_stack.size() <= 1) throw_(std::runtime_error, - _("'end fixed' directive does not match open directive")); + _("'end %1' found, but no enclosing '%2' directive") + << name << name); - if (context.state_stack.size() <= 1) + if (name != context.apply_stack.front().label) throw_(std::runtime_error, - _("'end' found, but no enclosing tag or account directive")); - else - context.state_stack.pop_front(); + _("'end %1' directive does not match 'apply %2' directive") + << name << context.apply_stack.front().label); + + context.apply_stack.pop_front(); +} + +void instance_t::account_directive(char * line) +{ + char * p = skip_ws(line); + //account_t * account = + context.journal.register_account(p, NULL, + file_context(pathname, linenum), + context.top_account()); } -void instance_t::alias_directive(char * line) +void instance_t::account_alias_directive(char * line) { char * b = skip_ws(line); +#if 0 if (char * e = std::strchr(b, '=')) { char * z = e - 1; while (std::isspace(*z)) @@ -828,21 +888,19 @@ void instance_t::alias_directive(char * line) = account_aliases.insert(accounts_map::value_type(b, acct)); assert(result.second); } +#endif } -void instance_t::fixed_directive(char * line) +void instance_t::account_payee_directive(char * line) { - if (optional<std::pair<commodity_t *, price_point_t> > price_point = - commodity_pool_t::current_pool->parse_price_directive(trim_ws(line), - true)) { - context.state_stack.push_front(fixed_rate_t(price_point->first, - price_point->second.price)); - } else { - throw_(std::runtime_error, _("Error in fixed directive")); - } } -void instance_t::payee_mapping_directive(char * line) +void instance_t::payee_directive(char * line) +{ + context.journal.register_payee(line, NULL, file_context(pathname, linenum)); +} + +void instance_t::payee_alias_directive(char * line) { char * payee = skip_ws(line); char * regex = next_element(payee, true); @@ -868,6 +926,27 @@ void instance_t::payee_mapping_directive(char * line) } } +void instance_t::commodity_directive(char * line) +{ + char * p = skip_ws(line); + string symbol; + commodity_t::parse_symbol(p, symbol); + + if (commodity_t * commodity = + commodity_pool_t::current_pool->find_or_create(symbol)) + context.journal.register_commodity(*commodity, 0, + file_context(pathname, linenum)); +} + +#if 0 +void instance_t::commodity_alias_directive(char * line) +{ +} + +void instance_t::commodity_nomarket_directive(char * line) +{ +} + void instance_t::account_mapping_directive(char * line) { char * account_name = skip_ws(line); @@ -895,16 +974,7 @@ void instance_t::account_mapping_directive(char * line) context.top_account()->find_account(account_name))); } } - -void instance_t::tag_directive(char * line) -{ - string tag(trim_ws(line)); - - if (tag.find(':') == string::npos) - tag = string(":") + tag + ":"; - - context.state_stack.push_front(tag); -} +#endif void instance_t::define_directive(char * line) { @@ -958,11 +1028,11 @@ bool instance_t::general_directive(char * line) switch (*p) { case 'a': if (std::strcmp(p, "account") == 0) { - master_account_directive(arg); + account_directive(arg); return true; } - else if (std::strcmp(p, "alias") == 0) { - alias_directive(arg); + else if (std::strcmp(p, "apply") == 0) { + apply_directive(arg); return true; } else if (std::strcmp(p, "assert") == 0) { @@ -979,11 +1049,7 @@ bool instance_t::general_directive(char * line) break; case 'c': - if (std::strcmp(p, "capture") == 0) { - account_mapping_directive(arg); - return true; - } - else if (std::strcmp(p, "check") == 0) { + if (std::strcmp(p, "check") == 0) { check_directive(arg); return true; } @@ -991,6 +1057,10 @@ bool instance_t::general_directive(char * line) comment_directive(arg); return true; } + else if (std::strcmp(p, "commodity") == 0) { + commodity_directive(arg); + return true; + } break; case 'd': @@ -1002,7 +1072,7 @@ bool instance_t::general_directive(char * line) case 'e': if (std::strcmp(p, "end") == 0) { - end_directive(arg); + end_apply_directive(arg); return true; } else if (std::strcmp(p, "expr") == 0) { @@ -1011,13 +1081,6 @@ bool instance_t::general_directive(char * line) } break; - case 'f': - if (std::strcmp(p, "fixed") == 0) { - fixed_directive(arg); - return true; - } - break; - case 'i': if (std::strcmp(p, "include") == 0) { include_directive(arg); @@ -1027,28 +1090,17 @@ bool instance_t::general_directive(char * line) case 'p': if (std::strcmp(p, "payee") == 0) { - payee_mapping_directive(arg); + payee_directive(arg); return true; } break; case 't': - if (std::strcmp(p, "tag") == 0) { - tag_directive(arg); - return true; - } - else if (std::strcmp(p, "test") == 0) { + if (std::strcmp(p, "test") == 0) { comment_directive(arg); return true; } break; - - case 'y': - if (std::strcmp(p, "year") == 0) { - year_directive(arg); - return true; - } - break; } if (expr_t::ptr_op_t op = lookup(symbol_t::DIRECTIVE, p)) { @@ -1140,30 +1192,10 @@ post_t * instance_t::parse_post(char * line, DEBUG("textual.parse", "line " << linenum << ": " << "Parsed account name " << name); - if (account_aliases.size() > 0) { - accounts_map::const_iterator i = account_aliases.find(name); - if (i != account_aliases.end()) - post->account = (*i).second; - } - if (! post->account) - post->account = account->find_account(name); - - if (context.strict && ! post->account->has_flags(ACCOUNT_KNOWN)) { - if (post->_state == item_t::UNCLEARED) - warning_(_("%1Unknown account '%2'") - << file_context(pathname, linenum) - << post->account->fullname()); - post->account->add_flags(ACCOUNT_KNOWN); - } - - if (post->account->name == _("Unknown")) { - foreach (account_mapping_t& value, context.journal.account_mappings) { - if (value.first.match(xact->payee)) { - post->account = value.second; - break; - } - } - } + post->account = + context.journal.register_account(name, post.get(), + file_context(pathname, linenum), + account); // Parse the optional amount @@ -1179,19 +1211,13 @@ post_t * instance_t::parse_post(char * line, defer_expr, &post->amount_expr); if (! post->amount.is_null() && post->amount.has_commodity()) { - if (context.strict && - ! post->amount.commodity().has_flags(COMMODITY_KNOWN)) { - if (post->_state == item_t::UNCLEARED) - warning_(_("%1Unknown commodity '%2'") - << file_context(pathname, linenum) - << post->amount.commodity()); - post->amount.commodity().add_flags(COMMODITY_KNOWN); - } + context.journal.register_commodity(post->amount.commodity(), post.get(), + file_context(pathname, linenum)); if (! post->amount.has_annotation()) { - foreach (state_t& state, context.state_stack) { - if (state.type() == typeid(fixed_rate_t)) { - fixed_rate_t& rate(boost::get<fixed_rate_t>(state)); + foreach (application_t& state, context.apply_stack) { + if (state.value.type() == typeid(fixed_rate_t)) { + fixed_rate_t& rate(boost::get<fixed_rate_t>(state.value)); if (*rate.first == post->amount.commodity()) { annotation_t details(rate.second); details.add_flags(ANNOTATION_PRICE_FIXATED); @@ -1388,10 +1414,11 @@ post_t * instance_t::parse_post(char * line, post->pos->end_pos = curr_pos; post->pos->end_line = linenum; - if (! context.state_stack.empty()) { - foreach (const state_t& state, context.state_stack) - if (state.type() == typeid(string)) - post->parse_tags(boost::get<string>(state).c_str(), context.scope, true); + if (! context.apply_stack.empty()) { + foreach (const application_t& state, context.apply_stack) + if (state.value.type() == typeid(string)) + post->parse_tags(boost::get<string>(state.value).c_str(), + context.scope, true); } TRACE_STOP(post_details, 1); @@ -1488,14 +1515,9 @@ xact_t * instance_t::parse_xact(char * line, if (next && *next) { char * p = next_element(next, true); - foreach (payee_mapping_t& value, context.journal.payee_mappings) { - if (value.first.match(next)) { - xact->payee = value.second; - break; - } - } - if (xact->payee.empty()) - xact->payee = next; + xact->payee = + context.journal.register_payee(next, xact.get(), + file_context(pathname, linenum)); next = p; } else { xact->payee = _("<Unspecified payee>"); @@ -1572,7 +1594,7 @@ xact_t * instance_t::parse_xact(char * line, #if 0 if (xact->_state == item_t::UNCLEARED) { - item_t::state_t result = item_t::CLEARED; + item_t::application_t result = item_t::CLEARED; foreach (post_t * post, xact->posts) { if (post->_state == item_t::UNCLEARED) { @@ -1589,11 +1611,11 @@ xact_t * instance_t::parse_xact(char * line, xact->pos->end_pos = curr_pos; xact->pos->end_line = linenum; - if (! context.state_stack.empty()) { - foreach (const state_t& state, context.state_stack) - if (state.type() == typeid(string)) - xact->parse_tags(boost::get<string>(state).c_str(), context.scope, - false); + if (! context.apply_stack.empty()) { + foreach (const application_t& state, context.apply_stack) + if (state.value.type() == typeid(string)) + xact->parse_tags(boost::get<string>(state.value).c_str(), + context.scope, false); } TRACE_STOP(xact_details, 1); @@ -1620,16 +1642,15 @@ expr_t::ptr_op_t instance_t::lookup(const symbol_t::kind_t kind, std::size_t journal_t::parse(std::istream& in, scope_t& scope, account_t * master_account, - const path * original_file, - bool strict) + const path * original_file) { TRACE_START(parsing_total, 1, "Total time spent parsing text:"); parse_context_t context(*this, scope); - context.strict = strict; if (master_account || this->master) - context.state_stack.push_front(master_account ? - master_account : this->master); + context.apply_stack.push_front(application_t("account", + master_account ? + master_account : this->master)); instance_t instance(context, in, original_file); instance.parse(); |