Added new account/payee/commodity directives
Also added supporting options: --explicit, --permissive, --pedantic, as well as new behavior for --strict.
This commit is contained in:
parent
30e8c0bc65
commit
61bc7362ca
10 changed files with 414 additions and 208 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
.Dd February 26, 2012
|
.Dd February 27, 2012
|
||||||
.Dt ledger 1
|
.Dt ledger 1
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm ledger
|
.Nm ledger
|
||||||
|
|
@ -313,6 +313,7 @@ See
|
||||||
.It Fl \-equity
|
.It Fl \-equity
|
||||||
.It Fl \-exact
|
.It Fl \-exact
|
||||||
.It Fl \-exchange Ar COMM Oo , COMM, ... Oc Pq Fl X
|
.It Fl \-exchange Ar COMM Oo , COMM, ... Oc Pq Fl X
|
||||||
|
.It Fl \-explicit
|
||||||
.It Fl \-file Ar FILE
|
.It Fl \-file Ar FILE
|
||||||
.It Fl \-first Ar INT
|
.It Fl \-first Ar INT
|
||||||
See
|
See
|
||||||
|
|
@ -367,10 +368,12 @@ See
|
||||||
.It Fl \-pager Ar STR
|
.It Fl \-pager Ar STR
|
||||||
.It Fl \-payee
|
.It Fl \-payee
|
||||||
.It Fl \-payee-width Ar INT
|
.It Fl \-payee-width Ar INT
|
||||||
|
.It Fl \-pedantic
|
||||||
.It Fl \-pending
|
.It Fl \-pending
|
||||||
.It Fl \-percent Pq Fl \%
|
.It Fl \-percent Pq Fl \%
|
||||||
.It Fl \-period Ar PERIOD Pq Fl p
|
.It Fl \-period Ar PERIOD Pq Fl p
|
||||||
.It Fl \-period-sort
|
.It Fl \-period-sort
|
||||||
|
.It Fl \-permissive
|
||||||
.It Fl \-pivot Ar STR
|
.It Fl \-pivot Ar STR
|
||||||
.It Fl \-plot-amount-format Ar FMT
|
.It Fl \-plot-amount-format Ar FMT
|
||||||
.It Fl \-plot-total-format Ar FMT
|
.It Fl \-plot-total-format Ar FMT
|
||||||
|
|
|
||||||
164
src/journal.cc
164
src/journal.cc
|
|
@ -36,6 +36,7 @@
|
||||||
#include "commodity.h"
|
#include "commodity.h"
|
||||||
#include "pool.h"
|
#include "pool.h"
|
||||||
#include "xact.h"
|
#include "xact.h"
|
||||||
|
#include "post.h"
|
||||||
#include "account.h"
|
#include "account.h"
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
@ -80,9 +81,15 @@ journal_t::~journal_t()
|
||||||
|
|
||||||
void journal_t::initialize()
|
void journal_t::initialize()
|
||||||
{
|
{
|
||||||
master = new account_t;
|
master = new account_t;
|
||||||
bucket = NULL;
|
bucket = NULL;
|
||||||
was_loaded = false;
|
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)
|
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);
|
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"))) {
|
account_t * result = NULL;
|
||||||
std::pair<checksum_map_t::iterator, bool> result
|
|
||||||
= checksum_map.insert(checksum_map_t::value_type(ref->to_string(), xact));
|
if (account_aliases.size() > 0) {
|
||||||
if (! result.second) {
|
accounts_map::const_iterator i = account_aliases.find(name);
|
||||||
throw_(std::runtime_error,
|
if (i != account_aliases.end())
|
||||||
_("Found duplicated transaction with SHA1: ")
|
result = (*i).second;
|
||||||
<< ref->to_string());
|
}
|
||||||
return false;
|
|
||||||
|
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;
|
xact->journal = this;
|
||||||
|
|
||||||
if (! xact->finalize()) {
|
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'")
|
_("No default scope in which to read journal file '%1'")
|
||||||
<< pathname);
|
<< pathname);
|
||||||
|
|
||||||
value_t strict = expr_t("strict").calc(*scope);
|
count = parse(in, *scope, master_alt ? master_alt : master, &pathname);
|
||||||
|
|
||||||
count = parse(in, *scope, master_alt ? master_alt : master,
|
|
||||||
&pathname, strict.to_boolean());
|
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
clear_xdata();
|
clear_xdata();
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,12 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
class commodity_t;
|
||||||
class xact_base_t;
|
class xact_base_t;
|
||||||
class xact_t;
|
class xact_t;
|
||||||
class auto_xact_t;
|
class auto_xact_t;
|
||||||
class period_xact_t;
|
class period_xact_t;
|
||||||
|
class post_t;
|
||||||
class account_t;
|
class account_t;
|
||||||
class scope_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<auto_xact_t *> auto_xacts_list;
|
||||||
typedef std::list<period_xact_t *> period_xacts_list;
|
typedef std::list<period_xact_t *> period_xacts_list;
|
||||||
|
|
||||||
typedef std::pair<mask_t, string> payee_mapping_t;
|
typedef std::pair<mask_t, string> payee_mapping_t;
|
||||||
typedef std::list<payee_mapping_t> payee_mappings_t;
|
typedef std::list<payee_mapping_t> payee_mappings_t;
|
||||||
typedef std::pair<mask_t, account_t *> account_mapping_t;
|
typedef std::pair<mask_t, account_t *> account_mapping_t;
|
||||||
typedef std::list<account_mapping_t> account_mappings_t;
|
typedef std::list<account_mapping_t> account_mappings_t;
|
||||||
typedef std::map<string, xact_t *> checksum_map_t;
|
typedef std::map<const string, account_t *> accounts_map;
|
||||||
|
typedef std::map<string, xact_t *> checksum_map_t;
|
||||||
|
|
||||||
class journal_t : public noncopyable
|
class journal_t : public noncopyable
|
||||||
{
|
{
|
||||||
|
|
@ -116,10 +119,25 @@ public:
|
||||||
auto_xacts_list auto_xacts;
|
auto_xacts_list auto_xacts;
|
||||||
period_xacts_list period_xacts;
|
period_xacts_list period_xacts;
|
||||||
std::list<fileinfo_t> sources;
|
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;
|
payee_mappings_t payee_mappings;
|
||||||
account_mappings_t account_mappings;
|
account_mappings_t account_mappings;
|
||||||
|
accounts_map account_aliases;
|
||||||
|
account_mappings_t payees_for_unknown_accounts;
|
||||||
checksum_map_t checksum_map;
|
checksum_map_t checksum_map;
|
||||||
bool was_loaded;
|
bool was_loaded;
|
||||||
|
bool force_checking;
|
||||||
|
|
||||||
|
enum checking_style_t {
|
||||||
|
CHECK_PERMISSIVE,
|
||||||
|
CHECK_WARNING,
|
||||||
|
CHECK_ERROR
|
||||||
|
} checking_style;
|
||||||
|
|
||||||
journal_t();
|
journal_t();
|
||||||
journal_t(const path& pathname);
|
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(const string& name, bool auto_create = true);
|
||||||
account_t * find_account_re(const string& regexp);
|
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);
|
bool add_xact(xact_t * xact);
|
||||||
void extend_xact(xact_base_t * xact);
|
void extend_xact(xact_base_t * xact);
|
||||||
bool remove_xact(xact_t * xact);
|
bool remove_xact(xact_t * xact);
|
||||||
|
|
@ -176,8 +208,7 @@ public:
|
||||||
std::size_t parse(std::istream& in,
|
std::size_t parse(std::istream& in,
|
||||||
scope_t& session_scope,
|
scope_t& session_scope,
|
||||||
account_t * master = NULL,
|
account_t * master = NULL,
|
||||||
const path * original_file = NULL,
|
const path * original_file = NULL);
|
||||||
bool strict = false);
|
|
||||||
|
|
||||||
bool has_xdata();
|
bool has_xdata();
|
||||||
void clear_xdata();
|
void clear_xdata();
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,16 @@ std::size_t session_t::read_data(const string& master_account)
|
||||||
if (HANDLED(price_db_))
|
if (HANDLED(price_db_))
|
||||||
price_db_path = resolve_path(HANDLER(price_db_).str());
|
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)
|
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||||
optional<archive_t> cache;
|
optional<archive_t> cache;
|
||||||
if (HANDLED(cache_) && master_account.empty())
|
if (HANDLED(cache_) && master_account.empty())
|
||||||
|
|
@ -251,6 +261,7 @@ option_t<session_t> * session_t::lookup_option(const char * p)
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
OPT_ALT(price_exp_, leeway_);
|
OPT_ALT(price_exp_, leeway_);
|
||||||
|
else OPT(explicit);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
OPT(master_account_);
|
OPT(master_account_);
|
||||||
|
|
@ -258,6 +269,8 @@ option_t<session_t> * session_t::lookup_option(const char * p)
|
||||||
case 'p':
|
case 'p':
|
||||||
OPT(price_db_);
|
OPT(price_db_);
|
||||||
else OPT(price_exp_);
|
else OPT(price_exp_);
|
||||||
|
else OPT(pedantic);
|
||||||
|
else OPT(permissive);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
OPT(strict);
|
OPT(strict);
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,10 @@ public:
|
||||||
HANDLER(decimal_comma).report(out);
|
HANDLER(decimal_comma).report(out);
|
||||||
HANDLER(file_).report(out);
|
HANDLER(file_).report(out);
|
||||||
HANDLER(input_date_format_).report(out);
|
HANDLER(input_date_format_).report(out);
|
||||||
|
HANDLER(explicit).report(out);
|
||||||
HANDLER(master_account_).report(out);
|
HANDLER(master_account_).report(out);
|
||||||
|
HANDLER(pedantic).report(out);
|
||||||
|
HANDLER(permissive).report(out);
|
||||||
HANDLER(price_db_).report(out);
|
HANDLER(price_db_).report(out);
|
||||||
HANDLER(price_exp_).report(out);
|
HANDLER(price_exp_).report(out);
|
||||||
HANDLER(strict).report(out);
|
HANDLER(strict).report(out);
|
||||||
|
|
@ -139,7 +142,10 @@ public:
|
||||||
set_input_date_format(args.get<string>(1).c_str());
|
set_input_date_format(args.get<string>(1).c_str());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
OPTION(session_t, explicit);
|
||||||
OPTION(session_t, master_account_);
|
OPTION(session_t, master_account_);
|
||||||
|
OPTION(session_t, pedantic);
|
||||||
|
OPTION(session_t, permissive);
|
||||||
OPTION(session_t, price_db_);
|
OPTION(session_t, price_db_);
|
||||||
OPTION(session_t, strict);
|
OPTION(session_t, strict);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
385
src/textual.cc
385
src/textual.cc
|
|
@ -49,43 +49,45 @@
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
typedef std::pair<commodity_t *, amount_t> fixed_rate_t;
|
typedef std::pair<commodity_t *, amount_t> fixed_rate_t;
|
||||||
typedef variant<account_t *, string, fixed_rate_t> state_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
|
class parse_context_t : public noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
journal_t& journal;
|
std::list<application_t> apply_stack;
|
||||||
scope_t& scope;
|
|
||||||
std::list<state_t> state_stack;
|
journal_t& journal;
|
||||||
|
scope_t& scope;
|
||||||
#if defined(TIMELOG_SUPPORT)
|
#if defined(TIMELOG_SUPPORT)
|
||||||
time_log_t timelog;
|
time_log_t timelog;
|
||||||
#endif
|
#endif
|
||||||
bool strict;
|
std::size_t count;
|
||||||
std::size_t count;
|
std::size_t errors;
|
||||||
std::size_t errors;
|
std::size_t sequence;
|
||||||
std::size_t sequence;
|
|
||||||
|
|
||||||
parse_context_t(journal_t& _journal, scope_t& _scope)
|
parse_context_t(journal_t& _journal, scope_t& _scope)
|
||||||
: journal(_journal), scope(_scope), timelog(journal, 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;
|
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() {
|
account_t * top_account() {
|
||||||
foreach (state_t& state, state_stack)
|
foreach (application_t& state, apply_stack)
|
||||||
if (state.type() == typeid(account_t *))
|
if (state.value.type() == typeid(account_t *))
|
||||||
return boost::get<account_t *>(state);
|
return boost::get<account_t *>(state.value);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,7 +103,6 @@ namespace {
|
||||||
public:
|
public:
|
||||||
parse_context_t& context;
|
parse_context_t& context;
|
||||||
instance_t * parent;
|
instance_t * parent;
|
||||||
accounts_map account_aliases;
|
|
||||||
const path * original_file;
|
const path * original_file;
|
||||||
path pathname;
|
path pathname;
|
||||||
std::istream& in;
|
std::istream& in;
|
||||||
|
|
@ -136,36 +137,52 @@ namespace {
|
||||||
void clock_out_directive(char * line, bool capitalized);
|
void clock_out_directive(char * line, bool capitalized);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void default_commodity_directive(char * line);
|
bool general_directive(char * line);
|
||||||
void default_account_directive(char * line);
|
|
||||||
void price_conversion_directive(char * line);
|
void account_directive(char * line);
|
||||||
void price_xact_directive(char * line);
|
void account_alias_directive(char * line);
|
||||||
void nomarket_directive(char * line);
|
void account_payee_directive(char * line);
|
||||||
void year_directive(char * line);
|
|
||||||
void option_directive(char * line);
|
void payee_directive(char * line);
|
||||||
void automated_xact_directive(char * line);
|
void payee_alias_directive(char * line);
|
||||||
void period_xact_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 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 default_account_directive(char * line);
|
||||||
|
void default_commodity_directive(char * line);
|
||||||
|
|
||||||
void include_directive(char * line);
|
void include_directive(char * line);
|
||||||
void master_account_directive(char * line);
|
void option_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 define_directive(char * line);
|
void define_directive(char * line);
|
||||||
|
void expr_directive(char * line);
|
||||||
void assert_directive(char * line);
|
void assert_directive(char * line);
|
||||||
void check_directive(char * line);
|
void check_directive(char * line);
|
||||||
void comment_directive(char * line);
|
void comment_directive(char * line);
|
||||||
void expr_directive(char * line);
|
|
||||||
bool general_directive(char * line);
|
|
||||||
|
|
||||||
post_t * parse_post(char * line,
|
post_t * parse_post(char * line,
|
||||||
std::streamsize len,
|
std::streamsize len,
|
||||||
account_t * account,
|
account_t * account,
|
||||||
xact_t * xact,
|
xact_t * xact,
|
||||||
bool defer_expr = false);
|
bool defer_expr = false);
|
||||||
|
|
||||||
bool parse_posts(account_t * account,
|
bool parse_posts(account_t * account,
|
||||||
xact_base_t& xact,
|
xact_base_t& xact,
|
||||||
|
|
@ -402,7 +419,7 @@ void instance_t::read_next_directive()
|
||||||
price_xact_directive(line);
|
price_xact_directive(line);
|
||||||
break;
|
break;
|
||||||
case 'Y': // set the current year
|
case 'Y': // set the current year
|
||||||
year_directive(line);
|
apply_year_directive(line);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -514,16 +531,6 @@ void instance_t::nomarket_directive(char * line)
|
||||||
commodity->add_flags(COMMODITY_NOMARKET | COMMODITY_KNOWN);
|
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)
|
void instance_t::option_directive(char * line)
|
||||||
{
|
{
|
||||||
char * p = next_element(line);
|
char * p = next_element(line);
|
||||||
|
|
@ -774,44 +781,97 @@ void instance_t::include_directive(char * line)
|
||||||
|
|
||||||
if (! files_found)
|
if (! files_found)
|
||||||
throw_(std::runtime_error,
|
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))
|
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)
|
#if !defined(NO_ASSERTS)
|
||||||
else
|
else
|
||||||
assert("Failed to create account" == NULL);
|
assert("Failed to create account" == NULL);
|
||||||
#endif
|
#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())
|
if (tag.find(':') == string::npos)
|
||||||
throw_(std::runtime_error,
|
tag = string(":") + tag + ":";
|
||||||
_("'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())
|
|
||||||
throw_(std::runtime_error,
|
|
||||||
_("'end fixed' directive does not match open directive"));
|
|
||||||
|
|
||||||
if (context.state_stack.size() <= 1)
|
context.apply_stack.push_front(application_t("tag", tag));
|
||||||
throw_(std::runtime_error,
|
|
||||||
_("'end' found, but no enclosing tag or account directive"));
|
|
||||||
else
|
|
||||||
context.state_stack.pop_front();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void instance_t::alias_directive(char * line)
|
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 %1' found, but no enclosing '%2' directive")
|
||||||
|
<< name << name);
|
||||||
|
|
||||||
|
if (name != context.apply_stack.front().label)
|
||||||
|
throw_(std::runtime_error,
|
||||||
|
_("'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::account_alias_directive(char * line)
|
||||||
{
|
{
|
||||||
char * b = skip_ws(line);
|
char * b = skip_ws(line);
|
||||||
|
#if 0
|
||||||
if (char * e = std::strchr(b, '=')) {
|
if (char * e = std::strchr(b, '=')) {
|
||||||
char * z = e - 1;
|
char * z = e - 1;
|
||||||
while (std::isspace(*z))
|
while (std::isspace(*z))
|
||||||
|
|
@ -828,21 +888,19 @@ void instance_t::alias_directive(char * line)
|
||||||
= account_aliases.insert(accounts_map::value_type(b, acct));
|
= account_aliases.insert(accounts_map::value_type(b, acct));
|
||||||
assert(result.second);
|
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 * payee = skip_ws(line);
|
||||||
char * regex = next_element(payee, true);
|
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)
|
void instance_t::account_mapping_directive(char * line)
|
||||||
{
|
{
|
||||||
char * account_name = skip_ws(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)));
|
context.top_account()->find_account(account_name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void instance_t::define_directive(char * line)
|
void instance_t::define_directive(char * line)
|
||||||
{
|
{
|
||||||
|
|
@ -958,11 +1028,11 @@ bool instance_t::general_directive(char * line)
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'a':
|
case 'a':
|
||||||
if (std::strcmp(p, "account") == 0) {
|
if (std::strcmp(p, "account") == 0) {
|
||||||
master_account_directive(arg);
|
account_directive(arg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (std::strcmp(p, "alias") == 0) {
|
else if (std::strcmp(p, "apply") == 0) {
|
||||||
alias_directive(arg);
|
apply_directive(arg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (std::strcmp(p, "assert") == 0) {
|
else if (std::strcmp(p, "assert") == 0) {
|
||||||
|
|
@ -979,11 +1049,7 @@ bool instance_t::general_directive(char * line)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
if (std::strcmp(p, "capture") == 0) {
|
if (std::strcmp(p, "check") == 0) {
|
||||||
account_mapping_directive(arg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (std::strcmp(p, "check") == 0) {
|
|
||||||
check_directive(arg);
|
check_directive(arg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -991,6 +1057,10 @@ bool instance_t::general_directive(char * line)
|
||||||
comment_directive(arg);
|
comment_directive(arg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (std::strcmp(p, "commodity") == 0) {
|
||||||
|
commodity_directive(arg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
|
|
@ -1002,7 +1072,7 @@ bool instance_t::general_directive(char * line)
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
if (std::strcmp(p, "end") == 0) {
|
if (std::strcmp(p, "end") == 0) {
|
||||||
end_directive(arg);
|
end_apply_directive(arg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (std::strcmp(p, "expr") == 0) {
|
else if (std::strcmp(p, "expr") == 0) {
|
||||||
|
|
@ -1011,13 +1081,6 @@ bool instance_t::general_directive(char * line)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
|
||||||
if (std::strcmp(p, "fixed") == 0) {
|
|
||||||
fixed_directive(arg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
if (std::strcmp(p, "include") == 0) {
|
if (std::strcmp(p, "include") == 0) {
|
||||||
include_directive(arg);
|
include_directive(arg);
|
||||||
|
|
@ -1027,28 +1090,17 @@ bool instance_t::general_directive(char * line)
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (std::strcmp(p, "payee") == 0) {
|
if (std::strcmp(p, "payee") == 0) {
|
||||||
payee_mapping_directive(arg);
|
payee_directive(arg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
if (std::strcmp(p, "tag") == 0) {
|
if (std::strcmp(p, "test") == 0) {
|
||||||
tag_directive(arg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (std::strcmp(p, "test") == 0) {
|
|
||||||
comment_directive(arg);
|
comment_directive(arg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
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)) {
|
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 << ": "
|
DEBUG("textual.parse", "line " << linenum << ": "
|
||||||
<< "Parsed account name " << name);
|
<< "Parsed account name " << name);
|
||||||
|
|
||||||
if (account_aliases.size() > 0) {
|
post->account =
|
||||||
accounts_map::const_iterator i = account_aliases.find(name);
|
context.journal.register_account(name, post.get(),
|
||||||
if (i != account_aliases.end())
|
file_context(pathname, linenum),
|
||||||
post->account = (*i).second;
|
account);
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the optional amount
|
// Parse the optional amount
|
||||||
|
|
||||||
|
|
@ -1179,19 +1211,13 @@ post_t * instance_t::parse_post(char * line,
|
||||||
defer_expr, &post->amount_expr);
|
defer_expr, &post->amount_expr);
|
||||||
|
|
||||||
if (! post->amount.is_null() && post->amount.has_commodity()) {
|
if (! post->amount.is_null() && post->amount.has_commodity()) {
|
||||||
if (context.strict &&
|
context.journal.register_commodity(post->amount.commodity(), post.get(),
|
||||||
! post->amount.commodity().has_flags(COMMODITY_KNOWN)) {
|
file_context(pathname, linenum));
|
||||||
if (post->_state == item_t::UNCLEARED)
|
|
||||||
warning_(_("%1Unknown commodity '%2'")
|
|
||||||
<< file_context(pathname, linenum)
|
|
||||||
<< post->amount.commodity());
|
|
||||||
post->amount.commodity().add_flags(COMMODITY_KNOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! post->amount.has_annotation()) {
|
if (! post->amount.has_annotation()) {
|
||||||
foreach (state_t& state, context.state_stack) {
|
foreach (application_t& state, context.apply_stack) {
|
||||||
if (state.type() == typeid(fixed_rate_t)) {
|
if (state.value.type() == typeid(fixed_rate_t)) {
|
||||||
fixed_rate_t& rate(boost::get<fixed_rate_t>(state));
|
fixed_rate_t& rate(boost::get<fixed_rate_t>(state.value));
|
||||||
if (*rate.first == post->amount.commodity()) {
|
if (*rate.first == post->amount.commodity()) {
|
||||||
annotation_t details(rate.second);
|
annotation_t details(rate.second);
|
||||||
details.add_flags(ANNOTATION_PRICE_FIXATED);
|
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_pos = curr_pos;
|
||||||
post->pos->end_line = linenum;
|
post->pos->end_line = linenum;
|
||||||
|
|
||||||
if (! context.state_stack.empty()) {
|
if (! context.apply_stack.empty()) {
|
||||||
foreach (const state_t& state, context.state_stack)
|
foreach (const application_t& state, context.apply_stack)
|
||||||
if (state.type() == typeid(string))
|
if (state.value.type() == typeid(string))
|
||||||
post->parse_tags(boost::get<string>(state).c_str(), context.scope, true);
|
post->parse_tags(boost::get<string>(state.value).c_str(),
|
||||||
|
context.scope, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE_STOP(post_details, 1);
|
TRACE_STOP(post_details, 1);
|
||||||
|
|
@ -1488,14 +1515,9 @@ xact_t * instance_t::parse_xact(char * line,
|
||||||
|
|
||||||
if (next && *next) {
|
if (next && *next) {
|
||||||
char * p = next_element(next, true);
|
char * p = next_element(next, true);
|
||||||
foreach (payee_mapping_t& value, context.journal.payee_mappings) {
|
xact->payee =
|
||||||
if (value.first.match(next)) {
|
context.journal.register_payee(next, xact.get(),
|
||||||
xact->payee = value.second;
|
file_context(pathname, linenum));
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (xact->payee.empty())
|
|
||||||
xact->payee = next;
|
|
||||||
next = p;
|
next = p;
|
||||||
} else {
|
} else {
|
||||||
xact->payee = _("<Unspecified payee>");
|
xact->payee = _("<Unspecified payee>");
|
||||||
|
|
@ -1572,7 +1594,7 @@ xact_t * instance_t::parse_xact(char * line,
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (xact->_state == item_t::UNCLEARED) {
|
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) {
|
foreach (post_t * post, xact->posts) {
|
||||||
if (post->_state == item_t::UNCLEARED) {
|
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_pos = curr_pos;
|
||||||
xact->pos->end_line = linenum;
|
xact->pos->end_line = linenum;
|
||||||
|
|
||||||
if (! context.state_stack.empty()) {
|
if (! context.apply_stack.empty()) {
|
||||||
foreach (const state_t& state, context.state_stack)
|
foreach (const application_t& state, context.apply_stack)
|
||||||
if (state.type() == typeid(string))
|
if (state.value.type() == typeid(string))
|
||||||
xact->parse_tags(boost::get<string>(state).c_str(), context.scope,
|
xact->parse_tags(boost::get<string>(state.value).c_str(),
|
||||||
false);
|
context.scope, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE_STOP(xact_details, 1);
|
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,
|
std::size_t journal_t::parse(std::istream& in,
|
||||||
scope_t& scope,
|
scope_t& scope,
|
||||||
account_t * master_account,
|
account_t * master_account,
|
||||||
const path * original_file,
|
const path * original_file)
|
||||||
bool strict)
|
|
||||||
{
|
{
|
||||||
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
|
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
|
||||||
|
|
||||||
parse_context_t context(*this, scope);
|
parse_context_t context(*this, scope);
|
||||||
context.strict = strict;
|
|
||||||
if (master_account || this->master)
|
if (master_account || this->master)
|
||||||
context.state_stack.push_front(master_account ?
|
context.apply_stack.push_front(application_t("account",
|
||||||
master_account : this->master);
|
master_account ?
|
||||||
|
master_account : this->master));
|
||||||
|
|
||||||
instance_t instance(context, in, original_file);
|
instance_t instance(context, in, original_file);
|
||||||
instance.parse();
|
instance.parse();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
fixed XCD $0.374531835206
|
apply fixed XCD $0.374531835206
|
||||||
|
|
||||||
2008/04/08 KFC
|
2008/04/08 KFC
|
||||||
Expenses:Food XCD 43.00
|
Expenses:Food XCD 43.00
|
||||||
Assets:Cash
|
Assets:Cash
|
||||||
|
|
||||||
end fixed
|
end apply fixed
|
||||||
|
|
||||||
test reg
|
test reg
|
||||||
08-Apr-08 KFC Expenses:Food XCD 43.00 XCD 43.00
|
08-Apr-08 KFC Expenses:Food XCD 43.00 XCD 43.00
|
||||||
|
|
|
||||||
0
test/baseline/opt-explicit.test
Normal file
0
test/baseline/opt-explicit.test
Normal file
0
test/baseline/opt-pedantic.test
Normal file
0
test/baseline/opt-pedantic.test
Normal file
0
test/baseline/opt-permissive.test
Normal file
0
test/baseline/opt-permissive.test
Normal file
Loading…
Add table
Reference in a new issue