Simplified error context handling.

This commit is contained in:
John Wiegley 2009-02-02 00:24:26 -04:00
parent ef3943c604
commit 9540406af1
19 changed files with 230 additions and 222 deletions

View file

@ -38,5 +38,5 @@ N $
; This is a transaction note! ; This is a transaction note!
; Sample: Another Value ; Sample: Another Value
; :MyTag: ; :MyTag:
Assets:Bank:Checking Assets:Bank:Checking $-21.00
; :AnotherTag: ; :AnotherTag:

View file

@ -37,8 +37,7 @@
namespace ledger { namespace ledger {
entry_base_t::entry_base_t(const entry_base_t& e) entry_base_t::entry_base_t(const entry_base_t& e) : item_t()
: item_t(), journal(NULL)
{ {
TRACE_CTOR(entry_base_t, "copy"); TRACE_CTOR(entry_base_t, "copy");
#if 0 #if 0
@ -80,11 +79,14 @@ item_t::state_t entry_base_t::state() const
void entry_base_t::add_xact(xact_t * xact) void entry_base_t::add_xact(xact_t * xact)
{ {
xacts.push_back(xact); xacts.push_back(xact);
xact->journal = journal;
} }
bool entry_base_t::remove_xact(xact_t * xact) bool entry_base_t::remove_xact(xact_t * xact)
{ {
xacts.remove(xact); xacts.remove(xact);
xact->entry = NULL;
xact->journal = NULL;
return true; return true;
} }
@ -226,10 +228,8 @@ bool entry_base_t::finalize()
DEBUG("entry.finalize", "final balance = " << balance); DEBUG("entry.finalize", "final balance = " << balance);
if (! balance.is_null() && ! balance.is_zero()) { if (! balance.is_null() && ! balance.is_zero()) {
#if 0 add_error_context(item_context(*this));
add_error_context(entry_context(*this)); add_error_context("Unbalanced remainder is:");
#endif
add_error_context("Unbalanced remainder is: ");
add_error_context(value_context(balance)); add_error_context(value_context(balance));
throw_(balance_error, "Entry does not balance"); throw_(balance_error, "Entry does not balance");
} }
@ -326,16 +326,6 @@ bool entry_t::valid() const
return true; return true;
} }
#if 0
void entry_context::describe(std::ostream& out) const throw()
{
if (! desc.empty())
out << desc << std::endl;
print_entry(out, entry, " ");
}
#endif
void auto_entry_t::extend_entry(entry_base_t& entry, bool post) void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
{ {
xacts_list initial_xacts(entry.xacts.begin(), xacts_list initial_xacts(entry.xacts.begin(),

View file

@ -61,10 +61,9 @@ class journal_t;
class entry_base_t : public item_t class entry_base_t : public item_t
{ {
public: public:
journal_t * journal;
xacts_list xacts; xacts_list xacts;
entry_base_t() : journal(NULL) { entry_base_t() {
TRACE_CTOR(entry_base_t, ""); TRACE_CTOR(entry_base_t, "");
} }
entry_base_t(const entry_base_t& e); entry_base_t(const entry_base_t& e);

View file

@ -153,6 +153,11 @@ public:
std::ostream& operator<<(std::ostream& out, const expr_t& expr); std::ostream& operator<<(std::ostream& out, const expr_t& expr);
inline string expr_context(const expr_t& expr) {
// jww (2009-02-01): NYI
return "EXPR";
}
} // namespace ledger } // namespace ledger
#endif // _EXPR_H #endif // _EXPR_H

View file

@ -201,10 +201,8 @@ void calc_xacts::operator()(xact_t& xact)
last_xact = &xact; last_xact = &xact;
} }
catch (const std::exception& err) { catch (const std::exception& err) {
add_error_context("Calculating transaction at"); add_error_context("While calculating transaction:");
#if 0 add_error_context(item_context(xact));
add_error_context(xact_context(xact));
#endif
throw; throw;
} }
} }

View file

@ -298,7 +298,8 @@ void format_t::format(std::ostream& out_str, scope_t& scope)
value.strip_annotations().dump(out, elem->min_width); value.strip_annotations().dump(out, elem->min_width);
} }
catch (const calc_error&) { catch (const calc_error&) {
out << (string("%") + elem->chars); add_error_context("While calculating format expression:");
add_error_context(expr_context(elem->expr));
throw; throw;
} }
break; break;

View file

@ -35,8 +35,6 @@
namespace ledger { namespace ledger {
bool item_t::use_effective_date = false;
bool item_t::has_tag(const string& tag) const bool item_t::has_tag(const string& tag) const
{ {
if (! metadata) if (! metadata)
@ -213,6 +211,14 @@ value_t get_comment(item_t& item)
} }
} }
optional<date_t> item_t::date() const
{
if (session_t::current->report->use_effective_date && _date_eff)
return effective_date();
else
return actual_date();
}
expr_t::ptr_op_t item_t::lookup(const string& name) expr_t::ptr_op_t item_t::lookup(const string& name)
{ {
switch (name[0]) { switch (name[0]) {
@ -289,4 +295,41 @@ bool item_t::valid() const
return true; return true;
} }
string item_context(const item_t& item)
{
unsigned short x = 0;
foreach (const path& path, item.journal->sources) {
if (x++ == item.src_idx) {
std::size_t len = item.end_pos - item.beg_pos;
assert(len > 0);
assert(len < 2048);
ifstream in(path);
in.seekg(item.beg_pos, std::ios::beg);
scoped_array<char> buf(new char[len + 1]);
in.read(buf.get(), len);
std::ostringstream out;
out << "While balancing item from \"" << path.string()
<< "\", line " << item.beg_line
<< ", byte " << item.beg_pos << ":\n";
bool first = true;
for (char * p = std::strtok(buf.get(), "\n");
p;
p = std::strtok(NULL, "\n")) {
if (first)
first = false;
else
out << '\n';
out << " " << p;
return out.str();
}
}
assert(false);
return empty_string;
}
} // namespace ledger } // namespace ledger

View file

@ -51,6 +51,8 @@
namespace ledger { namespace ledger {
class journal_t;
/** /**
* @brief Brief * @brief Brief
* *
@ -75,20 +77,25 @@ public:
typedef std::map<string, optional<string> > string_map; typedef std::map<string, optional<string> > string_map;
optional<string_map> metadata; optional<string_map> metadata;
journal_t * journal;
unsigned short src_idx; unsigned short src_idx;
#if 0
istream_pos_type full_beg_pos; istream_pos_type full_beg_pos;
std::size_t full_beg_line; std::size_t full_beg_line;
#endif
istream_pos_type beg_pos; istream_pos_type beg_pos;
std::size_t beg_line; std::size_t beg_line;
istream_pos_type end_pos; istream_pos_type end_pos;
std::size_t end_line; std::size_t end_line;
#if 0
istream_pos_type full_end_pos; istream_pos_type full_end_pos;
std::size_t full_end_line; std::size_t full_end_line;
#endif
static bool use_effective_date;
item_t(flags_t _flags = ITEM_NORMAL, const optional<string>& _note = none) item_t(flags_t _flags = ITEM_NORMAL, const optional<string>& _note = none)
: supports_flags<>(_flags), _state(UNCLEARED), note(_note), : supports_flags<>(_flags),
_state(UNCLEARED), note(_note), journal(NULL), src_idx(0),
beg_pos(0), beg_line(0), end_pos(0), end_line(0) beg_pos(0), beg_line(0), end_pos(0), end_line(0)
{ {
TRACE_CTOR(item_t, "flags_t, const string&"); TRACE_CTOR(item_t, "flags_t, const string&");
@ -112,6 +119,8 @@ public:
note = item.note; note = item.note;
journal = item.journal;
src_idx = item.src_idx;
beg_pos = item.beg_pos; beg_pos = item.beg_pos;
beg_line = item.beg_line; beg_line = item.beg_line;
end_pos = item.end_pos; end_pos = item.end_pos;
@ -144,12 +153,7 @@ public:
virtual optional<date_t> effective_date() const { virtual optional<date_t> effective_date() const {
return _date_eff; return _date_eff;
} }
optional<date_t> date() const { optional<date_t> date() const;
if (use_effective_date && _date_eff)
return effective_date();
else
return actual_date();
}
void set_state(state_t new_state) { void set_state(state_t new_state) {
_state = new_state; _state = new_state;
@ -165,6 +169,8 @@ public:
value_t get_comment(item_t& item); value_t get_comment(item_t& item);
string item_context(const item_t& item);
} // namespace ledger } // namespace ledger
#endif // _ITEM_H #endif // _ITEM_H

View file

@ -133,7 +133,7 @@ int main(int argc, char * argv[], char * envp[])
} }
catch (const std::exception& err) { catch (const std::exception& err) {
std::cout.flush(); std::cout.flush();
std::cerr << error_context() << "Error: " << err.what() << std::endl; report_error(err);
} }
catch (int _status) { catch (int _status) {
status = _status; status = _status;

View file

@ -86,7 +86,7 @@ value_t expr_t::op_t::calc(scope_t& scope)
catch (const std::exception& err) { catch (const std::exception& err) {
if (context_op_ptr) { if (context_op_ptr) {
add_error_context("While evaluating value expression:"); add_error_context("While evaluating value expression:");
add_error_context(expr_context(this, context_op_ptr)); add_error_context(op_context(this, context_op_ptr));
} }
throw; throw;
} }
@ -574,7 +574,7 @@ void expr_t::op_t::write(std::ostream& out) const
} }
} }
string expr_context(const expr_t::ptr_op_t op, const expr_t::ptr_op_t goal) string op_context(const expr_t::ptr_op_t op, const expr_t::ptr_op_t goal)
{ {
ostream_pos_type start_pos, end_pos; ostream_pos_type start_pos, end_pos;
expr_t::op_t::context_t context(op, goal, &start_pos, &end_pos); expr_t::op_t::context_t context(op, goal, &start_pos, &end_pos);
@ -588,7 +588,6 @@ string expr_context(const expr_t::ptr_op_t op, const expr_t::ptr_op_t goal)
else else
buf << " "; buf << " ";
} }
buf << '\n';
} }
return buf.str(); return buf.str();
} }

View file

@ -332,7 +332,7 @@ inline expr_t::ptr_op_t expr_t::op_t::wrap_functor(const function_t& fobj) {
#define MAKE_FUNCTOR(x) expr_t::op_t::wrap_functor(bind(&x, this, _1)) #define MAKE_FUNCTOR(x) expr_t::op_t::wrap_functor(bind(&x, this, _1))
#define WRAP_FUNCTOR(x) expr_t::op_t::wrap_functor(x) #define WRAP_FUNCTOR(x) expr_t::op_t::wrap_functor(x)
string expr_context(const expr_t::ptr_op_t op, const expr_t::ptr_op_t op); string op_context(const expr_t::ptr_op_t op, const expr_t::ptr_op_t op);
} // namespace ledger } // namespace ledger

View file

@ -75,7 +75,7 @@ namespace {
} }
void process_option(const function_t& opt, scope_t& scope, void process_option(const function_t& opt, scope_t& scope,
const char * arg) const char * arg, const string& name)
{ {
try { try {
call_scope_t args(scope); call_scope_t args(scope);
@ -85,23 +85,23 @@ namespace {
opt(args); opt(args);
} }
catch (const std::exception& err) { catch (const std::exception& err) {
#if 0 if (name[0] == '-')
add_error_context("While parsing option '--" << opt->long_opt add_error_context("While parsing option '" << name << "':");
<< "'" << (opt->short_opt != '\0' ?
(string(" (-") + opt->short_opt + "):") : else
": ")); add_error_context("While parsing environent variable '"
#endif << name << "':");
throw; throw;
} }
} }
} }
void process_option(const string& name, scope_t& scope, void process_option(const string& name, scope_t& scope,
const char * arg) const char * arg, const string& varname)
{ {
op_bool_tuple opt(find_option(scope, name)); op_bool_tuple opt(find_option(scope, name));
if (opt.get<0>()) if (opt.get<0>())
process_option(opt.get<0>()->as_function(), scope, arg); process_option(opt.get<0>()->as_function(), scope, arg, varname);
} }
void process_environment(const char ** envp, const string& tag, void process_environment(const char ** envp, const string& tag,
@ -126,7 +126,7 @@ void process_environment(const char ** envp, const string& tag,
if (*q == '=') { if (*q == '=') {
try { try {
process_option(string(buf), scope, q + 1); process_option(string(buf), scope, q + 1, string(*p, q - *p));
} }
catch (const std::exception& err) { catch (const std::exception& err) {
add_error_context("While parsing environment variable option '" add_error_context("While parsing environment variable option '"
@ -179,7 +179,8 @@ void process_arguments(int, char ** argv, scope_t& scope,
if (value == NULL) if (value == NULL)
throw_(option_error, "missing option argument for --" << name); throw_(option_error, "missing option argument for --" << name);
} }
process_option(opt.get<0>()->as_function(), scope, value); process_option(opt.get<0>()->as_function(), scope, value,
string("--") + name);
} }
else if ((*i)[1] == '\0') { else if ((*i)[1] == '\0') {
throw_(option_error, "illegal option -"); throw_(option_error, "illegal option -");
@ -210,7 +211,8 @@ void process_arguments(int, char ** argv, scope_t& scope,
throw_(option_error, throw_(option_error,
"missing option argument for -" << o.get<2>()); "missing option argument for -" << o.get<2>());
} }
process_option(o.get<0>()->as_function(), scope, value); process_option(o.get<0>()->as_function(), scope, value,
string("-") + o.get<2>());
} }
} }
} }

View file

@ -51,7 +51,7 @@
namespace ledger { namespace ledger {
void process_option(const string& name, scope_t& scope, void process_option(const string& name, scope_t& scope,
const char * arg = NULL); const char * arg, const string& name);
void process_environment(const char ** envp, const string& tag, void process_environment(const char ** envp, const string& tag,
scope_t& scope); scope_t& scope);

View file

@ -149,6 +149,8 @@ public:
bool entry_sort; bool entry_sort;
bool sort_all; bool sort_all;
bool anonymize; bool anonymize;
bool use_effective_date;
string account; string account;
optional<path> pager_path; optional<path> pager_path;
@ -184,6 +186,7 @@ public:
entry_sort(false), entry_sort(false),
sort_all(false), sort_all(false),
anonymize(false), anonymize(false),
use_effective_date(false),
raw_mode(false), raw_mode(false),
@ -274,7 +277,7 @@ public:
// Report filtering // Report filtering
value_t option_effective(call_scope_t& args) { value_t option_effective(call_scope_t& args) {
xact_t::use_effective_date = true; use_effective_date = true;
} }
#endif #endif

View file

@ -116,7 +116,11 @@ namespace {
#endif #endif
if (expr) { if (expr) {
amount = expr.calc(*xact).as_amount(); value_t result(expr.calc(*xact));
// jww (2009-02-01): What about storing time-dependent expressions?
if (! result.is_amount())
throw_(parse_error, "Transactions may only specify simple amounts");
amount = result.as_amount();
DEBUG("textual.parse", "The transaction amount is " << amount); DEBUG("textual.parse", "The transaction amount is " << amount);
return expr; return expr;
} }
@ -182,7 +186,8 @@ void textual_parser_t::instance_t::parse()
try { try {
read_next_directive(); read_next_directive();
beg_pos = end_pos; beg_pos = end_pos;
beg_line = linenum;
} }
catch (const std::exception& err) { catch (const std::exception& err) {
if (parent) { if (parent) {
@ -194,16 +199,14 @@ void textual_parser_t::instance_t::parse()
instances.push_front(instance); instances.push_front(instance);
foreach (instance_t * instance, instances) foreach (instance_t * instance, instances)
add_error_context("In file included from '" add_error_context("In file included from "
<< file_context(instance->pathname, << file_context(instance->pathname,
instance->linenum - 1) << "':"); instance->linenum - 1));
} }
add_error_context("While parsing file " add_error_context("While parsing file "
<< file_context(pathname, linenum - 1) << "\n"); << file_context(pathname, linenum - 1));
std::cout.flush(); report_error(err);
std::cerr << ledger::error_context()
<< "Error: " << err.what() << std::endl;
errors++; errors++;
} }
} }
@ -446,7 +449,7 @@ void textual_parser_t::instance_t::option_directive(char * line)
if (p) if (p)
*p++ = '\0'; *p++ = '\0';
} }
process_option(line + 2, session, p); process_option(line + 2, session, p, line);
} }
void textual_parser_t::instance_t::automated_entry_directive(char * line) void textual_parser_t::instance_t::automated_entry_directive(char * line)
@ -501,13 +504,15 @@ void textual_parser_t::instance_t::entry_directive(char * line)
// possibility that add_entry ma throw an exception, which // possibility that add_entry ma throw an exception, which
// would cause us to leak without this guard. // would cause us to leak without this guard.
std::auto_ptr<entry_t> entry_ptr(entry); std::auto_ptr<entry_t> entry_ptr(entry);
entry->src_idx = src_idx;
entry->beg_pos = beg_pos;
entry->beg_line = beg_line;
entry->end_pos = pos;
entry->end_line = linenum;
if (journal.add_entry(entry)) { if (journal.add_entry(entry)) {
entry_ptr.release(); // it's owned by the journal now entry_ptr.release(); // it's owned by the journal now
entry->src_idx = src_idx;
entry->beg_pos = beg_pos;
entry->beg_line = beg_line;
entry->end_pos = pos;
entry->end_line = linenum;
count++; count++;
} }
// It's perfectly valid for the journal to reject the entry, // It's perfectly valid for the journal to reject the entry,
@ -653,6 +658,9 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
{ {
std::istringstream in(line); std::istringstream in(line);
istream_pos_type beg = in.tellg();
istream_pos_type end = beg;
string err_desc; string err_desc;
try { try {
@ -683,22 +691,22 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
// Parse the account name // Parse the account name
istream_pos_type account_beg = in.tellg(); beg = in.tellg();
istream_pos_type account_end = account_beg; end = beg;
while (! in.eof()) { while (! in.eof()) {
in.get(p); in.get(p);
if (in.eof() || (std::isspace(p) && if (in.eof() || (std::isspace(p) &&
(p == '\t' || in.peek() == EOF || (p == '\t' || in.peek() == EOF ||
std::isspace(in.peek())))) std::isspace(in.peek()))))
break; break;
account_end += 1; end += 1;
} }
if (account_beg == account_end) if (beg == end)
throw parse_error("No account was specified"); throw parse_error("No account was specified");
char * b = &line[long(account_beg)]; char * b = &line[long(beg)];
char * e = &line[long(account_end)]; char * e = &line[long(end)];
if ((*b == '[' && *(e - 1) == ']') || if ((*b == '[' && *(e - 1) == ']') ||
(*b == '(' && *(e - 1) == ')')) { (*b == '(' && *(e - 1) == ')')) {
@ -738,34 +746,28 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
if (p == '=' && entry) if (p == '=' && entry)
goto parse_assign; goto parse_assign;
try { beg = in.tellg();
istream_pos_type beg = in.tellg();
xact->amount_expr = xact->amount_expr =
parse_amount_expr(in, xact->amount, xact.get(), parse_amount_expr(in, xact->amount, xact.get(),
static_cast<uint_least8_t>(expr_t::PARSE_NO_REDUCE) | static_cast<uint_least8_t>(expr_t::PARSE_NO_REDUCE) |
static_cast<uint_least8_t>(expr_t::PARSE_NO_ASSIGN)); static_cast<uint_least8_t>(expr_t::PARSE_NO_ASSIGN));
saw_amount = true; saw_amount = true;
if (! xact->amount.is_null()) { if (! xact->amount.is_null()) {
xact->amount.reduce(); xact->amount.reduce();
DEBUG("textual.parse", "line " << linenum << ": " << DEBUG("textual.parse", "line " << linenum << ": " <<
"Reduced amount is " << xact->amount); "Reduced amount is " << xact->amount);
}
// We don't need to store the actual expression that resulted in the
// amount if it's constant
if (xact->amount_expr) {
if (xact->amount_expr->is_constant())
xact->amount_expr = expr_t();
istream_pos_type end = in.tellg();
xact->amount_expr->set_text(string(line, long(beg), long(end - beg)));
}
} }
catch (const std::exception& err) {
add_error_context("While parsing transaction amount:\n"); // We don't need to store the actual expression that resulted in the
throw; // amount if it's constant
if (xact->amount_expr) {
if (xact->amount_expr->is_constant())
xact->amount_expr = expr_t();
end = in.tellg();
xact->amount_expr->set_text(string(line, long(beg), long(end - beg)));
} }
} }
@ -792,27 +794,21 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
if (in.good() && ! in.eof()) { if (in.good() && ! in.eof()) {
xact->cost = amount_t(); xact->cost = amount_t();
try { beg = in.tellg();
istream_pos_type beg = in.tellg();
xact->cost_expr = xact->cost_expr =
parse_amount_expr(in, *xact->cost, xact.get(), parse_amount_expr(in, *xact->cost, xact.get(),
static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE) | static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE) |
static_cast<uint_least8_t>(expr_t::PARSE_NO_ASSIGN)); static_cast<uint_least8_t>(expr_t::PARSE_NO_ASSIGN));
if (xact->cost_expr) { if (xact->cost_expr) {
istream_pos_type end = in.tellg(); end = in.tellg();
if (per_unit) if (per_unit)
xact->cost_expr->set_text(string("@") + xact->cost_expr->set_text(string("@") +
string(line, long(beg), long(end - beg))); string(line, long(beg), long(end - beg)));
else else
xact->cost_expr->set_text(string("@@") + xact->cost_expr->set_text(string("@@") +
string(line, long(beg), long(end - beg))); string(line, long(beg), long(end - beg)));
}
}
catch (const std::exception& err) {
add_error_context("While parsing transaction cost:\n");
throw;
} }
if (xact->cost->sign() < 0) if (xact->cost->sign() < 0)
@ -850,81 +846,75 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
if (in.good() && ! in.eof()) { if (in.good() && ! in.eof()) {
xact->assigned_amount = amount_t(); xact->assigned_amount = amount_t();
try { beg = in.tellg();
istream_pos_type beg = in.tellg();
xact->assigned_amount_expr = xact->assigned_amount_expr =
parse_amount_expr(in, *xact->assigned_amount, xact.get(), parse_amount_expr(in, *xact->assigned_amount, xact.get(),
static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE)); static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE));
if (xact->assigned_amount->is_null()) if (xact->assigned_amount->is_null())
throw parse_error throw parse_error
("An assigned balance must evaluate to a constant value"); ("An assigned balance must evaluate to a constant value");
DEBUG("textual.parse", "line " << linenum << ": " << DEBUG("textual.parse", "line " << linenum << ": " <<
"XACT assign: parsed amt = " << *xact->assigned_amount); "XACT assign: parsed amt = " << *xact->assigned_amount);
if (xact->assigned_amount_expr) { if (xact->assigned_amount_expr) {
istream_pos_type end = in.tellg(); end = in.tellg();
xact->assigned_amount_expr->set_text xact->assigned_amount_expr->set_text
(string("=") + string(line, long(beg), long(end - beg))); (string("=") + string(line, long(beg), long(end - beg)));
}
account_t::xdata_t& xdata(xact->account->xdata());
amount_t& amt(*xact->assigned_amount);
DEBUG("xact.assign",
"account balance = " << xdata.value.strip_annotations());
DEBUG("xact.assign",
"xact amount = " << amt.strip_annotations());
amount_t diff;
if (xdata.value.is_amount()) {
diff = amt - xdata.value.as_amount();
}
else if (xdata.value.is_balance()) {
if (optional<amount_t> comm_bal =
xdata.value.as_balance().commodity_amount(amt.commodity()))
diff = amt - *comm_bal;
else
diff = amt;
}
else if (xdata.value.is_balance_pair()) {
if (optional<amount_t> comm_bal =
xdata.value.as_balance_pair().commodity_amount(amt.commodity()))
diff = amt - *comm_bal;
else
diff = amt;
}
else {
diff = amt;
}
DEBUG("xact.assign", "diff = " << diff.strip_annotations());
DEBUG("textual.parse", "line " << linenum << ": " <<
"XACT assign: diff = " << diff.strip_annotations());
if (! diff.is_zero()) {
if (! xact->amount.is_null()) {
diff -= xact->amount;
if (! diff.is_zero()) {
xact_t * temp = new xact_t(xact->account, diff,
ITEM_GENERATED | XACT_CALCULATED);
entry->add_xact(temp);
DEBUG("textual.parse", "line " << linenum << ": " <<
"Created balancing transaction");
}
} else {
xact->amount = diff;
DEBUG("textual.parse", "line " << linenum << ": " <<
"Overwrite null transaction");
}
}
} }
catch (const std::exception& err) {
add_error_context("While parsing assigned balance:\n"); account_t::xdata_t& xdata(xact->account->xdata());
throw; amount_t& amt(*xact->assigned_amount);
DEBUG("xact.assign",
"account balance = " << xdata.value.strip_annotations());
DEBUG("xact.assign",
"xact amount = " << amt.strip_annotations());
amount_t diff;
if (xdata.value.is_amount()) {
diff = amt - xdata.value.as_amount();
}
else if (xdata.value.is_balance()) {
if (optional<amount_t> comm_bal =
xdata.value.as_balance().commodity_amount(amt.commodity()))
diff = amt - *comm_bal;
else
diff = amt;
}
else if (xdata.value.is_balance_pair()) {
if (optional<amount_t> comm_bal =
xdata.value.as_balance_pair().commodity_amount(amt.commodity()))
diff = amt - *comm_bal;
else
diff = amt;
}
else {
diff = amt;
}
DEBUG("xact.assign", "diff = " << diff.strip_annotations());
DEBUG("textual.parse", "line " << linenum << ": " <<
"XACT assign: diff = " << diff.strip_annotations());
if (! diff.is_zero()) {
if (! xact->amount.is_null()) {
diff -= xact->amount;
if (! diff.is_zero()) {
xact_t * temp = new xact_t(xact->account, diff,
ITEM_GENERATED | XACT_CALCULATED);
entry->add_xact(temp);
DEBUG("textual.parse", "line " << linenum << ": " <<
"Created balancing transaction");
}
} else {
xact->amount = diff;
DEBUG("textual.parse", "line " << linenum << ": " <<
"Overwrite null transaction");
}
} }
} }
} }
@ -967,8 +957,8 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
} }
catch (const std::exception& err) { catch (const std::exception& err) {
add_error_context("While parsing transaction:\n"); add_error_context("While parsing transaction:");
add_error_context(line_context(line, in.tellg())); add_error_context(line_context(line, beg, in.tellg()));
throw; throw;
} }
} }

View file

@ -642,18 +642,6 @@ void finish_timer(const char * name)
#endif // LOGGING_ON && TIMERS_ON #endif // LOGGING_ON && TIMERS_ON
/**********************************************************************
*
* Exception handling
*/
namespace ledger {
std::ostringstream _desc_buffer;
std::ostringstream _ctxt_buffer;
} // namespace ledger
/********************************************************************** /**********************************************************************
* *
* General utility functions * General utility functions

View file

@ -973,7 +973,6 @@ inline string value_context(const value_t& val) {
buf << std::right; buf << std::right;
buf.width(20); buf.width(20);
val.print(buf); val.print(buf);
buf << std::endl;
return buf.str(); return buf.str();
} }

View file

@ -101,13 +101,13 @@ void read_environment_settings(report_t& report, char * envp[])
// These are here for backwards compatability, but are deprecated. // These are here for backwards compatability, but are deprecated.
if (const char * p = std::getenv("LEDGER")) if (const char * p = std::getenv("LEDGER"))
process_option("file", report, p); process_option("file", report, p, "LEDGER");
if (const char * p = std::getenv("LEDGER_INIT")) if (const char * p = std::getenv("LEDGER_INIT"))
process_option("init-file", report, p); process_option("init-file", report, p, "LEDGER_INIT");
if (const char * p = std::getenv("PRICE_HIST")) if (const char * p = std::getenv("PRICE_HIST"))
process_option("price-db", report, p); process_option("price-db", report, p, "PRICE_HIST");
if (const char * p = std::getenv("PRICE_EXP")) if (const char * p = std::getenv("PRICE_EXP"))
process_option("price-exp", report, p); process_option("price-exp", report, p, "PRICE_EXP");
#endif #endif
TRACE_FINISH(environment, 1); TRACE_FINISH(environment, 1);

View file

@ -234,21 +234,6 @@ bool xact_t::valid() const
return true; return true;
} }
#if 0
xact_context::xact_context(const xact_t& _xact, const string& desc) throw()
: file_context("", 0, desc), xact(_xact)
{
const paths_list& sources(xact.entry->journal->sources);
std::size_t x = 0;
foreach (const path& path, sources)
if (x == xact.entry->src_idx) {
file = path;
break;
}
line = xact.beg_line;
}
#endif
void xact_t::add_to_value(value_t& value) void xact_t::add_to_value(value_t& value)
{ {
if (xdata_ && xdata_->has_flags(XACT_EXT_COMPOUND)) { if (xdata_ && xdata_->has_flags(XACT_EXT_COMPOUND)) {