summaryrefslogtreecommitdiff
path: root/src/textual.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/textual.cc')
-rw-r--r--src/textual.cc580
1 files changed, 290 insertions, 290 deletions
diff --git a/src/textual.cc b/src/textual.cc
index dba31323..5308fa18 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -49,26 +49,26 @@
namespace ledger {
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;
class parse_context_t : public noncopyable
{
public:
- journal_t& journal;
- scope_t& scope;
+ journal_t& journal;
+ scope_t& scope;
std::list<state_t> state_stack;
#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;
+ bool strict;
+ 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),
- strict(false), count(0), errors(0), sequence(1) {}
+ strict(false), count(0), errors(0), sequence(1) {}
bool front_is_account() {
return state_stack.front().type() == typeid(account_t *);
@@ -82,8 +82,8 @@ namespace {
account_t * top_account() {
foreach (state_t& state, state_stack)
- if (state.type() == typeid(account_t *))
- return boost::get<account_t *>(state);
+ if (state.type() == typeid(account_t *))
+ return boost::get<account_t *>(state);
return NULL;
}
};
@@ -97,9 +97,9 @@ namespace {
instance_t * parent;
accounts_map account_aliases;
const path * original_file;
- path pathname;
+ path pathname;
std::istream& in;
- char linebuf[MAX_LINE + 1];
+ char linebuf[MAX_LINE + 1];
std::size_t linenum;
istream_pos_type line_beg_pos;
istream_pos_type curr_pos;
@@ -107,9 +107,9 @@ namespace {
optional<date_t::year_type> current_year;
instance_t(parse_context_t& _context,
- std::istream& _in,
- const path * _original_file = NULL,
- instance_t * _parent = NULL);
+ std::istream& _in,
+ const path * _original_file = NULL,
+ instance_t * _parent = NULL);
~instance_t();
@@ -117,7 +117,7 @@ namespace {
std::streamsize read_line(char *& line);
bool peek_whitespace_line() {
return (in.good() && ! in.eof() &&
- (in.peek() == ' ' || in.peek() == '\t'));
+ (in.peek() == ' ' || in.peek() == '\t'));
}
void read_next_directive();
@@ -148,31 +148,31 @@ namespace {
void define_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);
+ post_t * parse_post(char * line,
+ std::streamsize len,
+ account_t * account,
+ xact_t * xact,
+ bool defer_expr = false);
bool parse_posts(account_t * account,
- xact_base_t& xact,
- const bool defer_expr = false);
+ xact_base_t& xact,
+ const bool defer_expr = false);
- xact_t * parse_xact(char * line,
- std::streamsize len,
- account_t * account);
+ xact_t * parse_xact(char * line,
+ std::streamsize len,
+ account_t * account);
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
- const string& name);
+ const string& name);
};
- void parse_amount_expr(std::istream& in,
- scope_t& scope,
- post_t& post,
- amount_t& amount,
- const parse_flags_t& flags = PARSE_DEFAULT,
- const bool defer_expr = false,
- optional<expr_t> * amount_expr = NULL)
+ void parse_amount_expr(std::istream& in,
+ scope_t& scope,
+ post_t& post,
+ amount_t& amount,
+ const parse_flags_t& flags = PARSE_DEFAULT,
+ const bool defer_expr = false,
+ optional<expr_t> * amount_expr = NULL)
{
expr_t expr(in, flags.plus_flags(PARSE_PARTIAL));
@@ -181,25 +181,25 @@ namespace {
#if defined(DEBUG_ENABLED)
DEBUG_IF("textual.parse") {
if (_debug_stream) {
- ledger::dump_value_expr(*_debug_stream, expr);
- *_debug_stream << std::endl;
+ ledger::dump_value_expr(*_debug_stream, expr);
+ *_debug_stream << std::endl;
}
}
#endif
if (expr) {
if (amount_expr)
- *amount_expr = expr;
+ *amount_expr = expr;
if (! defer_expr)
- amount = post.resolve_expr(scope, expr);
+ amount = post.resolve_expr(scope, expr);
}
}
}
instance_t::instance_t(parse_context_t& _context,
- std::istream& _in,
- const path * _original_file,
- instance_t * _parent)
+ std::istream& _in,
+ const path * _original_file,
+ instance_t * _parent)
: context(_context), parent(_parent), original_file(_original_file),
pathname(original_file ? *original_file : "/dev/stdin"), in(_in)
{
@@ -216,7 +216,7 @@ void instance_t::parse()
INFO("Parsing file '" << pathname.string() << "'");
TRACE_START(instance_parse, 1,
- "Done parsing file '" << pathname.string() << "'");
+ "Done parsing file '" << pathname.string() << "'");
if (! in.good() || in.eof())
return;
@@ -232,30 +232,30 @@ void instance_t::parse()
string current_context = error_context();
if (parent) {
- std::list<instance_t *> instances;
+ std::list<instance_t *> instances;
- for (instance_t * instance = parent;
- instance;
- instance = instance->parent)
- instances.push_front(instance);
+ for (instance_t * instance = parent;
+ instance;
+ instance = instance->parent)
+ instances.push_front(instance);
- foreach (instance_t * instance, instances)
- add_error_context(_("In file included from %1")
- << file_context(instance->pathname,
- instance->linenum));
+ foreach (instance_t * instance, instances)
+ add_error_context(_("In file included from %1")
+ << file_context(instance->pathname,
+ instance->linenum));
}
add_error_context(_("While parsing file %1")
- << file_context(pathname, linenum));
+ << file_context(pathname, linenum));
if (caught_signal != NONE_CAUGHT)
- throw;
+ throw;
string err_context = error_context();
if (! err_context.empty())
- std::cerr << err_context << std::endl;
+ std::cerr << err_context << std::endl;
if (! current_context.empty())
- std::cerr << current_context << std::endl;
+ std::cerr << current_context << std::endl;
std::cerr << _("Error: ") << err.what() << std::endl;
context.errors++;
@@ -268,7 +268,7 @@ void instance_t::parse()
std::streamsize instance_t::read_line(char *& line)
{
assert(in.good());
- assert(! in.eof()); // no one should call us in that case
+ assert(! in.eof()); // no one should call us in that case
line_beg_pos = curr_pos;
@@ -283,7 +283,7 @@ std::streamsize instance_t::read_line(char *& line)
else
line = linebuf;
- if (line[len - 1] == '\r') // strip Windows CRLF down to LF
+ if (line[len - 1] == '\r') // strip Windows CRLF down to LF
line[--len] = '\0';
linenum++;
@@ -291,7 +291,7 @@ std::streamsize instance_t::read_line(char *& line)
curr_pos = line_beg_pos;
curr_pos += len;
- return len - 1; // LF is being silently dropped
+ return len - 1; // LF is being silently dropped
}
return 0;
}
@@ -306,7 +306,7 @@ void instance_t::read_next_directive()
switch (line[0]) {
case '\0':
- assert(false); // shouldn't ever reach here
+ assert(false); // shouldn't ever reach here
break;
case ' ':
@@ -314,13 +314,13 @@ void instance_t::read_next_directive()
break;
}
- case ';': // comments
+ case ';': // comments
case '#':
case '*':
case '|':
break;
- case '-': // option setting
+ case '-': // option setting
option_directive(line);
break;
@@ -336,10 +336,10 @@ void instance_t::read_next_directive()
case '9':
xact_directive(line, len);
break;
- case '=': // automated xact
+ case '=': // automated xact
automated_xact_directive(line);
break;
- case '~': // period xact
+ case '~': // period xact
period_xact_directive(line);
break;
@@ -347,47 +347,47 @@ void instance_t::read_next_directive()
case '!':
line++;
// fall through...
- default: // some other directive
+ default: // some other directive
if (! general_directive(line)) {
switch (line[0]) {
#if defined(TIMELOG_SUPPORT)
case 'i':
- clock_in_directive(line, false);
- break;
+ clock_in_directive(line, false);
+ break;
case 'I':
- clock_in_directive(line, true);
- break;
+ clock_in_directive(line, true);
+ break;
case 'o':
- clock_out_directive(line, false);
- break;
+ clock_out_directive(line, false);
+ break;
case 'O':
- clock_out_directive(line, true);
- break;
+ clock_out_directive(line, true);
+ break;
case 'h':
case 'b':
- break;
+ break;
#endif // TIMELOG_SUPPORT
- case 'A': // a default account for unbalanced posts
- default_account_directive(line);
- break;
- case 'C': // a set of conversions
- price_conversion_directive(line);
- break;
- case 'D': // a default commodity for "xact"
- default_commodity_directive(line);
- break;
- case 'N': // don't download prices
- nomarket_directive(line);
- break;
- case 'P': // a pricing xact
- price_xact_directive(line);
- break;
- case 'Y': // set the current year
- year_directive(line);
- break;
+ case 'A': // a default account for unbalanced posts
+ default_account_directive(line);
+ break;
+ case 'C': // a set of conversions
+ price_conversion_directive(line);
+ break;
+ case 'D': // a default commodity for "xact"
+ default_commodity_directive(line);
+ break;
+ case 'N': // don't download prices
+ nomarket_directive(line);
+ break;
+ case 'P': // a pricing xact
+ price_xact_directive(line);
+ break;
+ case 'Y': // set the current year
+ year_directive(line);
+ break;
}
}
break;
@@ -418,9 +418,9 @@ void instance_t::clock_in_directive(char * line, bool /*capitalized*/)
position.sequence = context.sequence++;
time_xact_t event(position, parse_datetime(datetime, current_year),
- p ? context.top_account()->find_account(p) : NULL,
- n ? n : "",
- end ? end : "");
+ p ? context.top_account()->find_account(p) : NULL,
+ n ? n : "",
+ end ? end : "");
context.timelog.clock_in(event);
}
@@ -447,9 +447,9 @@ void instance_t::clock_out_directive(char * line, bool /*capitalized*/)
position.sequence = context.sequence++;
time_xact_t event(position, parse_datetime(datetime, current_year),
- p ? context.top_account()->find_account(p) : NULL,
- n ? n : "",
- end ? end : "");
+ p ? context.top_account()->find_account(p) : NULL,
+ n ? n : "",
+ end ? end : "");
context.timelog.clock_out(event);
context.count++;
@@ -526,8 +526,8 @@ void instance_t::automated_xact_directive(char * line)
std::auto_ptr<auto_xact_t> ae
(new auto_xact_t(query_t(string(skip_ws(line + 1)),
- keep_details_t(true, true, true), false)));
- ae->pos = position_t();
+ keep_details_t(true, true, true), false)));
+ ae->pos = position_t();
ae->pos->pathname = pathname;
ae->pos->beg_pos = line_beg_pos;
ae->pos->beg_line = linenum;
@@ -540,7 +540,7 @@ void instance_t::automated_xact_directive(char * line)
context.journal.auto_xacts.push_back(ae.get());
- ae->journal = &context.journal;
+ ae->journal = &context.journal;
ae->pos->end_pos = curr_pos;
ae->pos->end_line = linenum;
@@ -610,7 +610,7 @@ void instance_t::xact_directive(char * line, std::streamsize len)
std::auto_ptr<xact_t> manager(xact);
if (context.journal.add_xact(xact)) {
- manager.release(); // it's owned by the journal now
+ manager.release(); // it's owned by the journal now
context.count++;
}
// It's perfectly valid for the journal to reject the xact, which it will
@@ -650,10 +650,10 @@ void instance_t::include_directive(char * line)
mask_t glob;
#if BOOST_VERSION >= 103700
- path parent_path = filename.parent_path();
+ path parent_path = filename.parent_path();
glob.assign_glob(filename.filename());
#else // BOOST_VERSION >= 103700
- path parent_path = filename.branch_path();
+ path parent_path = filename.branch_path();
glob.assign_glob(filename.leaf());
#endif // BOOST_VERSION >= 103700
@@ -661,33 +661,33 @@ void instance_t::include_directive(char * line)
if (exists(parent_path)) {
filesystem::directory_iterator end;
for (filesystem::directory_iterator iter(parent_path);
- iter != end;
- ++iter) {
+ iter != end;
+ ++iter) {
#if BOOST_VERSION <= 103500
if (is_regular(*iter))
#else
if (is_regular_file(*iter))
#endif
- {
+ {
#if BOOST_VERSION >= 103700
- string base = (*iter).filename();
+ string base = (*iter).filename();
#else // BOOST_VERSION >= 103700
- string base = (*iter).leaf();
+ string base = (*iter).leaf();
#endif // BOOST_VERSION >= 103700
- if (glob.match(base)) {
- path inner_file(*iter);
- ifstream stream(inner_file);
- instance_t instance(context, stream, &inner_file, this);
- instance.parse();
- files_found = true;
- }
+ if (glob.match(base)) {
+ path inner_file(*iter);
+ ifstream stream(inner_file);
+ instance_t instance(context, stream, &inner_file, this);
+ instance.parse();
+ files_found = true;
+ }
}
}
}
if (! files_found)
throw_(std::runtime_error,
- _("File to include was not found: '%1'") << filename);
+ _("File to include was not found: '%1'") << filename);
}
@@ -707,17 +707,17 @@ void instance_t::end_directive(char * kind)
if ((name.empty() || name == "account") && ! context.front_is_account())
throw_(std::runtime_error,
- _("'end account' directive does not match open directive"));
+ _("'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"));
+ _("'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"));
+ _("'end fixed' directive does not match open directive"));
if (context.state_stack.size() <= 1)
throw_(std::runtime_error,
- _("'end' found, but no enclosing tag or account directive"));
+ _("'end' found, but no enclosing tag or account directive"));
else
context.state_stack.pop_front();
}
@@ -747,9 +747,9 @@ void instance_t::fixed_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)) {
+ true)) {
context.state_stack.push_front(fixed_rate_t(price_point->first,
- price_point->second.price));
+ price_point->second.price));
} else {
throw_(std::runtime_error, _("Error in fixed directive"));
}
@@ -789,7 +789,7 @@ void instance_t::account_mapping_directive(char * line)
if (payee_regex)
context.journal.account_mappings.push_back
(account_mapping_t(mask_t(payee_regex),
- context.top_account()->find_account(account_name)));
+ context.top_account()->find_account(account_name)));
while (peek_whitespace_line()) {
#if defined(NO_ASSERTS)
@@ -805,7 +805,7 @@ void instance_t::account_mapping_directive(char * line)
context.journal.account_mappings.push_back
(account_mapping_t(mask_t(payee_regex),
- context.top_account()->find_account(account_name)));
+ context.top_account()->find_account(account_name)));
}
}
@@ -822,7 +822,7 @@ void instance_t::tag_directive(char * line)
void instance_t::define_directive(char * line)
{
expr_t def(skip_ws(line));
- def.compile(context.scope); // causes definitions to be established
+ def.compile(context.scope); // causes definitions to be established
}
bool instance_t::general_directive(char * line)
@@ -923,18 +923,18 @@ bool instance_t::general_directive(char * line)
return false;
}
-post_t * instance_t::parse_post(char * line,
- std::streamsize len,
- account_t * account,
- xact_t * xact,
- bool defer_expr)
+post_t * instance_t::parse_post(char * line,
+ std::streamsize len,
+ account_t * account,
+ xact_t * xact,
+ bool defer_expr)
{
TRACE_START(post_details, 1, "Time spent parsing postings:");
std::auto_ptr<post_t> post(new post_t);
- post->xact = xact; // this could be NULL
- post->pos = position_t();
+ post->xact = xact; // this could be NULL
+ post->pos = position_t();
post->pos->pathname = pathname;
post->pos->beg_pos = line_beg_pos;
post->pos->beg_line = linenum;
@@ -958,14 +958,14 @@ post_t * instance_t::parse_post(char * line,
post->set_state(item_t::CLEARED);
p = skip_ws(p + 1);
DEBUG("textual.parse", "line " << linenum << ": "
- << "Parsed the CLEARED flag");
+ << "Parsed the CLEARED flag");
break;
case '!':
post->set_state(item_t::PENDING);
p = skip_ws(p + 1);
DEBUG("textual.parse", "line " << linenum << ": "
- << "Parsed the PENDING flag");
+ << "Parsed the PENDING flag");
break;
}
@@ -988,19 +988,19 @@ post_t * instance_t::parse_post(char * line,
if ((*p == '[' && *(e - 1) == ']') || (*p == '(' && *(e - 1) == ')')) {
post->add_flags(POST_VIRTUAL);
DEBUG("textual.parse", "line " << linenum << ": "
- << "Parsed a virtual account name");
+ << "Parsed a virtual account name");
if (*p == '[') {
post->add_flags(POST_MUST_BALANCE);
DEBUG("textual.parse", "line " << linenum << ": "
- << "Posting must balance");
+ << "Posting must balance");
}
p++; e--;
}
string name(p, e - p);
DEBUG("textual.parse", "line " << linenum << ": "
- << "Parsed account name " << name);
+ << "Parsed account name " << name);
if (account_aliases.size() > 0) {
accounts_map::const_iterator i = account_aliases.find(name);
@@ -1013,15 +1013,15 @@ post_t * instance_t::parse_post(char * line,
if (context.strict && ! post->account->has_flags(ACCOUNT_KNOWN)) {
if (post->_state == item_t::UNCLEARED)
warning_(_("\"%1\", line %2: Unknown account '%3'")
- << pathname << linenum << post->account->fullname());
+ << 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 = value.second;
+ break;
}
}
}
@@ -1036,39 +1036,39 @@ post_t * instance_t::parse_post(char * line,
beg = next - line;
ptristream stream(next, len - beg);
- if (*next != '(') // indicates a value expression
+ if (*next != '(') // indicates a value expression
post->amount.parse(stream, PARSE_NO_REDUCE);
else
parse_amount_expr(stream, context.scope, *post.get(), post->amount,
- PARSE_NO_REDUCE | PARSE_SINGLE | PARSE_NO_ASSIGN,
- defer_expr, &post->amount_expr);
+ PARSE_NO_REDUCE | PARSE_SINGLE | PARSE_NO_ASSIGN,
+ 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_(_("\"%1\", line %2: Unknown commodity '%3'")
- << pathname << linenum << post->amount.commodity());
- post->amount.commodity().add_flags(COMMODITY_KNOWN);
+ ! post->amount.commodity().has_flags(COMMODITY_KNOWN)) {
+ if (post->_state == item_t::UNCLEARED)
+ warning_(_("\"%1\", line %2: Unknown commodity '%3'")
+ << pathname << linenum << post->amount.commodity());
+ post->amount.commodity().add_flags(COMMODITY_KNOWN);
}
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));
- if (*rate.first == post->amount.commodity()) {
- annotation_t details(rate.second);
- details.add_flags(ANNOTATION_PRICE_FIXATED);
- post->amount.annotate(details);
- break;
- }
- }
- }
+ foreach (state_t& state, context.state_stack) {
+ if (state.type() == typeid(fixed_rate_t)) {
+ fixed_rate_t& rate(boost::get<fixed_rate_t>(state));
+ if (*rate.first == post->amount.commodity()) {
+ annotation_t details(rate.second);
+ details.add_flags(ANNOTATION_PRICE_FIXATED);
+ post->amount.annotate(details);
+ break;
+ }
+ }
+ }
}
}
DEBUG("textual.parse", "line " << linenum << ": "
- << "post amount = " << post->amount);
+ << "post amount = " << post->amount);
if (stream.eof()) {
next = NULL;
@@ -1078,73 +1078,73 @@ post_t * instance_t::parse_post(char * line,
// Parse the optional cost (@ PER-UNIT-COST, @@ TOTAL-COST)
if (*next == '@') {
- DEBUG("textual.parse", "line " << linenum << ": "
- << "Found a price indicator");
-
- bool per_unit = true;
-
- if (*++next == '@') {
- per_unit = false;
- post->add_flags(POST_COST_IN_FULL);
- DEBUG("textual.parse", "line " << linenum << ": "
- << "And it's for a total price");
- }
-
- beg = ++next - line;
-
- p = skip_ws(next);
- if (*p) {
- post->cost = amount_t();
-
- bool fixed_cost = false;
- if (*p == '=') {
- p++;
- fixed_cost = true;
- if (*p == '\0')
- throw parse_error(_("Posting is missing a cost amount"));
- }
-
- beg = p - line;
- ptristream cstream(p, len - beg);
-
- if (*p != '(') // indicates a value expression
- post->cost->parse(cstream, PARSE_NO_MIGRATE);
- else
- parse_amount_expr(cstream, context.scope, *post.get(), *post->cost,
- PARSE_NO_MIGRATE | PARSE_SINGLE | PARSE_NO_ASSIGN);
-
- if (post->cost->sign() < 0)
- throw parse_error(_("A posting's cost may not be negative"));
-
- post->cost->in_place_unround();
-
- if (per_unit) {
- // For the sole case where the cost might be uncommoditized,
- // guarantee that the commodity of the cost after multiplication
- // is the same as it was before.
- commodity_t& cost_commodity(post->cost->commodity());
- *post->cost *= post->amount;
- post->cost->set_commodity(cost_commodity);
- }
- else if (post->amount.sign() < 0) {
- post->cost->in_place_negate();
- }
-
- if (fixed_cost)
- post->add_flags(POST_COST_FIXATED);
-
- DEBUG("textual.parse", "line " << linenum << ": "
- << "Total cost is " << *post->cost);
- DEBUG("textual.parse", "line " << linenum << ": "
- << "Annotated amount is " << post->amount);
-
- if (cstream.eof())
- next = NULL;
- else
- next = skip_ws(p + static_cast<std::ptrdiff_t>(cstream.tellg()));
- } else {
- throw parse_error(_("Expected a cost amount"));
- }
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Found a price indicator");
+
+ bool per_unit = true;
+
+ if (*++next == '@') {
+ per_unit = false;
+ post->add_flags(POST_COST_IN_FULL);
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "And it's for a total price");
+ }
+
+ beg = ++next - line;
+
+ p = skip_ws(next);
+ if (*p) {
+ post->cost = amount_t();
+
+ bool fixed_cost = false;
+ if (*p == '=') {
+ p++;
+ fixed_cost = true;
+ if (*p == '\0')
+ throw parse_error(_("Posting is missing a cost amount"));
+ }
+
+ beg = p - line;
+ ptristream cstream(p, len - beg);
+
+ if (*p != '(') // indicates a value expression
+ post->cost->parse(cstream, PARSE_NO_MIGRATE);
+ else
+ parse_amount_expr(cstream, context.scope, *post.get(), *post->cost,
+ PARSE_NO_MIGRATE | PARSE_SINGLE | PARSE_NO_ASSIGN);
+
+ if (post->cost->sign() < 0)
+ throw parse_error(_("A posting's cost may not be negative"));
+
+ post->cost->in_place_unround();
+
+ if (per_unit) {
+ // For the sole case where the cost might be uncommoditized,
+ // guarantee that the commodity of the cost after multiplication
+ // is the same as it was before.
+ commodity_t& cost_commodity(post->cost->commodity());
+ *post->cost *= post->amount;
+ post->cost->set_commodity(cost_commodity);
+ }
+ else if (post->amount.sign() < 0) {
+ post->cost->in_place_negate();
+ }
+
+ if (fixed_cost)
+ post->add_flags(POST_COST_FIXATED);
+
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Total cost is " << *post->cost);
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Annotated amount is " << post->amount);
+
+ if (cstream.eof())
+ next = NULL;
+ else
+ next = skip_ws(p + static_cast<std::ptrdiff_t>(cstream.tellg()));
+ } else {
+ throw parse_error(_("Expected a cost amount"));
+ }
}
}
}
@@ -1153,7 +1153,7 @@ post_t * instance_t::parse_post(char * line,
if (xact && next && *next == '=') {
DEBUG("textual.parse", "line " << linenum << ": "
- << "Found a balance assignment indicator");
+ << "Found a balance assignment indicator");
beg = ++next - line;
@@ -1164,70 +1164,70 @@ post_t * instance_t::parse_post(char * line,
beg = p - line;
ptristream stream(p, len - beg);
- if (*p != '(') // indicates a value expression
- post->assigned_amount->parse(stream, PARSE_NO_MIGRATE);
+ if (*p != '(') // indicates a value expression
+ post->assigned_amount->parse(stream, PARSE_NO_MIGRATE);
else
- parse_amount_expr(stream, context.scope, *post.get(),
- *post->assigned_amount,
- PARSE_SINGLE | PARSE_NO_MIGRATE);
+ parse_amount_expr(stream, context.scope, *post.get(),
+ *post->assigned_amount,
+ PARSE_SINGLE | PARSE_NO_MIGRATE);
if (post->assigned_amount->is_null()) {
- if (post->amount.is_null())
- throw parse_error(_("Balance assignment must evaluate to a constant"));
- else
- throw parse_error(_("Balance assertion must evaluate to a constant"));
+ if (post->amount.is_null())
+ throw parse_error(_("Balance assignment must evaluate to a constant"));
+ else
+ throw parse_error(_("Balance assertion must evaluate to a constant"));
}
DEBUG("textual.parse", "line " << linenum << ": "
- << "POST assign: parsed amt = " << *post->assigned_amount);
+ << "POST assign: parsed amt = " << *post->assigned_amount);
- amount_t& amt(*post->assigned_amount);
+ amount_t& amt(*post->assigned_amount);
value_t account_total
- (post->account->amount(false).strip_annotations(keep_details_t()));
+ (post->account->amount(false).strip_annotations(keep_details_t()));
DEBUG("post.assign",
- "line " << linenum << ": " "account balance = " << account_total);
+ "line " << linenum << ": " "account balance = " << account_total);
DEBUG("post.assign",
- "line " << linenum << ": " "post amount = " << amt);
+ "line " << linenum << ": " "post amount = " << amt);
amount_t diff = amt;
switch (account_total.type()) {
case value_t::AMOUNT:
- diff -= account_total.as_amount();
- break;
+ diff -= account_total.as_amount();
+ break;
case value_t::BALANCE:
- if (optional<amount_t> comm_bal =
- account_total.as_balance().commodity_amount(amt.commodity()))
- diff -= *comm_bal;
- break;
+ if (optional<amount_t> comm_bal =
+ account_total.as_balance().commodity_amount(amt.commodity()))
+ diff -= *comm_bal;
+ break;
default:
- break;
+ break;
}
DEBUG("post.assign",
- "line " << linenum << ": " << "diff = " << diff);
+ "line " << linenum << ": " << "diff = " << diff);
DEBUG("textual.parse",
- "line " << linenum << ": " << "POST assign: diff = " << diff);
+ "line " << linenum << ": " << "POST assign: diff = " << diff);
if (! diff.is_zero()) {
- if (! post->amount.is_null()) {
- diff -= post->amount;
- if (! diff.is_zero())
- throw_(parse_error, _("Balance assertion off by %1") << diff);
- } else {
- post->amount = diff;
- DEBUG("textual.parse", "line " << linenum << ": "
- << "Overwrite null posting");
- }
+ if (! post->amount.is_null()) {
+ diff -= post->amount;
+ if (! diff.is_zero())
+ throw_(parse_error, _("Balance assertion off by %1") << diff);
+ } else {
+ post->amount = diff;
+ DEBUG("textual.parse", "line " << linenum << ": "
+ << "Overwrite null posting");
+ }
}
if (stream.eof())
- next = NULL;
+ next = NULL;
else
- next = skip_ws(p + static_cast<std::ptrdiff_t>(stream.tellg()));
+ next = skip_ws(p + static_cast<std::ptrdiff_t>(stream.tellg()));
} else {
throw parse_error(_("Expected an balance assignment/assertion amount"));
}
@@ -1239,15 +1239,15 @@ post_t * instance_t::parse_post(char * line,
post->append_note(++next, true, current_year);
next = line + len;
DEBUG("textual.parse", "line " << linenum << ": "
- << "Parsed a posting note");
+ << "Parsed a posting note");
}
// There should be nothing more to read
if (next && *next)
throw_(parse_error,
- _("Unexpected char '%1' (Note: inline math requires parentheses)")
- << *next);
+ _("Unexpected char '%1' (Note: inline math requires parentheses)")
+ << *next);
post->pos->end_pos = curr_pos;
post->pos->end_line = linenum;
@@ -1255,7 +1255,7 @@ post_t * instance_t::parse_post(char * line,
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(), true);
+ post->parse_tags(boost::get<string>(state).c_str(), true);
}
TRACE_STOP(post_details, 1);
@@ -1271,8 +1271,8 @@ post_t * instance_t::parse_post(char * line,
}
bool instance_t::parse_posts(account_t * account,
- xact_base_t& xact,
- const bool defer_expr)
+ xact_base_t& xact,
+ const bool defer_expr)
{
TRACE_START(xact_posts, 1, "Time spent parsing postings:");
@@ -1294,15 +1294,15 @@ bool instance_t::parse_posts(account_t * account,
return added;
}
-xact_t * instance_t::parse_xact(char * line,
- std::streamsize len,
- account_t * account)
+xact_t * instance_t::parse_xact(char * line,
+ std::streamsize len,
+ account_t * account)
{
TRACE_START(xact_text, 1, "Time spent parsing transaction text:");
std::auto_ptr<xact_t> xact(new xact_t);
- xact->pos = position_t();
+ xact->pos = position_t();
xact->pos->pathname = pathname;
xact->pos->beg_pos = line_beg_pos;
xact->pos->beg_line = linenum;
@@ -1353,8 +1353,8 @@ xact_t * instance_t::parse_xact(char * line,
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;
+ xact->payee = value.second;
+ break;
}
}
if (xact->payee.empty())
@@ -1387,9 +1387,9 @@ xact_t * instance_t::parse_xact(char * line,
if (*p == ';') {
item_t * item;
if (last_post)
- item = last_post;
+ item = last_post;
else
- item = xact.get();
+ item = xact.get();
// This is a trailing note, and possibly a metadata info tag
item->append_note(p + 1, true, current_year);
@@ -1399,9 +1399,9 @@ xact_t * instance_t::parse_xact(char * line,
reveal_context = false;
if (post_t * post =
- parse_post(p, len - (p - line), account, xact.get())) {
- xact->add_post(post);
- last_post = post;
+ parse_post(p, len - (p - line), account, xact.get())) {
+ xact->add_post(post);
+ last_post = post;
}
}
}
@@ -1411,11 +1411,11 @@ xact_t * instance_t::parse_xact(char * line,
foreach (post_t * post, xact->posts) {
if (post->_state == item_t::UNCLEARED) {
- result = item_t::UNCLEARED;
- break;
+ result = item_t::UNCLEARED;
+ break;
}
else if (post->_state == item_t::PENDING) {
- result = item_t::PENDING;
+ result = item_t::PENDING;
}
}
}
@@ -1426,7 +1426,7 @@ xact_t * instance_t::parse_xact(char * line,
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(), false);
+ xact->parse_tags(boost::get<string>(state).c_str(), false);
}
TRACE_STOP(xact_details, 1);
@@ -1438,23 +1438,23 @@ xact_t * instance_t::parse_xact(char * line,
if (reveal_context) {
add_error_context(_("While parsing transaction:"));
add_error_context(source_context(xact->pos->pathname,
- xact->pos->beg_pos, curr_pos, "> "));
+ xact->pos->beg_pos, curr_pos, "> "));
}
throw;
}
}
expr_t::ptr_op_t instance_t::lookup(const symbol_t::kind_t kind,
- const string& name)
+ const string& name)
{
return context.scope.lookup(kind, name);
}
std::size_t journal_t::parse(std::istream& in,
- scope_t& scope,
- account_t * master,
- const path * original_file,
- bool strict)
+ scope_t& scope,
+ account_t * master,
+ const path * original_file,
+ bool strict)
{
TRACE_START(parsing_total, 1, "Total time spent parsing text:");