summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2008-07-31 06:24:45 -0400
committerJohn Wiegley <johnw@newartisans.com>2008-07-31 06:24:45 -0400
commit99313ebc6c3779f692f9f1bd70cc69a236f5eb78 (patch)
tree44a553891a9aaa148084d8e011b2d326401343e9
parent8afd926a27af55862ce360970e05d747f249a0da (diff)
downloadfork-ledger-99313ebc6c3779f692f9f1bd70cc69a236f5eb78.tar.gz
fork-ledger-99313ebc6c3779f692f9f1bd70cc69a236f5eb78.tar.bz2
fork-ledger-99313ebc6c3779f692f9f1bd70cc69a236f5eb78.zip
Revised the way that exceptions are thrown around. Instead of context being a
complicated string of pointers, it's now just a global block of text that gets appended to as the error is being thrown up, and can be displayed at the catch point if desired. There are almost no cases where a thrown exception will not result in an error message being displayed to the user.
-rw-r--r--amount.h2
-rw-r--r--balance.h2
-rw-r--r--cache.cc8
-rw-r--r--cache.h2
-rw-r--r--derive.cc4
-rw-r--r--entry.cc6
-rw-r--r--entry.h12
-rw-r--r--error.h198
-rw-r--r--expr.h6
-rw-r--r--format.cc4
-rw-r--r--format.h8
-rw-r--r--gnucash.cc2
-rw-r--r--journal.h8
-rw-r--r--main.cc25
-rw-r--r--op.cc57
-rw-r--r--option.cc47
-rw-r--r--option.h2
-rw-r--r--parser.cc13
-rw-r--r--qif.cc5
-rw-r--r--quotes.cc6
-rw-r--r--reconcile.cc9
-rw-r--r--report.cc2
-rw-r--r--session.cc4
-rw-r--r--textual.cc82
-rw-r--r--textual.h2
-rw-r--r--times.cc2
-rw-r--r--times.h2
-rw-r--r--utils.cc12
-rw-r--r--utils.h48
-rw-r--r--value.cc13
-rw-r--r--value.h22
-rw-r--r--walk.cc8
-rw-r--r--walk.h8
-rw-r--r--xact.cc6
-rw-r--r--xact.h9
-rw-r--r--xml.cc4
36 files changed, 243 insertions, 407 deletions
diff --git a/amount.h b/amount.h
index 05508814..8fb5aa14 100644
--- a/amount.h
+++ b/amount.h
@@ -54,7 +54,7 @@ class commodity_t;
class annotation_t;
class commodity_pool_t;
-DECLARE_EXCEPTION(error, amount_error);
+DECLARE_EXCEPTION(amount_error, std::runtime_error);
/**
* @class amount_t
diff --git a/balance.h b/balance.h
index ea070ea3..0326ef13 100644
--- a/balance.h
+++ b/balance.h
@@ -48,7 +48,7 @@
namespace ledger {
-DECLARE_EXCEPTION(error, balance_error);
+DECLARE_EXCEPTION(balance_error, std::runtime_error);
/**
* @class balance_t
diff --git a/cache.cc b/cache.cc
index c04bcf1c..dd29fbd7 100644
--- a/cache.cc
+++ b/cache.cc
@@ -727,8 +727,8 @@ std::size_t read_session(std::istream& in,
// expression passed to an option, we'll just override the flags, but
// keep the commodity pointer intact.
if (c == commodity_t::base_t::commodities.end())
- throw new error(string("Failed to read base commodity from cache: ") +
- commodity->symbol);
+ throw_(cache_error, "Failed to read base commodity from cache: "
+ << commodity->symbol);
(*c).second->name = commodity->name;
(*c).second->note = commodity->note;
@@ -769,8 +769,8 @@ std::size_t read_session(std::istream& in,
commodities_map::iterator c =
commodity_t::commodities.find(mapping_key);
if (c == commodity_t::commodities.end())
- throw new error(string("Failed to read commodity from cache: ") +
- commodity->symbol());
+ throw_(cache_error, "Failed to read commodity from cache: "
+ << commodity->symbol());
*(commodities_next - 1) = (*c).second;
checked_delete(commodity);
diff --git a/cache.h b/cache.h
index 0e1005dd..43123f9f 100644
--- a/cache.h
+++ b/cache.h
@@ -39,6 +39,8 @@
namespace ledger {
+DECLARE_EXCEPTION(cache_error, std::runtime_error);
+
class binary_cache_t
{
static const unsigned long binary_magic_number = 0xFFEED765;
diff --git a/derive.cc b/derive.cc
index 9f6aeca8..bcf8f8f3 100644
--- a/derive.cc
+++ b/derive.cc
@@ -18,7 +18,7 @@ entry_t * derive_new_entry(report_t& report,
//added->_date = *i++;
added->_date = boost::posix_time::time_from_string(*i++);
if (i == end)
- throw new error("Too few arguments to 'entry'");
+ throw std::runtime_error("Too few arguments to 'entry'");
mask_t regexp(*i++);
@@ -196,7 +196,7 @@ entry_t * derive_new_entry(report_t& report,
! added->finalize() ||
(matching &&
! matching->journal->entry_finalize_hooks.run_hooks(*added, true)))
- throw new error("Failed to finalize derived entry (check commodities)");
+ throw std::runtime_error("Failed to finalize derived entry (check commodities)");
return added.release();
}
diff --git a/entry.cc b/entry.cc
index 05fcfe9e..ab9ea9f0 100644
--- a/entry.cc
+++ b/entry.cc
@@ -320,12 +320,14 @@ bool entry_base_t::finalize()
if (! balance.is_null()) {
balance.round();
if (! balance.is_zero()) {
+#if 0
error * err =
new balance_error("Entry does not balance",
new entry_context(*this, "While balancing entry:"));
err->context.push_front
(new value_context(balance, "Unbalanced remainder is:"));
throw err;
+#endif
}
}
@@ -381,7 +383,7 @@ namespace {
value_t get_payee(call_scope_t& scope)
{
entry_t& entry(downcast<entry_t>(*scope.parent));
- return value_t(entry.payee, true);
+ return string_value(entry.payee);
}
}
@@ -425,6 +427,7 @@ bool entry_t::valid() const
return true;
}
+#if 0
void entry_context::describe(std::ostream& out) const throw()
{
if (! desc.empty())
@@ -432,6 +435,7 @@ void entry_context::describe(std::ostream& out) const throw()
print_entry(out, entry, " ");
}
+#endif
void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
{
diff --git a/entry.h b/entry.h
index 5764624c..16fc3bf3 100644
--- a/entry.h
+++ b/entry.h
@@ -124,18 +124,6 @@ struct entry_finalizer_t {
virtual bool operator()(entry_t& entry, bool post) = 0;
};
-class entry_context : public error_context {
- public:
- const entry_base_t& entry;
-
- entry_context(const entry_base_t& _entry,
- const string& _desc = "") throw()
- : error_context(_desc), entry(_entry) {}
- virtual ~entry_context() throw() {}
-
- virtual void describe(std::ostream& out) const throw();
-};
-
class auto_entry_t : public entry_base_t
{
public:
diff --git a/error.h b/error.h
index 16cb197e..4eaf72a8 100644
--- a/error.h
+++ b/error.h
@@ -1,132 +1,84 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#ifndef _ERROR_H
#define _ERROR_H
-#include <exception>
-#include <stdexcept>
-#include <string>
-#include <cstring>
-#include <sstream>
-#include <list>
-
namespace ledger {
-class error_context
-{
-public:
- string desc;
-
- error_context(const string& _desc) throw() : desc(_desc) {}
- virtual ~error_context() throw() {}
- virtual void describe(std::ostream& out) const throw() {
- if (! desc.empty())
- out << desc << std::endl;
- }
-};
-
-class file_context : public error_context
-{
- protected:
- path file;
- unsigned long line;
- public:
- file_context(const path& _file, unsigned long _line,
- const string& desc = "") throw()
- : error_context(desc), file(_file), line(_line) {}
- virtual ~file_context() throw() {}
-
- virtual void describe(std::ostream& out) const throw() {
- if (! desc.empty())
- out << desc << " ";
-
- out << "\"" << file << "\", line " << line << ": ";
+extern std::ostringstream _desc_buffer;
+
+template <typename T>
+inline void throw_func(const std::string& message) {
+ _desc_buffer.str("");
+ throw T(message);
+}
+
+#define throw_(cls, msg) \
+ ((_desc_buffer << msg), throw_func<cls>(_desc_buffer.str()))
+
+extern std::ostringstream _ctxt_buffer;
+
+#define add_error_context(msg) \
+ ((static_cast<unsigned long>(_ctxt_buffer.tellp()) == 0) ? \
+ (_ctxt_buffer << msg) : (_ctxt_buffer << std::endl << msg))
+
+inline string error_context() {
+ string context = _ctxt_buffer.str();
+ _ctxt_buffer.str("");
+ return context;
+}
+
+inline string file_context(const path& file, std::size_t line) {
+ std::ostringstream buf;
+ buf << "\"" << file << "\", line " << line << ": ";
+ return buf.str();
+}
+
+inline string line_context(const string& line, long pos) {
+ std::ostringstream buf;
+ buf << " " << line << std::endl << " ";
+ long idx = pos < 0 ? line.length() - 1 : pos;
+ for (int i = 0; i < idx; i++)
+ buf << " ";
+ buf << "^" << std::endl;
+ return buf.str();
+}
+
+#define DECLARE_EXCEPTION(name, kind) \
+ class name : public kind { \
+ public: \
+ explicit name(const string& why) throw() : kind(why) {} \
+ virtual ~name() throw() {} \
}
-};
-
-class line_context : public error_context
-{
-public:
- string line;
- long pos;
-
- line_context(const string& _line, long _pos,
- const string& desc = "") throw()
- : error_context(desc), line(_line), pos(_pos) {}
- virtual ~line_context() throw() {}
-
- virtual void describe(std::ostream& out) const throw() {
- if (! desc.empty())
- out << desc << std::endl;
-
- out << " " << line << std::endl << " ";
- long idx = pos < 0 ? line.length() - 1 : pos;
- for (int i = 0; i < idx; i++)
- out << " ";
- out << "^" << std::endl;
- }
-};
-
-//////////////////////////////////////////////////////////////////////
-
-class str_exception : public std::logic_error
-{
-public:
- std::list<error_context *> context;
-
- str_exception(const string& why,
- error_context * ctxt = NULL) throw()
- : std::logic_error(why), context() {
- if (ctxt)
- context.push_back(ctxt);
- }
-
- virtual ~str_exception() throw() {
- for (std::list<error_context *>::iterator i = context.begin();
- i != context.end();
- i++)
- checked_delete(*i);
- }
-
- virtual void reveal_context(std::ostream& out,
- const string& kind) const throw() {
- for (std::list<error_context *>::const_reverse_iterator i =
- context.rbegin();
- i != context.rend();
- i++) {
- std::list<error_context *>::const_reverse_iterator x = i;
- if (++x == context.rend())
- out << kind << ": ";
- (*i)->describe(out);
- }
- }
-};
-
-#define DECLARE_EXCEPTION(kind, name) \
- class name : public kind { \
- public: \
- name(const string& why, error_context * ctxt = NULL) throw() \
- : kind(why, ctxt) {} \
- }
-
-class error : public str_exception {
- public:
- error(const string& why, error_context * ctxt = NULL) throw()
- : str_exception(why, ctxt) {}
- virtual ~error() throw() {}
-};
-
-class fatal : public str_exception {
- public:
- fatal(const string& why, error_context * ctxt = NULL) throw()
- : str_exception(why, ctxt) {}
- virtual ~fatal() throw() {}
-};
-
-class fatal_assert : public fatal {
- public:
- fatal_assert(const string& why, error_context * ctxt = NULL) throw()
- : fatal(string("assertion failed '") + why + "'", ctxt) {}
- virtual ~fatal_assert() throw() {}
-};
} // namespace ledger
diff --git a/expr.h b/expr.h
index c81a24df..ab8c07f2 100644
--- a/expr.h
+++ b/expr.h
@@ -36,9 +36,9 @@
namespace ledger {
-DECLARE_EXCEPTION(error, parse_error);
-DECLARE_EXCEPTION(error, compile_error);
-DECLARE_EXCEPTION(error, calc_error);
+DECLARE_EXCEPTION(parse_error, std::runtime_error);
+DECLARE_EXCEPTION(compile_error, std::runtime_error);
+DECLARE_EXCEPTION(calc_error, std::runtime_error);
class scope_t;
class call_scope_t;
diff --git a/format.cc b/format.cc
index 1be9651c..db639edd 100644
--- a/format.cc
+++ b/format.cc
@@ -214,7 +214,7 @@ element_t * format_t::parse_elements(const string& fmt)
p++;
}
if (*p != ')')
- throw new format_error("Missing ')'");
+ throw format_error("Missing ')'");
current->type = element_t::VALUE_EXPR;
@@ -235,7 +235,7 @@ element_t * format_t::parse_elements(const string& fmt)
p++;
}
if (*p != ']')
- throw new format_error("Missing ']'");
+ throw format_error("Missing ']'");
current->type = element_t::DATE_STRING;
current->chars = string(b, p);
diff --git a/format.h b/format.h
index 6c9d2e5f..8348e863 100644
--- a/format.h
+++ b/format.h
@@ -219,13 +219,7 @@ class format_equity : public item_handler<account_t>
virtual void operator()(account_t& account);
};
-class format_error : public error
-{
- public:
- format_error(const string& reason, error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~format_error() throw() {}
-};
+DECLARE_EXCEPTION(format_error, std::runtime_error);
} // namespace ledger
diff --git a/gnucash.cc b/gnucash.cc
index 59902da2..0be5661e 100644
--- a/gnucash.cc
+++ b/gnucash.cc
@@ -394,7 +394,7 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
const char * msg = XML_ErrorString(XML_GetErrorCode(parser));
XML_ParserFree(parser);
- throw new parse_error(msg);
+ throw parse_error(msg);
}
if (! have_error.empty()) {
diff --git a/journal.h b/journal.h
index e61ab114..d24e4fc1 100644
--- a/journal.h
+++ b/journal.h
@@ -118,14 +118,6 @@ public:
const path * original_file = NULL);
};
- class parse_error : public error
- {
- public:
- parse_error(const string& reason, error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~parse_error() throw() {}
- };
-
bool valid() const;
};
diff --git a/main.cc b/main.cc
index 4e475620..8d9f64dd 100644
--- a/main.cc
+++ b/main.cc
@@ -297,7 +297,7 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
command_args.push_back(value_t(out));
for (strings_list::iterator i = arg; i != args.end(); i++)
- command_args.push_back(value_t(*i, true));
+ command_args.push_back(string_value(*i));
INFO_START(command, "Did user command '" << verb << "'");
@@ -422,29 +422,10 @@ int main(int argc, char * argv[], char * envp[])
session.release();
}
}
- catch (ledger::error * err) {
- std::cout.flush();
- // Push a null here since there's no file context
- if (err->context.empty() ||
- ! dynamic_cast<ledger::xact_context *>(err->context.front()))
- err->context.push_front(new ledger::error_context(""));
- err->reveal_context(std::cerr, "Error");
- std::cerr << err->what() << std::endl;
- ledger::checked_delete(err);
- }
- catch (ledger::fatal * err) {
- std::cout.flush();
- // Push a null here since there's no file context
- if (err->context.empty() ||
- ! dynamic_cast<ledger::xact_context *>(err->context.front()))
- err->context.push_front(new ledger::error_context(""));
- err->reveal_context(std::cerr, "Fatal");
- std::cerr << err->what() << std::endl;
- ledger::checked_delete(err);
- }
catch (const std::exception& err) {
std::cout.flush();
- std::cerr << "Exception: " << err.what() << std::endl;
+ std::cerr << "Error: " << ledger::error_context() << err.what()
+ << std::endl;
}
catch (int _status) {
status = _status;
diff --git a/op.cc b/op.cc
index d65ec715..dd808eb2 100644
--- a/op.cc
+++ b/op.cc
@@ -43,7 +43,7 @@ void expr_t::op_t::compute(value_t& result,
try {
switch (kind) {
case INDEX:
- throw new compute_error("Cannot directly compute an argument index");
+ throw compute_error("Cannot directly compute an argument index");
case VALUE:
result = as_value();
@@ -280,8 +280,8 @@ void expr_t::op_t::compute(value_t& result,
moment.cast(value_t::INTEGER);
result -= moment;
} else {
- throw new compute_error("Invalid date passed to datecmp(value,date)",
- new valexpr_context(expr));
+ add_error_context(expr_context(expr));
+ throw compute_error("Invalid date passed to datecmp(value,date)");
}
break;
}
@@ -293,9 +293,10 @@ void expr_t::op_t::compute(value_t& result,
ptr_op_t expr = find_leaf(context, 0, arg_index);
expr->compute(result, details, context);
- if (! result.is_type(value_t::DATETIME))
- throw new compute_error("Invalid date passed to year|month|day(date)",
- new valexpr_context(expr));
+ if (! result.is_type(value_t::DATETIME)) {
+ add_error_context(expr_context(expr));
+ throw compute_error("Invalid date passed to year|month|day(date)");
+ }
const datetime_t& moment(result.as_datetime());
switch (kind) {
@@ -357,9 +358,10 @@ void expr_t::op_t::compute(value_t& result,
long arg_index = 0;
ptr_op_t expr = find_leaf(context, 0, arg_index);
expr->compute(result, details, context);
- if (! result.is_type(value_t::AMOUNT))
- throw new compute_error("Argument to commodity() must be a commoditized amount",
- new valexpr_context(expr));
+ if (! result.is_type(value_t::AMOUNT)) {
+ add_error_context(expr_context(expr));
+ throw compute_error("Argument to commodity() must be a commoditized amount");
+ }
amount_t temp("1");
temp.set_commodity(result.as_amount().commodity());
result = temp;
@@ -375,10 +377,10 @@ void expr_t::op_t::compute(value_t& result,
arg_index = 0;
expr = find_leaf(context, 1, arg_index);
expr->compute(result, details, context);
- if (! result.is_type(value_t::AMOUNT))
- throw new compute_error
- ("Second argument to set_commodity() must be a commoditized amount",
- new valexpr_context(expr));
+ if (! result.is_type(value_t::AMOUNT)) {
+ add_error_context(expr_context(expr));
+ throw compute_error("Second argument to set_commodity() must be a commoditized amount");
+ }
amount_t one("1");
one.set_commodity(result.as_amount().commodity());
result = one;
@@ -482,13 +484,14 @@ void expr_t::op_t::compute(value_t& result,
}
case O_COMMA:
- if (! left())
- throw new compute_error("Comma operator missing left operand",
- new valexpr_context(const_cast<op_t *>(this)));
- if (! right())
- throw new compute_error("Comma operator missing right operand",
- new valexpr_context(const_cast<op_t *>(this)));
- left()->compute(result, details, context);
+ if (! left()) {
+ add_error_context(expr_context(*this));
+ throw compute_error("Comma operator missing left operand");
+ }
+ if (! right()) {
+ add_error_context(expr_context(*this));
+ throw compute_error("Comma operator missing right operand");
+ }
right()->compute(result, details, context);
break;
@@ -516,10 +519,10 @@ void expr_t::op_t::compute(value_t& result,
expr = find_leaf(context, 1, arg_index);
value_t moment;
expr->compute(moment, details, context);
- if (! moment.is_type(value_t::DATETIME))
- throw new compute_error("Invalid date passed to P(value,date)",
- new valexpr_context(expr));
-
+ if (! moment.is_type(value_t::DATETIME)) {
+ add_error_context(expr_context(expr));
+ throw compute_error("Invalid date passed to P(value,date)");
+ }
result = result.value(moment.as_datetime());
break;
}
@@ -624,10 +627,8 @@ void expr_t::op_t::compute(value_t& result,
break;
}
}
- catch (error * err) {
- if (err->context.empty() ||
- ! dynamic_cast<valexpr_context *>(err->context.back()))
- err->context.push_back(new valexpr_context(const_cast<op_t *>(this)));
+ catch (const std::exception& err) {
+ add_error_context(expr_context(*this));
throw err;
}
}
diff --git a/option.cc b/option.cc
index a94a6a00..b3673633 100644
--- a/option.cc
+++ b/option.cc
@@ -79,25 +79,22 @@ namespace {
void process_option(const function_t& opt, scope_t& scope,
const char * arg)
{
-#if 0
try {
-#endif
call_scope_t args(scope);
if (arg)
- args.push_back(value_t(arg, true));
+ args.push_back(string_value(arg));
opt(args);
-#if 0
}
- catch (error * err) {
- err->context.push_back
- (new error_context
- (string("While parsing option '--") + opt->long_opt +
- "'" + (opt->short_opt != '\0' ?
- (string(" (-") + opt->short_opt + "):") : ":")));
+ 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
throw err;
}
-#endif
}
}
@@ -130,20 +127,14 @@ void process_environment(const char ** envp, const string& tag,
*r = '\0';
if (*q == '=') {
-#if 0
try {
-#endif
process_option(string(buf), scope, q + 1);
-#if 0
}
- catch (error * err) {
- err->context.push_back
- (new error_context
- (string("While parsing environment variable option '") +
- *p + "':"));
+ catch (const std::exception& err) {
+ add_error_context("While parsing environment variable option '"
+ << *p << "':");
throw err;
}
-#endif
}
}
}
@@ -429,8 +420,8 @@ OPT_BEGIN(init_file, "i:") {
if (access(path.c_str(), R_OK) != -1)
config->init_file = path;
else
- throw new error(std::string("The init file '") + path +
- "' does not exist or is not readable");
+ throw_(std::invalid_argument,
+ "The init file '" << path << "' does not exist or is not readable");
} OPT_END(init_file);
OPT_BEGIN(file, "f:") {
@@ -441,8 +432,8 @@ OPT_BEGIN(file, "f:") {
if (access(path.c_str(), R_OK) != -1)
config->data_file = path;
else
- throw new error(std::string("The ledger file '") + path +
- "' does not exist or is not readable");
+ throw_(std::invalid_argument,
+ "The ledger file '" << path << "' does not exist or is not readable");
}
} OPT_END(file);
@@ -490,8 +481,8 @@ OPT_BEGIN(begin, "b:") {
char buf[128];
interval_t interval(optarg);
if (! interval.begin)
- throw new error(std::string("Could not determine beginning of period '") +
- optarg + "'");
+ throw_(std::invalid_argument,
+ "Could not determine beginning of period '" << optarg << "'");
if (! report->predicate.empty())
report->predicate += "&";
@@ -504,8 +495,8 @@ OPT_BEGIN(end, "e:") {
char buf[128];
interval_t interval(optarg);
if (! interval.begin)
- throw new error(std::string("Could not determine end of period '") +
- optarg + "'");
+ throw_(std::invalid_argument,
+ "Could not determine end of period '" << optarg << "'");
if (! report->predicate.empty())
report->predicate += "&";
diff --git a/option.h b/option.h
index fa908eff..23439b9d 100644
--- a/option.h
+++ b/option.h
@@ -45,7 +45,7 @@ void process_environment(const char ** envp, const string& tag,
void process_arguments(int argc, char ** argv, const bool anywhere,
scope_t& scope, std::list<string>& args);
-DECLARE_EXCEPTION(error, option_error);
+DECLARE_EXCEPTION(option_error, std::runtime_error);
} // namespace ledger
diff --git a/parser.cc b/parser.cc
index a03ea9df..85d92901 100644
--- a/parser.cc
+++ b/parser.cc
@@ -419,9 +419,7 @@ expr_t::parser_t::parse_value_expr(std::istream& in,
expr_t::ptr_op_t
expr_t::parser_t::parse(std::istream& in, const flags_t flags)
{
-#if 0
try {
-#endif
ptr_op_t top_node = parse_value_expr(in, flags);
if (use_lookahead) {
@@ -431,15 +429,14 @@ expr_t::parser_t::parse(std::istream& in, const flags_t flags)
lookahead.clear();
return top_node;
-#if 0
}
- catch (error * err) {
- err->context.push_back
- (new line_context(str, (long)in.tellg() - 1,
- "While parsing value expression:"));
+ catch (const std::exception& err) {
+ add_error_context("While parsing value expression:\n");
+#if 0
+ add_error_context(line_context(str, (long)in.tellg() - 1));
+#endif
throw err;
}
-#endif
}
} // namespace ledger
diff --git a/qif.cc b/qif.cc
index bb8d2c55..ee9318d2 100644
--- a/qif.cc
+++ b/qif.cc
@@ -75,7 +75,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
case '\t':
if (peek_next_nonws(in) != '\n') {
get_line(in);
- throw new parse_error("Line begins with whitespace");
+ throw parse_error("Line begins with whitespace");
}
// fall through...
@@ -92,8 +92,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
std::strcmp(line, "Type:Cat") == 0 ||
std::strcmp(line, "Type:Class") == 0 ||
std::strcmp(line, "Type:Memorized") == 0)
- throw new parse_error(string("QIF files of type ") + line +
- " are not supported.");
+ throw_(parse_error, "QIF files of type " << line << " are not supported.");
break;
case 'D':
diff --git a/quotes.cc b/quotes.cc
index e2ff97c8..bc6e5840 100644
--- a/quotes.cc
+++ b/quotes.cc
@@ -68,9 +68,9 @@ void quotes_by_script::operator()(commodity_base_t& commodity,
<< " " << commodity.symbol << " " << price << endl;
}
} else {
- throw new error(string("Failed to download price for '") +
- commodity.symbol + "' (command: \"getquote " +
- commodity.symbol + "\")");
+ throw_(std::runtime_error,
+ "Failed to download price for '" << commodity.symbol
+ << "' (command: \"getquote " << commodity.symbol << "\")");
}
}
#endif
diff --git a/reconcile.cc b/reconcile.cc
index d83eb37a..b3f53483 100644
--- a/reconcile.cc
+++ b/reconcile.cc
@@ -59,7 +59,7 @@ void reconcile_xacts::flush()
}
if (cleared_balance.type() >= value_t::BALANCE)
- throw new error("Cannot reconcile accounts with multiple commodities");
+ throw std::runtime_error("Cannot reconcile accounts with multiple commodities");
cleared_balance.cast(value_t::AMOUNT);
balance.cast(value_t::AMOUNT);
@@ -69,8 +69,9 @@ void reconcile_xacts::flush()
balance -= cleared_balance;
if (balance.type() >= value_t::BALANCE)
- throw new error(string("Reconcile balance is not of the same commodity ('") +
- b_comm.symbol() + string("' != '") + cb_comm.symbol() + "')");
+ throw_(std::runtime_error,
+ "Reconcile balance is not of the same commodity ('"
+ << b_comm.symbol() << "' != '" << cb_comm.symbol() << "')");
// If the amount to reconcile is the same as the pending balance,
// then assume an exact match and return the results right away.
@@ -80,7 +81,7 @@ void reconcile_xacts::flush()
search_for_balance(to_reconcile, &first, first)) {
push_to_handler(first);
} else {
- throw new error("Could not reconcile account!");
+ throw std::runtime_error("Could not reconcile account!");
}
}
diff --git a/report.cc b/report.cc
index 51516acd..83acc179 100644
--- a/report.cc
+++ b/report.cc
@@ -319,7 +319,7 @@ value_t report_t::ftime(call_scope_t& args)
else
date_format = moment_t::output_format;
- return value_t(date.as_string(date_format), true);
+ return string_value(date.as_string(date_format));
#else
return NULL_VALUE;
#endif
diff --git a/session.cc b/session.cc
index bb70862f..6f44cee2 100644
--- a/session.cc
+++ b/session.cc
@@ -266,7 +266,7 @@ value_t session_t::resolve(const string& name, expr_t::scope_t& locals)
#if 0
if (name == "date_format") {
// jww (2007-04-18): What to do here?
- return value_t(moment_t::output_format, true);
+ return string_value(moment_t::output_format);
}
#endif
break;
@@ -282,7 +282,7 @@ value_t session_t::resolve(const string& name, expr_t::scope_t& locals)
case 'r':
if (name == "register_format")
- return value_t(register_format, true);
+ return string_value(register_format);
break;
}
return expr_t::scope_t::resolve(name, locals);
diff --git a/textual.cc b/textual.cc
index 7906cc8f..733a6c19 100644
--- a/textual.cc
+++ b/textual.cc
@@ -124,7 +124,7 @@ xact_t * parse_xact(char * line, account_t * account,
}
if (account_beg == account_end)
- throw new parse_error("No account was specified");
+ throw parse_error("No account was specified");
char * b = &line[account_beg];
char * e = &line[account_end];
@@ -189,8 +189,8 @@ xact_t * parse_xact(char * line, account_t * account,
xact->amount_expr->set_text(string(line, beg, end - beg));
}
}
- catch (error * err) {
- err_desc = "While parsing transaction amount:";
+ catch (const std::exception& err) {
+ add_error_context("While parsing transaction amount:\n");
throw err;
}
}
@@ -201,7 +201,7 @@ xact_t * parse_xact(char * line, account_t * account,
p = peek_next_nonws(in);
if (p == '@') {
if (! saw_amount)
- throw new parse_error
+ throw parse_error
("Transaction cannot have a cost expression with an amount");
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
@@ -236,13 +236,13 @@ xact_t * parse_xact(char * line, account_t * account,
string(line, beg, end - beg));
}
}
- catch (error * err) {
- err_desc = "While parsing transaction cost:";
+ catch (const std::exception& err) {
+ add_error_context("While parsing transaction cost:\n");
throw err;
}
if (xact->cost->sign() < 0)
- throw new parse_error("A transaction's cost may not be negative");
+ throw parse_error("A transaction's cost may not be negative");
amount_t per_unit_cost(*xact->cost);
if (per_unit)
@@ -303,7 +303,7 @@ xact_t * parse_xact(char * line, account_t * account,
if (parse_amount_expr(in, amt, xact.get(),
EXPR_PARSE_NO_MIGRATE))
- throw new parse_error
+ throw parse_error
("An assigned balance must evaluate to a constant value");
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
@@ -352,8 +352,8 @@ xact_t * parse_xact(char * line, account_t * account,
xdata.value = amt;
}
}
- catch (error * err) {
- err_desc = "While parsing assigned balance:";
+ catch (const std::exception& err) {
+ add_error_context("While parsing assigned balance:\n");
throw err;
}
}
@@ -396,11 +396,9 @@ xact_t * parse_xact(char * line, account_t * account,
return xact.release();
}
- catch (error * err) {
- err->context.push_back
- (new line_context(line, static_cast<unsigned long>(in.tellg()) - 1,
- ! err_desc.empty() ?
- err_desc : "While parsing transaction:"));
+ catch (const std::exception& err) {
+ add_error_context("While parsing transaction:\n");
+ add_error_context(line_context(line, static_cast<unsigned long>(in.tellg()) - 1));
throw err;
}
}
@@ -549,7 +547,7 @@ static inline void parse_symbol(char *& p, string& symbol)
if (*p == '"') {
char * q = std::strchr(p + 1, '"');
if (! q)
- throw new parse_error("Quoted commodity symbol lacks closing quote");
+ throw parse_error("Quoted commodity symbol lacks closing quote");
symbol = string(p + 1, 0, q - p - 1);
p = q + 2;
} else {
@@ -561,7 +559,7 @@ static inline void parse_symbol(char *& p, string& symbol)
p += symbol.length();
}
if (symbol.empty())
- throw new parse_error("Failed to parse commodity");
+ throw parse_error("Failed to parse commodity");
}
bool textual_parser_t::test(std::istream& in) const
@@ -571,9 +569,9 @@ bool textual_parser_t::test(std::istream& in) const
in.read(buf, 5);
if (std::strncmp(buf, "<?xml", 5) == 0) {
#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
- throw new parse_error("Ledger file contains XML data, but format was not recognized");
+ throw parse_error("Ledger file contains XML data, but format was not recognized");
#else
- throw new parse_error("Ledger file contains XML data, but no XML support present");
+ throw parse_error("Ledger file contains XML data, but no XML support present");
#endif
}
@@ -596,10 +594,10 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
time_entries.clear();
}
else if (time_entries.empty()) {
- throw new parse_error("Timelog check-out event without a check-in");
+ throw parse_error("Timelog check-out event without a check-in");
}
else if (! account) {
- throw new parse_error
+ throw parse_error
("When multiple check-ins are active, checking out requires an account");
}
else {
@@ -616,7 +614,7 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
}
if (! found)
- throw new parse_error
+ throw parse_error
("Timelog check-out event does not match any current check-ins");
}
@@ -631,7 +629,7 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
curr->payee = event.desc;
if (curr->_date < event.checkin)
- throw new parse_error
+ throw parse_error
("Timelog check-out date less than corresponding check-in");
char buf[32];
@@ -646,7 +644,7 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
curr->add_xact(xact);
if (! journal.add_entry(curr.get()))
- throw new parse_error("Failed to record 'out' timelog entry");
+ throw parse_error("Failed to record 'out' timelog entry");
else
curr.release();
}
@@ -704,7 +702,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
case '\t': {
char * p = skip_ws(line);
if (*p)
- throw new parse_error("Line begins with whitespace");
+ throw parse_error("Line begins with whitespace");
break;
}
@@ -724,7 +722,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
i != time_entries.end();
i++)
if (event.account == (*i).account)
- throw new parse_error
+ throw parse_error
("Cannot double check-in to the same account");
time_entries.push_back(event);
@@ -734,7 +732,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
case 'o':
case 'O':
if (time_entries.empty()) {
- throw new parse_error("Timelog check-out event without a check-in");
+ throw parse_error("Timelog check-out event without a check-in");
} else {
string date(line, 2, 19);
@@ -858,7 +856,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
case '~': { // period entry
period_entry_t * pe = new period_entry_t(skip_ws(line + 1));
if (! pe->period)
- throw new parse_error(string("Parsing time period '") + line + "'");
+ throw_(parse_error, "Parsing time period '" << line << "'");
if (parse_xacts(in, account_stack.front(), *pe,
"period", end_pos)) {
@@ -960,10 +958,10 @@ unsigned int textual_parser_t::parse(std::istream& in,
count++;
} else {
checked_delete(entry);
- throw new parse_error("Entry does not balance");
+ throw parse_error("Entry does not balance");
}
} else {
- throw new parse_error("Failed to parse entry");
+ throw parse_error("Failed to parse entry");
}
end_pos = pos;
TRACE_STOP(entries, 1);
@@ -971,21 +969,21 @@ unsigned int textual_parser_t::parse(std::istream& in,
}
}
}
- catch (error * err) {
+ catch (const std::exception& err) {
for (std::list<std::pair<path, int> >::reverse_iterator i =
include_stack.rbegin();
i != include_stack.rend();
- i++)
- err->context.push_back(new include_context((*i).first, (*i).second,
- "In file included from"));
- err->context.push_front(new file_context(pathname, linenum - 1));
+ i++) {
+ add_error_context("In file included from ");
+#if 0
+ add_error_context(include_context((*i).first, (*i).second));
+#endif
+ }
+ add_error_context(file_context(pathname, linenum - 1));
std::cout.flush();
- if (errors > 0 && err->context.size() > 1)
- std::cerr << std::endl;
- err->reveal_context(std::cerr, "Error");
- std::cerr << err->what() << std::endl;
- checked_delete(err);
+ std::cerr << "Error: " << error_context() << err.what()
+ << std::endl;
errors++;
}
beg_pos = end_pos;
@@ -1061,8 +1059,8 @@ void write_textual_journal(journal_t& journal,
}
if (found.empty())
- throw new error(string("Journal does not refer to file '") +
- string(pathname.string()) + "'");
+ throw_(std::runtime_error,
+ "Journal does not refer to file '" << pathname << "'");
entries_list::iterator el = journal.entries.begin();
auto_entries_list::iterator al = journal.auto_entries.begin();
diff --git a/textual.h b/textual.h
index 438d5ea2..418b273b 100644
--- a/textual.h
+++ b/textual.h
@@ -28,6 +28,7 @@ void write_textual_journal(journal_t& journal,
const string& write_hdr_format,
std::ostream& out);
+#if 0
class include_context : public file_context
{
public:
@@ -43,6 +44,7 @@ class include_context : public file_context
<< std::endl;
}
};
+#endif
} // namespace ledger
diff --git a/times.cc b/times.cc
index be1b10f1..772158fb 100644
--- a/times.cc
+++ b/times.cc
@@ -192,7 +192,7 @@ namespace {
struct std::tm when;
if (! parse_date_mask(word.c_str(), &when))
- throw new datetime_error(string("Could not parse date mask: ") + word);
+ throw_(datetime_error, "Could not parse date mask: " << word);
when.tm_hour = 0;
when.tm_min = 0;
diff --git a/times.h b/times.h
index a6cd9e4d..ba765027 100644
--- a/times.h
+++ b/times.h
@@ -61,7 +61,7 @@ extern int current_year;
extern string input_time_format;
extern string output_time_format;
-DECLARE_EXCEPTION(error, datetime_error);
+DECLARE_EXCEPTION(datetime_error, std::runtime_error);
struct interval_t
{
diff --git a/utils.cc b/utils.cc
index d2cd1e1b..9be92c7b 100644
--- a/utils.cc
+++ b/utils.cc
@@ -40,7 +40,7 @@
namespace ledger {
-DECLARE_EXCEPTION(fatal, assertion_failed);
+DECLARE_EXCEPTION(assertion_failed, std::logic_error);
void debug_assert(const string& reason,
const string& func,
@@ -649,8 +649,8 @@ void finish_timer(const char * name)
namespace ledger {
-std::ostringstream _exc_buffer;
-/*ptr_list<context> context_stack;*/
+std::ostringstream _desc_buffer;
+std::ostringstream _ctxt_buffer;
} // namespace ledger
@@ -666,9 +666,7 @@ path expand_path(const path& pathname)
if (pathname.empty())
return pathname;
-#if 1
- return pathname;
-#else
+#if 0
// jww (2007-04-30): I need to port this code to use
// boost::filesystem::path
const char * pfx = NULL;
@@ -711,6 +709,8 @@ path expand_path(const path& pathname)
result += pathname.substr(pos + 1);
return result;
+#else
+ return pathname;
#endif
}
diff --git a/utils.h b/utils.h
index 05a214a7..60d47ec1 100644
--- a/utils.h
+++ b/utils.h
@@ -463,53 +463,13 @@ void finish_timer(const char * name);
/**********************************************************************
*
- * Exception handling
+ * - Exception handling helpers
+ * - Date/time support classes
+ * - General support for objects with "flags"
+ * - Support for scoped execution and variable restoration
*/
#include "error.h"
-
-namespace ledger {
-
-extern std::ostringstream _exc_buffer;
-
-template <typename T>
-inline void throw_func(const std::string& message) {
- _exc_buffer.str("");
- throw T(message);
-}
-
-#define throw_(cls, msg) \
- ((_exc_buffer << msg), throw_func<cls>(_exc_buffer.str()))
-
-#if 0
-inline void throw_unexpected_error(char c, char wanted) {
- if (c == -1) {
- if (wanted)
- throw new error(string("Missing '") + wanted + "'");
- else
- throw new error("Unexpected end of input");
- } else {
- if (wanted)
- throw new error(string("Invalid char '") + c +
- "' (wanted '" + wanted + "')");
- else
- throw new error(string("Invalid char '") + c + "'");
- }
-}
-#else
-inline void throw_unexpected_error(char, char) {
-}
-#endif
-
-} // namespace ledger
-
-/**********************************************************************
- *
- * Date/time support classes
- * General support for objects with "flags"
- * Support for scoped execution and variable restoration
- */
-
#include "times.h"
#include "flags.h"
#include "pushvar.h"
diff --git a/value.cc b/value.cc
index a6969af9..8edc5df1 100644
--- a/value.cc
+++ b/value.cc
@@ -1378,7 +1378,7 @@ value_t value_t::annotated_tag() const
optional<string> temp = as_amount().annotation_details().tag;
if (! temp)
return false;
- return value_t(*temp, true);
+ return string_value(*temp);
}
case STRING:
@@ -1679,15 +1679,4 @@ bool value_t::valid() const
return true;
}
-void value_context::describe(std::ostream& out) const throw()
-{
- if (! desc.empty())
- out << desc << std::endl;
-
- out << std::right;
- out.width(20);
- bal.print(out);
- out << std::endl;
-}
-
} // namespace ledger
diff --git a/value.h b/value.h
index 6bcce319..35a44828 100644
--- a/value.h
+++ b/value.h
@@ -48,6 +48,8 @@
namespace ledger {
+DECLARE_EXCEPTION(value_error, std::runtime_error);
+
/**
* @class value_t
*
@@ -880,18 +882,14 @@ inline std::ostream& operator<<(std::ostream& out, const value_t& val) {
return out;
}
-class value_context : public error_context
-{
- value_t bal;
- public:
- value_context(const value_t& _bal, const string& desc = "") throw()
- : error_context(desc), bal(_bal) {}
- virtual ~value_context() throw() {}
-
- virtual void describe(std::ostream& out) const throw();
-};
-
-DECLARE_EXCEPTION(error, value_error);
+inline string value_context(const value_t& val) {
+ std::ostringstream buf;
+ buf << std::right;
+ buf.width(20);
+ val.print(buf);
+ buf << std::endl;
+ return buf.str();
+}
} // namespace ledger
diff --git a/walk.cc b/walk.cc
index bf93ea92..61681808 100644
--- a/walk.cc
+++ b/walk.cc
@@ -217,9 +217,11 @@ void calc_xacts::operator()(xact_t& xact)
last_xact = &xact;
}
- catch (error * err) {
- err->context.push_front
- (new xact_context(xact, "Calculating transaction at"));
+ catch (const std::exception& err) {
+ add_error_context("Calculating transaction at");
+#if 0
+ add_error_context(xact_context(xact));
+#endif
throw err;
}
}
diff --git a/walk.h b/walk.h
index cb13a826..c92366e0 100644
--- a/walk.h
+++ b/walk.h
@@ -693,14 +693,6 @@ public:
virtual void operator()(xact_t& xact);
};
-class interval_expr_error : public error {
- public:
- interval_expr_error(const string& reason,
- error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~interval_expr_error() throw() {}
-};
-
class interval_xacts : public subtotal_xacts
{
interval_t interval;
diff --git a/xact.cc b/xact.cc
index 7e363333..211553a9 100644
--- a/xact.cc
+++ b/xact.cc
@@ -72,7 +72,7 @@ namespace {
value_t get_payee(call_scope_t& scope)
{
xact_t& xact(downcast<xact_t>(*scope.parent));
- return value_t(xact.entry->payee, true);
+ return string_value(xact.entry->payee);
}
value_t get_account(call_scope_t& scope)
@@ -87,7 +87,7 @@ namespace {
else
name = string("(") + name + ")";
}
- return value_t(name, true);
+ return string_value(name);
}
value_t get_account_base(call_scope_t& scope)
@@ -163,6 +163,7 @@ 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)
{
@@ -177,5 +178,6 @@ xact_context::xact_context(const xact_t& _xact, const string& desc) throw()
}
line = xact.beg_line;
}
+#endif
} // namespace ledger
diff --git a/xact.h b/xact.h
index 2078dabd..a597876d 100644
--- a/xact.h
+++ b/xact.h
@@ -131,15 +131,6 @@ class xact_t : public supports_flags<>, public scope_t
bool valid() const;
};
-class xact_context : public file_context {
- public:
- const xact_t& xact;
-
- xact_context(const xact_t& _xact,
- const string& desc = "") throw();
- virtual ~xact_context() throw() {}
-};
-
} // namespace ledger
#endif // _XACT_H
diff --git a/xml.cc b/xml.cc
index 562dcf7e..297b710a 100644
--- a/xml.cc
+++ b/xml.cc
@@ -209,7 +209,7 @@ unsigned int xml_parser_t::parse(std::istream& in,
catch (const std::exception& err) {
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
XML_ParserFree(parser);
- throw new parse_error(err.what());
+ throw parse_error(err.what());
}
if (! have_error.empty()) {
@@ -223,7 +223,7 @@ unsigned int xml_parser_t::parse(std::istream& in,
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
const char * err = XML_ErrorString(XML_GetErrorCode(parser));
XML_ParserFree(parser);
- throw new parse_error(err);
+ throw parse_error(err);
}
}