summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xacprep4
-rw-r--r--config.cc12
-rw-r--r--format.cc15
-rw-r--r--journal.cc5
-rw-r--r--valexpr.cc35
-rw-r--r--valexpr.h13
-rw-r--r--walk.cc2
-rw-r--r--walk.h11
8 files changed, 63 insertions, 34 deletions
diff --git a/acprep b/acprep
index 3c651e19..b946c27e 100755
--- a/acprep
+++ b/acprep
@@ -3,7 +3,7 @@
glibtoolize --automake -f -c
aclocal
autoheader
-touch AUTHORS ChangeLog COPYING
+touch AUTHORS COPYING
if [ "$1" = "--dist" ]; then
automake -acfi
@@ -30,4 +30,4 @@ elif [ "$1" = "--perf" ]; then
./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="-g -pg"
fi
-rm AUTHORS ChangeLog COPYING
+rm AUTHORS COPYING
diff --git a/config.cc b/config.cc
index d8304d95..65af5d3c 100644
--- a/config.cc
+++ b/config.cc
@@ -171,23 +171,17 @@ void config_t::process_options(const std::string& command,
try {
if (! format_t::amount_expr)
format_t::amount_expr = parse_value_expr(amount_expr);
- if (! format_t::amount_expr)
- throw value_expr_error(std::string("Failed to parse '") +
- amount_expr + "'");
}
catch (const value_expr_error& err) {
- throw error(std::string("In value expression to -t: ") + err.what());
+ throw error(std::string("In amount expression (-t): ") + err.what());
}
try {
if (! format_t::total_expr)
format_t::total_expr = parse_value_expr(total_expr);
- if (! format_t::total_expr)
- throw value_expr_error(std::string("Failed to parse '") +
- total_expr + "'");
}
catch (const value_expr_error& err) {
- throw error(std::string("In value expression to -T: ") + err.what());
+ throw error(std::string("In total expression (-T): ") + err.what());
}
// If downloading is to be supported, configure the updater
@@ -197,7 +191,7 @@ void config_t::process_options(const std::string& command,
pricing_leeway,
cache_dirty);
- if (format_t::date_format.empty() && ! date_format.empty())
+ if (! date_format.empty())
format_t::date_format = date_format;
}
diff --git a/format.cc b/format.cc
index 20f8611a..16807243 100644
--- a/format.cc
+++ b/format.cc
@@ -14,7 +14,7 @@ std::string truncated(const std::string& str, unsigned int width)
return buf;
}
-std::string partial_account_name(const account_t& account)
+std::string partial_account_name(const account_t& account)
{
std::string name;
@@ -135,8 +135,14 @@ element_t * format_t::parse_elements(const std::string& fmt)
if (*p != ')')
throw format_error("Missing ')'");
- current->type = element_t::VALUE_EXPR;
- current->val_expr = parse_value_expr(std::string(b, p));
+ current->type = element_t::VALUE_EXPR;
+ try {
+ current->val_expr = parse_value_expr(std::string(b, p));
+ }
+ catch (value_expr_error& err) {
+ throw value_expr_error(std::string("In format expression '") +
+ std::string(b, p) + "': " + err.what());
+ }
break;
}
@@ -210,11 +216,12 @@ void format_t::format(std::ostream& out, const details_t& details) const
case element_t::AMOUNT: expr = amount_expr; break;
case element_t::TOTAL: expr = total_expr; break;
case element_t::VALUE_EXPR: expr = elem->val_expr; break;
-
default:
assert(0);
break;
}
+ if (! expr)
+ break;
value_t value;
expr->compute(value, details);
switch (value.type) {
diff --git a/journal.cc b/journal.cc
index 4fedc206..4b0b063a 100644
--- a/journal.cc
+++ b/journal.cc
@@ -631,12 +631,7 @@ void export_journal()
.def_readonly("sources", &journal_t::sources)
.def("__len__", entries_len)
-#if 0
.def("__getitem__", entries_getitem, return_internal_reference<1>())
-#else
- .def("__getitem__", entries_getitem,
- return_value_policy<reference_existing_object>())
-#endif
.def("add_account", &journal_t::add_account)
.def("remove_account", &journal_t::remove_account)
.def("find_account", py_find_account_1, return_internal_reference<1>())
diff --git a/valexpr.cc b/valexpr.cc
index e417a66f..6be93879 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -474,10 +474,10 @@ value_expr_t * parse_value_term(std::istream& in)
node.reset(new value_expr_t(value_expr_t::F_VALUE));
if (peek_next_nonws(in) == '(') {
in.get(c);
- node->left = parse_value_expr(in);
+ node->left = parse_value_expr(in, true);
if (peek_next_nonws(in) == ',') {
in.get(c);
- node->right = parse_value_expr(in);
+ node->right = parse_value_expr(in, true);
}
if (peek_next_nonws(in) == ')')
in.get(c);
@@ -527,12 +527,12 @@ value_expr_t * parse_value_term(std::istream& in)
in.get(c);
node.reset(new value_expr_t(value_expr_t::F_INTERP_FUNC));
node->constant_s = buf;
- node->right = parse_value_expr(in);
+ node->right = parse_value_expr(in, true);
break;
}
case '(':
- node.reset(parse_value_expr(in));
+ node.reset(parse_value_expr(in, true));
if (peek_next_nonws(in) == ')')
in.get(c);
else
@@ -687,7 +687,7 @@ value_expr_t * parse_logic_expr(std::istream& in)
return node.release();
}
-value_expr_t * parse_value_expr(std::istream& in)
+value_expr_t * parse_value_expr(std::istream& in, const bool partial)
{
std::auto_ptr<value_expr_t> node(parse_logic_expr(in));
@@ -738,6 +738,20 @@ value_expr_t * parse_value_expr(std::istream& in)
}
}
+ if (! partial) {
+ char c;
+ in.get(c);
+ if (! node.get()) {
+ if (in.eof())
+ throw value_expr_error(std::string("Failed to parse value expression"));
+ else
+ throw value_expr_error(std::string("Unexpected character '") + c + "'");
+ } else if (! in.eof()) {
+ throw value_expr_error(std::string("Unexpected character '") +
+ c + "'");
+ }
+ }
+
return node.release();
}
@@ -915,11 +929,16 @@ value_t py_compute(value_expr_t& value_expr, const T& item)
return result;
}
-value_expr_t * py_parse_value_expr(const std::string& str)
+value_expr_t * py_parse_value_expr_1(const std::string& str)
{
return parse_value_expr(str);
}
+value_expr_t * py_parse_value_expr_2(const std::string& str, const bool partial)
+{
+ return parse_value_expr(str, partial);
+}
+
void export_valexpr()
{
class_< details_t > ("Details", init<const entry_t&>())
@@ -943,7 +962,9 @@ void export_valexpr()
.def("compute", py_compute<transaction_t>)
;
- def("parse_value_expr", py_parse_value_expr,
+ def("parse_value_expr", py_parse_value_expr_1,
+ return_value_policy<manage_new_object>());
+ def("parse_value_expr", py_parse_value_expr_2,
return_value_policy<manage_new_object>());
class_< item_predicate<transaction_t> >
diff --git a/valexpr.h b/valexpr.h
index 29333092..4dd9fbda 100644
--- a/valexpr.h
+++ b/valexpr.h
@@ -120,15 +120,18 @@ struct value_expr_t
void compute(value_t& result, const details_t& details) const;
};
-value_expr_t * parse_value_expr(std::istream& in);
+value_expr_t * parse_value_expr(std::istream& in,
+ const bool partial = false);
-inline value_expr_t * parse_value_expr(const char * p) {
+inline value_expr_t * parse_value_expr(const char * p,
+ const bool partial = false) {
std::istringstream stream(p);
- return parse_value_expr(stream);
+ return parse_value_expr(stream, partial);
}
-inline value_expr_t * parse_value_expr(const std::string& str) {
- return parse_value_expr(str.c_str());
+inline value_expr_t * parse_value_expr(const std::string& str,
+ const bool partial = false) {
+ return parse_value_expr(str.c_str(), partial);
}
#ifdef DEBUG_ENABLED
diff --git a/walk.cc b/walk.cc
index 844099a2..154014e8 100644
--- a/walk.cc
+++ b/walk.cc
@@ -361,6 +361,8 @@ void walk_accounts(account_t& account,
{
if (! sort_string.empty()) {
std::auto_ptr<value_expr_t> sort_order(parse_value_expr(sort_string));
+ if (! sort_order.get())
+ throw error(std::string("Sort string failed to parse: " + sort_string));
walk_accounts(account, handler, sort_order.get());
} else {
walk_accounts(account, handler);
diff --git a/walk.h b/walk.h
index 147c900b..a234ed85 100644
--- a/walk.h
+++ b/walk.h
@@ -182,8 +182,15 @@ class sort_transactions : public item_handler<transaction_t>
sort_transactions(item_handler<transaction_t> * handler,
const std::string& _sort_order)
- : item_handler<transaction_t>(handler),
- sort_order(parse_value_expr(_sort_order)), allocated(true) {}
+ : item_handler<transaction_t>(handler), allocated(true) {
+ try {
+ sort_order = parse_value_expr(_sort_order);
+ }
+ catch (value_expr_error& err) {
+ throw value_expr_error(std::string("In sort string '") + _sort_order +
+ "': " + err.what());
+ }
+ }
virtual ~sort_transactions() {
assert(sort_order);