summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
}
}