more error checking and robustness mods

This commit is contained in:
John Wiegley 2004-09-23 07:05:03 -04:00
parent c57a2e74b8
commit be18ab2f1a
5 changed files with 58 additions and 56 deletions

View file

@ -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");
}

View file

@ -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);

View file

@ -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();

View file

@ -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());
}
}
}

11
walk.cc
View file

@ -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);