summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/account.h5
-rw-r--r--src/commodity.h1
-rw-r--r--src/journal.h5
-rw-r--r--src/precmd.cc2
-rw-r--r--src/session.cc6
-rw-r--r--src/session.h1
-rw-r--r--src/textual.cc48
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);