diff options
-rw-r--r-- | amount.h | 2 | ||||
-rw-r--r-- | balance.h | 2 | ||||
-rw-r--r-- | cache.cc | 8 | ||||
-rw-r--r-- | cache.h | 2 | ||||
-rw-r--r-- | derive.cc | 4 | ||||
-rw-r--r-- | entry.cc | 6 | ||||
-rw-r--r-- | entry.h | 12 | ||||
-rw-r--r-- | error.h | 198 | ||||
-rw-r--r-- | expr.h | 6 | ||||
-rw-r--r-- | format.cc | 4 | ||||
-rw-r--r-- | format.h | 8 | ||||
-rw-r--r-- | gnucash.cc | 2 | ||||
-rw-r--r-- | journal.h | 8 | ||||
-rw-r--r-- | main.cc | 25 | ||||
-rw-r--r-- | op.cc | 57 | ||||
-rw-r--r-- | option.cc | 47 | ||||
-rw-r--r-- | option.h | 2 | ||||
-rw-r--r-- | parser.cc | 13 | ||||
-rw-r--r-- | qif.cc | 5 | ||||
-rw-r--r-- | quotes.cc | 6 | ||||
-rw-r--r-- | reconcile.cc | 9 | ||||
-rw-r--r-- | report.cc | 2 | ||||
-rw-r--r-- | session.cc | 4 | ||||
-rw-r--r-- | textual.cc | 82 | ||||
-rw-r--r-- | textual.h | 2 | ||||
-rw-r--r-- | times.cc | 2 | ||||
-rw-r--r-- | times.h | 2 | ||||
-rw-r--r-- | utils.cc | 12 | ||||
-rw-r--r-- | utils.h | 48 | ||||
-rw-r--r-- | value.cc | 13 | ||||
-rw-r--r-- | value.h | 22 | ||||
-rw-r--r-- | walk.cc | 8 | ||||
-rw-r--r-- | walk.h | 8 | ||||
-rw-r--r-- | xact.cc | 6 | ||||
-rw-r--r-- | xact.h | 9 | ||||
-rw-r--r-- | xml.cc | 4 |
36 files changed, 243 insertions, 407 deletions
@@ -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 @@ -48,7 +48,7 @@ namespace ledger { -DECLARE_EXCEPTION(error, balance_error); +DECLARE_EXCEPTION(balance_error, std::runtime_error); /** * @class balance_t @@ -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); @@ -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; @@ -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(); } @@ -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) { @@ -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: @@ -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 @@ -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; @@ -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); @@ -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 @@ -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()) { @@ -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; }; @@ -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; @@ -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; } } @@ -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 += "&"; @@ -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 @@ -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 @@ -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': @@ -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!"); } } @@ -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 @@ -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); @@ -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(); @@ -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 @@ -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; @@ -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 { @@ -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 } @@ -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" @@ -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 @@ -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 @@ -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; } } @@ -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; @@ -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 @@ -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 @@ -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); } } |