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!
|
; This is a transaction note!
|
||||||
; Sample: Another Value
|
; Sample: Another Value
|
||||||
; :MyTag:
|
; :MyTag:
|
||||||
Assets:Bank:Checking
|
Assets:Bank:Checking $-21.00
|
||||||
; :AnotherTag:
|
; :AnotherTag:
|
||||||
|
|
|
||||||
22
src/entry.cc
22
src/entry.cc
|
|
@ -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(),
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
47
src/item.cc
47
src/item.cc
|
|
@ -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
|
||||||
|
|
|
||||||
24
src/item.h
24
src/item.h
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
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 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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
262
src/textual.cc
262
src/textual.cc
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
src/utils.cc
12
src/utils.cc
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
15
src/xact.cc
15
src/xact.cc
|
|
@ -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)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue