summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.cc6
-rw-r--r--quotes.cc3
-rw-r--r--valexpr.cc69
-rw-r--r--valexpr.h25
-rw-r--r--walk.cc11
5 files changed, 58 insertions, 56 deletions
diff --git a/config.cc b/config.cc
index 65af5d3c..85c90427 100644
--- a/config.cc
+++ b/config.cc
@@ -187,8 +187,7 @@ void config_t::process_options(const std::string& command,
// If downloading is to be supported, configure the updater
if (! commodity_t::updater && download_quotes)
- commodity_t::updater = new quotes_by_script(price_db,
- pricing_leeway,
+ commodity_t::updater = new quotes_by_script(price_db, pricing_leeway,
cache_dirty);
if (! date_format.empty())
@@ -235,7 +234,8 @@ void parse_ledger_data(journal_t * journal,
entry_count += parse_journal_file(config.data_file, journal, account);
}
- if (! config.price_db.empty())
+ if (! config.price_db.empty() &&
+ access(config.price_db.c_str(), R_OK) != -1)
if (parse_journal_file(config.price_db, journal))
throw error("Entries not allowed in price history file");
}
diff --git a/quotes.cc b/quotes.cc
index b994c630..60e09117 100644
--- a/quotes.cc
+++ b/quotes.cc
@@ -3,6 +3,7 @@
#include "debug.h"
#include <fstream>
+#include <stdlib.h>
namespace ledger {
@@ -56,7 +57,7 @@ void quotes_by_script::operator()(commodity_t& commodity,
price.parse(buf);
commodity.add_price(now, price);
- if (price && ! price_db.empty()) {
+ if (price && ! price_db.empty() && access(price_db.c_str(), W_OK) != -1) {
char buf[128];
strftime(buf, 127, "%Y/%m/%d %H:%M:%S", localtime(&now));
ofstream database(price_db.c_str(), ios_base::out | ios_base::app);
diff --git a/valexpr.cc b/valexpr.cc
index 6be93879..ae55c10f 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -379,6 +379,21 @@ void value_expr_t::compute(value_t& result, const details_t& details) const
}
}
+static inline void unexpected(char c, char wanted = '\0') {
+ if (c == -1) {
+ if (wanted)
+ throw value_expr_error(std::string("Missing '") + wanted + "'");
+ else
+ throw value_expr_error("Unexpected end");
+ } else {
+ if (wanted)
+ throw value_expr_error(std::string("Invalid char '") + c +
+ "' (wanted '" + wanted + "')");
+ else
+ throw value_expr_error(std::string("Invalid char '") + c + "'");
+ }
+}
+
value_expr_t * parse_value_term(std::istream& in);
inline value_expr_t * parse_value_term(const char * p) {
@@ -406,7 +421,7 @@ value_expr_t * parse_value_term(std::istream& in)
if (c == '}')
in.get(c);
else
- throw value_expr_error("Missing '}'");
+ unexpected(c, '}');
node.reset(new value_expr_t(value_expr_t::CONSTANT_A));
node->constant_a.parse(buf);
@@ -479,10 +494,9 @@ value_expr_t * parse_value_term(std::istream& in)
in.get(c);
node->right = parse_value_expr(in, true);
}
- if (peek_next_nonws(in) == ')')
- in.get(c);
- else
- throw value_expr_error("Missing ')'");
+ in.get(c);
+ if (c != ')')
+ unexpected(c, ')');
} else {
node->left = parse_value_term(in);
}
@@ -508,7 +522,7 @@ value_expr_t * parse_value_term(std::istream& in)
READ_INTO(in, buf, 255, c, c != '/');
if (c != '/')
- throw value_expr_error("Missing closing '/'");
+ unexpected(c, '/');
in.get(c);
node.reset(new value_expr_t(short_account_mask ?
@@ -522,7 +536,7 @@ value_expr_t * parse_value_term(std::istream& in)
case '\'': {
READ_INTO(in, buf, 255, c, c != '\'');
if (c != '\'')
- throw value_expr_error("Missing closing '\''");
+ unexpected(c, '\'');
in.get(c);
node.reset(new value_expr_t(value_expr_t::F_INTERP_FUNC));
@@ -533,16 +547,15 @@ value_expr_t * parse_value_term(std::istream& in)
case '(':
node.reset(parse_value_expr(in, true));
- if (peek_next_nonws(in) == ')')
- in.get(c);
- else
- throw value_expr_error("Missing ')'");
+ in.get(c);
+ if (c != ')')
+ unexpected(c, ')');
break;
case '[': {
READ_INTO(in, buf, 255, c, c != ']');
if (c != ']')
- throw value_expr_error("Missing ']'");
+ unexpected(c, ']');
in.get(c);
node.reset(new value_expr_t(value_expr_t::CONSTANT_T));
@@ -677,8 +690,7 @@ value_expr_t * parse_logic_expr(std::istream& in)
default:
if (! in.eof())
- throw value_expr_error(std::string("Unexpected character '") +
- c + "'");
+ unexpected(c);
break;
}
}
@@ -721,8 +733,7 @@ value_expr_t * parse_value_expr(std::istream& in, const bool partial)
choices->left = parse_logic_expr(in);
c = peek_next_nonws(in);
if (c != ':')
- throw value_expr_error(std::string("Unexpected character '") +
- c + "'");
+ unexpected(c, ':');
in.get(c);
choices->right = parse_logic_expr(in);
break;
@@ -730,26 +741,26 @@ value_expr_t * parse_value_expr(std::istream& in, const bool partial)
default:
if (! in.eof())
- throw value_expr_error(std::string("Unexpected character '") +
- c + "'");
+ unexpected(c);
break;
}
c = peek_next_nonws(in);
}
}
- if (! partial) {
- char c;
+ char c;
+ if (! node.get()) {
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 + "'");
- }
+ if (in.eof())
+ throw value_expr_error(std::string("Failed to parse value expression"));
+ else
+ unexpected(c);
+ } else if (! partial) {
+ in.get(c);
+ if (! in.eof())
+ unexpected(c);
+ else
+ in.unget();
}
return node.release();
diff --git a/valexpr.h b/valexpr.h
index 4dd9fbda..1ae9d5a9 100644
--- a/valexpr.h
+++ b/valexpr.h
@@ -131,7 +131,7 @@ inline value_expr_t * parse_value_expr(const char * p,
inline value_expr_t * parse_value_expr(const std::string& str,
const bool partial = false) {
- return parse_value_expr(str.c_str(), partial);
+ return parse_value_expr(str.c_str());
}
#ifdef DEBUG_ENABLED
@@ -146,30 +146,15 @@ class item_predicate
const value_expr_t * predicate;
public:
- item_predicate(const std::string& _predicate) {
+ item_predicate(const std::string& _predicate) : predicate(NULL) {
DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>");
- predicate = NULL;
if (! _predicate.empty()) {
try {
-#ifdef DEBUG_ENABLED
- DEBUG_CLASS("valexpr.predicate.parse");
-
- DEBUG_PRINT_("parsing: '" << _predicate << "'");
-#endif
predicate = parse_value_expr(_predicate);
-
-#ifdef DEBUG_ENABLED
- if (DEBUG_() && _debug_stream) {
- *_debug_stream << "dump: ";
- dump_value_expr(*_debug_stream, predicate);
- *_debug_stream << std::endl;
- }
-#endif
}
- catch (const value_expr_error& err) {
- std::cerr << "Error in predicate '" << _predicate << "': "
- << err.what() << std::endl;
- std::exit(1);
+ catch (value_expr_error& err) {
+ throw value_expr_error(std::string("In predicate '") +
+ _predicate + "': " + err.what());
}
}
}
diff --git a/walk.cc b/walk.cc
index 154014e8..6621a263 100644
--- a/walk.cc
+++ b/walk.cc
@@ -360,9 +360,14 @@ void walk_accounts(account_t& account,
const std::string& sort_string)
{
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));
+ std::auto_ptr<value_expr_t> sort_order;
+ try {
+ sort_order.reset(parse_value_expr(sort_string));
+ }
+ catch (value_expr_error& err) {
+ throw error(std::string("In sort string '" + sort_string + "': " +
+ err.what()));
+ }
walk_accounts(account, handler, sort_order.get());
} else {
walk_accounts(account, handler);