Simplified error context handling.
This commit is contained in:
parent
ef3943c604
commit
9540406af1
19 changed files with 230 additions and 222 deletions
|
|
@ -38,5 +38,5 @@ N $
|
|||
; This is a transaction note!
|
||||
; Sample: Another Value
|
||||
; :MyTag:
|
||||
Assets:Bank:Checking
|
||||
Assets:Bank:Checking $-21.00
|
||||
; :AnotherTag:
|
||||
|
|
|
|||
22
src/entry.cc
22
src/entry.cc
|
|
@ -37,8 +37,7 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
entry_base_t::entry_base_t(const entry_base_t& e)
|
||||
: item_t(), journal(NULL)
|
||||
entry_base_t::entry_base_t(const entry_base_t& e) : item_t()
|
||||
{
|
||||
TRACE_CTOR(entry_base_t, "copy");
|
||||
#if 0
|
||||
|
|
@ -80,11 +79,14 @@ item_t::state_t entry_base_t::state() const
|
|||
void entry_base_t::add_xact(xact_t * xact)
|
||||
{
|
||||
xacts.push_back(xact);
|
||||
xact->journal = journal;
|
||||
}
|
||||
|
||||
bool entry_base_t::remove_xact(xact_t * xact)
|
||||
{
|
||||
xacts.remove(xact);
|
||||
xact->entry = NULL;
|
||||
xact->journal = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -226,10 +228,8 @@ bool entry_base_t::finalize()
|
|||
DEBUG("entry.finalize", "final balance = " << balance);
|
||||
|
||||
if (! balance.is_null() && ! balance.is_zero()) {
|
||||
#if 0
|
||||
add_error_context(entry_context(*this));
|
||||
#endif
|
||||
add_error_context("Unbalanced remainder is: ");
|
||||
add_error_context(item_context(*this));
|
||||
add_error_context("Unbalanced remainder is:");
|
||||
add_error_context(value_context(balance));
|
||||
throw_(balance_error, "Entry does not balance");
|
||||
}
|
||||
|
|
@ -326,16 +326,6 @@ bool entry_t::valid() const
|
|||
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)
|
||||
{
|
||||
xacts_list initial_xacts(entry.xacts.begin(),
|
||||
|
|
|
|||
|
|
@ -61,10 +61,9 @@ class journal_t;
|
|||
class entry_base_t : public item_t
|
||||
{
|
||||
public:
|
||||
journal_t * journal;
|
||||
xacts_list xacts;
|
||||
|
||||
entry_base_t() : journal(NULL) {
|
||||
entry_base_t() {
|
||||
TRACE_CTOR(entry_base_t, "");
|
||||
}
|
||||
entry_base_t(const entry_base_t& e);
|
||||
|
|
|
|||
|
|
@ -153,6 +153,11 @@ public:
|
|||
|
||||
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
|
||||
|
||||
#endif // _EXPR_H
|
||||
|
|
|
|||
|
|
@ -201,10 +201,8 @@ void calc_xacts::operator()(xact_t& xact)
|
|||
last_xact = &xact;
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
add_error_context("Calculating transaction at");
|
||||
#if 0
|
||||
add_error_context(xact_context(xact));
|
||||
#endif
|
||||
add_error_context("While calculating transaction:");
|
||||
add_error_context(item_context(xact));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -298,7 +298,8 @@ void format_t::format(std::ostream& out_str, scope_t& scope)
|
|||
value.strip_annotations().dump(out, elem->min_width);
|
||||
}
|
||||
catch (const calc_error&) {
|
||||
out << (string("%") + elem->chars);
|
||||
add_error_context("While calculating format expression:");
|
||||
add_error_context(expr_context(elem->expr));
|
||||
throw;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
47
src/item.cc
47
src/item.cc
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
bool item_t::use_effective_date = false;
|
||||
|
||||
bool item_t::has_tag(const string& tag) const
|
||||
{
|
||||
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)
|
||||
{
|
||||
switch (name[0]) {
|
||||
|
|
@ -289,4 +295,41 @@ bool item_t::valid() const
|
|||
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
|
||||
|
|
|
|||
24
src/item.h
24
src/item.h
|
|
@ -51,6 +51,8 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
class journal_t;
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
|
|
@ -75,20 +77,25 @@ public:
|
|||
typedef std::map<string, optional<string> > string_map;
|
||||
optional<string_map> metadata;
|
||||
|
||||
journal_t * journal;
|
||||
|
||||
unsigned short src_idx;
|
||||
#if 0
|
||||
istream_pos_type full_beg_pos;
|
||||
std::size_t full_beg_line;
|
||||
#endif
|
||||
istream_pos_type beg_pos;
|
||||
std::size_t beg_line;
|
||||
istream_pos_type end_pos;
|
||||
std::size_t end_line;
|
||||
#if 0
|
||||
istream_pos_type full_end_pos;
|
||||
std::size_t full_end_line;
|
||||
|
||||
static bool use_effective_date;
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
TRACE_CTOR(item_t, "flags_t, const string&");
|
||||
|
|
@ -112,6 +119,8 @@ public:
|
|||
|
||||
note = item.note;
|
||||
|
||||
journal = item.journal;
|
||||
src_idx = item.src_idx;
|
||||
beg_pos = item.beg_pos;
|
||||
beg_line = item.beg_line;
|
||||
end_pos = item.end_pos;
|
||||
|
|
@ -144,12 +153,7 @@ public:
|
|||
virtual optional<date_t> effective_date() const {
|
||||
return _date_eff;
|
||||
}
|
||||
optional<date_t> date() const {
|
||||
if (use_effective_date && _date_eff)
|
||||
return effective_date();
|
||||
else
|
||||
return actual_date();
|
||||
}
|
||||
optional<date_t> date() const;
|
||||
|
||||
void set_state(state_t new_state) {
|
||||
_state = new_state;
|
||||
|
|
@ -165,6 +169,8 @@ public:
|
|||
|
||||
value_t get_comment(item_t& item);
|
||||
|
||||
string item_context(const item_t& item);
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _ITEM_H
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ int main(int argc, char * argv[], char * envp[])
|
|||
}
|
||||
catch (const std::exception& err) {
|
||||
std::cout.flush();
|
||||
std::cerr << error_context() << "Error: " << err.what() << std::endl;
|
||||
report_error(err);
|
||||
}
|
||||
catch (int _status) {
|
||||
status = _status;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ value_t expr_t::op_t::calc(scope_t& scope)
|
|||
catch (const std::exception& err) {
|
||||
if (context_op_ptr) {
|
||||
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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
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
|
||||
buf << " ";
|
||||
}
|
||||
buf << '\n';
|
||||
}
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
|||
2
src/op.h
2
src/op.h
|
|
@ -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 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
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ namespace {
|
|||
}
|
||||
|
||||
void process_option(const function_t& opt, scope_t& scope,
|
||||
const char * arg)
|
||||
const char * arg, const string& name)
|
||||
{
|
||||
try {
|
||||
call_scope_t args(scope);
|
||||
|
|
@ -85,23 +85,23 @@ namespace {
|
|||
opt(args);
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
#if 0
|
||||
add_error_context("While parsing option '--" << opt->long_opt
|
||||
<< "'" << (opt->short_opt != '\0' ?
|
||||
(string(" (-") + opt->short_opt + "):") :
|
||||
": "));
|
||||
#endif
|
||||
if (name[0] == '-')
|
||||
add_error_context("While parsing option '" << name << "':");
|
||||
|
||||
else
|
||||
add_error_context("While parsing environent variable '"
|
||||
<< name << "':");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
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,
|
||||
|
|
@ -126,7 +126,7 @@ void process_environment(const char ** envp, const string& tag,
|
|||
|
||||
if (*q == '=') {
|
||||
try {
|
||||
process_option(string(buf), scope, q + 1);
|
||||
process_option(string(buf), scope, q + 1, string(*p, q - *p));
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
add_error_context("While parsing environment variable option '"
|
||||
|
|
@ -179,7 +179,8 @@ void process_arguments(int, char ** argv, scope_t& scope,
|
|||
if (value == NULL)
|
||||
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') {
|
||||
throw_(option_error, "illegal option -");
|
||||
|
|
@ -210,7 +211,8 @@ void process_arguments(int, char ** argv, scope_t& scope,
|
|||
throw_(option_error,
|
||||
"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>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
namespace ledger {
|
||||
|
||||
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,
|
||||
scope_t& scope);
|
||||
|
|
|
|||
|
|
@ -149,6 +149,8 @@ public:
|
|||
bool entry_sort;
|
||||
bool sort_all;
|
||||
bool anonymize;
|
||||
bool use_effective_date;
|
||||
|
||||
|
||||
string account;
|
||||
optional<path> pager_path;
|
||||
|
|
@ -184,6 +186,7 @@ public:
|
|||
entry_sort(false),
|
||||
sort_all(false),
|
||||
anonymize(false),
|
||||
use_effective_date(false),
|
||||
|
||||
raw_mode(false),
|
||||
|
||||
|
|
@ -274,7 +277,7 @@ public:
|
|||
// Report filtering
|
||||
|
||||
value_t option_effective(call_scope_t& args) {
|
||||
xact_t::use_effective_date = true;
|
||||
use_effective_date = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
262
src/textual.cc
262
src/textual.cc
|
|
@ -116,7 +116,11 @@ namespace {
|
|||
#endif
|
||||
|
||||
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);
|
||||
return expr;
|
||||
}
|
||||
|
|
@ -182,7 +186,8 @@ void textual_parser_t::instance_t::parse()
|
|||
try {
|
||||
read_next_directive();
|
||||
|
||||
beg_pos = end_pos;
|
||||
beg_pos = end_pos;
|
||||
beg_line = linenum;
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
if (parent) {
|
||||
|
|
@ -194,16 +199,14 @@ void textual_parser_t::instance_t::parse()
|
|||
instances.push_front(instance);
|
||||
|
||||
foreach (instance_t * instance, instances)
|
||||
add_error_context("In file included from '"
|
||||
add_error_context("In file included from "
|
||||
<< file_context(instance->pathname,
|
||||
instance->linenum - 1) << "':");
|
||||
instance->linenum - 1));
|
||||
}
|
||||
add_error_context("While parsing file "
|
||||
<< file_context(pathname, linenum - 1) << "\n");
|
||||
<< file_context(pathname, linenum - 1));
|
||||
|
||||
std::cout.flush();
|
||||
std::cerr << ledger::error_context()
|
||||
<< "Error: " << err.what() << std::endl;
|
||||
report_error(err);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
|
@ -446,7 +449,7 @@ void textual_parser_t::instance_t::option_directive(char * line)
|
|||
if (p)
|
||||
*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)
|
||||
|
|
@ -501,13 +504,15 @@ void textual_parser_t::instance_t::entry_directive(char * line)
|
|||
// possibility that add_entry ma throw an exception, which
|
||||
// would cause us to leak without this guard.
|
||||
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)) {
|
||||
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++;
|
||||
}
|
||||
// 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);
|
||||
|
||||
istream_pos_type beg = in.tellg();
|
||||
istream_pos_type end = beg;
|
||||
|
||||
string err_desc;
|
||||
try {
|
||||
|
||||
|
|
@ -683,22 +691,22 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
|
|||
|
||||
// Parse the account name
|
||||
|
||||
istream_pos_type account_beg = in.tellg();
|
||||
istream_pos_type account_end = account_beg;
|
||||
beg = in.tellg();
|
||||
end = beg;
|
||||
while (! in.eof()) {
|
||||
in.get(p);
|
||||
if (in.eof() || (std::isspace(p) &&
|
||||
(p == '\t' || in.peek() == EOF ||
|
||||
std::isspace(in.peek()))))
|
||||
break;
|
||||
account_end += 1;
|
||||
end += 1;
|
||||
}
|
||||
|
||||
if (account_beg == account_end)
|
||||
if (beg == end)
|
||||
throw parse_error("No account was specified");
|
||||
|
||||
char * b = &line[long(account_beg)];
|
||||
char * e = &line[long(account_end)];
|
||||
char * b = &line[long(beg)];
|
||||
char * e = &line[long(end)];
|
||||
|
||||
if ((*b == '[' && *(e - 1) == ']') ||
|
||||
(*b == '(' && *(e - 1) == ')')) {
|
||||
|
|
@ -738,34 +746,28 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
|
|||
if (p == '=' && entry)
|
||||
goto parse_assign;
|
||||
|
||||
try {
|
||||
istream_pos_type beg = in.tellg();
|
||||
beg = in.tellg();
|
||||
|
||||
xact->amount_expr =
|
||||
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_ASSIGN));
|
||||
saw_amount = true;
|
||||
xact->amount_expr =
|
||||
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_ASSIGN));
|
||||
saw_amount = true;
|
||||
|
||||
if (! xact->amount.is_null()) {
|
||||
xact->amount.reduce();
|
||||
DEBUG("textual.parse", "line " << linenum << ": " <<
|
||||
"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)));
|
||||
}
|
||||
if (! xact->amount.is_null()) {
|
||||
xact->amount.reduce();
|
||||
DEBUG("textual.parse", "line " << linenum << ": " <<
|
||||
"Reduced amount is " << xact->amount);
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
add_error_context("While parsing transaction amount:\n");
|
||||
throw;
|
||||
|
||||
// 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();
|
||||
|
||||
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()) {
|
||||
xact->cost = amount_t();
|
||||
|
||||
try {
|
||||
istream_pos_type beg = in.tellg();
|
||||
beg = in.tellg();
|
||||
|
||||
xact->cost_expr =
|
||||
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_ASSIGN));
|
||||
xact->cost_expr =
|
||||
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_ASSIGN));
|
||||
|
||||
if (xact->cost_expr) {
|
||||
istream_pos_type end = in.tellg();
|
||||
if (per_unit)
|
||||
xact->cost_expr->set_text(string("@") +
|
||||
string(line, long(beg), long(end - beg)));
|
||||
else
|
||||
xact->cost_expr->set_text(string("@@") +
|
||||
string(line, long(beg), long(end - beg)));
|
||||
}
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
add_error_context("While parsing transaction cost:\n");
|
||||
throw;
|
||||
if (xact->cost_expr) {
|
||||
end = in.tellg();
|
||||
if (per_unit)
|
||||
xact->cost_expr->set_text(string("@") +
|
||||
string(line, long(beg), long(end - beg)));
|
||||
else
|
||||
xact->cost_expr->set_text(string("@@") +
|
||||
string(line, long(beg), long(end - beg)));
|
||||
}
|
||||
|
||||
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()) {
|
||||
xact->assigned_amount = amount_t();
|
||||
|
||||
try {
|
||||
istream_pos_type beg = in.tellg();
|
||||
beg = in.tellg();
|
||||
|
||||
xact->assigned_amount_expr =
|
||||
parse_amount_expr(in, *xact->assigned_amount, xact.get(),
|
||||
static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE));
|
||||
xact->assigned_amount_expr =
|
||||
parse_amount_expr(in, *xact->assigned_amount, xact.get(),
|
||||
static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE));
|
||||
|
||||
if (xact->assigned_amount->is_null())
|
||||
throw parse_error
|
||||
("An assigned balance must evaluate to a constant value");
|
||||
if (xact->assigned_amount->is_null())
|
||||
throw parse_error
|
||||
("An assigned balance must evaluate to a constant value");
|
||||
|
||||
DEBUG("textual.parse", "line " << linenum << ": " <<
|
||||
"XACT assign: parsed amt = " << *xact->assigned_amount);
|
||||
DEBUG("textual.parse", "line " << linenum << ": " <<
|
||||
"XACT assign: parsed amt = " << *xact->assigned_amount);
|
||||
|
||||
if (xact->assigned_amount_expr) {
|
||||
istream_pos_type end = in.tellg();
|
||||
xact->assigned_amount_expr->set_text
|
||||
(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");
|
||||
}
|
||||
}
|
||||
if (xact->assigned_amount_expr) {
|
||||
end = in.tellg();
|
||||
xact->assigned_amount_expr->set_text
|
||||
(string("=") + string(line, long(beg), long(end - beg)));
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
add_error_context("While parsing assigned balance:\n");
|
||||
throw;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -967,8 +957,8 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
|
|||
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
add_error_context("While parsing transaction:\n");
|
||||
add_error_context(line_context(line, in.tellg()));
|
||||
add_error_context("While parsing transaction:");
|
||||
add_error_context(line_context(line, beg, in.tellg()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
src/utils.cc
12
src/utils.cc
|
|
@ -642,18 +642,6 @@ void finish_timer(const char * name)
|
|||
|
||||
#endif // LOGGING_ON && TIMERS_ON
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Exception handling
|
||||
*/
|
||||
|
||||
namespace ledger {
|
||||
|
||||
std::ostringstream _desc_buffer;
|
||||
std::ostringstream _ctxt_buffer;
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* General utility functions
|
||||
|
|
|
|||
|
|
@ -973,7 +973,6 @@ inline string value_context(const value_t& val) {
|
|||
buf << std::right;
|
||||
buf.width(20);
|
||||
val.print(buf);
|
||||
buf << std::endl;
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,13 +101,13 @@ void read_environment_settings(report_t& report, char * envp[])
|
|||
// These are here for backwards compatability, but are deprecated.
|
||||
|
||||
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"))
|
||||
process_option("init-file", report, p);
|
||||
process_option("init-file", report, p, "LEDGER_INIT");
|
||||
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"))
|
||||
process_option("price-exp", report, p);
|
||||
process_option("price-exp", report, p, "PRICE_EXP");
|
||||
#endif
|
||||
|
||||
TRACE_FINISH(environment, 1);
|
||||
|
|
|
|||
15
src/xact.cc
15
src/xact.cc
|
|
@ -234,21 +234,6 @@ bool xact_t::valid() const
|
|||
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)
|
||||
{
|
||||
if (xdata_ && xdata_->has_flags(XACT_EXT_COMPOUND)) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue