diff options
-rw-r--r-- | COPYRIGHT | 30 | ||||
-rw-r--r-- | amount.cc | 168 | ||||
-rw-r--r-- | amount.h | 8 | ||||
-rw-r--r-- | balance.cc | 25 | ||||
-rw-r--r-- | error.h | 15 | ||||
-rw-r--r-- | format.cc | 4 | ||||
-rw-r--r-- | format.h | 7 | ||||
-rw-r--r-- | gnucash.cc | 5 | ||||
-rw-r--r-- | gnucash.h | 4 | ||||
-rw-r--r-- | journal.cc | 38 | ||||
-rw-r--r-- | journal.h | 12 | ||||
-rw-r--r-- | main.cc | 73 | ||||
-rw-r--r-- | mask.h | 6 | ||||
-rw-r--r-- | ofx.cc | 8 | ||||
-rw-r--r-- | option.cc | 35 | ||||
-rw-r--r-- | option.h | 6 | ||||
-rw-r--r-- | parser.h | 60 | ||||
-rw-r--r-- | py_amount.cc | 10 | ||||
-rw-r--r-- | py_eval.cc | 19 | ||||
-rw-r--r-- | qif.cc | 10 | ||||
-rw-r--r-- | quotes.cc | 27 | ||||
-rw-r--r-- | register.cc | 89 | ||||
-rw-r--r-- | register.h | 13 | ||||
-rw-r--r-- | report.cc | 4 | ||||
-rw-r--r-- | session.cc | 27 | ||||
-rw-r--r-- | session.h | 1 | ||||
-rw-r--r-- | system.hh | 7 | ||||
-rw-r--r-- | tests/corelib/numerics/BasicAmount.cc | 4 | ||||
-rw-r--r-- | tests/corelib/numerics/Commodity.cc | 4 | ||||
-rw-r--r-- | tests/corelib/numerics/CommodityAmount.cc | 46 | ||||
-rw-r--r-- | textual.cc | 117 | ||||
-rw-r--r-- | textual.h | 2 | ||||
-rw-r--r-- | times.cc | 2 | ||||
-rw-r--r-- | times.h | 14 | ||||
-rw-r--r-- | util.cc | 146 | ||||
-rw-r--r-- | util.h | 88 | ||||
-rw-r--r-- | utils.cc | 226 | ||||
-rw-r--r-- | utils.h | 301 | ||||
-rw-r--r-- | value.cc | 498 | ||||
-rw-r--r-- | value.h | 10 | ||||
-rw-r--r-- | xml.cc | 23 | ||||
-rw-r--r-- | xml.h | 19 | ||||
-rw-r--r-- | xmlparse.cc | 7 | ||||
-rw-r--r-- | xpath.cc | 152 | ||||
-rw-r--r-- | xpath.h | 44 |
45 files changed, 1264 insertions, 1150 deletions
diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 00000000..c9d4bd18 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2003-2007, 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. + */ @@ -1,33 +1,44 @@ -// amount.cc - -// Copyright (c) 2003-2007, 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. +/** + * @file amount.cc + * @author John Wiegley + * @date Thu Apr 26 15:19:46 2007 + * + * @brief Types for handling commoditized math. + * + * This file defines member functions for amount_t and the various + * flavors of commodity_t. + */ + +/* + * Copyright (c) 2003-2007, 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. + */ #include "amount.h" #include "binary.h" @@ -325,7 +336,7 @@ amount_t::amount_t(const double val) void amount_t::_release() { - DEBUG_PRINT("amounts.refs", + DEBUG_("amounts.refs", quantity << " ref--, now " << (quantity->ref - 1)); if (--quantity->ref == 0) { if (! (quantity->flags & BIGINT_BULK_ALLOC)) @@ -367,7 +378,7 @@ void amount_t::_copy(const amount_t& amt) quantity = new bigint_t(*amt.quantity); } else { quantity = amt.quantity; - DEBUG_PRINT("amounts.refs", + DEBUG_("amounts.refs", quantity << " ref++, now " << (quantity->ref + 1)); quantity->ref++; } @@ -473,10 +484,11 @@ void amount_t::_clear() amount_t& amount_t::operator+=(const amount_t& amt) { if (commodity() != amt.commodity()) { - throw new amount_error + throw amount_exception (string("Adding amounts with different commodities: ") + (has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " + - (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE")); + (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"), + context()); } if (! amt.quantity) @@ -508,10 +520,11 @@ amount_t& amount_t::operator+=(const amount_t& amt) amount_t& amount_t::operator-=(const amount_t& amt) { if (commodity() != amt.commodity()) - throw new amount_error + throw amount_exception (string("Subtracting amounts with different commodities: ") + (has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " + - (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE")); + (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"), + context()); if (! amt.quantity) return *this; @@ -545,10 +558,11 @@ amount_t& amount_t::operator*=(const amount_t& amt) { if (has_commodity() && amt.has_commodity() && commodity() != amt.commodity()) { - throw new amount_error + throw amount_exception (string("Multiplying amounts with different commodities: ") + (has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " + - (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE")); + (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"), + context()); } if (! amt.quantity) { @@ -585,14 +599,15 @@ amount_t& amount_t::operator/=(const amount_t& amt) { if (has_commodity() && amt.has_commodity() && commodity() != amt.commodity()) { - throw new amount_error + throw amount_exception (string("Dividing amounts with different commodities: ") + (has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " + - (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE")); + (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"), + context()); } if (! amt.quantity || ! amt) { - throw new amount_error("Divide by zero"); + throw amount_exception("Divide by zero", context()); } else if (! quantity) { *this = amt; @@ -658,9 +673,10 @@ int amount_t::compare(const amount_t& amt) const return sign(); if (has_commodity() && amt.commodity() && commodity() != amt.commodity()) - throw new amount_error + throw amount_exception (string("Cannot compare amounts with different commodities: ") + - commodity().symbol() + " and " + amt.commodity().symbol()); + commodity().symbol() + " and " + amt.commodity().symbol(), + context()); if (quantity->prec == amt.quantity->prec) { return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)); @@ -1119,7 +1135,8 @@ static void parse_commodity(std::istream& in, string& symbol) if (c == '"') in.get(c); else - throw new amount_error("Quoted commodity symbol lacks closing quote"); + throw amount_exception("Quoted commodity symbol lacks closing quote", + context()); } else { READ_INTO(in, buf, 255, c, ! invalid_chars[(unsigned char)c]); } @@ -1136,14 +1153,15 @@ bool parse_annotations(std::istream& in, amount_t& price, char c = peek_next_nonws(in); if (c == '{') { if (price) - throw new amount_error("Commodity specifies more than one price"); + throw amount_exception("Commodity specifies more than one price", + context()); in.get(c); READ_INTO(in, buf, 255, c, c != '}'); if (c == '}') in.get(c); else - throw new amount_error("Commodity price lacks closing brace"); + throw amount_exception("Commodity price lacks closing brace", context()); price.parse(buf, AMOUNT_PARSE_NO_MIGRATE); price.in_place_reduce(); @@ -1158,28 +1176,32 @@ bool parse_annotations(std::istream& in, amount_t& price, } else if (c == '[') { if (is_valid_moment(date)) - throw new amount_error("Commodity specifies more than one date"); + throw amount_exception("Commodity specifies more than one date", + context()); in.get(c); READ_INTO(in, buf, 255, c, c != ']'); if (c == ']') in.get(c); else - throw new amount_error("Commodity date lacks closing bracket"); + throw amount_exception("Commodity date lacks closing bracket", + context()); date = parse_datetime(buf); has_date = true; } else if (c == '(') { if (! tag.empty()) - throw new amount_error("Commodity specifies more than one tag"); + throw amount_exception("Commodity specifies more than one tag", + context()); in.get(c); READ_INTO(in, buf, 255, c, c != ')'); if (c == ')') in.get(c); else - throw new amount_error("Commodity tag lacks closing parenthesis"); + throw amount_exception("Commodity tag lacks closing parenthesis", + context()); tag = buf; } @@ -1188,7 +1210,7 @@ bool parse_annotations(std::istream& in, amount_t& price, } } while (true); - DEBUG_PRINT("amounts.commodities", + DEBUG_("amounts.commodities", "Parsed commodity annotations: " << " price " << price << " " << " date " << date << " " @@ -1251,7 +1273,8 @@ void amount_t::parse(std::istream& in, unsigned char flags) } if (quant.empty()) - throw new amount_error("No quantity specified for amount"); + throw amount_exception("No quantity specified for amount", + context()); _init(); @@ -1446,7 +1469,7 @@ void amount_t::read_quantity(char *& data) data += sizeof(unsigned int); quantity = (bigint_t *) (bigints + (index - 1) * sizeof(bigint_t)); - DEBUG_PRINT("amounts.refs", + DEBUG_("amounts.refs", quantity << " ref++, now " << (quantity->ref + 1)); quantity->ref++; } @@ -1535,12 +1558,12 @@ bool amount_t::valid() const { if (quantity) { if (quantity->ref == 0) { - DEBUG_PRINT("ledger.validate", "amount_t: quantity->ref == 0"); + DEBUG_("ledger.validate", "amount_t: quantity->ref == 0"); return false; } } else if (commodity_) { - DEBUG_PRINT("ledger.validate", "amount_t: commodity_ != NULL"); + DEBUG_("ledger.validate", "amount_t: commodity_ != NULL"); return false; } return true; @@ -1561,7 +1584,7 @@ void amount_t::annotate_commodity(const amount_t& tprice, } assert(this_base); - DEBUG_PRINT("amounts.commodities", "Annotating commodity for amount " + DEBUG_("amounts.commodities", "Annotating commodity for amount " << *this << std::endl << " price " << tprice << " " << " date " << tdate << " " @@ -1575,7 +1598,7 @@ void amount_t::annotate_commodity(const amount_t& tprice, if (ann_comm) set_commodity(*ann_comm); - DEBUG_PRINT("amounts.commodities", " Annotated amount is " << *this); + DEBUG_("amounts.commodities", " Annotated amount is " << *this); } amount_t amount_t::strip_annotations(const bool _keep_price, @@ -1586,7 +1609,7 @@ amount_t amount_t::strip_annotations(const bool _keep_price, (_keep_price && _keep_date && _keep_tag)) return *this; - DEBUG_PRINT("amounts.commodities", "Reducing commodity for amount " + DEBUG_("amounts.commodities", "Reducing commodity for amount " << *this << std::endl << " keep price " << _keep_price << " " << " keep date " << _keep_date << " " @@ -1613,7 +1636,7 @@ amount_t amount_t::strip_annotations(const bool _keep_price, amount_t t(*this); t.set_commodity(*new_comm); - DEBUG_PRINT("amounts.commodities", " Reduced amount is " << t); + DEBUG_("amounts.commodities", " Reduced amount is " << t); return t; } @@ -1623,7 +1646,7 @@ amount_t amount_t::price() const if (commodity_ && commodity_->annotated) { amount_t t(((annotated_commodity_t *)commodity_)->price); t *= number(); - DEBUG_PRINT("amounts.commodities", + DEBUG_("amounts.commodities", "Returning price of " << *this << " = " << t); return t; } @@ -1633,7 +1656,7 @@ amount_t amount_t::price() const moment_t amount_t::date() const { if (commodity_ && commodity_->annotated) { - DEBUG_PRINT("amounts.commodities", + DEBUG_("amounts.commodities", "Returning date of " << *this << " = " << ((annotated_commodity_t *)commodity_)->date); return ((annotated_commodity_t *)commodity_)->date; @@ -1675,7 +1698,7 @@ commodity_base_t * commodity_base_t::create(const string& symbol) { commodity_base_t * commodity = new commodity_base_t(symbol); - DEBUG_PRINT("amounts.commodities", "Creating base commodity " << symbol); + DEBUG_("amounts.commodities", "Creating base commodity " << symbol); std::pair<base_commodities_map::iterator, bool> result = commodities.insert(base_commodities_pair(symbol, commodity)); @@ -1696,18 +1719,18 @@ bool commodity_t::needs_quotes(const string& symbol) bool commodity_t::valid() const { if (symbol().empty() && this != null_commodity) { - DEBUG_PRINT("ledger.validate", + DEBUG_("ledger.validate", "commodity_t: symbol().empty() && this != null_commodity"); return false; } if (annotated && ! base) { - DEBUG_PRINT("ledger.validate", "commodity_t: annotated && ! base"); + DEBUG_("ledger.validate", "commodity_t: annotated && ! base"); return false; } if (precision() > 16) { - DEBUG_PRINT("ledger.validate", "commodity_t: precision() > 16"); + DEBUG_("ledger.validate", "commodity_t: precision() > 16"); return false; } @@ -1728,7 +1751,7 @@ commodity_t * commodity_t::create(const string& symbol) commodity->qualified_symbol = symbol; } - DEBUG_PRINT("amounts.commodities", + DEBUG_("amounts.commodities", "Creating commodity " << commodity->qualified_symbol); std::pair<commodities_map::iterator, bool> result @@ -1750,7 +1773,7 @@ commodity_t * commodity_t::create(const string& symbol) commodity_t * commodity_t::find_or_create(const string& symbol) { - DEBUG_PRINT("amounts.commodities", "Find-or-create commodity " << symbol); + DEBUG_("amounts.commodities", "Find-or-create commodity " << symbol); commodity_t * commodity = find(symbol); if (commodity) @@ -1760,7 +1783,7 @@ commodity_t * commodity_t::find_or_create(const string& symbol) commodity_t * commodity_t::find(const string& symbol) { - DEBUG_PRINT("amounts.commodities", "Find commodity " << symbol); + DEBUG_("amounts.commodities", "Find commodity " << symbol); commodities_map::const_iterator i = commodities.find(symbol); if (i != commodities.end()) @@ -1872,7 +1895,7 @@ annotated_commodity_t::create(const commodity_t& comm, commodity->qualified_symbol = comm.symbol(); - DEBUG_PRINT("amounts.commodities", "Creating annotated commodity " + DEBUG_("amounts.commodities", "Creating annotated commodity " << "symbol " << commodity->symbol() << " key " << mapping_key << std::endl << " price " << price << " " @@ -1899,20 +1922,21 @@ namespace { const string& tag) { if (price < 0) - throw new amount_error("A commodity's price may not be negative"); + throw amount_exception("A commodity's price may not be negative", + context()); std::ostringstream name; comm.write(name); annotated_commodity_t::write_annotations(name, price, date, tag); - DEBUG_PRINT("amounts.commodities", "make_qualified_name for " + DEBUG_("amounts.commodities", "make_qualified_name for " << comm.qualified_symbol << std::endl << " price " << price << " " << " date " << date << " " << " tag " << tag); - DEBUG_PRINT("amounts.commodities", "qualified_name is " << name.str()); + DEBUG_("amounts.commodities", "qualified_name is " << name.str()); return name.str(); } @@ -746,16 +746,10 @@ inline commodity_t& amount_t::commodity() const { return *commodity_; } - void parse_conversion(const string& larger_str, const string& smaller_str); - -class amount_error : public error { - public: - amount_error(const string& _reason) throw() : error(_reason) {} - virtual ~amount_error() throw() {} -}; +DECLARE_EXCEPTION(amount_exception); struct compare_amount_commodities { bool operator()(const amount_t * left, const amount_t * right) const; @@ -15,10 +15,8 @@ amount_t balance_t::amount(const commodity_t& commodity) const if (temp.amounts.size() == 1) return temp.amount(commodity); - std::ostringstream errmsg; - errmsg << "Requested amount of a balance with multiple commodities: " - << temp; - throw new amount_error(errmsg.str()); + throw_(amount_exception, + "Requested amount of a balance with multiple commodities: " << temp); } } else if (amounts.size() > 0) { @@ -176,7 +174,7 @@ balance_t& balance_t::operator*=(const balance_t& bal) std::ostringstream errmsg; errmsg << "Cannot multiply two balances: " << temp << " * " << bal; - throw new amount_error(errmsg.str()); + throw amount_exception(errmsg.str(), context()); } } @@ -215,7 +213,7 @@ balance_t& balance_t::operator*=(const amount_t& amt) errmsg << "Attempt to multiply balance by a commodity" << " not found in that balance: " << temp << " * " << amt; - throw new amount_error(errmsg.str()); + throw amount_exception(errmsg.str(), context()); } } return *this; @@ -226,7 +224,7 @@ balance_t& balance_t::operator/=(const balance_t& bal) if (bal.realzero()) { std::ostringstream errmsg; errmsg << "Attempt to divide by zero: " << *this << " / " << bal; - throw new amount_error(errmsg.str()); + throw amount_exception(errmsg.str(), context()); } else if (realzero()) { return *this = 0L; @@ -245,7 +243,7 @@ balance_t& balance_t::operator/=(const balance_t& bal) std::ostringstream errmsg; errmsg << "Cannot divide between two balances: " << temp << " / " << bal; - throw new amount_error(errmsg.str()); + throw amount_exception(errmsg.str(), context()); } } @@ -254,7 +252,7 @@ balance_t& balance_t::operator/=(const amount_t& amt) if (amt.realzero()) { std::ostringstream errmsg; errmsg << "Attempt to divide by zero: " << *this << " / " << amt; - throw new amount_error(errmsg.str()); + throw amount_exception(errmsg.str(), context()); } else if (realzero()) { return *this = 0L; @@ -286,7 +284,7 @@ balance_t& balance_t::operator/=(const amount_t& amt) errmsg << "Attempt to divide balance by a commodity" << " not found in that balance: " << temp << " * " << amt; - throw new amount_error(errmsg.str()); + throw amount_exception(errmsg.str(), context()); } } return *this; @@ -306,10 +304,9 @@ balance_t::operator amount_t() const if (temp.amounts.size() == 1) return (*temp.amounts.begin()).second; - std::ostringstream errmsg; - errmsg << "Cannot convert a balance with " - << "multiple commodities to an amount: " << temp; - throw new amount_error(errmsg.str()); + throw_(amount_exception, + "Cannot convert a balance with " << + "multiple commodities to an amount: " << temp); } } @@ -16,19 +16,24 @@ public: exception(const string& _reason, const context& immediate_ctxt) throw() : reason(_reason) { + EXCEPTION(reason); push(immediate_ctxt); } + virtual ~exception() throw() {} + void push(const context& intermediate_ctxt) throw() { context_stack.push_front(intermediate_ctxt); } void write(std::ostream& out) const throw() { +#if 0 for (std::list<context>::const_iterator - i = context.begin(); - i != context.end(); + i = context_stack.begin(); + i != context_stack.end(); i++) (*i).write(out); +#endif } const char * what() const throw() { @@ -36,13 +41,13 @@ public: } }; -#define DEFINE_EXCEPTION(name) \ +#define DECLARE_EXCEPTION(name) \ class name : public exception { \ public: \ name(const string& _reason, \ const context& immediate_ctxt) throw() \ : exception(_reason, immediate_ctxt) {} \ - }; + } #if 0 @@ -125,6 +130,7 @@ class fatal_assert : public fatal { inline void unexpected(char c, char wanted) { +#if 0 if ((unsigned char) c == 0xff) { if (wanted) throw new error(string("Missing '") + wanted + "'"); @@ -137,6 +143,7 @@ inline void unexpected(char c, char wanted) else throw new error(string("Invalid char '") + c + "'"); } +#endif } } // namespace ledger @@ -89,7 +89,7 @@ void format_t::parse(const string& fmt) if (current->max_width != -1 && current->min_width != -1 && current->max_width < current->min_width) - throw new format_error("Maximum width is less than the minimum width"); + throw_(format_exception, "Maximum width is less than the minimum width"); switch (*p) { case '|': @@ -111,7 +111,7 @@ void format_t::parse(const string& fmt) p++; } if (*p != close) - throw new format_error(string("Missing '") + close + "'"); + throw_(format_exception, "Missing '" << close << "'"); if (open == '{') { assert(! current->xpath); @@ -101,12 +101,7 @@ class format_t } }; -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_exception); } // namespace ledger @@ -341,13 +341,16 @@ 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_exception, msg); } if (! have_error.empty()) { //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++; +#if 0 + // jww (2007-04-26): What is this doing? parse_error err(have_error); std::cerr << "Error: " << err.what() << std::endl; +#endif have_error = ""; } } @@ -32,9 +32,9 @@ struct gnucash_parser_t : public parser_t std::istream * instreamp; unsigned int offset; XML_Parser parser; - string path; + string path; unsigned int src_idx; - istream_pos_type beg_pos; + unsigned long beg_pos; unsigned long beg_line; transaction_t::state_t curr_state; @@ -35,12 +35,12 @@ moment_t transaction_t::effective_date() const bool transaction_t::valid() const { if (! entry) { - DEBUG_PRINT("ledger.validate", "transaction_t: ! entry"); + DEBUG_("ledger.validate", "transaction_t: ! entry"); return false; } if (state != UNCLEARED && state != CLEARED && state != PENDING) { - DEBUG_PRINT("ledger.validate", "transaction_t: state is bad"); + DEBUG_("ledger.validate", "transaction_t: state is bad"); return false; } @@ -53,27 +53,27 @@ bool transaction_t::valid() const break; } if (! found) { - DEBUG_PRINT("ledger.validate", "transaction_t: ! found"); + DEBUG_("ledger.validate", "transaction_t: ! found"); return false; } if (! account) { - DEBUG_PRINT("ledger.validate", "transaction_t: ! account"); + DEBUG_("ledger.validate", "transaction_t: ! account"); return false; } if (! amount.valid()) { - DEBUG_PRINT("ledger.validate", "transaction_t: ! amount.valid()"); + DEBUG_("ledger.validate", "transaction_t: ! amount.valid()"); return false; } if (cost && ! cost->valid()) { - DEBUG_PRINT("ledger.validate", "transaction_t: cost && ! cost->valid()"); + DEBUG_("ledger.validate", "transaction_t: cost && ! cost->valid()"); return false; } if (flags & ~0x003f) { - DEBUG_PRINT("ledger.validate", "transaction_t: flags are bad"); + DEBUG_("ledger.validate", "transaction_t: flags are bad"); return false; } @@ -199,7 +199,7 @@ bool entry_base_t::finalize() continue; if (! empty_allowed) - throw new error("Only one transaction with null amount allowed per entry"); + throw_(exception, "Only one transaction with null amount allowed per entry"); empty_allowed = false; // If one transaction gives no value at all, its value will become @@ -255,12 +255,16 @@ bool entry_base_t::finalize() } if (balance) { +#if 1 + throw_(balance_exception, "Entry does not balance"); +#else 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 } return true; @@ -307,7 +311,7 @@ void entry_t::add_transaction(transaction_t * xact) bool entry_t::valid() const { if (! is_valid_moment(_date) || ! journal) { - DEBUG_PRINT("ledger.validate", "entry_t: ! _date || ! journal"); + DEBUG_("ledger.validate", "entry_t: ! _date || ! journal"); return false; } @@ -315,7 +319,7 @@ bool entry_t::valid() const i != transactions.end(); i++) if ((*i)->entry != this || ! (*i)->valid()) { - DEBUG_PRINT("ledger.validate", "entry_t: transaction not valid"); + DEBUG_("ledger.validate", "entry_t: transaction not valid"); return false; } @@ -466,7 +470,7 @@ std::ostream& operator<<(std::ostream& out, const account_t& account) bool account_t::valid() const { if (depth > 256 || ! journal) { - DEBUG_PRINT("ledger.validate", "account_t: depth > 256 || ! journal"); + DEBUG_("ledger.validate", "account_t: depth > 256 || ! journal"); return false; } @@ -474,12 +478,12 @@ bool account_t::valid() const i != accounts.end(); i++) { if (this == (*i).second) { - DEBUG_PRINT("ledger.validate", "account_t: parent refers to itself!"); + DEBUG_("ledger.validate", "account_t: parent refers to itself!"); return false; } if (! (*i).second->valid()) { - DEBUG_PRINT("ledger.validate", "account_t: child not valid"); + DEBUG_("ledger.validate", "account_t: child not valid"); return false; } } @@ -575,7 +579,7 @@ bool journal_t::remove_entry(entry_t * entry) bool journal_t::valid() const { if (! master->valid()) { - DEBUG_PRINT("ledger.validate", "journal_t: master not valid"); + DEBUG_("ledger.validate", "journal_t: master not valid"); return false; } @@ -583,7 +587,7 @@ bool journal_t::valid() const i != entries.end(); i++) if (! (*i)->valid()) { - DEBUG_PRINT("ledger.validate", "journal_t: entry not valid"); + DEBUG_("ledger.validate", "journal_t: entry not valid"); return false; } @@ -591,7 +595,7 @@ bool journal_t::valid() const i != commodity_t::commodities.end(); i++) if (! (*i).second->valid()) { - DEBUG_PRINT("ledger.validate", "journal_t: commodity not valid"); + DEBUG_("ledger.validate", "journal_t: commodity not valid"); return false; } @@ -634,6 +638,7 @@ void print_entry(std::ostream& out, const entry_base_t& entry_base, #endif } +#if 0 void entry_context::describe(std::ostream& out) const throw() { if (! desc.empty()) @@ -657,6 +662,7 @@ xact_context::xact_context(const ledger::transaction_t& _xact, } line = xact.beg_line; } +#endif } // namespace ledger @@ -85,6 +85,7 @@ class transaction_t bool valid() const; }; +#if 0 class xact_context : public file_context { public: const transaction_t& xact; @@ -93,6 +94,7 @@ class xact_context : public file_context { const string& desc = "") throw(); virtual ~xact_context() throw() {} }; +#endif class journal_t; @@ -196,6 +198,7 @@ struct entry_finalizer_t { void print_entry(std::ostream& out, const entry_base_t& entry, const string& prefix = ""); +#if 0 class entry_context : public error_context { public: const entry_base_t& entry; @@ -207,14 +210,9 @@ class entry_context : public error_context { virtual void describe(std::ostream& out) const throw(); }; +#endif -class balance_error : public error { - public: - balance_error(const string& _reason, - error_context * _ctxt = NULL) throw() - : error(_reason, _ctxt) {} - virtual ~balance_error() throw() {} -}; +DECLARE_EXCEPTION(balance_exception); class auto_entry_t : public entry_base_t @@ -38,11 +38,11 @@ static int read_and_report(report_t * report, int argc, char * argv[], else session.use_cache = session.data_file.empty() && session.price_db.empty(); - DEBUG_PRINT("ledger.session.cache", "1. use_cache = " << session.use_cache); + DEBUG_("ledger.session.cache", "1. use_cache = " << session.use_cache); // Process the environment settings - TRACE(main, "Processing options and environment settings"); + TRACE(1, "Processing options and environment settings"); process_environment(const_cast<const char **>(envp), "LEDGER_", report); @@ -60,15 +60,15 @@ static int read_and_report(report_t * report, int argc, char * argv[], if (session.data_file == session.cache_file) session.use_cache = false; - DEBUG_PRINT("ledger.session.cache", "2. use_cache = " << session.use_cache); + DEBUG_("ledger.session.cache", "2. use_cache = " << session.use_cache); - TRACE(main, string("Initialization file is ") + session.init_file); - TRACE(main, string("Price database is ") + session.price_db); - TRACE(main, string("Binary cache is ") + session.cache_file); - TRACE(main, string("Main journal is ") + session.data_file); + TRACE(1, "Initialization file is " << session.init_file); + TRACE(1, "Price database is " << session.price_db); + TRACE(1, "Binary cache is " << session.cache_file); + TRACE(1, "Main journal is " << session.data_file); - TRACE(main, string("Based on option settings, binary cache ") + - (session.use_cache ? "WILL " : "will NOT ") + "be used"); + TRACE(1, "Based on option settings, binary cache " << + (session.use_cache ? "WILL " : "will NOT ") << "be used"); // Read the command word and create a command object based on it @@ -160,7 +160,7 @@ static int read_and_report(report_t * report, int argc, char * argv[], command.reset(def->functor_obj()); if (! command.get()) - throw new error(string("Unrecognized command '") + verb + "'"); + throw_(exception, string("Unrecognized command '") + verb + "'"); } // Parse the initialization file, which can only be textual; then @@ -186,11 +186,11 @@ static int read_and_report(report_t * report, int argc, char * argv[], else if (! report->pager.empty()) { status = pipe(pfd); if (status == -1) - throw new error("Failed to create pipe"); + throw_(exception, "Failed to create pipe"); status = fork(); if (status < 0) { - throw new error("Failed to fork child process"); + throw_(exception, "Failed to fork child process"); } else if (status == 0) { // child const char *arg0; @@ -332,29 +332,29 @@ static int read_and_report(report_t * report, int argc, char * argv[], if (session.use_cache && session.cache_dirty && ! session.cache_file.empty()) { - TRACE_PUSH(binary_cache, "Writing journal file"); + TRACE_START(binary_cache, 1, "Writing journal file"); std::ofstream stream(session.cache_file.c_str()); #if 0 write_binary_journal(stream, journal); #endif - TRACE_POP(binary_cache, "Finished writing"); + TRACE_FINISH(binary_cache, 1); } +#if defined(FREE_MEMORY) // Cleanup memory -- if this is a beta or development build. -#if DEBUG_LEVEL >= BETA - { TRACE_PUSH(cleanup, "Cleaning up allocated memory"); + TRACE_START(cleanup, 1, "Cleaning up allocated memory"); #ifdef USE_BOOST_PYTHON - shutdown_ledger_for_python(); + shutdown_ledger_for_python(); #endif - if (! report->output_file.empty()) - delete out; + if (! report->output_file.empty()) + delete out; - TRACE_POP(cleanup, "Finished cleaning"); } + TRACE_STOP(cleanup, 1); #endif // If the user specified a pager, wait for it to exit now @@ -367,7 +367,7 @@ static int read_and_report(report_t * report, int argc, char * argv[], // Wait for child to finish wait(&status); if (status & 0xffff != 0) - throw new error("Something went wrong in the pager"); + throw_(exception, "Something went wrong in the pager"); } #endif @@ -388,10 +388,8 @@ int main(int argc, char * argv[], char * envp[]) #if DEBUG_LEVEL < BETA ledger::do_cleanup = false; -#else - ledger::tracing_active = true; #endif - TRACE_PUSH(main, "Ledger starting"); + TRACE(1, "Ledger starting"); ledger::amount_t::initialize(); @@ -410,12 +408,6 @@ int main(int argc, char * argv[], char * envp[]) session->register_parser(new qif_parser_t); session->register_parser(new textual_parser_t); -#if DEBUG_LEVEL >= BETA - DEBUG_IF("ledger.trace.memory") { - ledger::trace_class_mode = true; - } -#endif - std::auto_ptr<ledger::report_t> report(new ledger::report_t(session.get())); status = read_and_report(report.get(), argc, argv, envp); @@ -427,9 +419,8 @@ int main(int argc, char * argv[], char * envp[]) } else { ledger::amount_t::shutdown(); } - - TRACE_POP(main, "Ledger done"); } +#if 0 catch (error * err) { std::cout.flush(); // Push a null here since there's no file context @@ -439,9 +430,6 @@ int main(int argc, char * argv[], char * envp[]) err->reveal_context(std::cerr, "Error"); std::cerr << err->what() << std::endl; delete err; -#if DEBUG_LEVEL >= BETA - ledger::tracing_active = false; -#endif } catch (fatal * err) { std::cout.flush(); @@ -452,32 +440,21 @@ int main(int argc, char * argv[], char * envp[]) err->reveal_context(std::cerr, "Fatal"); std::cerr << err->what() << std::endl; delete err; -#if DEBUG_LEVEL >= BETA - ledger::tracing_active = false; -#endif } +#endif catch (const std::exception& err) { std::cout.flush(); std::cerr << "Error: " << err.what() << std::endl; -#if DEBUG_LEVEL >= BETA - ledger::tracing_active = false; -#endif } catch (int _status) { -#if DEBUG_LEVEL >= BETA - ledger::tracing_active = false; -#endif status = _status; } -#if DEBUG_LEVEL >= BETA - DEBUG_IF("ledger.trace.memory") { + IF_DEBUG_("ledger.trace.memory") { report_memory(std::cerr); std::cerr << "Total calls to new: " << new_calls << std::endl << "Total memory new'd: " << new_size << std::endl; } - ledger::tracing_active = false; -#endif return status; } @@ -21,12 +21,6 @@ class mask_t } }; -class mask_error : public error { - public: - mask_error(const string& _reason) throw() : error(_reason) {} - virtual ~mask_error() throw() {} -}; - } // namespace ledger #endif // _MASK_H @@ -23,7 +23,7 @@ int ofx_proc_account_cb(struct OfxAccountData data, void * account_data) if (! data.account_id_valid) return -1; - DEBUG_PRINT("ledger.ofx.parse", "account " << data.account_name); + DEBUG_("ledger.ofx.parse", "account " << data.account_name); account_t * account = new account_t(master_account, data.account_name); curr_journal->add_account(account); ofx_accounts.insert(accounts_pair(data.account_id, account)); @@ -80,7 +80,7 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data, xact->cost = new amount_t(stream.str() + " " + default_commodity->base_symbol()); } - DEBUG_PRINT("ledger.ofx.parse", "xact " << xact->amount + DEBUG_("ledger.ofx.parse", "xact " << xact->amount << " from " << *xact->account); if (data.date_initiated_valid) @@ -142,13 +142,13 @@ int ofx_proc_security_cb(struct OfxSecurityData data, void * security_data) commodities_map::iterator i = ofx_securities.find(data.unique_id); if (i == ofx_securities.end()) { - DEBUG_PRINT("ledger.ofx.parse", "security " << symbol); + DEBUG_("ledger.ofx.parse", "security " << symbol); ofx_securities.insert(commodities_pair(data.unique_id, commodity)); } // jww (2005-02-09): What is the commodity for data.unitprice? if (data.date_unitprice_valid && data.unitprice_valid) { - DEBUG_PRINT("ledger.ofx.parse", " price " << data.unitprice); + DEBUG_("ledger.ofx.parse", " price " << data.unitprice); commodity->add_price(data.date_unitprice, amount_t(data.unitprice)); } @@ -45,7 +45,9 @@ namespace { void process_option(xml::xpath_t::functor_t * opt, xml::xpath_t::scope_t * scope, const char * arg) { +#if 0 try { +#endif std::auto_ptr<xml::xpath_t::scope_t> args; if (arg) { args.reset(new xml::xpath_t::scope_t(scope, xml::xpath_t::scope_t::ARGUMENT)); @@ -54,17 +56,17 @@ namespace { value_t temp; (*opt)(temp, args.get()); +#if 0 } catch (error * err) { -#if 0 err->context.push_back (new error_context (string("While parsing option '--") + opt->long_opt + "'" + (opt->short_opt != '\0' ? (string(" (-") + opt->short_opt + "):") : ":"))); -#endif throw err; } +#endif } } @@ -103,9 +105,15 @@ void process_environment(const char ** envp, const string& tag, *r = '\0'; if (*q == '=') { +#if 0 try { +#endif if (! process_option(buf, scope, q + 1)) - /*throw new option_error("unknown option")*/; +#if 0 + throw new option_error("unknown option") +#endif + ; +#if 0 } catch (error * err) { err->context.push_back @@ -114,6 +122,7 @@ void process_environment(const char ** envp, const string& tag, *p + "':")); throw err; } +#endif } } } @@ -149,22 +158,21 @@ void process_arguments(int argc, char ** argv, const bool anywhere, std::auto_ptr<xml::xpath_t::op_t> opt(find_option(scope, name)); if (! opt.get()) - throw new option_error(string("illegal option --") + name); + throw_(option_exception, "illegal option --" << name); xml::xpath_t::functor_t * def = opt->functor_obj(); if (! def) - throw new option_error(string("illegal option --") + name); + throw_(option_exception, "illegal option --" << name); if (def->wants_args && value == NULL) { value = *++i; if (value == NULL) - throw new option_error(string("missing option argument for --") + - name); + throw_(option_exception, "missing option argument for --" << name); } process_option(def, scope, value); } else if ((*i)[1] == '\0') { - throw new option_error(string("illegal option -")); + throw_(option_exception, "illegal option -"); } else { std::list<xml::xpath_t::op_t *> option_queue; @@ -173,11 +181,11 @@ void process_arguments(int argc, char ** argv, const bool anywhere, for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) { xml::xpath_t::op_t * opt = find_option(scope, c); if (! opt) - throw new option_error(string("illegal option -") + c); + throw_(option_exception, "illegal option -" << c); xml::xpath_t::functor_t * def = opt->functor_obj(); if (! def) - throw new option_error(string("illegal option -") + c); + throw_(option_exception, "illegal option -" << c); option_queue.push_back(opt); } @@ -194,12 +202,13 @@ void process_arguments(int argc, char ** argv, const bool anywhere, if (def->wants_args) { value = *++i; if (value == NULL) - throw new option_error(string("missing option argument for -") + + throw_(option_exception, "missing option argument for -" << #if 0 - def->short_opt); + def->short_opt #else - '?'); + '?' #endif + ); } process_option(def, scope, value); @@ -15,11 +15,7 @@ void process_arguments(int argc, char ** argv, const bool anywhere, xml::xpath_t::scope_t * scope, std::list<string>& args); -class option_error : public error { - public: - option_error(const string& reason) throw() : error(reason) {} - virtual ~option_error() throw() {} -}; +DECLARE_EXCEPTION(option_exception); } // namespace ledger @@ -21,7 +21,65 @@ class parser_t const string * original_file = NULL) = 0; }; -DEFINE_EXCEPTION(parse_exception) +DECLARE_EXCEPTION(parse_exception); + +/************************************************************************ + * + * General utility parsing functions + */ + +inline char * skip_ws(char * ptr) { + while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') + ptr++; + return ptr; +} + +inline char peek_next_nonws(std::istream& in) { + char c = in.peek(); + while (! in.eof() && std::isspace(c)) { + in.get(c); + c = in.peek(); + } + return c; +} + +#define READ_INTO(str, targ, size, var, cond) { \ + char * _p = targ; \ + var = str.peek(); \ + while (! str.eof() && var != '\n' && (cond) && _p - targ < size) { \ + str.get(var); \ + if (str.eof()) \ + break; \ + if (var == '\\') { \ + str.get(var); \ + if (in.eof()) \ + break; \ + } \ + *_p++ = var; \ + var = str.peek(); \ + } \ + *_p = '\0'; \ +} + +#define READ_INTO_(str, targ, size, var, idx, cond) { \ + char * _p = targ; \ + var = str.peek(); \ + while (! str.eof() && var != '\n' && (cond) && _p - targ < size) { \ + str.get(var); \ + if (str.eof()) \ + break; \ + idx++; \ + if (var == '\\') { \ + str.get(var); \ + if (in.eof()) \ + break; \ + idx++; \ + } \ + *_p++ = var; \ + var = str.peek(); \ + } \ + *_p = '\0'; \ +} } // namespace ledger diff --git a/py_amount.cc b/py_amount.cc index 6b13c9af..607d0be5 100644 --- a/py_amount.cc +++ b/py_amount.cc @@ -46,11 +46,11 @@ commodity_t * py_find_commodity(const string& symbol) } #define EXC_TRANSLATOR(type) \ - void exc_translate_ ## type(const type * const err) { \ - PyErr_SetString(PyExc_ArithmeticError, err->what()); \ + void exc_translate_ ## type(const type& err) { \ + PyErr_SetString(PyExc_ArithmeticError, err.what()); \ } -EXC_TRANSLATOR(amount_error) +EXC_TRANSLATOR(amount_exception) void export_amount() { @@ -236,7 +236,7 @@ void export_amount() ; #define EXC_TRANSLATE(type) \ - register_exception_translator<type *>(&exc_translate_ ## type); + register_exception_translator<type>(&exc_translate_ ## type); - EXC_TRANSLATE(amount_error); + EXC_TRANSLATE(amount_exception); } @@ -71,7 +71,7 @@ object python_interpreter_t::import(const string& str) try { PyObject * mod = PyImport_Import(PyString_FromString(str.c_str())); if (! mod) - throw error(string("Failed to import Python module ") + str); + throw_(exception, "Failed to import Python module " << str); object newmod(handle<>(borrowed(mod))); @@ -86,7 +86,7 @@ object python_interpreter_t::import(const string& str) } catch (const error_already_set&) { PyErr_Print(); - throw error(string("Importing Python module ") + str); + throw_(exception, "Importing Python module " << str); } } @@ -120,7 +120,7 @@ object python_interpreter_t::eval(std::istream& in, py_eval_mode_t mode) } catch (const error_already_set&) { PyErr_Print(); - throw error("Evaluating Python code"); + throw_(exception, "Evaluating Python code"); } } @@ -138,7 +138,7 @@ object python_interpreter_t::eval(const string& str, py_eval_mode_t mode) } catch (const error_already_set&) { PyErr_Print(); - throw error("Evaluating Python code"); + throw_(exception, "Evaluating Python code"); } } @@ -165,8 +165,8 @@ void python_interpreter_t::functor_t::operator()(value_t& result, } else if (PyObject * err = PyErr_Occurred()) { PyErr_Print(); - throw new xml::xpath_t::calc_error - (string("While calling Python function '") + name() + "'"); + throw_(xml::xpath_t::calc_exception, + "While calling Python function '" << name() << "'"); } else { assert(0); } @@ -177,8 +177,8 @@ void python_interpreter_t::functor_t::operator()(value_t& result, } catch (const error_already_set&) { PyErr_Print(); - throw new xml::xpath_t::calc_error - (string("While calling Python function '") + name() + "'"); + throw_(xml::xpath_t::calc_exception, + "While calling Python function '" << name() << "'"); } } @@ -194,7 +194,8 @@ void python_interpreter_t::lambda_t::operator()(value_t& result, } catch (const error_already_set&) { PyErr_Print(); - throw new xml::xpath_t::calc_error("While evaluating Python lambda expression"); + throw_(xml::xpath_t::calc_exception, + "While evaluating Python lambda expression"); } } @@ -56,8 +56,8 @@ unsigned int qif_parser_t::parse(std::istream& in, src_idx = journal->sources.size() - 1; linenum = 1; - istream_pos_type beg_pos = 0; - unsigned long beg_line = 0; + unsigned long beg_pos = 0; + unsigned long beg_line = 0; #define SET_BEG_POS_AND_LINE() \ if (! beg_line) { \ @@ -73,7 +73,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_exception, "Line begins with whitespace"); } // fall through... @@ -90,8 +90,8 @@ 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_exception, + "QIF files of type " << line << " are not supported."); break; case 'D': @@ -8,17 +8,17 @@ void quotes_by_script::operator()(commodity_base_t& commodity, const ptime& last, amount_t& price) { - DEBUG_CLASS("ledger.quotes.download"); + logger("quotes.download"); - DEBUG_PRINT_("commodity: " << commodity.symbol); - DEBUG_PRINT_TIME_(now); - DEBUG_PRINT_TIME_(moment); - DEBUG_PRINT_TIME_(date); - DEBUG_PRINT_TIME_(last); + DEBUG("commodity: " << commodity.symbol); + DEBUG(" now: " << now); + DEBUG(" moment: " << moment); + DEBUG(" date: " << date); + DEBUG(" last: " << last); - if (commodity.history) - DEBUG_PRINT_TIME_(commodity.history->last_lookup); - DEBUG_PRINT_("pricing_leeway is " << pricing_leeway); + if (SHOW_DEBUG() && commodity.history) + DEBUG("last_lookup: " << commodity.history->last_lookup); + DEBUG("pricing_leeway is " << pricing_leeway); if ((commodity.history && (time_now - commodity.history->last_lookup) < pricing_leeway) || @@ -26,7 +26,7 @@ void quotes_by_script::operator()(commodity_base_t& commodity, (price && moment > date && (moment - date) <= pricing_leeway)) return; - DEBUG_PRINT_("downloading quote for symbol " << commodity.symbol); + DEBUG("downloading quote for symbol " << commodity.symbol); char buf[256]; buf[0] = '\0'; @@ -47,7 +47,7 @@ void quotes_by_script::operator()(commodity_base_t& commodity, char * p = strchr(buf, '\n'); if (p) *p = '\0'; - DEBUG_PRINT_("downloaded quote: " << buf); + DEBUG("downloaded quote: " << buf); price.parse(buf); commodity.add_price(now, price); @@ -70,9 +70,10 @@ void quotes_by_script::operator()(commodity_base_t& commodity, #endif } } else { - throw new error(string("Failed to download price for '") + + throw exception(string("Failed to download price for '") + commodity.symbol + "' (command: \"getquote " + - commodity.symbol + "\")"); + commodity.symbol + "\")", + context()); } } diff --git a/register.cc b/register.cc index 8df5f556..2633def6 100644 --- a/register.cc +++ b/register.cc @@ -3,6 +3,95 @@ namespace ledger { +string abbreviate(const string& str, + unsigned int width, + elision_style_t elision_style, + const bool is_account, + int abbrev_length) +{ + const unsigned int len = str.length(); + if (len <= width) + return str; + + assert(width < 4095); + + static char buf[4096]; + + switch (elision_style) { + case TRUNCATE_LEADING: + // This method truncates at the beginning. + std::strncpy(buf, str.c_str() + (len - width), width); + buf[0] = '.'; + buf[1] = '.'; + break; + + case TRUNCATE_MIDDLE: + // This method truncates in the middle. + std::strncpy(buf, str.c_str(), width / 2); + std::strncpy(buf + width / 2, + str.c_str() + (len - (width / 2 + width % 2)), + width / 2 + width % 2); + buf[width / 2 - 1] = '.'; + buf[width / 2] = '.'; + break; + + case ABBREVIATE: + if (is_account) { + std::list<string> parts; + string::size_type beg = 0; + for (string::size_type pos = str.find(':'); + pos != string::npos; + beg = pos + 1, pos = str.find(':', beg)) + parts.push_back(string(str, beg, pos - beg)); + parts.push_back(string(str, beg)); + + string result; + unsigned int newlen = len; + for (std::list<string>::iterator i = parts.begin(); + i != parts.end(); + i++) { + // Don't contract the last element + std::list<string>::iterator x = i; + if (++x == parts.end()) { + result += *i; + break; + } + + if (newlen > width) { + result += string(*i, 0, abbrev_length); + result += ":"; + newlen -= (*i).length() - abbrev_length; + } else { + result += *i; + result += ":"; + } + } + + if (newlen > width) { + // Even abbreviated its too big to show the last account, so + // abbreviate all but the last and truncate at the beginning. + std::strncpy(buf, result.c_str() + (result.length() - width), width); + buf[0] = '.'; + buf[1] = '.'; + } else { + std::strcpy(buf, result.c_str()); + } + break; + } + // fall through... + + case TRUNCATE_TRAILING: + // This method truncates at the end (the default). + std::strncpy(buf, str.c_str(), width - 2); + buf[width - 2] = '.'; + buf[width - 1] = '.'; + break; + } + buf[width] = '\0'; + + return buf; +} + static void scan_for_transactions(std::ostream& out, const xml::node_t * node) { if (! (node->flags & XML_NODE_IS_PARENT)) @@ -20,6 +20,19 @@ class register_command : public xml::xpath_t::functor_t virtual void print_document(std::ostream& out, xml::document_t * doc); }; +enum elision_style_t { + TRUNCATE_TRAILING, + TRUNCATE_MIDDLE, + TRUNCATE_LEADING, + ABBREVIATE +}; + +string abbreviate(const string& str, + unsigned int width, + elision_style_t elision_style = TRUNCATE_TRAILING, + const bool is_account = false, + int abbrev_length = 2); + } // namespace ledger #endif // _REGISTER_H @@ -22,7 +22,7 @@ void report_t::apply_transforms(xml::document_t * document) void report_t::abbrev(value_t& result, xml::xpath_t::scope_t * locals) { if (locals->args.size() < 2) - throw new error("usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])"); + throw_(exception, "usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])"); string str = locals->args[0].to_string(); long wid = locals->args[1]; @@ -41,7 +41,7 @@ void report_t::abbrev(value_t& result, xml::xpath_t::scope_t * locals) void report_t::ftime(value_t&, xml::xpath_t::scope_t * locals) { if (locals->args.size() < 1) - throw new error("usage: ftime(DATE [, DATE_FORMAT])"); + throw_(exception, "usage: ftime(DATE [, DATE_FORMAT])"); moment_t date = locals->args[0].to_datetime(); @@ -27,7 +27,7 @@ unsigned int session_t::read_journal(const string& path, journal->sources.push_back(path); if (access(path.c_str(), R_OK) == -1) - throw new error(string("Cannot read file '") + path + "'"); + throw_(exception, "Cannot read file '" << path << "'"); if (! original_file) original_file = &path; @@ -42,7 +42,7 @@ void session_t::read_init() return; if (access(init_file.c_str(), R_OK) == -1) - throw new error(string("Cannot read init file '") + init_file + "'"); + throw_(exception, "Cannot read init file '" << init_file << "'"); std::ifstream init(init_file.c_str()); @@ -51,7 +51,7 @@ void session_t::read_init() journal_t * session_t::read_data(const string& master_account) { - TRACE_PUSH(parser, "Parsing journal file"); + TRACE_START(parser, 1, "Parsing journal file"); journal_t * journal = new_journal(); journal->document = new xml::document_t; @@ -59,12 +59,12 @@ journal_t * session_t::read_data(const string& master_account) unsigned int entry_count = 0; - DEBUG_PRINT("ledger.cache", + DEBUG_("ledger.cache", "3. use_cache = " << use_cache); if (use_cache && ! cache_file.empty() && ! data_file.empty()) { - DEBUG_PRINT("ledger.cache", + DEBUG_("ledger.cache", "using_cache " << cache_file); cache_dirty = true; if (access(cache_file.c_str(), R_OK) != -1) { @@ -90,15 +90,15 @@ journal_t * session_t::read_data(const string& master_account) if (! journal->price_db.empty() && access(journal->price_db.c_str(), R_OK) != -1) { if (read_journal(journal->price_db, journal)) { - throw new error("Entries not allowed in price history file"); + throw_(exception, "Entries not allowed in price history file"); } else { - DEBUG_PRINT("ledger.cache", + DEBUG_("ledger.cache", "read price database " << journal->price_db); journal->sources.pop_back(); } } - DEBUG_PRINT("ledger.cache", + DEBUG_("ledger.cache", "rejected cache, parsing " << data_file); if (data_file == "-") { use_cache = false; @@ -112,13 +112,13 @@ journal_t * session_t::read_data(const string& master_account) } } - VALIDATE(journal->valid()); + VERIFY(journal->valid()); if (entry_count == 0) - throw new error("Failed to locate any journal entries; " - "did you specify a valid file with -f?"); + throw_(exception, "Failed to locate any journal entries; " + "did you specify a valid file with -f?"); - TRACE_POP(parser, "Finished parsing"); + TRACE_STOP(parser, 1); return journal; } @@ -185,6 +185,8 @@ xml::xpath_t::op_t * session_t::lookup(const string& name) return xml::xpath_t::scope_t::lookup(name); } +// jww (2007-04-26): All of Ledger should be accessed through a +// session_t object void initialize() { amount_t::initialize(); @@ -193,7 +195,6 @@ void initialize() void shutdown() { amount_t::shutdown(); - assert(live_count.size() == 0); } } // namespace ledger @@ -3,6 +3,7 @@ #include "journal.h" #include "parser.h" +#include "register.h" namespace ledger { @@ -21,16 +21,17 @@ #include <algorithm> #include <exception> -#include <fstream> #include <iostream> +#include <streambuf> +#include <iomanip> +#include <fstream> +#include <sstream> #include <iterator> #include <list> #include <map> #include <memory> #include <new> -#include <sstream> #include <stack> -#include <streambuf> #include <string> #include <vector> diff --git a/tests/corelib/numerics/BasicAmount.cc b/tests/corelib/numerics/BasicAmount.cc index fbab8877..90cf26ec 100644 --- a/tests/corelib/numerics/BasicAmount.cc +++ b/tests/corelib/numerics/BasicAmount.cc @@ -339,7 +339,7 @@ void BasicAmountTestCase::testIntegerDivision() amount_t x1(123L); amount_t y1(456L); - assertThrow(x1 / 0L, amount_error *); + assertThrow(x1 / 0L, amount_exception); assertEqual(amount_t(0L), amount_t(0L) / x1); assertEqual(amount_t(0L), 0L / x1); assertEqual(x1, x1 / 1L); @@ -376,7 +376,7 @@ void BasicAmountTestCase::testFractionalDivision() amount_t x1(123.123); amount_t y1(456.456); - assertThrow(x1 / 0L, amount_error *); + assertThrow(x1 / 0L, amount_exception); assertEqual(amount_t("0.008121959"), amount_t(1.0) / x1); assertEqual(amount_t("0.008121959"), 1.0 / x1); assertEqual(x1, x1 / 1.0); diff --git a/tests/corelib/numerics/Commodity.cc b/tests/corelib/numerics/Commodity.cc index e43ee7b7..e7e2a18c 100644 --- a/tests/corelib/numerics/Commodity.cc +++ b/tests/corelib/numerics/Commodity.cc @@ -3,10 +3,10 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CommodityTestCase, "numerics"); void CommodityTestCase::setUp() { - amount_t::initialize(); + ledger::initialize(); } void CommodityTestCase::tearDown() { - amount_t::shutdown(); + ledger::shutdown(); } void CommodityTestCase::testPriceHistory() diff --git a/tests/corelib/numerics/CommodityAmount.cc b/tests/corelib/numerics/CommodityAmount.cc index afdbe89e..7ed7f403 100644 --- a/tests/corelib/numerics/CommodityAmount.cc +++ b/tests/corelib/numerics/CommodityAmount.cc @@ -6,7 +6,7 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CommodityAmountTestCase, "numerics"); void CommodityAmountTestCase::setUp() { - amount_t::initialize(); + ledger::initialize(); // Cause the display precision for dollars to be initialized to 2. amount_t x1("$1.00"); @@ -17,7 +17,7 @@ void CommodityAmountTestCase::setUp() void CommodityAmountTestCase::tearDown() { amount_t::full_strings = false; - amount_t::shutdown(); + ledger::shutdown(); } void CommodityAmountTestCase::testConstructors() @@ -232,13 +232,13 @@ void CommodityAmountTestCase::testAddition() assertEqual(string("$246.90"), (x1 + x1).to_string()); assertEqual(string("$246.91"), (x1 + x2).to_string()); - assertThrow(x1 + x0, amount_error *); - assertThrow(x1 + x3, amount_error *); - assertThrow(x1 + x4, amount_error *); - assertThrow(x1 + x5, amount_error *); - assertThrow(x1 + x6, amount_error *); - assertThrow(x1 + 123.45, amount_error *); - assertThrow(x1 + 123L, amount_error *); + assertThrow(x1 + x0, amount_exception); + assertThrow(x1 + x3, amount_exception); + assertThrow(x1 + x4, amount_exception); + assertThrow(x1 + x5, amount_exception); + assertThrow(x1 + x6, amount_exception); + assertThrow(x1 + 123.45, amount_exception); + assertThrow(x1 + 123L, amount_exception); assertEqual(amount_t("DM 246.90"), x3 + x3); assertEqual(amount_t("246.90 euro"), x4 + x4); @@ -290,13 +290,13 @@ void CommodityAmountTestCase::testSubtraction() assertEqual(string("$0.00"), (x1 - x1).to_string()); assertEqual(string("$-0.01"), (x1 - x2).to_string()); - assertThrow(x1 - x0, amount_error *); - assertThrow(x1 - x3, amount_error *); - assertThrow(x1 - x4, amount_error *); - assertThrow(x1 - x5, amount_error *); - assertThrow(x1 - x6, amount_error *); - assertThrow(x1 - 123.45, amount_error *); - assertThrow(x1 - 123L, amount_error *); + assertThrow(x1 - x0, amount_exception); + assertThrow(x1 - x3, amount_exception); + assertThrow(x1 - x4, amount_exception); + assertThrow(x1 - x5, amount_exception); + assertThrow(x1 - x6, amount_exception); + assertThrow(x1 - 123.45, amount_exception); + assertThrow(x1 - 123L, amount_exception); assertEqual(amount_t("DM 0.00"), x3 - x3); assertEqual(amount_t("DM 23.45"), x3 - amount_t("DM 100.00")); @@ -374,9 +374,9 @@ void CommodityAmountTestCase::testMultiplication() assertEqual(string("$15200.00"), (x1 * x2).to_string()); assertEqual(string("$15199.99986168"), (x2 * x1).to_string()); - assertThrow(x1 * x3, amount_error *); - assertThrow(x1 * x4, amount_error *); - assertThrow(x1 * x5, amount_error *); + assertThrow(x1 * x3, amount_exception); + assertThrow(x1 * x4, amount_exception); + assertThrow(x1 * x5, amount_exception); x1 *= amount_t("123.12"); assertEqual(internalAmount("$15158.5344"), x1); @@ -410,7 +410,7 @@ void CommodityAmountTestCase::testDivision() amount_t x4("123.45 euro"); amount_t x5("123.45€"); - assertThrow(x1 / 0L, amount_error *); + assertThrow(x1 / 0L, amount_exception); assertEqual(amount_t("$0.00"), 0L / x1); assertEqual(x1, x1 / 1L); assertEqual(internalAmount("$0.00812216"), 1L / x1); @@ -428,9 +428,9 @@ void CommodityAmountTestCase::testDivision() assertEqual(string("$1.00"), (x1 / x2).to_string()); assertEqual(string("$1.00273545321637426901"), (x2 / x1).to_string()); - assertThrow(x1 / x3, amount_error *); - assertThrow(x1 / x4, amount_error *); - assertThrow(x1 / x5, amount_error *); + assertThrow(x1 / x3, amount_exception); + assertThrow(x1 / x4, amount_exception); + assertThrow(x1 / x5, amount_exception); x1 /= amount_t("123.12"); assertEqual(internalAmount("$1.00"), x1); @@ -52,7 +52,7 @@ parse_amount_expr(std::istream& in, journal_t *, { xml::xpath_t xpath(in, flags | XPATH_PARSE_RELAXED | XPATH_PARSE_PARTIAL); - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Parsed an amount expression"); #ifdef DEBUG_ENABLED @@ -66,7 +66,7 @@ parse_amount_expr(std::istream& in, journal_t *, amount = xpath.calc(static_cast<xml::transaction_node_t *>(xact.data)).to_amount(); - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "The transaction amount is " << amount); } @@ -112,7 +112,9 @@ transaction_t * parse_transaction(char * line, } string err_desc; +#if 0 try { +#endif xact->entry = entry; // this might be NULL @@ -122,12 +124,12 @@ transaction_t * parse_transaction(char * line, switch (*state) { case '*': xact->state = transaction_t::CLEARED; - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Parsed the CLEARED flag"); break; case '!': xact->state = transaction_t::PENDING; - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Parsed the PENDING flag"); break; } @@ -139,18 +141,18 @@ transaction_t * parse_transaction(char * line, if ((*b == '[' && *e == ']') || (*b == '(' && *e == ')')) { xact->flags |= TRANSACTION_VIRTUAL; - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Parsed a virtual account name"); if (*b == '[') { xact->flags |= TRANSACTION_BALANCE; - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Parsed a balanced virtual account name"); } *account_path++ = '\0'; *e = '\0'; } - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Parsed account name " << account_path); if (account_aliases.size() > 0) { accounts_map::const_iterator i = account_aliases.find(account_path); @@ -202,9 +204,9 @@ transaction_t * parse_transaction(char * line, xact->amount_expr = string(line, beg, end - beg); } } - catch (error * err) { + catch (exception& err) { err_desc = "While parsing transaction amount:"; - throw err; + throw; } // Parse the optional cost (@ PER-UNIT-COST, @@ TOTAL-COST) @@ -212,14 +214,14 @@ transaction_t * parse_transaction(char * line, if (in.good() && ! in.eof()) { char c = peek_next_nonws(in); if (c == '@') { - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Found a price indicator"); bool per_unit = true; in.get(c); if (in.peek() == '@') { in.get(c); per_unit = false; - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "And it's for a total price"); } @@ -240,13 +242,13 @@ transaction_t * parse_transaction(char * line, xact->cost_expr = (string("@@") + string(amount, beg, end - beg)); } - catch (error * err) { + catch (exception& err) { err_desc = "While parsing transaction cost:"; - throw err; + throw; } if (*xact->cost < 0) - throw new parse_error("A transaction's cost may not be negative"); + throw_(parse_exception, "A transaction's cost may not be negative"); amount_t per_unit_cost(*xact->cost); if (per_unit) @@ -260,13 +262,13 @@ transaction_t * parse_transaction(char * line, xact->entry->actual_date(), xact->entry->code); - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Total cost is " << *xact->cost); - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Per-unit cost is " << per_unit_cost); - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Annotated amount is " << xact->amount); - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Bare amount is " << xact->amount.number()); } } @@ -274,7 +276,7 @@ transaction_t * parse_transaction(char * line, xact->amount.in_place_reduce(); - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Reduced amount is " << xact->amount); } @@ -282,7 +284,7 @@ transaction_t * parse_transaction(char * line, if (note) { xact->note = note; - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Parsed a note '" << xact->note << "'"); if (char * b = std::strchr(xact->note.c_str(), '[')) @@ -291,7 +293,7 @@ transaction_t * parse_transaction(char * line, std::strncpy(buf, b + 1, e - b - 1); buf[e - b - 1] = '\0'; - DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << + DEBUG_("ledger.textual.parse", "line " << linenum << ": " << "Parsed a transaction date " << buf); if (char * p = std::strchr(buf, '=')) { @@ -305,6 +307,7 @@ transaction_t * parse_transaction(char * line, return xact.release(); +#if 0 } catch (error * err) { err->context.push_back @@ -312,6 +315,7 @@ transaction_t * parse_transaction(char * line, err_desc : "While parsing transaction:")); throw err; } +#endif } bool parse_transactions(std::istream& in, @@ -345,13 +349,6 @@ bool parse_transactions(std::istream& in, return added; } -namespace { - TIMER_DEF(parsing_total, "total parsing time") - TIMER_DEF(entry_xacts, "parsing transactions") - TIMER_DEF(entry_details, "parsing entry details") - TIMER_DEF(entry_date, "parsing entry date") -} - entry_t * parse_entry(std::istream& in, char * line, journal_t * journal, account_t * master, textual_parser_t& /* parser */, unsigned long beg_pos) @@ -415,18 +412,18 @@ entry_t * parse_entry(std::istream& in, char * line, journal_t * journal, // Parse the date - TIMER_START(entry_date); + TRACE_START(entry_date, 2, "Parsing entry date"); curr->_date = parse_datetime(date); if (date_eff) curr->_date_eff = parse_datetime(date_eff); - TIMER_STOP(entry_date); + TRACE_STOP(entry_date, 2); // Parse the optional cleared flag: * - TIMER_START(entry_details); + TRACE_START(entry_details, 2, "Parsing entry details"); transaction_t::state_t state = transaction_t::UNCLEARED; if (statep) { @@ -450,11 +447,11 @@ entry_t * parse_entry(std::istream& in, char * line, journal_t * journal, assert(payee); curr->payee = *payee != '\0' ? payee : "<Unspecified payee>"; - TIMER_STOP(entry_details); + TRACE_STOP(entry_details, 2); // Parse all of the transactions associated with this entry - TIMER_START(entry_xacts); + TRACE_START(entry_xacts, 2, "Parsing entry transactions"); unsigned long end_pos; unsigned long beg_line = linenum; @@ -495,7 +492,7 @@ entry_t * parse_entry(std::istream& in, char * line, journal_t * journal, curr->data = NULL; } - TIMER_STOP(entry_xacts); + TRACE_STOP(entry_xacts, 2); return curr.release(); } @@ -513,7 +510,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_exception, "Quoted commodity symbol lacks closing quote"); symbol = string(p + 1, 0, q - p - 1); p = q + 2; } else { @@ -525,7 +522,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_exception, "Failed to parse commodity"); } bool textual_parser_t::test(std::istream& in) const @@ -535,9 +532,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_exception, "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_exception, "Ledger file contains XML data, but no XML support present"); #endif } @@ -559,11 +556,11 @@ static void clock_out_from_timelog(const moment_t& when, time_entries.clear(); } else if (time_entries.empty()) { - throw new parse_error("Timelog check-out event without a check-in"); + throw_(parse_exception, "Timelog check-out event without a check-in"); } else if (! account) { - throw new parse_error - ("When multiple check-ins are active, checking out requires an account"); + throw_(parse_exception, + "When multiple check-ins are active, checking out requires an account"); } else { bool found = false; @@ -579,8 +576,8 @@ static void clock_out_from_timelog(const moment_t& when, } if (! found) - throw new parse_error - ("Timelog check-out event does not match any current check-ins"); + throw_(parse_exception, + "Timelog check-out event does not match any current check-ins"); } if (desc && event.desc.empty()) { @@ -594,8 +591,8 @@ static void clock_out_from_timelog(const moment_t& when, curr->payee = event.desc; if (curr->_date < event.checkin) - throw new parse_error - ("Timelog check-out date less than corresponding check-in"); + throw_(parse_exception, + "Timelog check-out date less than corresponding check-in"); char buf[32]; std::sprintf(buf, "%lds", (long)(curr->_date - event.checkin).total_seconds()); @@ -608,7 +605,7 @@ static void clock_out_from_timelog(const moment_t& when, curr->add_transaction(xact); if (! journal->add_entry(curr.get())) - throw new parse_error("Failed to record 'out' timelog entry"); + throw_(parse_exception, "Failed to record 'out' timelog entry"); else curr.release(); } @@ -623,7 +620,7 @@ unsigned int textual_parser_t::parse(std::istream& in, unsigned int count = 0; unsigned int errors = 0; - TIMER_START(parsing_total); + TRACE_START(parsing_total, 2, "Parsing textual file"); std::list<account_t *> account_stack; @@ -643,7 +640,9 @@ unsigned int textual_parser_t::parse(std::istream& in, unsigned long beg_line = linenum; while (in.good() && ! in.eof()) { +#if 0 try { +#endif in.getline(line, MAX_LINE); if (in.eof()) break; @@ -659,7 +658,7 @@ unsigned int textual_parser_t::parse(std::istream& in, case '\t': { char * p = skip_ws(line); if (*p && *p != '\r') - throw new parse_error("Line begins with whitespace"); + throw_(parse_exception, "Line begins with whitespace"); break; } @@ -681,8 +680,8 @@ unsigned int textual_parser_t::parse(std::istream& in, i != time_entries.end(); i++) if (event.account == (*i).account) - throw new parse_error - ("Cannot double check-in to the same account"); + throw_(parse_exception, + "Cannot double check-in to the same account"); time_entries.push_back(event); break; @@ -691,7 +690,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_exception, "Timelog check-out event without a check-in"); } else { string date(line, 2, 19); @@ -776,7 +775,7 @@ unsigned int textual_parser_t::parse(std::istream& in, break; case '-': // option setting - throw new parse_error("Option settings are not allowed in journal files"); + throw_(parse_exception, "Option settings are not allowed in journal files"); case '=': { // automated entry if (! added_auto_entry_hook) { @@ -800,7 +799,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 '") + skip_ws(line + 1) + "'"); + throw_(parse_exception, string("Parsing time period '") + skip_ws(line + 1) + "'"); if (parse_transactions(in, journal, account_stack.front(), *pe, "period", end_pos)) { @@ -813,7 +812,7 @@ unsigned int textual_parser_t::parse(std::istream& in, pe->end_pos = end_pos; pe->end_line = linenum; } else { - throw new parse_error("Period entry failed to balance"); + throw_(parse_exception, "Period entry failed to balance"); } } break; @@ -840,7 +839,7 @@ unsigned int textual_parser_t::parse(std::istream& in, } path = resolve_path(path); - DEBUG_PRINT("ledger.textual.include", "line " << linenum << ": " << + DEBUG_("ledger.textual.include", "line " << linenum << ": " << "Including path '" << path << "'"); include_stack.push_back(std::pair<string, int> @@ -903,15 +902,16 @@ unsigned int textual_parser_t::parse(std::istream& in, count++; } else { delete entry; - throw new parse_error("Entry does not balance"); + throw_(parse_exception, "Entry does not balance"); } } else { - throw new parse_error("Failed to parse entry"); + throw_(parse_exception, "Failed to parse entry"); } end_pos = pos; break; } } +#if 0 } catch (error * err) { for (std::list<std::pair<string, int> >::reverse_iterator i = @@ -930,6 +930,7 @@ unsigned int textual_parser_t::parse(std::istream& in, delete err; errors++; } +#endif beg_pos = end_pos; } @@ -947,7 +948,7 @@ unsigned int textual_parser_t::parse(std::istream& in, if (errors > 0) throw (int)errors; - TIMER_STOP(parsing_total); + TRACE_STOP(parsing_total, 2); return count; } @@ -23,6 +23,7 @@ void write_textual_journal(journal_t& journal, string path, std::ostream& out); #endif +#if 0 class include_context : public file_context { public: include_context(const string& file, unsigned long line, @@ -36,6 +37,7 @@ class include_context : public file_context { out << "\"" << file << "\", line " << line << ":" << std::endl; } }; +#endif } // namespace ledger @@ -46,4 +46,4 @@ moment_t datetime_range_from_stream(std::istream& in) { } -} +} // namespace ledger @@ -36,11 +36,7 @@ inline bool is_valid_moment(const moment_t& moment) { extern moment_t& now; -class datetime_error : public error { - public: - datetime_error(const string& _reason) throw() : error(_reason) {} - virtual ~datetime_error() throw() {} -}; +DECLARE_EXCEPTION(datetime_exception); class interval_t { @@ -86,6 +82,7 @@ extern ptime time_now; extern date date_now; extern bool day_before_month; +#if 0 struct intorchar { int ival; @@ -97,8 +94,9 @@ struct intorchar intorchar(const intorchar& o) : ival(o.ival), sval(o.sval) {} }; -} - ledger::moment_t parse_abs_datetime(std::istream& input); +#endif + +} // namespace ledger -#endif /* _TIMES_H */ +#endif // _TIMES_H diff --git a/util.cc b/util.cc deleted file mode 100644 index 09d35b2f..00000000 --- a/util.cc +++ /dev/null @@ -1,146 +0,0 @@ -#include "utils.h" - -namespace ledger { - -string expand_path(const string& path) -{ - if (path.length() == 0 || path[0] != '~') - return path; - - const char * pfx = NULL; - string::size_type pos = path.find_first_of('/'); - - if (path.length() == 1 || pos == 1) { - pfx = std::getenv("HOME"); -#ifdef HAVE_GETPWUID - if (! pfx) { - // Punt. We're trying to expand ~/, but HOME isn't set - struct passwd * pw = getpwuid(getuid()); - if (pw) - pfx = pw->pw_dir; - } -#endif - } -#ifdef HAVE_GETPWNAM - else { - string user(path, 1, pos == string::npos ? - string::npos : pos - 1); - struct passwd * pw = getpwnam(user.c_str()); - if (pw) - pfx = pw->pw_dir; - } -#endif - - // if we failed to find an expansion, return the path unchanged. - - if (! pfx) - return path; - - string result(pfx); - - if (pos == string::npos) - return result; - - if (result.length() == 0 || result[result.length() - 1] != '/') - result += '/'; - - result += path.substr(pos + 1); - - return result; -} - -string resolve_path(const string& path) -{ - if (path[0] == '~') - return expand_path(path); - return path; -} - -string abbreviate(const string& str, unsigned int width, - elision_style_t elision_style, const bool is_account, - int abbrev_length) -{ - const unsigned int len = str.length(); - if (len <= width) - return str; - - assert(width < 4095); - - static char buf[4096]; - - switch (elision_style) { - case TRUNCATE_LEADING: - // This method truncates at the beginning. - std::strncpy(buf, str.c_str() + (len - width), width); - buf[0] = '.'; - buf[1] = '.'; - break; - - case TRUNCATE_MIDDLE: - // This method truncates in the middle. - std::strncpy(buf, str.c_str(), width / 2); - std::strncpy(buf + width / 2, - str.c_str() + (len - (width / 2 + width % 2)), - width / 2 + width % 2); - buf[width / 2 - 1] = '.'; - buf[width / 2] = '.'; - break; - - case ABBREVIATE: - if (is_account) { - std::list<string> parts; - string::size_type beg = 0; - for (string::size_type pos = str.find(':'); - pos != string::npos; - beg = pos + 1, pos = str.find(':', beg)) - parts.push_back(string(str, beg, pos - beg)); - parts.push_back(string(str, beg)); - - string result; - unsigned int newlen = len; - for (std::list<string>::iterator i = parts.begin(); - i != parts.end(); - i++) { - // Don't contract the last element - std::list<string>::iterator x = i; - if (++x == parts.end()) { - result += *i; - break; - } - - if (newlen > width) { - result += string(*i, 0, abbrev_length); - result += ":"; - newlen -= (*i).length() - abbrev_length; - } else { - result += *i; - result += ":"; - } - } - - if (newlen > width) { - // Even abbreviated its too big to show the last account, so - // abbreviate all but the last and truncate at the beginning. - std::strncpy(buf, result.c_str() + (result.length() - width), width); - buf[0] = '.'; - buf[1] = '.'; - } else { - std::strcpy(buf, result.c_str()); - } - break; - } - // fall through... - - case TRUNCATE_TRAILING: - // This method truncates at the end (the default). - std::strncpy(buf, str.c_str(), width - 2); - buf[width - 2] = '.'; - buf[width - 1] = '.'; - break; - } - buf[width] = '\0'; - - return buf; -} - -} // namespace ledger diff --git a/util.h b/util.h deleted file mode 100644 index 5965a5ed..00000000 --- a/util.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef _UTIL_H -#define _UTIL_H - -namespace ledger { - -inline char * skip_ws(char * ptr) { - while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') - ptr++; - return ptr; -} - -inline char peek_next_nonws(std::istream& in) { - char c = in.peek(); - while (! in.eof() && std::isspace(c)) { - in.get(c); - c = in.peek(); - } - return c; -} - -#define READ_INTO(str, targ, size, var, cond) { \ - char * _p = targ; \ - var = str.peek(); \ - while (! str.eof() && var != '\n' && (cond) && _p - targ < size) { \ - str.get(var); \ - if (str.eof()) \ - break; \ - if (var == '\\') { \ - str.get(var); \ - if (in.eof()) \ - break; \ - } \ - *_p++ = var; \ - var = str.peek(); \ - } \ - *_p = '\0'; \ -} - -#define READ_INTO_(str, targ, size, var, idx, cond) { \ - char * _p = targ; \ - var = str.peek(); \ - while (! str.eof() && var != '\n' && (cond) && _p - targ < size) { \ - str.get(var); \ - if (str.eof()) \ - break; \ - idx++; \ - if (var == '\\') { \ - str.get(var); \ - if (in.eof()) \ - break; \ - idx++; \ - } \ - *_p++ = var; \ - var = str.peek(); \ - } \ - *_p = '\0'; \ -} - -ledger::string resolve_path(const ledger::string& path); - -#ifdef HAVE_REALPATH -extern "C" char *realpath(const char *, char resolved_path[]); -#endif - -enum elision_style_t { - TRUNCATE_TRAILING, - TRUNCATE_MIDDLE, - TRUNCATE_LEADING, - ABBREVIATE -}; - -ledger::string abbreviate(const ledger::string& str, unsigned int width, - elision_style_t elision_style = TRUNCATE_TRAILING, - const bool is_account = false, int abbrev_length = 2); - -static inline const -ledger::string& either_or(const ledger::string& first, - const ledger::string& second) -{ - if (first.empty()) - return second; - else - return first; -} - -} // namespace ledger - -#endif // _UTIL_H @@ -1,10 +1,14 @@ #include "utils.h" -#include "times.h" -namespace ledger +/********************************************************************** + * + * Assertions + */ #if defined(ASSERTS_ON) +namespace ledger { + void debug_assert(const string& reason, const string& func, const string& file, @@ -16,35 +20,50 @@ void debug_assert(const string& reason, throw exception(buf.str(), context()); } +} // namespace ledger + #endif +/********************************************************************** + * + * Verification (basically, very slow asserts) + */ + #if defined(VERIFY_ON) -int new_calls = 0; -unsigned long new_size = 0; +namespace ledger { +#if defined(FULL_DEBUG) + bool verify_enabled = true; +#else + bool verify_enabled = false; +#endif + + int new_calls = 0; + unsigned long new_size = 0; +} void * operator new(std::size_t size) throw (std::bad_alloc) { void * ptr = std::malloc(size); - new_calls++; - new_size += size; + ledger::new_calls++; + ledger::new_size += size; return ptr; } void * operator new[](std::size_t size) throw (std::bad_alloc) { void * ptr = std::malloc(size); - new_calls++; - new_size += size; + ledger::new_calls++; + ledger::new_size += size; return ptr; } void * operator new(std::size_t size, const std::nothrow_t&) throw() { void * ptr = std::malloc(size); - new_calls++; - new_size += size; + ledger::new_calls++; + ledger::new_size += size; return ptr; } void * operator new[](std::size_t size, const std::nothrow_t&) throw() { void * ptr = std::malloc(size); - new_calls++; - new_size += size; + ledger::new_calls++; + ledger::new_size += size; return ptr; } void operator delete(void * ptr) throw() { @@ -60,6 +79,8 @@ void operator delete[](void * ptr, const std::nothrow_t&) throw() { std::free(ptr); } +namespace ledger { + live_objects_map live_objects; object_count_map ctor_count; object_count_map object_count; @@ -99,8 +120,7 @@ bool trace_ctor_func(void * ptr, const char * cls_name, const char * args, std::strcat(name, args); std::strcat(name, ")"); - DEBUG_PRINT("ledger.trace.debug", - "trace_ctor " << ptr << " " << name); + DEBUG_("ledger.trace.debug", "TRACE_CTOR " << ptr << " " << name); live_objects.insert(live_objects_pair(ptr, cls_name)); @@ -114,7 +134,7 @@ bool trace_ctor_func(void * ptr, const char * cls_name, const char * args, bool trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size) { - DEBUG_PRINT("ledger.trace.debug", "trace_dtor " << ptr << " " << cls_name); + DEBUG_("ledger.trace.debug", "TRACE_DTOR " << ptr << " " << cls_name); live_objects_map::iterator i = live_objects.find(ptr); if (i == live_objects.end()) { @@ -179,103 +199,177 @@ void report_memory(std::ostream& out) #if ! defined(USE_BOOST_PYTHON) string::string() : std::string() { - trace_ctor(string, ""); + TRACE_CTOR(string, ""); } string::string(const string& str) : std::string(str) { - trace_ctor(string, "const string&"); + TRACE_CTOR(string, "const string&"); } string::string(const std::string& str) : std::string(str) { - trace_ctor(string, "const std::string&"); + TRACE_CTOR(string, "const std::string&"); } string::string(const int len, char x) : std::string(len, x) { - trace_ctor(string, "const int, char"); + TRACE_CTOR(string, "const int, char"); } string::string(const char * str) : std::string(str) { - trace_ctor(string, "const char *"); + TRACE_CTOR(string, "const char *"); } string::string(const char * str, const char * end) : std::string(str, end) { - trace_ctor(string, "const char *, const char *"); + TRACE_CTOR(string, "const char *, const char *"); } string::string(const string& str, int x) : std::string(str, x) { - trace_ctor(string, "const string&, int"); + TRACE_CTOR(string, "const string&, int"); } string::string(const string& str, int x, int y) : std::string(str, x, y) { - trace_ctor(string, "const string&, int, int"); + TRACE_CTOR(string, "const string&, int, int"); } string::string(const char * str, int x) : std::string(str, x) { - trace_ctor(string, "const char *, int"); + TRACE_CTOR(string, "const char *, int"); } string::string(const char * str, int x, int y) : std::string(str, x, y) { - trace_ctor(string, "const char *, int, int"); + TRACE_CTOR(string, "const char *, int, int"); } string::~string() { - trace_dtor(string); + TRACE_DTOR(string); } #endif +} // namespace ledger + #endif // VERIFY_ON -#if defined(TIMERS_ON) +/********************************************************************** + * + * Logging + */ + +#if defined(LOGGING_ON) && defined(DEBUG_ON) + +#include <boost/regex.hpp> + +namespace ledger { + +log_level_t _log_level; +unsigned int _trace_level; +std::string _log_category; +std::ostream * _log_stream = &std::cerr; +std::ostringstream _log_buffer; + +bool logger_func(log_level_t level) +{ + _log_buffer.str(""); +} + +} // namespace ledger + +#endif // LOGGING_ON && DEBUG_ON + +/********************************************************************** + * + * Timers (allows log entries to specify cumulative time spent) + */ + +#if defined(LOGGING_ON) && defined(TIMERS_ON) + +namespace ledger { void start_timer(const char * name) { +#if 0 begin = std::clock(); +#endif } void stop_timer(const char * name) { +#if 0 cumulative += std::clock() - begin; +#endif } void finish_timer(const char * name) { - DEBUG_PRINT(cls.c_str(), file << ":" << line << ": " - << category << " = " - << (double(cumulative) / double(CLOCKS_PER_SEC)) << "s"); +#if 0 + DEBUG_(cls.c_str(), file << ":" << line << ": " + << category << " = " + << (double(cumulative) / double(CLOCKS_PER_SEC)) << "s"); +#endif } -#endif // TIMERS_ON +} // namespace ledger + +#endif // LOGGING_ON && TIMERS_ON -#if defined(LOGGING_ON) && defined(DEBUG_ON) +/********************************************************************** + * + * Exception handling + */ + +namespace ledger { + +std::ostringstream _exc_buffer; + +} // namespace ledger + +/********************************************************************** + * + * General utility functions + */ -std::ostream * _debug_stream = &std::cerr; -bool _free_debug_stream = false; -boost::regex _debug_regex; -bool _set_debug_regex = false; -bool _debug_regex_on = false; - -bool _debug_active(const char * const cls) { - if (! _set_debug_regex) { - const char * user_class = std::getenv("DEBUG_CLASS"); - if (user_class) { - _debug_regex = user_class; - _debug_regex_on = true; +namespace ledger { + +string expand_path(const string& path) +{ + if (path.length() == 0 || path[0] != '~') + return path; + + const char * pfx = NULL; + string::size_type pos = path.find_first_of('/'); + + if (path.length() == 1 || pos == 1) { + pfx = std::getenv("HOME"); +#ifdef HAVE_GETPWUID + if (! pfx) { + // Punt. We're trying to expand ~/, but HOME isn't set + struct passwd * pw = getpwuid(getuid()); + if (pw) + pfx = pw->pw_dir; } - _set_debug_regex = true; +#endif } - if (_debug_regex_on) - return boost::regex_match(cls, _debug_regex); - return false; -} - -static struct init_streams { - init_streams() { - // If debugging is enabled and DEBUG_FILE is set, all debugging - // output goes to that file. - if (const char * p = std::getenv("DEBUG_FILE")) { - _debug_stream = new std::ofstream(p); - _free_debug_stream = true; - } +#ifdef HAVE_GETPWNAM + else { + string user(path, 1, pos == string::npos ? + string::npos : pos - 1); + struct passwd * pw = getpwnam(user.c_str()); + if (pw) + pfx = pw->pw_dir; } - ~init_streams() { - if (_free_debug_stream && _debug_stream) { - delete _debug_stream; - _debug_stream = NULL; - } - } -} _debug_init; +#endif -#endif // LOGGING_ON && DEBUG_ON + // if we failed to find an expansion, return the path unchanged. + + if (! pfx) + return path; + + string result(pfx); + + if (pos == string::npos) + return result; + + if (result.length() == 0 || result[result.length() - 1] != '/') + result += '/'; + + result += path.substr(pos + 1); + + return result; +} + +string resolve_path(const string& path) +{ + if (path[0] == '~') + return expand_path(path); + return path; +} } // namespace ledger @@ -3,7 +3,18 @@ #include <system.hh> +/********************************************************************** + * + * Forward declarations + */ + namespace ledger { +#if ! defined(USE_BOOST_PYTHON) + class string; +#else + typedef std::string string; +#endif +} /********************************************************************** * @@ -11,15 +22,17 @@ namespace ledger { */ #if defined(FULL_DEBUG) -#define VERIFY_ON 1 -#define TRACING_ON 1 -#define DEBUG_ON 1 -#define TIMERS_ON 1 +#define VERIFY_ON 1 +#define TRACING_ON 1 +#define DEBUG_ON 1 +#define TIMERS_ON 1 +#define FREE_MEMORY 1 #elif defined(NO_DEBUG) -#define NO_ASSERTS 1 -#define NO_LOGGING 1 +#define NO_ASSERTS 1 +#define NO_LOGGING 1 #else -#define TIMERS_ON 1 // jww (2007-04-25): is this correct? +#define VERIFY_ON 1 // compiled in, use --verify to enable +#define TIMERS_ON 1 // jww (2007-04-25): is this correct? #endif /********************************************************************** @@ -38,14 +51,14 @@ namespace ledger { #include <boost/current_function.hpp> -void debug_assert(const ledger::string& reason, - const ledger::string& func, - const ledger::string& file, - unsigned long line); +namespace ledger { + void debug_assert(const string& reason, const string& func, + const string& file, unsigned long line); +} #define assert(x) \ ((x) ? ((void)0) : debug_assert(#x, BOOST_CURRENT_FUNCTION, \ - __FILE__, __LINE__) + __FILE__, __LINE__)) #endif // ASSERTS_ON @@ -56,22 +69,15 @@ void debug_assert(const ledger::string& reason, #if defined(VERIFY_ON) +namespace ledger { + extern bool verify_enabled; -#define verify(x) (verify_enabled ? assert(x) : ((void)0)) +#define VERIFY(x) (verify_enabled ? assert(x) : ((void)0)) extern int new_calls; extern unsigned long new_size; -void * operator new(std::size_t) throw(std::bad_alloc); -void * operator new[](std::size_t) throw(std::bad_alloc); -void operator delete(void*) throw(); -void operator delete[](void*) throw(); -void * operator new(std::size_t, const std::nothrow_t&) throw(); -void * operator new[](std::size_t, const std::nothrow_t&) throw(); -void operator delete(void*, const std::nothrow_t&) throw(); -void operator delete[](void*, const std::nothrow_t&) throw(); - typedef std::multimap<void *, std::string> live_objects_map; typedef std::pair<void *, std::string> live_objects_pair; typedef std::pair<unsigned int, std::size_t> count_size_pair; @@ -87,10 +93,10 @@ bool trace_ctor_func(void * ptr, const char * cls_name, const char * args, std::size_t cls_size); bool trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size); -#define trace_ctor(cls, args) \ - verify(trace_ctor_func(this, #cls, args, sizeof(cls))) -#define trace_dtor(cls) \ - verify(trace_dtor_func(this, #cls, sizeof(cls))) +#define TRACE_CTOR(cls, args) \ + VERIFY(trace_ctor_func(this, #cls, args, sizeof(cls))) +#define TRACE_DTOR(cls) \ + VERIFY(trace_dtor_func(this, #cls, sizeof(cls))) void report_memory(std::ostream& out); @@ -158,11 +164,13 @@ inline bool operator!=(const string& __lhs, const char* __rhs) #endif +} // namespace ledger + #else // ! VERIFY_ON -#define verify(x) -#define trace_ctor(cls, args) -#define trace_dtor(cls) +#define VERIFY(x) +#define TRACE_CTOR(cls, args) +#define TRACE_DTOR(cls) #endif // VERIFY_ON @@ -176,7 +184,7 @@ inline bool operator!=(const string& __lhs, const char* __rhs) #endif #if defined(LOGGING_ON) -// Logging +namespace ledger { enum log_level_t { LOG_OFF = 0, @@ -199,65 +207,99 @@ extern std::string _log_category; extern std::ostream * _log_stream; extern std::ostringstream _log_buffer; -#define category(cat) \ - static const char * const _this_category = (cat) +bool logger_func(log_level_t level); + +#define logger(cat) \ + static const char * const _this_category = cat + +#define SHOW_TRACE(lvl) \ + (_log_level >= LOG_TRACE && lvl >= _trace_level) + +#define SHOW_DEBUG_(cat) \ + (_log_level >= LOG_DEBUG && \ + (_log_category == cat || \ + _log_category.find(string(cat) + ".") == 0)) +#define SHOW_DEBUG() SHOW_DEBUG_(_this_category) + +#define SHOW_INFO_(cat) \ + (_log_level >= LOG_INFO && \ + (_log_category == cat || \ + _log_category.find(string(cat) + ".") == 0)) +#define SHOW_INFO() SHOW_INFO_(_this_category) -bool logger(log_level_t level); +#define SHOW_WARN() (_log_level >= LOG_WARN) +#define SHOW_ERROR() (_log_level >= LOG_ERROR) +#define SHOW_FATAL() (_log_level >= LOG_FATAL) +#define SHOW_CRITICAL() (_log_level >= LOG_CRIT) #if defined(TRACING_ON) -#define trace(lvl, msg) \ - (_log_level >= LOG_TRACE && lvl >= _trace_level ? \ - ((_log_buffer << msg), logger(LOG_TRACE)) : false) +#define TRACE(lvl, msg) \ + (SHOW_TRACE(lvl) ? ((_log_buffer << msg), logger_func(LOG_TRACE)) : false) #else -#define trace(lvl, msg) +#define TRACE(lvl, msg) #endif #if defined(DEBUG_ON) -#define debug_(cat, msg) \ - (_log_level >= LOG_DEBUG && \ - (_log_category == cat || \ - _log_category.find(cat ".") == 0) ? \ - ((_log_buffer << msg), logger(LOG_DEBUG)) : false) -#define debug(msg) debug_(_this_category, msg) +#define DEBUG_(cat, msg) \ + (SHOW_DEBUG_(cat) ? ((_log_buffer << msg), logger_func(LOG_DEBUG)) : false) +#define DEBUG(msg) DEBUG_(_this_category, msg) #else -#define debug_(cat, msg) -#define debug(msg) +#define DEBUG_(cat, msg) +#define DEBUG(msg) #endif -#define exception_occurred(msg) \ - log_macro(LOG_EXCEPT, msg) +#define INFO_(cat, msg) \ + (SHOW_INFO(cat) ? ((_log_buffer << msg), logger_func(LOG_INFO)) : false) +#define INFO(msg) INFO_(_this_category, msg) -#define info_(cat, msg) \ - (_log_level >= LOG_INFO && \ - (_log_category == cat || \ - _log_category.find(cat ".") == 0) ? \ - ((_log_buffer << msg), logger(LOG_INFO)) : false) -#define info(msg) info_(_this_category, msg) - -#define log_macro(level, msg) \ +#define LOG_MACRO(level, msg) \ (_log_level >= level ? \ - ((_log_buffer << msg), logger(level)) : false) + ((_log_buffer << msg), logger_func(level)) : false) + +#define WARN(msg) LOG_MACRO(LOG_WARN, msg) +#define ERROR(msg) LOG_MACRO(LOG_ERROR, msg) +#define FATAL(msg) LOG_MACRO(LOG_FATAL, msg) +#define CRITICAL(msg) LOG_MACRO(LOG_CRIT, msg) +#define EXCEPTION(msg) LOG_MACRO(LOG_EXCEPT, msg) -#define warn(msg) log_macro(LOG_WARN, msg) -#define error(msg) log_macro(LOG_ERROR, msg) -#define fatal(msg) log_macro(LOG_FATAL, msg) -#define critical(msg) log_macro(LOG_CRIT, msg) +} // namespace ledger #else // ! LOGGING_ON -#define category(cat) -#define trace(lvl, msg) -#define debug(msg) -#define debug_(cat, msg) -#define info(msg) -#define info_(cat, msg) -#define warn(msg) -#define error(msg) -#define fatal(msg) -#define critical(msg) +#define logger(cat) + +#define SHOW_TRACE(lvl) false +#define SHOW_DEBUG_(cat) false +#define SHOW_DEBUG() false +#define SHOW_INFO_(cat) false +#define SHOW_INFO() false +#define SHOW_WARN() false +#define SHOW_ERROR() false +#define SHOW_FATAL() false +#define SHOW_CRITICAL() false + +#define TRACE(lvl, msg) +#define DEBUG(msg) +#define DEBUG_(cat, msg) +#define INFO(msg) +#define INFO_(cat, msg) +#define WARN(msg) +#define ERROR(msg) +#define FATAL(msg) +#define CRITICAL(msg) #endif // LOGGING_ON +#define IF_TRACE(lvl) if (SHOW_TRACE(lvl)) +#define IF_DEBUG_(cat) if (SHOW_DEBUG_(cat)) +#define IF_DEBUG() if (SHOW_DEBUG()) +#define IF_INFO_(cat) if (SHOW_INFO_(cat)) +#define IF_INFO() if (SHOW_INFO()) +#define IF_WARN() if (SHOW_WARN()) +#define IF_ERROR() if (SHOW_ERROR()) +#define IF_FATAL() if (SHOW_FATAL()) +#define IF_CRITICAL() if (SHOW_CRITICAL()) + /********************************************************************** * * Timers (allows log entries to specify cumulative time spent) @@ -265,6 +307,8 @@ bool logger(log_level_t level); #if defined(LOGGING_ON) && defined(TIMERS_ON) +namespace ledger { + struct timer_t { std::clock_t count; std::string message; @@ -278,46 +322,63 @@ void stop_timer(const char * name); void finish_timer(const char * name); #if defined(TRACING_ON) -#define trace_start(name, lvl, msg) \ - (trace(lvl, msg) && start_timer(name)) -#define trace_stop(name) stop_timer(name) -#define trace_finish(name) finish_timer(name) +#define TRACE_START(name, lvl, msg) \ + (TRACE(lvl, msg) ? start_timer(#name) : ((void)0)) +#define TRACE_STOP(name, lvl) \ + (SHOW_TRACE(lvl) ? stop_timer(#name) : ((void)0)) +#define TRACE_FINISH(name, lvl) \ + (SHOW_TRACE(lvl) ? finish_timer(#name) : ((void)0)) #else -#define trace_start(name, lvl, msg) -#define trace_stop(name) -#define trace_finish(name) +#define TRACE_START(name, lvl, msg) +#define TRACE_STOP(name) +#define TRACE_FINISH(name) #endif #if defined(DEBUG_ON) -#define debug_start(name, msg) \ - (debug(msg) && start_timer(name)) -#define debug_start_(name, cat, msg) \ - (debug_(cat, msg) && start_timer(name)) -#define debug_stop(name) stop_timer(name) -#define debug_finish(name) finish_timer(name) +#define DEBUG_START_(name, cat, msg) \ + (DEBUG_(cat, msg) ? start_timer(#name) : ((void)0)) +#define DEBUG_START(name, msg) \ + DEBUG_START_(name, _this_category, msg) +#define DEBUG_STOP_(name, cat) \ + (SHOW_DEBUG_(cat) ? stop_timer(#name) : ((void)0)) +#define DEBUG_STOP(name) \ + DEBUG_STOP_(name, _this_category) +#define DEBUG_FINISH_(name, cat) \ + (SHOW_DEBUG_(cat) ? finish_timer(#name) : ((void)0)) +#define DEBUG_FINISH(name) \ + DEBUG_FINISH_(name, _this_category) #else -#define debug_start(name, msg) -#define debug_start_(name, cat, msg) -#define debug_stop(name) -#define debug_finish(name) +#define DEBUG_START(name, msg) +#define DEBUG_START_(name, cat, msg) +#define DEBUG_STOP(name) +#define DEBUG_FINISH(name) #endif -#define info_start(name, msg) \ - (info(msg) && start_timer(name)) -#define info_start_(name, cat, msg) -#define info_stop(name) stop_timer(name) -#define info_finish(name) finish_timer(name) +#define info_start_(name, cat, msg) \ + (info_(cat, msg) && start_timer(#name)) +#define info_start(name, msg) \ + info_start_(name, _this_category, msg) +#define info_stop_(name, cat) \ + (show_info_(cat) ? stop_timer(#name) : ((void)0)) +#define info_stop(name) \ + info_stop_(name, _this_category) +#define info_finish_(name, cat) \ + (show_info_(cat) ? finish_timer(#name) : ((void)0)) +#define info_finish(name) \ + info_finish_(name, _this_category) + +} // namespace ledger #else // ! (LOGGING_ON && TIMERS_ON) -#define trace_start(lvl, msg, name) -#define trace_stop(name) -#define trace_finish(name) +#define TRACE_START(lvl, msg, name) +#define TRACE_STOP(name) +#define TRACE_FINISH(name) -#define debug_start(name, msg) -#define debug_start_(name, cat, msg) -#define debug_stop(name) -#define debug_finish(name) +#define DEBUG_START(name, msg) +#define DEBUG_START_(name, cat, msg) +#define DEBUG_STOP(name) +#define DEBUG_FINISH(name) #define info_start(name, msg) #define info_start_(name, cat, msg) @@ -328,30 +389,44 @@ void finish_timer(const char * name); /********************************************************************** * - * Debug macros + * Exception handling */ -#if defined(DEBUG_ON) +#include "error.h" -#define if_debug_(cat) \ - if (_log_level >= LOG_DEBUG && \ - (_log_category == cat || \ - _log_category.find(cat ".") == 0)) -#define if_debug() if_debug_(_this_category) - -#else // ! DEBUG_ON +namespace ledger { -#define if_debug(cat) if (false) +extern std::ostringstream _exc_buffer; -#endif // DEBUG_ON +template <typename T> +inline void throw_func(const std::string& message) { + _exc_buffer.str(""); + throw T(message, context()); +} + +#define throw_(cls, msg) \ + ((_exc_buffer << msg), throw_func<cls>(_exc_buffer.str())) + +} // namespace ledger /********************************************************************** * - * Exception handling + * General utility functions */ -#import "error.h" +namespace ledger { + +string resolve_path(const string& path); + +#ifdef HAVE_REALPATH +extern "C" char * realpath(const char *, char resolved_path[]); +#endif + +inline const string& either_or(const string& first, + const string& second) { + return first.empty() ? second : first; +} -// } namespace ledger +} // namespace ledger #endif // _UTILS_H @@ -85,7 +85,7 @@ xml::node_t * value_t::to_xml_node() const if (type == XML_NODE) return *(xml::node_t **) data; else - throw new value_error("Value is not an XML node"); + throw_(value_exception, "Value is not an XML node"); } void * value_t::to_pointer() const @@ -93,7 +93,7 @@ void * value_t::to_pointer() const if (type == POINTER) return *(void **) data; else - throw new value_error("Value is not a pointer"); + throw_(value_exception, "Value is not a pointer"); } value_t::sequence_t * value_t::to_sequence() const @@ -101,7 +101,7 @@ value_t::sequence_t * value_t::to_sequence() const if (type == SEQUENCE) return *(sequence_t **) data; else - throw new value_error("Value is not a sequence"); + throw_(value_exception, "Value is not a sequence"); } void value_t::destroy() @@ -130,7 +130,7 @@ void value_t::destroy() void value_t::simplify() { if (realzero()) { - DEBUG_PRINT("amounts.values.simplify", "Zeroing type " << type); + DEBUG_("amounts.values.simplify", "Zeroing type " << type); *this = 0L; return; } @@ -138,19 +138,19 @@ void value_t::simplify() if (type == BALANCE_PAIR && (! ((balance_pair_t *) data)->cost || ((balance_pair_t *) data)->cost->realzero())) { - DEBUG_PRINT("amounts.values.simplify", "Reducing balance pair to balance"); + DEBUG_("amounts.values.simplify", "Reducing balance pair to balance"); in_place_cast(BALANCE); } if (type == BALANCE && ((balance_t *) data)->amounts.size() == 1) { - DEBUG_PRINT("amounts.values.simplify", "Reducing balance to amount"); + DEBUG_("amounts.values.simplify", "Reducing balance to amount"); in_place_cast(AMOUNT); } if (type == AMOUNT && ! ((amount_t *) data)->commodity()) { - DEBUG_PRINT("amounts.values.simplify", "Reducing amount to integer"); + DEBUG_("amounts.values.simplify", "Reducing amount to integer"); in_place_cast(INTEGER); } } @@ -249,19 +249,19 @@ value_t& value_t::operator=(const value_t& val) value_t& value_t::operator+=(const value_t& val) { if (val.type == BOOLEAN) - throw new value_error("Cannot add a boolean to a value"); + throw_(value_exception, "Cannot add a boolean to a value"); else if (val.type == DATETIME) - throw new value_error("Cannot add a date/time to a value"); + throw_(value_exception, "Cannot add a date/time to a value"); else if (val.type == POINTER) - throw new value_error("Cannot add a pointer to a value"); + throw_(value_exception, "Cannot add a pointer to a value"); else if (val.type == SEQUENCE) - throw new value_error("Cannot add a sequence to a value"); + throw_(value_exception, "Cannot add a sequence to a value"); else if (val.type == XML_NODE) // recurse return *this += (*(xml::node_t **) val.data)->to_value(); switch (type) { case BOOLEAN: - throw new value_error("Cannot add a value to a boolean"); + throw_(value_exception, "Cannot add a value to a boolean"); case INTEGER: switch (val.type) { @@ -281,7 +281,7 @@ value_t& value_t::operator+=(const value_t& val) *((balance_pair_t *) data) += *((balance_pair_t *) val.data); break; case STRING: - throw new value_error("Cannot add a string to an integer"); + throw_(value_exception, "Cannot add a string to an integer"); default: assert(0); break; @@ -303,7 +303,7 @@ value_t& value_t::operator+=(const value_t& val) *((moment_t *) data) += date_duration(long(*((balance_pair_t *) val.data))); break; case STRING: - throw new value_error("Cannot add a string to an date/time"); + throw_(value_exception, "Cannot add a string to an date/time"); default: assert(0); break; @@ -341,7 +341,7 @@ value_t& value_t::operator+=(const value_t& val) break; case STRING: - throw new value_error("Cannot add a string to an amount"); + throw_(value_exception, "Cannot add a string to an amount"); default: assert(0); @@ -365,7 +365,7 @@ value_t& value_t::operator+=(const value_t& val) *((balance_pair_t *) data) += *((balance_pair_t *) val.data); break; case STRING: - throw new value_error("Cannot add a string to an balance"); + throw_(value_exception, "Cannot add a string to an balance"); default: assert(0); break; @@ -387,7 +387,7 @@ value_t& value_t::operator+=(const value_t& val) *((balance_pair_t *) data) += *((balance_pair_t *) val.data); break; case STRING: - throw new value_error("Cannot add a string to an balance pair"); + throw_(value_exception, "Cannot add a string to an balance pair"); default: assert(0); break; @@ -397,13 +397,13 @@ value_t& value_t::operator+=(const value_t& val) case STRING: switch (val.type) { case INTEGER: - throw new value_error("Cannot add an integer to a string"); + throw_(value_exception, "Cannot add an integer to a string"); case AMOUNT: - throw new value_error("Cannot add an amount to a string"); + throw_(value_exception, "Cannot add an amount to a string"); case BALANCE: - throw new value_error("Cannot add a balance to a string"); + throw_(value_exception, "Cannot add a balance to a string"); case BALANCE_PAIR: - throw new value_error("Cannot add a balance pair to a string"); + throw_(value_exception, "Cannot add a balance pair to a string"); case STRING: **(string **) data += **(string **) val.data; break; @@ -414,13 +414,13 @@ value_t& value_t::operator+=(const value_t& val) break; case XML_NODE: - throw new value_error("Cannot add a value to an XML node"); + throw_(value_exception, "Cannot add a value to an XML node"); case POINTER: - throw new value_error("Cannot add a value to a pointer"); + throw_(value_exception, "Cannot add a value to a pointer"); case SEQUENCE: - throw new value_error("Cannot add a value to a sequence"); + throw_(value_exception, "Cannot add a value to a sequence"); default: assert(0); @@ -432,21 +432,21 @@ value_t& value_t::operator+=(const value_t& val) value_t& value_t::operator-=(const value_t& val) { if (val.type == BOOLEAN) - throw new value_error("Cannot subtract a boolean from a value"); + throw_(value_exception, "Cannot subtract a boolean from a value"); else if (val.type == DATETIME && type != DATETIME) - throw new value_error("Cannot subtract a date/time from a value"); + throw_(value_exception, "Cannot subtract a date/time from a value"); else if (val.type == STRING) - throw new value_error("Cannot subtract a string from a value"); + throw_(value_exception, "Cannot subtract a string from a value"); else if (val.type == POINTER) - throw new value_error("Cannot subtract a pointer from a value"); + throw_(value_exception, "Cannot subtract a pointer from a value"); else if (val.type == SEQUENCE) - throw new value_error("Cannot subtract a sequence from a value"); + throw_(value_exception, "Cannot subtract a sequence from a value"); else if (val.type == XML_NODE) // recurse return *this -= (*(xml::node_t **) val.data)->to_value(); switch (type) { case BOOLEAN: - throw new value_error("Cannot subtract a value from a boolean"); + throw_(value_exception, "Cannot subtract a value from a boolean"); case INTEGER: switch (val.type) { @@ -575,13 +575,13 @@ value_t& value_t::operator-=(const value_t& val) break; case STRING: - throw new value_error("Cannot subtract a value from a string"); + throw_(value_exception, "Cannot subtract a value from a string"); case XML_NODE: - throw new value_error("Cannot subtract a value from an XML node"); + throw_(value_exception, "Cannot subtract a value from an XML node"); case POINTER: - throw new value_error("Cannot subtract a value from a pointer"); + throw_(value_exception, "Cannot subtract a value from a pointer"); case SEQUENCE: - throw new value_error("Cannot subtract a value from a sequence"); + throw_(value_exception, "Cannot subtract a value from a sequence"); default: assert(0); @@ -596,15 +596,15 @@ value_t& value_t::operator-=(const value_t& val) value_t& value_t::operator*=(const value_t& val) { if (val.type == BOOLEAN) - throw new value_error("Cannot multiply a value by a boolean"); + throw_(value_exception, "Cannot multiply a value by a boolean"); else if (val.type == DATETIME) - throw new value_error("Cannot multiply a value by a date/time"); + throw_(value_exception, "Cannot multiply a value by a date/time"); else if (val.type == STRING) - throw new value_error("Cannot multiply a value by a string"); + throw_(value_exception, "Cannot multiply a value by a string"); else if (val.type == POINTER) - throw new value_error("Cannot multiply a value by a pointer"); + throw_(value_exception, "Cannot multiply a value by a pointer"); else if (val.type == SEQUENCE) - throw new value_error("Cannot multiply a value by a sequence"); + throw_(value_exception, "Cannot multiply a value by a sequence"); else if (val.type == XML_NODE) // recurse return *this *= (*(xml::node_t **) val.data)->to_value(); @@ -615,7 +615,7 @@ value_t& value_t::operator*=(const value_t& val) switch (type) { case BOOLEAN: - throw new value_error("Cannot multiply a value by a boolean"); + throw_(value_exception, "Cannot multiply a value by a boolean"); case INTEGER: switch (val.type) { @@ -722,9 +722,9 @@ value_t& value_t::operator*=(const value_t& val) break; } case BALANCE: - throw new value_error("Cannot multiply a string by a balance"); + throw_(value_exception, "Cannot multiply a string by a balance"); case BALANCE_PAIR: - throw new value_error("Cannot multiply a string by a balance pair"); + throw_(value_exception, "Cannot multiply a string by a balance pair"); default: assert(0); break; @@ -732,11 +732,11 @@ value_t& value_t::operator*=(const value_t& val) break; case XML_NODE: - throw new value_error("Cannot multiply an XML node by a value"); + throw_(value_exception, "Cannot multiply an XML node by a value"); case POINTER: - throw new value_error("Cannot multiply a pointer by a value"); + throw_(value_exception, "Cannot multiply a pointer by a value"); case SEQUENCE: - throw new value_error("Cannot multiply a sequence by a value"); + throw_(value_exception, "Cannot multiply a sequence by a value"); default: assert(0); @@ -748,21 +748,21 @@ value_t& value_t::operator*=(const value_t& val) value_t& value_t::operator/=(const value_t& val) { if (val.type == BOOLEAN) - throw new value_error("Cannot divide a boolean by a value"); + throw_(value_exception, "Cannot divide a boolean by a value"); else if (val.type == DATETIME) - throw new value_error("Cannot divide a date/time by a value"); + throw_(value_exception, "Cannot divide a date/time by a value"); else if (val.type == STRING) - throw new value_error("Cannot divide a string by a value"); + throw_(value_exception, "Cannot divide a string by a value"); else if (val.type == POINTER) - throw new value_error("Cannot divide a pointer by a value"); + throw_(value_exception, "Cannot divide a pointer by a value"); else if (val.type == SEQUENCE) - throw new value_error("Cannot divide a value by a sequence"); + throw_(value_exception, "Cannot divide a value by a sequence"); else if (val.type == XML_NODE) // recurse return *this /= (*(xml::node_t **) val.data)->to_value(); switch (type) { case BOOLEAN: - throw new value_error("Cannot divide a value by a boolean"); + throw_(value_exception, "Cannot divide a value by a boolean"); case INTEGER: switch (val.type) { @@ -851,13 +851,13 @@ value_t& value_t::operator/=(const value_t& val) break; case STRING: - throw new value_error("Cannot divide a value from a string"); + throw_(value_exception, "Cannot divide a value from a string"); case XML_NODE: - throw new value_error("Cannot divide a value from an XML node"); + throw_(value_exception, "Cannot divide a value from an XML node"); case POINTER: - throw new value_error("Cannot divide a value from a pointer"); + throw_(value_exception, "Cannot divide a value from a pointer"); case SEQUENCE: - throw new value_error("Cannot divide a value from a sequence"); + throw_(value_exception, "Cannot divide a value from a sequence"); default: assert(0); @@ -905,25 +905,25 @@ value_t::operator long() const { switch (type) { case BOOLEAN: - throw new value_error("Cannot convert a boolean to an integer"); + throw_(value_exception, "Cannot convert a boolean to an integer"); case INTEGER: return *((long *) data); case DATETIME: - throw new value_error("Cannot convert a date/time to an integer"); + throw_(value_exception, "Cannot convert a date/time to an integer"); case AMOUNT: return *((amount_t *) data); case BALANCE: - throw new value_error("Cannot convert a balance to an integer"); + throw_(value_exception, "Cannot convert a balance to an integer"); case BALANCE_PAIR: - throw new value_error("Cannot convert a balance pair to an integer"); + throw_(value_exception, "Cannot convert a balance pair to an integer"); case STRING: - throw new value_error("Cannot convert a string to an integer"); + throw_(value_exception, "Cannot convert a string to an integer"); case XML_NODE: return (*(xml::node_t **) data)->to_value().to_integer(); case POINTER: - throw new value_error("Cannot convert a pointer to an integer"); + throw_(value_exception, "Cannot convert a pointer to an integer"); case SEQUENCE: - throw new value_error("Cannot convert a sequence to an integer"); + throw_(value_exception, "Cannot convert a sequence to an integer"); default: assert(0); @@ -938,25 +938,25 @@ value_t::operator moment_t() const { switch (type) { case BOOLEAN: - throw new value_error("Cannot convert a boolean to a date/time"); + throw_(value_exception, "Cannot convert a boolean to a date/time"); case INTEGER: - throw new value_error("Cannot convert an integer to a date/time"); + throw_(value_exception, "Cannot convert an integer to a date/time"); case DATETIME: return *((moment_t *) data); case AMOUNT: - throw new value_error("Cannot convert an amount to a date/time"); + throw_(value_exception, "Cannot convert an amount to a date/time"); case BALANCE: - throw new value_error("Cannot convert a balance to a date/time"); + throw_(value_exception, "Cannot convert a balance to a date/time"); case BALANCE_PAIR: - throw new value_error("Cannot convert a balance pair to a date/time"); + throw_(value_exception, "Cannot convert a balance pair to a date/time"); case STRING: - throw new value_error("Cannot convert a string to a date/time"); + throw_(value_exception, "Cannot convert a string to a date/time"); case XML_NODE: return (*(xml::node_t **) data)->to_value().to_datetime(); case POINTER: - throw new value_error("Cannot convert a pointer to a date/time"); + throw_(value_exception, "Cannot convert a pointer to a date/time"); case SEQUENCE: - throw new value_error("Cannot convert a sequence to a date/time"); + throw_(value_exception, "Cannot convert a sequence to a date/time"); default: assert(0); @@ -971,25 +971,25 @@ value_t::operator double() const { switch (type) { case BOOLEAN: - throw new value_error("Cannot convert a boolean to a double"); + throw_(value_exception, "Cannot convert a boolean to a double"); case INTEGER: return *((long *) data); case DATETIME: - throw new value_error("Cannot convert a date/time to a double"); + throw_(value_exception, "Cannot convert a date/time to a double"); case AMOUNT: return *((amount_t *) data); case BALANCE: - throw new value_error("Cannot convert a balance to a double"); + throw_(value_exception, "Cannot convert a balance to a double"); case BALANCE_PAIR: - throw new value_error("Cannot convert a balance pair to a double"); + throw_(value_exception, "Cannot convert a balance pair to a double"); case STRING: - throw new value_error("Cannot convert a string to a double"); + throw_(value_exception, "Cannot convert a string to a double"); case XML_NODE: return (*(xml::node_t **) data)->to_value().to_amount().number(); case POINTER: - throw new value_error("Cannot convert a pointer to a double"); + throw_(value_exception, "Cannot convert a pointer to a double"); case SEQUENCE: - throw new value_error("Cannot convert a sequence to a double"); + throw_(value_exception, "Cannot convert a sequence to a double"); default: assert(0); @@ -1019,9 +1019,9 @@ value_t::operator string() const return (*(xml::node_t **) data)->to_value().to_string(); case POINTER: - throw new value_error("Cannot convert a pointer to a string"); + throw_(value_exception, "Cannot convert a pointer to a string"); case SEQUENCE: - throw new value_error("Cannot convert a sequence to a string"); + throw_(value_exception, "Cannot convert a sequence to a string"); default: assert(0); @@ -1044,7 +1044,7 @@ bool value_t::operator OP(const value_t& val) \ return *((bool *) data) OP bool(*((long *) val.data)); \ \ case DATETIME: \ - throw new value_error("Cannot compare a boolean to a date/time"); \ + throw_(value_exception, "Cannot compare a boolean to a date/time"); \ \ case AMOUNT: \ return *((bool *) data) OP bool(*((amount_t *) val.data)); \ @@ -1056,15 +1056,15 @@ bool value_t::operator OP(const value_t& val) \ return *((bool *) data) OP bool(*((balance_pair_t *) val.data)); \ \ case STRING: \ - throw new value_error("Cannot compare a boolean to a string"); \ + throw_(value_exception, "Cannot compare a boolean to a string"); \ \ case XML_NODE: \ return *this OP (*(xml::node_t **) data)->to_value(); \ \ case POINTER: \ - throw new value_error("Cannot compare a boolean to a pointer"); \ + throw_(value_exception, "Cannot compare a boolean to a pointer"); \ case SEQUENCE: \ - throw new value_error("Cannot compare a boolean to a sequence"); \ + throw_(value_exception, "Cannot compare a boolean to a sequence"); \ \ default: \ assert(0); \ @@ -1082,7 +1082,7 @@ bool value_t::operator OP(const value_t& val) \ return (*((long *) data) OP *((long *) val.data)); \ \ case DATETIME: \ - throw new value_error("Cannot compare an integer to a date/time"); \ + throw_(value_exception, "Cannot compare an integer to a date/time"); \ \ case AMOUNT: \ return (amount_t(*((long *) data)) OP \ @@ -1097,15 +1097,15 @@ bool value_t::operator OP(const value_t& val) \ *((balance_pair_t *) val.data)); \ \ case STRING: \ - throw new value_error("Cannot compare an integer to a string"); \ + throw_(value_exception, "Cannot compare an integer to a string"); \ \ case XML_NODE: \ return *this OP (*(xml::node_t **) data)->to_value(); \ \ case POINTER: \ - throw new value_error("Cannot compare an integer to a pointer"); \ + throw_(value_exception, "Cannot compare an integer to a pointer"); \ case SEQUENCE: \ - throw new value_error("Cannot compare an integer to a sequence"); \ + throw_(value_exception, "Cannot compare an integer to a sequence"); \ \ default: \ assert(0); \ @@ -1116,30 +1116,30 @@ bool value_t::operator OP(const value_t& val) \ case DATETIME: \ switch (val.type) { \ case BOOLEAN: \ - throw new value_error("Cannot compare a date/time to a boolean"); \ + throw_(value_exception, "Cannot compare a date/time to a boolean"); \ \ case INTEGER: \ - throw new value_error("Cannot compare a date/time to an integer"); \ + throw_(value_exception, "Cannot compare a date/time to an integer"); \ \ case DATETIME: \ return *((moment_t *) data) OP *((moment_t *) val.data); \ \ case AMOUNT: \ - throw new value_error("Cannot compare a date/time to an amount"); \ + throw_(value_exception, "Cannot compare a date/time to an amount"); \ case BALANCE: \ - throw new value_error("Cannot compare a date/time to a balance"); \ + throw_(value_exception, "Cannot compare a date/time to a balance"); \ case BALANCE_PAIR: \ - throw new value_error("Cannot compare a date/time to a balance pair"); \ + throw_(value_exception, "Cannot compare a date/time to a balance pair"); \ case STRING: \ - throw new value_error("Cannot compare a date/time to a string"); \ + throw_(value_exception, "Cannot compare a date/time to a string"); \ \ case XML_NODE: \ return *this OP (*(xml::node_t **) data)->to_value(); \ \ case POINTER: \ - throw new value_error("Cannot compare a date/time to a pointer"); \ + throw_(value_exception, "Cannot compare a date/time to a pointer"); \ case SEQUENCE: \ - throw new value_error("Cannot compare a date/time to a sequence"); \ + throw_(value_exception, "Cannot compare a date/time to a sequence"); \ \ default: \ assert(0); \ @@ -1150,14 +1150,14 @@ bool value_t::operator OP(const value_t& val) \ case AMOUNT: \ switch (val.type) { \ case BOOLEAN: \ - throw new value_error("Cannot compare an amount to a boolean"); \ + throw_(value_exception, "Cannot compare an amount to a boolean"); \ \ case INTEGER: \ return (*((amount_t *) data) OP \ amount_t(*((long *) val.data))); \ \ case DATETIME: \ - throw new value_error("Cannot compare an amount to a date/time"); \ + throw_(value_exception, "Cannot compare an amount to a date/time"); \ \ case AMOUNT: \ return *((amount_t *) data) OP *((amount_t *) val.data); \ @@ -1171,15 +1171,15 @@ bool value_t::operator OP(const value_t& val) \ *((balance_pair_t *) val.data)); \ \ case STRING: \ - throw new value_error("Cannot compare an amount to a string"); \ + throw_(value_exception, "Cannot compare an amount to a string"); \ \ case XML_NODE: \ return *this OP (*(xml::node_t **) data)->to_value(); \ \ case POINTER: \ - throw new value_error("Cannot compare an amount to a pointer"); \ + throw_(value_exception, "Cannot compare an amount to a pointer"); \ case SEQUENCE: \ - throw new value_error("Cannot compare an amount to a sequence"); \ + throw_(value_exception, "Cannot compare an amount to a sequence"); \ \ default: \ assert(0); \ @@ -1190,13 +1190,13 @@ bool value_t::operator OP(const value_t& val) \ case BALANCE: \ switch (val.type) { \ case BOOLEAN: \ - throw new value_error("Cannot compare a balance to a boolean"); \ + throw_(value_exception, "Cannot compare a balance to a boolean"); \ \ case INTEGER: \ return *((balance_t *) data) OP *((long *) val.data); \ \ case DATETIME: \ - throw new value_error("Cannot compare a balance to a date/time"); \ + throw_(value_exception, "Cannot compare a balance to a date/time"); \ \ case AMOUNT: \ return *((balance_t *) data) OP *((amount_t *) val.data); \ @@ -1209,15 +1209,15 @@ bool value_t::operator OP(const value_t& val) \ ((balance_pair_t *) val.data)->quantity); \ \ case STRING: \ - throw new value_error("Cannot compare a balance to a string"); \ + throw_(value_exception, "Cannot compare a balance to a string"); \ \ case XML_NODE: \ return *this OP (*(xml::node_t **) data)->to_value(); \ \ case POINTER: \ - throw new value_error("Cannot compare a balance to a pointer"); \ + throw_(value_exception, "Cannot compare a balance to a pointer"); \ case SEQUENCE: \ - throw new value_error("Cannot compare a balance to a sequence"); \ + throw_(value_exception, "Cannot compare a balance to a sequence"); \ \ default: \ assert(0); \ @@ -1228,14 +1228,14 @@ bool value_t::operator OP(const value_t& val) \ case BALANCE_PAIR: \ switch (val.type) { \ case BOOLEAN: \ - throw new value_error("Cannot compare a balance pair to a boolean"); \ + throw_(value_exception, "Cannot compare a balance pair to a boolean"); \ \ case INTEGER: \ return (((balance_pair_t *) data)->quantity OP \ *((long *) val.data)); \ \ case DATETIME: \ - throw new value_error("Cannot compare a balance pair to a date/time"); \ + throw_(value_exception, "Cannot compare a balance pair to a date/time"); \ \ case AMOUNT: \ return (((balance_pair_t *) data)->quantity OP \ @@ -1250,15 +1250,15 @@ bool value_t::operator OP(const value_t& val) \ *((balance_pair_t *) val.data)); \ \ case STRING: \ - throw new value_error("Cannot compare a balance pair to a string"); \ + throw_(value_exception, "Cannot compare a balance pair to a string"); \ \ case XML_NODE: \ return *this OP (*(xml::node_t **) data)->to_value(); \ \ case POINTER: \ - throw new value_error("Cannot compare a balance pair to a pointer"); \ + throw_(value_exception, "Cannot compare a balance pair to a pointer"); \ case SEQUENCE: \ - throw new value_error("Cannot compare a balance pair to a sequence"); \ + throw_(value_exception, "Cannot compare a balance pair to a sequence"); \ \ default: \ assert(0); \ @@ -1269,17 +1269,17 @@ bool value_t::operator OP(const value_t& val) \ case STRING: \ switch (val.type) { \ case BOOLEAN: \ - throw new value_error("Cannot compare a string to a boolean"); \ + throw_(value_exception, "Cannot compare a string to a boolean"); \ case INTEGER: \ - throw new value_error("Cannot compare a string to an integer"); \ + throw_(value_exception, "Cannot compare a string to an integer"); \ case DATETIME: \ - throw new value_error("Cannot compare a string to a date/time"); \ + throw_(value_exception, "Cannot compare a string to a date/time"); \ case AMOUNT: \ - throw new value_error("Cannot compare a string to an amount"); \ + throw_(value_exception, "Cannot compare a string to an amount"); \ case BALANCE: \ - throw new value_error("Cannot compare a string to a balance"); \ + throw_(value_exception, "Cannot compare a string to a balance"); \ case BALANCE_PAIR: \ - throw new value_error("Cannot compare a string to a balance pair"); \ + throw_(value_exception, "Cannot compare a string to a balance pair"); \ \ case STRING: \ return (**((string **) data) OP \ @@ -1289,9 +1289,9 @@ bool value_t::operator OP(const value_t& val) \ return *this OP (*(xml::node_t **) data)->to_value(); \ \ case POINTER: \ - throw new value_error("Cannot compare a string to a pointer"); \ + throw_(value_exception, "Cannot compare a string to a pointer"); \ case SEQUENCE: \ - throw new value_error("Cannot compare a string to a sequence"); \ + throw_(value_exception, "Cannot compare a string to a sequence"); \ \ default: \ assert(0); \ @@ -1321,9 +1321,9 @@ bool value_t::operator OP(const value_t& val) \ (*(xml::node_t **) val.data)->to_value()); \ \ case POINTER: \ - throw new value_error("Cannot compare an XML node to a pointer"); \ + throw_(value_exception, "Cannot compare an XML node to a pointer"); \ case SEQUENCE: \ - throw new value_error("Cannot compare an XML node to a sequence"); \ + throw_(value_exception, "Cannot compare an XML node to a sequence"); \ \ default: \ assert(0); \ @@ -1334,25 +1334,25 @@ bool value_t::operator OP(const value_t& val) \ case POINTER: \ switch (val.type) { \ case BOOLEAN: \ - throw new value_error("Cannot compare a pointer to a boolean"); \ + throw_(value_exception, "Cannot compare a pointer to a boolean"); \ case INTEGER: \ - throw new value_error("Cannot compare a pointer to an integer"); \ + throw_(value_exception, "Cannot compare a pointer to an integer"); \ case DATETIME: \ - throw new value_error("Cannot compare a pointer to a date/time"); \ + throw_(value_exception, "Cannot compare a pointer to a date/time"); \ case AMOUNT: \ - throw new value_error("Cannot compare a pointer to an amount"); \ + throw_(value_exception, "Cannot compare a pointer to an amount"); \ case BALANCE: \ - throw new value_error("Cannot compare a pointer to a balance"); \ + throw_(value_exception, "Cannot compare a pointer to a balance"); \ case BALANCE_PAIR: \ - throw new value_error("Cannot compare a pointer to a balance pair"); \ + throw_(value_exception, "Cannot compare a pointer to a balance pair"); \ case STRING: \ - throw new value_error("Cannot compare a pointer to a string node"); \ + throw_(value_exception, "Cannot compare a pointer to a string node"); \ case XML_NODE: \ - throw new value_error("Cannot compare a pointer to an XML node"); \ + throw_(value_exception, "Cannot compare a pointer to an XML node"); \ case POINTER: \ return (*((void **) data) OP *((void **) val.data)); \ case SEQUENCE: \ - throw new value_error("Cannot compare a pointer to a sequence"); \ + throw_(value_exception, "Cannot compare a pointer to a sequence"); \ \ default: \ assert(0); \ @@ -1361,7 +1361,7 @@ bool value_t::operator OP(const value_t& val) \ break; \ \ case SEQUENCE: \ - throw new value_error("Cannot compare a value to a sequence"); \ + throw_(value_exception, "Cannot compare a value to a sequence"); \ \ default: \ assert(0); \ @@ -1384,24 +1384,24 @@ void value_t::in_place_cast(type_t cast_type) case BOOLEAN: break; case INTEGER: - throw new value_error("Cannot convert a boolean to an integer"); + throw_(value_exception, "Cannot convert a boolean to an integer"); case DATETIME: - throw new value_error("Cannot convert a boolean to a date/time"); + throw_(value_exception, "Cannot convert a boolean to a date/time"); case AMOUNT: - throw new value_error("Cannot convert a boolean to an amount"); + throw_(value_exception, "Cannot convert a boolean to an amount"); case BALANCE: - throw new value_error("Cannot convert a boolean to a balance"); + throw_(value_exception, "Cannot convert a boolean to a balance"); case BALANCE_PAIR: - throw new value_error("Cannot convert a boolean to a balance pair"); + throw_(value_exception, "Cannot convert a boolean to a balance pair"); case STRING: *(string **) data = new string(*((bool *) data) ? "true" : "false"); break; case XML_NODE: - throw new value_error("Cannot convert a boolean to an XML node"); + throw_(value_exception, "Cannot convert a boolean to an XML node"); case POINTER: - throw new value_error("Cannot convert a boolean to a pointer"); + throw_(value_exception, "Cannot convert a boolean to a pointer"); case SEQUENCE: - throw new value_error("Cannot convert a boolean to a sequence"); + throw_(value_exception, "Cannot convert a boolean to a sequence"); default: assert(0); @@ -1417,7 +1417,7 @@ void value_t::in_place_cast(type_t cast_type) case INTEGER: break; case DATETIME: - throw new value_error("Cannot convert an integer to a date/time"); + throw_(value_exception, "Cannot convert an integer to a date/time"); case AMOUNT: new((amount_t *)data) amount_t(*((long *) data)); @@ -1435,11 +1435,11 @@ void value_t::in_place_cast(type_t cast_type) break; } case XML_NODE: - throw new value_error("Cannot convert an integer to an XML node"); + throw_(value_exception, "Cannot convert an integer to an XML node"); case POINTER: - throw new value_error("Cannot convert an integer to a pointer"); + throw_(value_exception, "Cannot convert an integer to a pointer"); case SEQUENCE: - throw new value_error("Cannot convert an integer to a sequence"); + throw_(value_exception, "Cannot convert an integer to a sequence"); default: assert(0); @@ -1453,23 +1453,23 @@ void value_t::in_place_cast(type_t cast_type) *((bool *) data) = is_valid_moment(*((moment_t *) data)); break; case INTEGER: - throw new value_error("Cannot convert a date/time to an integer"); + throw_(value_exception, "Cannot convert a date/time to an integer"); case DATETIME: break; case AMOUNT: - throw new value_error("Cannot convert a date/time to an amount"); + throw_(value_exception, "Cannot convert a date/time to an amount"); case BALANCE: - throw new value_error("Cannot convert a date/time to a balance"); + throw_(value_exception, "Cannot convert a date/time to a balance"); case BALANCE_PAIR: - throw new value_error("Cannot convert a date/time to a balance pair"); + throw_(value_exception, "Cannot convert a date/time to a balance pair"); case STRING: - throw new value_error("Cannot convert a date/time to a string"); + throw_(value_exception, "Cannot convert a date/time to a string"); case XML_NODE: - throw new value_error("Cannot convert a date/time to an XML node"); + throw_(value_exception, "Cannot convert a date/time to an XML node"); case POINTER: - throw new value_error("Cannot convert a date/time to a pointer"); + throw_(value_exception, "Cannot convert a date/time to a pointer"); case SEQUENCE: - throw new value_error("Cannot convert a date/time to a sequence"); + throw_(value_exception, "Cannot convert a date/time to a sequence"); default: assert(0); @@ -1492,7 +1492,7 @@ void value_t::in_place_cast(type_t cast_type) break; } case DATETIME: - throw new value_error("Cannot convert an amount to a date/time"); + throw_(value_exception, "Cannot convert an amount to a date/time"); case AMOUNT: break; case BALANCE: { @@ -1515,11 +1515,11 @@ void value_t::in_place_cast(type_t cast_type) break; } case XML_NODE: - throw new value_error("Cannot convert an amount to an XML node"); + throw_(value_exception, "Cannot convert an amount to an XML node"); case POINTER: - throw new value_error("Cannot convert an amount to a pointer"); + throw_(value_exception, "Cannot convert an amount to a pointer"); case SEQUENCE: - throw new value_error("Cannot convert an amount to a sequence"); + throw_(value_exception, "Cannot convert an amount to a sequence"); default: assert(0); @@ -1536,9 +1536,9 @@ void value_t::in_place_cast(type_t cast_type) break; } case INTEGER: - throw new value_error("Cannot convert a balance to an integer"); + throw_(value_exception, "Cannot convert a balance to an integer"); case DATETIME: - throw new value_error("Cannot convert a balance to a date/time"); + throw_(value_exception, "Cannot convert a balance to a date/time"); case AMOUNT: { balance_t * temp = (balance_t *) data; @@ -1551,7 +1551,7 @@ void value_t::in_place_cast(type_t cast_type) new((amount_t *)data) amount_t(); } else { - throw new value_error("Cannot convert a balance with " + throw_(value_exception, "Cannot convert a balance with " "multiple commodities to an amount"); } break; @@ -1565,13 +1565,13 @@ void value_t::in_place_cast(type_t cast_type) break; } case STRING: - throw new value_error("Cannot convert a balance to a string"); + throw_(value_exception, "Cannot convert a balance to a string"); case XML_NODE: - throw new value_error("Cannot convert a balance to an XML node"); + throw_(value_exception, "Cannot convert a balance to an XML node"); case POINTER: - throw new value_error("Cannot convert a balance to a pointer"); + throw_(value_exception, "Cannot convert a balance to a pointer"); case SEQUENCE: - throw new value_error("Cannot convert a balance to a sequence"); + throw_(value_exception, "Cannot convert a balance to a sequence"); default: assert(0); @@ -1588,9 +1588,9 @@ void value_t::in_place_cast(type_t cast_type) break; } case INTEGER: - throw new value_error("Cannot convert a balance pair to an integer"); + throw_(value_exception, "Cannot convert a balance pair to an integer"); case DATETIME: - throw new value_error("Cannot convert a balance pair to a date/time"); + throw_(value_exception, "Cannot convert a balance pair to a date/time"); case AMOUNT: { balance_t * temp = &((balance_pair_t *) data)->quantity; @@ -1603,7 +1603,7 @@ void value_t::in_place_cast(type_t cast_type) new((amount_t *)data) amount_t(); } else { - throw new value_error("Cannot convert a balance pair with " + throw_(value_exception, "Cannot convert a balance pair with " "multiple commodities to an amount"); } break; @@ -1617,13 +1617,13 @@ void value_t::in_place_cast(type_t cast_type) case BALANCE_PAIR: break; case STRING: - throw new value_error("Cannot convert a balance pair to a string"); + throw_(value_exception, "Cannot convert a balance pair to a string"); case XML_NODE: - throw new value_error("Cannot convert a balance pair to an XML node"); + throw_(value_exception, "Cannot convert a balance pair to an XML node"); case POINTER: - throw new value_error("Cannot convert a balance pair to a pointer"); + throw_(value_exception, "Cannot convert a balance pair to a pointer"); case SEQUENCE: - throw new value_error("Cannot convert a balance pair to a sequence"); + throw_(value_exception, "Cannot convert a balance pair to a sequence"); default: assert(0); @@ -1643,7 +1643,7 @@ void value_t::in_place_cast(type_t cast_type) *(bool *) data = false; } else { - throw new value_error("Cannot convert string to an boolean"); + throw_(value_exception, "Cannot convert string to an boolean"); } break; } @@ -1661,13 +1661,13 @@ void value_t::in_place_cast(type_t cast_type) destroy(); *(long *) data = temp; } else { - throw new value_error("Cannot convert string to an integer"); + throw_(value_exception, "Cannot convert string to an integer"); } break; } case DATETIME: - throw new value_error("Cannot convert a string to a date/time"); + throw_(value_exception, "Cannot convert a string to a date/time"); case AMOUNT: { amount_t temp = **(string **) data; @@ -1676,17 +1676,17 @@ void value_t::in_place_cast(type_t cast_type) break; } case BALANCE: - throw new value_error("Cannot convert a string to a balance"); + throw_(value_exception, "Cannot convert a string to a balance"); case BALANCE_PAIR: - throw new value_error("Cannot convert a string to a balance pair"); + throw_(value_exception, "Cannot convert a string to a balance pair"); case STRING: break; case XML_NODE: - throw new value_error("Cannot convert a string to an XML node"); + throw_(value_exception, "Cannot convert a string to an XML node"); case POINTER: - throw new value_error("Cannot convert a string to a pointer"); + throw_(value_exception, "Cannot convert a string to a pointer"); case SEQUENCE: - throw new value_error("Cannot convert a string to a sequence"); + throw_(value_exception, "Cannot convert a string to a sequence"); default: assert(0); @@ -1708,9 +1708,9 @@ void value_t::in_place_cast(type_t cast_type) case XML_NODE: break; case POINTER: - throw new value_error("Cannot convert an XML node to a pointer"); + throw_(value_exception, "Cannot convert an XML node to a pointer"); case SEQUENCE: - throw new value_error("Cannot convert an XML node to a sequence"); + throw_(value_exception, "Cannot convert an XML node to a sequence"); default: assert(0); @@ -1721,25 +1721,25 @@ void value_t::in_place_cast(type_t cast_type) case POINTER: switch (cast_type) { case BOOLEAN: - throw new value_error("Cannot convert a pointer to a boolean"); + throw_(value_exception, "Cannot convert a pointer to a boolean"); case INTEGER: - throw new value_error("Cannot convert a pointer to an integer"); + throw_(value_exception, "Cannot convert a pointer to an integer"); case DATETIME: - throw new value_error("Cannot convert a pointer to a date/time"); + throw_(value_exception, "Cannot convert a pointer to a date/time"); case AMOUNT: - throw new value_error("Cannot convert a pointer to an amount"); + throw_(value_exception, "Cannot convert a pointer to an amount"); case BALANCE: - throw new value_error("Cannot convert a pointer to a balance"); + throw_(value_exception, "Cannot convert a pointer to a balance"); case BALANCE_PAIR: - throw new value_error("Cannot convert a pointer to a balance pair"); + throw_(value_exception, "Cannot convert a pointer to a balance pair"); case STRING: - throw new value_error("Cannot convert a pointer to a string"); + throw_(value_exception, "Cannot convert a pointer to a string"); case XML_NODE: - throw new value_error("Cannot convert a pointer to an XML node"); + throw_(value_exception, "Cannot convert a pointer to an XML node"); case POINTER: break; case SEQUENCE: - throw new value_error("Cannot convert a pointer to a sequence"); + throw_(value_exception, "Cannot convert a pointer to a sequence"); default: assert(0); @@ -1750,23 +1750,23 @@ void value_t::in_place_cast(type_t cast_type) case SEQUENCE: switch (cast_type) { case BOOLEAN: - throw new value_error("Cannot convert a sequence to a boolean"); + throw_(value_exception, "Cannot convert a sequence to a boolean"); case INTEGER: - throw new value_error("Cannot convert a sequence to an integer"); + throw_(value_exception, "Cannot convert a sequence to an integer"); case DATETIME: - throw new value_error("Cannot convert a sequence to a date/time"); + throw_(value_exception, "Cannot convert a sequence to a date/time"); case AMOUNT: - throw new value_error("Cannot convert a sequence to an amount"); + throw_(value_exception, "Cannot convert a sequence to an amount"); case BALANCE: - throw new value_error("Cannot convert a sequence to a balance"); + throw_(value_exception, "Cannot convert a sequence to a balance"); case BALANCE_PAIR: - throw new value_error("Cannot convert a sequence to a balance pair"); + throw_(value_exception, "Cannot convert a sequence to a balance pair"); case STRING: - throw new value_error("Cannot convert a sequence to a string"); + throw_(value_exception, "Cannot convert a sequence to a string"); case XML_NODE: - throw new value_error("Cannot compare a sequence to an XML node"); + throw_(value_exception, "Cannot compare a sequence to an XML node"); case POINTER: - throw new value_error("Cannot convert a sequence to a pointer"); + throw_(value_exception, "Cannot convert a sequence to a pointer"); case SEQUENCE: break; @@ -1793,7 +1793,7 @@ void value_t::in_place_negate() *((long *) data) = - *((long *) data); break; case DATETIME: - throw new value_error("Cannot negate a date/time"); + throw_(value_exception, "Cannot negate a date/time"); case AMOUNT: ((amount_t *) data)->in_place_negate(); break; @@ -1804,15 +1804,15 @@ void value_t::in_place_negate() ((balance_pair_t *) data)->in_place_negate(); break; case STRING: - throw new value_error("Cannot negate a string"); + throw_(value_exception, "Cannot negate a string"); case XML_NODE: *this = (*(xml::node_t **) data)->to_value(); in_place_negate(); break; case POINTER: - throw new value_error("Cannot negate a pointer"); + throw_(value_exception, "Cannot negate a pointer"); case SEQUENCE: - throw new value_error("Cannot negate a sequence"); + throw_(value_exception, "Cannot negate a sequence"); default: assert(0); @@ -1841,15 +1841,15 @@ void value_t::in_place_abs() ((balance_pair_t *) data)->abs(); break; case STRING: - throw new value_error("Cannot take the absolute value of a string"); + throw_(value_exception, "Cannot take the absolute value of a string"); case XML_NODE: *this = (*(xml::node_t **) data)->to_value(); in_place_abs(); break; case POINTER: - throw new value_error("Cannot take the absolute value of a pointer"); + throw_(value_exception, "Cannot take the absolute value of a pointer"); case SEQUENCE: - throw new value_error("Cannot take the absolute value of a sequence"); + throw_(value_exception, "Cannot take the absolute value of a sequence"); default: assert(0); @@ -1861,9 +1861,9 @@ value_t value_t::value(const moment_t& moment) const { switch (type) { case BOOLEAN: - throw new value_error("Cannot find the value of a boolean"); + throw_(value_exception, "Cannot find the value of a boolean"); case DATETIME: - throw new value_error("Cannot find the value of a date/time"); + throw_(value_exception, "Cannot find the value of a date/time"); case INTEGER: return *this; case AMOUNT: @@ -1873,13 +1873,13 @@ value_t value_t::value(const moment_t& moment) const case BALANCE_PAIR: return ((balance_pair_t *) data)->quantity.value(moment); case STRING: - throw new value_error("Cannot find the value of a string"); + throw_(value_exception, "Cannot find the value of a string"); case XML_NODE: return (*(xml::node_t **) data)->to_value().value(moment); case POINTER: - throw new value_error("Cannot find the value of a pointer"); + throw_(value_exception, "Cannot find the value of a pointer"); case SEQUENCE: - throw new value_error("Cannot find the value of a sequence"); + throw_(value_exception, "Cannot find the value of a sequence"); default: assert(0); return value_t(); @@ -1903,15 +1903,15 @@ void value_t::in_place_reduce() ((balance_pair_t *) data)->in_place_reduce(); break; case STRING: - throw new value_error("Cannot reduce a string"); + throw_(value_exception, "Cannot reduce a string"); case XML_NODE: *this = (*(xml::node_t **) data)->to_value(); in_place_reduce(); // recurse break; case POINTER: - throw new value_error("Cannot reduce a pointer"); + throw_(value_exception, "Cannot reduce a pointer"); case SEQUENCE: - throw new value_error("Cannot reduce a sequence"); + throw_(value_exception, "Cannot reduce a sequence"); } } @@ -1919,9 +1919,9 @@ value_t value_t::round() const { switch (type) { case BOOLEAN: - throw new value_error("Cannot round a boolean"); + throw_(value_exception, "Cannot round a boolean"); case DATETIME: - throw new value_error("Cannot round a date/time"); + throw_(value_exception, "Cannot round a date/time"); case INTEGER: return *this; case AMOUNT: @@ -1931,13 +1931,13 @@ value_t value_t::round() const case BALANCE_PAIR: return ((balance_pair_t *) data)->round(); case STRING: - throw new value_error("Cannot round a string"); + throw_(value_exception, "Cannot round a string"); case XML_NODE: return (*(xml::node_t **) data)->to_value().round(); case POINTER: - throw new value_error("Cannot round a pointer"); + throw_(value_exception, "Cannot round a pointer"); case SEQUENCE: - throw new value_error("Cannot round a sequence"); + throw_(value_exception, "Cannot round a sequence"); } assert(0); return value_t(); @@ -1947,9 +1947,9 @@ value_t value_t::unround() const { switch (type) { case BOOLEAN: - throw new value_error("Cannot un-round a boolean"); + throw_(value_exception, "Cannot un-round a boolean"); case DATETIME: - throw new value_error("Cannot un-round a date/time"); + throw_(value_exception, "Cannot un-round a date/time"); case INTEGER: return *this; case AMOUNT: @@ -1959,13 +1959,13 @@ value_t value_t::unround() const case BALANCE_PAIR: return ((balance_pair_t *) data)->unround(); case STRING: - throw new value_error("Cannot un-round a string"); + throw_(value_exception, "Cannot un-round a string"); case XML_NODE: return (*(xml::node_t **) data)->to_value().unround(); case POINTER: - throw new value_error("Cannot un-round a pointer"); + throw_(value_exception, "Cannot un-round a pointer"); case SEQUENCE: - throw new value_error("Cannot un-round a sequence"); + throw_(value_exception, "Cannot un-round a sequence"); } assert(0); return value_t(); @@ -1975,11 +1975,11 @@ value_t value_t::price() const { switch (type) { case BOOLEAN: - throw new value_error("Cannot find the price of a boolean"); + throw_(value_exception, "Cannot find the price of a boolean"); case INTEGER: return *this; case DATETIME: - throw new value_error("Cannot find the price of a date/time"); + throw_(value_exception, "Cannot find the price of a date/time"); case AMOUNT: return ((amount_t *) data)->price(); @@ -1989,15 +1989,15 @@ value_t value_t::price() const return ((balance_pair_t *) data)->quantity.price(); case STRING: - throw new value_error("Cannot find the price of a string"); + throw_(value_exception, "Cannot find the price of a string"); case XML_NODE: return (*(xml::node_t **) data)->to_value().price(); case POINTER: - throw new value_error("Cannot find the price of a pointer"); + throw_(value_exception, "Cannot find the price of a pointer"); case SEQUENCE: - throw new value_error("Cannot find the price of a sequence"); + throw_(value_exception, "Cannot find the price of a sequence"); default: assert(0); @@ -2011,9 +2011,9 @@ value_t value_t::date() const { switch (type) { case BOOLEAN: - throw new value_error("Cannot find the date of a boolean"); + throw_(value_exception, "Cannot find the date of a boolean"); case INTEGER: - throw new value_error("Cannot find the date of an integer"); + throw_(value_exception, "Cannot find the date of an integer"); case DATETIME: return *this; @@ -2026,15 +2026,15 @@ value_t value_t::date() const return ((balance_pair_t *) data)->quantity.date(); case STRING: - throw new value_error("Cannot find the date of a string"); + throw_(value_exception, "Cannot find the date of a string"); case XML_NODE: return (*(xml::node_t **) data)->to_value().date(); case POINTER: - throw new value_error("Cannot find the date of a pointer"); + throw_(value_exception, "Cannot find the date of a pointer"); case SEQUENCE: - throw new value_error("Cannot find the date of a sequence"); + throw_(value_exception, "Cannot find the date of a sequence"); default: assert(0); @@ -2083,13 +2083,13 @@ value_t value_t::cost() const { switch (type) { case BOOLEAN: - throw new value_error("Cannot find the cost of a boolean"); + throw_(value_exception, "Cannot find the cost of a boolean"); case INTEGER: case AMOUNT: case BALANCE: return *this; case DATETIME: - throw new value_error("Cannot find the cost of a date/time"); + throw_(value_exception, "Cannot find the cost of a date/time"); case BALANCE_PAIR: assert(((balance_pair_t *) data)->cost); @@ -2099,13 +2099,13 @@ value_t value_t::cost() const return ((balance_pair_t *) data)->quantity; case STRING: - throw new value_error("Cannot find the cost of a string"); + throw_(value_exception, "Cannot find the cost of a string"); case XML_NODE: return (*(xml::node_t **) data)->to_value().cost(); case POINTER: - throw new value_error("Cannot find the cost of a pointer"); + throw_(value_exception, "Cannot find the cost of a pointer"); case SEQUENCE: - throw new value_error("Cannot find the cost of a sequence"); + throw_(value_exception, "Cannot find the cost of a sequence"); default: assert(0); @@ -2119,9 +2119,9 @@ value_t& value_t::add(const amount_t& amount, const amount_t * tcost) { switch (type) { case BOOLEAN: - throw new value_error("Cannot add an amount to a boolean"); + throw_(value_exception, "Cannot add an amount to a boolean"); case DATETIME: - throw new value_error("Cannot add an amount to a date/time"); + throw_(value_exception, "Cannot add an amount to a date/time"); case INTEGER: case AMOUNT: if (tcost) { @@ -2153,13 +2153,13 @@ value_t& value_t::add(const amount_t& amount, const amount_t * tcost) break; case STRING: - throw new value_error("Cannot add an amount to a string"); + throw_(value_exception, "Cannot add an amount to a string"); case XML_NODE: - throw new value_error("Cannot add an amount to an XML node"); + throw_(value_exception, "Cannot add an amount to an XML node"); case POINTER: - throw new value_error("Cannot add an amount to a pointer"); + throw_(value_exception, "Cannot add an amount to a pointer"); case SEQUENCE: - throw new value_error("Cannot add an amount to a sequence"); + throw_(value_exception, "Cannot add an amount to a sequence"); default: assert(0); @@ -2188,7 +2188,7 @@ void value_t::write(std::ostream& out, const int first_width, case SEQUENCE: assert(0); // jww (2006-09-28): write them all out! - throw new value_error("Cannot write out a sequence"); + throw_(value_exception, "Cannot write out a sequence"); case BALANCE: ((balance_t *) data)->write(out, first_width, latter_width); @@ -2231,7 +2231,7 @@ std::ostream& operator<<(std::ostream& out, const value_t& val) break; case value_t::POINTER: - throw new value_error("Cannot output a pointer value"); + throw_(value_exception, "Cannot output a pointer value"); case value_t::SEQUENCE: { out << '('; @@ -2257,6 +2257,7 @@ std::ostream& operator<<(std::ostream& out, const value_t& val) return out; } +#if 0 value_context::value_context(const value_t& _bal, const string& _desc) throw() : error_context(_desc), bal(new value_t(_bal)) {} @@ -2305,6 +2306,7 @@ void value_context::describe(std::ostream& out) const throw() } out << std::endl; } +#endif } // namespace ledger @@ -2361,13 +2363,13 @@ amount_t value_getitem(value_t& val, int i) switch (val.type) { case value_t::BOOLEAN: - throw new value_error("Cannot cast a boolean to an amount"); + throw_(value_exception, "Cannot cast a boolean to an amount"); case value_t::INTEGER: return long(val); case value_t::DATETIME: - throw new value_error("Cannot cast a date/time to an amount"); + throw_(value_exception, "Cannot cast a date/time to an amount"); case value_t::AMOUNT: return *((amount_t *) val.data); @@ -2379,13 +2381,13 @@ amount_t value_getitem(value_t& val, int i) return balance_pair_getitem(*((balance_pair_t *) val.data), i); case value_t::STRING: - throw new value_error("Cannot cast a string to an amount"); + throw_(value_exception, "Cannot cast a string to an amount"); case value_t::XML_NODE: return (*(xml::node_t **) data)->to_value(); case value_t::POINTER: - throw new value_error("Cannot cast a pointer to an amount"); + throw_(value_exception, "Cannot cast a pointer to an amount"); case value_t::SEQUENCE: return (*(value_t::sequence_t **) val.data)[i]; @@ -560,6 +560,7 @@ template <> value_t::operator string() const; std::ostream& operator<<(std::ostream& out, const value_t& val); +#if 0 class value_context : public error_context { value_t * bal; @@ -570,14 +571,9 @@ class value_context : public error_context virtual void describe(std::ostream& out) const throw(); }; +#endif -class value_error : public error { - public: - value_error(const string& _reason, - error_context * _ctxt = NULL) throw() - : error(_reason, _ctxt) {} - virtual ~value_error() throw() {} -}; +DECLARE_EXCEPTION(value_exception); } // namespace ledger @@ -48,7 +48,7 @@ int document_t::register_name(const string& name) names.push_back(name); index = names.size() - 1; - DEBUG_PRINT("xml.lookup", this << " Inserting name: " << names.back()); + DEBUG_("xml.lookup", this << " Inserting name: " << names.back()); std::pair<names_map::iterator, bool> result = names_index.insert(names_pair(names.back(), index)); @@ -63,7 +63,7 @@ int document_t::lookup_name_id(const string& name) const if ((id = lookup_builtin_id(name)) != -1) return id; - DEBUG_PRINT("xml.lookup", this << " Finding name: " << name); + DEBUG_("xml.lookup", this << " Finding name: " << name); names_map::const_iterator i = names_index.find(name); if (i != names_index.end()) @@ -131,7 +131,7 @@ document_t * node_t::document; node_t::node_t(document_t * _document, parent_node_t * _parent, unsigned int _flags) : name_id(0), parent(_parent), next(NULL), prev(NULL), - flags(_flags), info(NULL), attrs(NULL) + flags(_flags), attrs(NULL) { TRACE_CTOR(node_t, "document_t *, node_t *"); document = _document; @@ -268,7 +268,7 @@ static void startElement(void *userData, const char *name, const char **attrs) { parser_t * parser = static_cast<parser_t *>(userData); - DEBUG_PRINT("xml.parse", "startElement(" << name << ")"); + DEBUG_("xml.parse", "startElement(" << name << ")"); if (parser->pending) { parent_node_t * node = create_node<parent_node_t>(parser); @@ -295,7 +295,7 @@ static void endElement(void *userData, const char *name) { parser_t * parser = static_cast<parser_t *>(userData); - DEBUG_PRINT("xml.parse", "endElement(" << name << ")"); + DEBUG_("xml.parse", "endElement(" << name << ")"); if (parser->pending) { terminal_node_t * node = create_node<terminal_node_t>(parser); @@ -317,7 +317,7 @@ static void dataHandler(void *userData, const char *s, int len) { parser_t * parser = static_cast<parser_t *>(userData); - DEBUG_PRINT("xml.parse", "dataHandler(" << string(s, len) << ")"); + DEBUG_("xml.parse", "dataHandler(" << string(s, len) << ")"); bool all_whitespace = true; for (int i = 0; i < len; i++) { @@ -382,21 +382,24 @@ document_t * 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_exception, err.what()); } if (! have_error.empty()) { //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++; - parse_error err(have_error); +#if 0 + // jww (2007-04-26): What is this doing?? + parse_exception err(have_error); std::cerr << "Error: " << err.what() << std::endl; +#endif have_error = ""; } if (! result) { //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++; - const char * err = XML_ErrorString(XML_GetErrorCode(parser)); + const char * err = XML_ErrorString(XML_GetErrorCode(parser)); XML_ParserFree(parser); - throw new parse_error(err); + throw_(parse_exception, err); } } @@ -14,13 +14,7 @@ namespace xml { #define XML_NODE_IS_PARENT 0x1 -class conversion_error : public error { - public: - conversion_error(const string& _reason, - error_context * _ctxt = NULL) throw() - : error(_reason, _ctxt) {} - virtual ~conversion_error() throw() {} -}; +DECLARE_EXCEPTION(conversion_exception); class parent_node_t; class document_t; @@ -38,7 +32,6 @@ public: node_t * next; node_t * prev; unsigned int flags; - void * info; typedef std::map<string, string> attrs_map; typedef std::pair<string, string> attrs_pair; @@ -91,7 +84,7 @@ public: } virtual value_t to_value() const { - throw new conversion_error("Cannot convert node to a value"); + throw_(conversion_exception, "Cannot convert node to a value"); } virtual void write(std::ostream& out, int depth = 0) const = 0; @@ -248,13 +241,7 @@ class parser_t virtual document_t * parse(std::istream& in); }; -class parse_error : public error { - public: - parse_error(const string& _reason, - error_context * _ctxt = NULL) throw() - : error(_reason, _ctxt) {} - virtual ~parse_error() throw() {} -}; +DECLARE_EXCEPTION(parse_exception); #endif diff --git a/xmlparse.cc b/xmlparse.cc index bcd6cefb..35d26e5a 100644 --- a/xmlparse.cc +++ b/xmlparse.cc @@ -207,13 +207,16 @@ 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_exception, err.what()); } if (! have_error.empty()) { //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++; +#if 0 + // jww (2007-04-26): What is this code doing? parse_error err(have_error); std::cerr << "Error: " << err.what() << std::endl; +#endif have_error = ""; } @@ -221,7 +224,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_exception, err); } } @@ -1,4 +1,5 @@ #include "xpath.h" +#include "parser.h" #if 0 #ifdef USE_BOOST_PYTHON #include "py_eval.h" @@ -375,14 +376,12 @@ void xpath_t::token_t::next(std::istream& in, unsigned short flags) kind = VALUE; value = temp; } - catch (amount_error * err) { + catch (amount_exception& err) { // If the amount had no commodity, it must be an unambiguous // variable reference // jww (2007-04-19): There must be a more efficient way to do this! - if (std::strcmp(err->what(), "No quantity specified for amount") == 0) { - delete err; - + if (std::strcmp(err.what(), "No quantity specified for amount") == 0) { in.clear(); in.seekg(pos, std::ios::beg); @@ -390,7 +389,7 @@ void xpath_t::token_t::next(std::istream& in, unsigned short flags) assert(! (std::isdigit(c) || c == '.')); parse_ident(in); } else { - throw err; + throw; } } } @@ -409,15 +408,13 @@ void xpath_t::token_t::unexpected() { switch (kind) { case TOK_EOF: - throw new parse_error("Unexpected end of expression"); + throw_(parse_exception, "Unexpected end of expression"); case IDENT: - throw new parse_error(string("Unexpected symbol '") + - value.to_string() + "'"); + throw_(parse_exception, "Unexpected symbol '" << value << "'"); case VALUE: - throw new parse_error(string("Unexpected value '") + - value.to_string() + "'"); + throw_(parse_exception, "Unexpected value '" << value << "'"); default: - throw new parse_error(string("Unexpected operator '") + symbol + "'"); + throw_(parse_exception, "Unexpected operator '" << symbol << "'"); } } @@ -425,15 +422,15 @@ void xpath_t::token_t::unexpected(char c, char wanted) { if ((unsigned char) c == 0xff) { if (wanted) - throw new parse_error(string("Missing '") + wanted + "'"); + throw_(parse_exception, "Missing '" << wanted << "'"); else - throw new parse_error("Unexpected end"); + throw_(parse_exception, "Unexpected end"); } else { if (wanted) - throw new parse_error(string("Invalid char '") + c + - "' (wanted '" + wanted + "')"); + throw_(parse_exception, "Invalid char '" << c << + "' (wanted '" << wanted << "')"); else - throw new parse_error(string("Invalid char '") + c + "'"); + throw_(parse_exception, "Invalid char '" << c << "'"); } } @@ -472,7 +469,7 @@ xpath_t::op_t * xpath_t::wrap_mask(const string& pattern) void xpath_t::scope_t::define(const string& name, op_t * def) { - DEBUG_PRINT("ledger.xpath.syms", "Defining '" << name << "' = " << def); + DEBUG_("ledger.xpath.syms", "Defining '" << name << "' = " << def); std::pair<symbol_map::iterator, bool> result = symbols.insert(symbol_pair(name, def)); @@ -485,8 +482,8 @@ void xpath_t::scope_t::define(const string& name, op_t * def) std::pair<symbol_map::iterator, bool> result2 = symbols.insert(symbol_pair(name, def)); if (! result2.second) - throw new compile_error(string("Redefinition of '") + - name + "' in same scope"); + throw_(compile_exception, + "Redefinition of '" << name << "' in same scope"); } def->acquire(); } @@ -533,7 +530,7 @@ bool xpath_t::function_scope_t::resolve(const string& name, if (value->type == value_t::XML_NODE) result.set_string(value->to_xml_node()->text()); else - throw new calc_error("Attempt to call text() on a non-node value"); + throw_(calc_exception, "Attempt to call text() on a non-node value"); return true; } break; @@ -545,7 +542,7 @@ xpath_t::op_t::~op_t() { TRACE_DTOR(xpath_t::op_t); - DEBUG_PRINT("ledger.xpath.memory", "Destroying " << this); + DEBUG_("ledger.xpath.memory", "Destroying " << this); assert(refc == 0); switch (kind) { @@ -600,13 +597,9 @@ void xpath_t::op_t::get_value(value_t& result) const case ARG_INDEX: result = (long)arg_index; break; - default: { - std::ostringstream buf; - write(buf); - throw new calc_error - (string("Cannot determine value of expression symbol '") + - string(buf.str()) + "'"); - } + default: + throw_(calc_exception, + "Cannot determine value of expression symbol '" << *this << "'"); } } @@ -646,7 +639,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const goto done; } catch(const boost::python::error_already_set&) { - throw new parse_error("Error parsing lambda expression"); + throw_(parse_exception, "Error parsing lambda expression"); } #endif /* USE_BOOST_PYTHON */ #endif @@ -690,7 +683,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const case token_t::AT_SYM: tok = next_token(in, tflags); if (tok.kind != token_t::IDENT) - throw parse_error("@ symbol must be followed by attribute name"); + throw_(parse_exception, "@ symbol must be followed by attribute name"); node.reset(new op_t(op_t::ATTR_NAME)); node->name = new string(tok.value.to_string()); @@ -728,8 +721,8 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const case token_t::LPAREN: node.reset(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL)); if (! node.get()) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); tok = next_token(in, tflags); if (tok.kind != token_t::RPAREN) tok.unexpected(); // jww (2006-09-09): wanted ) @@ -767,7 +760,7 @@ xpath_t::parse_predicate_expr(std::istream& in, unsigned short tflags) const node->set_left(prev.release()); node->set_right(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL)); if (! node->right) - throw new parse_error("[ operator not followed by valid expression"); + throw_(parse_exception, "[ operator not followed by valid expression"); tok = next_token(in, tflags); if (tok.kind != token_t::RBRACKET) @@ -801,7 +794,7 @@ xpath_t::parse_path_expr(std::istream& in, unsigned short tflags) const node->set_left(prev.release()); node->set_right(parse_predicate_expr(in, tflags)); if (! node->right) - throw new parse_error("/ operator not followed by a valid term"); + throw_(parse_exception, "/ operator not followed by a valid term"); tok = next_token(in, tflags); } @@ -823,8 +816,8 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const case token_t::EXCLAM: { std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags)); if (! texpr.get()) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); // A very quick optimization if (texpr->kind == op_t::VALUE) { *texpr->valuep = ! *texpr->valuep; @@ -839,8 +832,8 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const case token_t::MINUS: { std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags)); if (! texpr.get()) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); // A very quick optimization if (texpr->kind == op_t::VALUE) { texpr->valuep->in_place_negate(); @@ -856,8 +849,8 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const case token_t::PERCENT: { std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags)); if (! texpr.get()) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); // A very quick optimization if (texpr->kind == op_t::VALUE) { static value_t perc("100.0%"); @@ -893,8 +886,8 @@ xpath_t::parse_union_expr(std::istream& in, unsigned short tflags) const node->set_left(prev.release()); node->set_right(parse_union_expr(in, tflags)); if (! node->right) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); } else { push_token(tok); } @@ -916,8 +909,8 @@ xpath_t::parse_mul_expr(std::istream& in, unsigned short tflags) const node->set_left(prev.release()); node->set_right(parse_mul_expr(in, tflags)); if (! node->right) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); tok = next_token(in, tflags); } @@ -942,8 +935,8 @@ xpath_t::parse_add_expr(std::istream& in, unsigned short tflags) const node->set_left(prev.release()); node->set_right(parse_add_expr(in, tflags)); if (! node->right) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); tok = next_token(in, tflags); } @@ -1012,11 +1005,11 @@ xpath_t::parse_logic_expr(std::istream& in, unsigned short tflags) const if (! node->right) { if (tok.kind == token_t::PLUS) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); else - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); } } } @@ -1037,8 +1030,8 @@ xpath_t::parse_and_expr(std::istream& in, unsigned short tflags) const node->set_left(prev.release()); node->set_right(parse_and_expr(in, tflags)); if (! node->right) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); } else { push_token(tok); } @@ -1059,8 +1052,8 @@ xpath_t::parse_or_expr(std::istream& in, unsigned short tflags) const node->set_left(prev.release()); node->set_right(parse_or_expr(in, tflags)); if (! node->right) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); } else { push_token(tok); } @@ -1082,15 +1075,15 @@ xpath_t::parse_querycolon_expr(std::istream& in, unsigned short tflags) const node->set_right(new op_t(op_t::O_COLON)); node->right->set_left(parse_querycolon_expr(in, tflags)); if (! node->right) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); tok = next_token(in, tflags); if (tok.kind != token_t::COLON) tok.unexpected(); // jww (2006-09-09): wanted : node->right->set_right(parse_querycolon_expr(in, tflags)); if (! node->right) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); } else { push_token(tok); } @@ -1111,8 +1104,8 @@ xpath_t::parse_value_expr(std::istream& in, unsigned short tflags) const node->set_left(prev.release()); node->set_right(parse_value_expr(in, tflags)); if (! node->right) - throw new parse_error(string(tok.symbol) + - " operator not followed by argument"); + throw_(parse_exception, + tok.symbol << " operator not followed by argument"); tok = next_token(in, tflags); } @@ -1124,7 +1117,7 @@ xpath_t::parse_value_expr(std::istream& in, unsigned short tflags) const } } else if (! (tflags & XPATH_PARSE_PARTIAL)) { - throw new parse_error(string("Failed to parse value expression")); + throw_(parse_exception, "Failed to parse value expression"); } return node.release(); @@ -1188,7 +1181,7 @@ void xpath_t::op_t::find_values(value_t * context, scope_t * scope, } } } else { - throw new calc_error("Recursive path selection on a non-node value"); + throw_(calc_exception, "Recursive path selection on a non-node value"); } } } @@ -1199,7 +1192,7 @@ bool xpath_t::op_t::test_value(value_t * context, scope_t * scope, xpath_t expr(compile(context, scope, true)); if (expr->kind != VALUE) - throw new calc_error("Predicate expression does not yield a constant value"); + throw_(calc_exception, "Predicate expression does not yield a constant value"); switch (expr->valuep->type) { case value_t::INTEGER: @@ -1262,7 +1255,9 @@ void xpath_t::op_t::append_value(value_t& val, xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, bool resolve) { +#if 0 try { +#endif switch (kind) { case VALUE: return acquire(); @@ -1274,25 +1269,25 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, case document_t::PARENT: if (context->type != value_t::XML_NODE) - throw new compile_error("Referencing parent node from a non-node value"); + throw_(compile_exception, "Referencing parent node from a non-node value"); else if (context->to_xml_node()->parent) return wrap_value(context->to_xml_node()->parent)->acquire(); else - throw new compile_error("Referencing parent node from the root node"); + throw_(compile_exception, "Referencing parent node from the root node"); case document_t::ROOT: if (context->type != value_t::XML_NODE) - throw new compile_error("Referencing root node from a non-node value"); + throw_(compile_exception, "Referencing root node from a non-node value"); else return wrap_value(context->to_xml_node()->document->top)->acquire(); case document_t::ALL: { if (context->type != value_t::XML_NODE) - throw new compile_error("Referencing child nodes from a non-node value"); + throw_(compile_exception, "Referencing child nodes from a non-node value"); node_t * ptr = context->to_xml_node(); if (! (ptr->flags & XML_NODE_IS_PARENT)) - throw new compile_error("Request for child nodes of a leaf node"); + throw_(compile_exception, "Request for child nodes of a leaf node"); parent_node_t * parent = static_cast<parent_node_t *>(ptr); @@ -1366,7 +1361,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, if (arg_index < scope->args.to_sequence()->size()) return wrap_value((*scope->args.to_sequence())[arg_index])->acquire(); else - throw new compile_error("Reference to non-existing argument"); + throw_(compile_exception, "Reference to non-existing argument"); } else { return acquire(); } @@ -1650,7 +1645,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, } if (lexpr->valuep->type != value_t::STRING) - throw new compile_error("Left operand of mask operator is not a string"); + throw_(compile_exception, "Left operand of mask operator is not a string"); assert(rexpr->mask); @@ -1759,8 +1754,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, return func->compile(context, call_args.get(), resolve); } else { - throw new calc_error(string("Unknown function name '") + - *left->name + "'"); + throw_(calc_exception, "Unknown function name '" << *left->name << "'"); } } else if (left->kind == FUNCTOR) { @@ -1815,7 +1809,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, i++, index++) { assert((*i).type != value_t::SEQUENCE); if ((*i).type != value_t::XML_NODE) - throw new compile_error("Attempting to apply path selection " + throw_(compile_exception, "Attempting to apply path selection " "to non-node(s)"); function_scope_t xpath_fscope(seq, &(*i), index, scope); @@ -1831,8 +1825,8 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, } default: - throw new compile_error("Attempting to apply path selection " - "to non-node(s)"); + throw_(compile_exception, "Attempting to apply path selection " + "to non-node(s)"); } if (result_seq->size() == 1) @@ -1863,6 +1857,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, assert(0); break; } +#if 0 } catch (error * err) { #if 0 @@ -1873,6 +1868,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, #endif throw err; } +#endif assert(0); return NULL; @@ -1880,7 +1876,9 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, void xpath_t::calc(value_t& result, node_t * node, scope_t * scope) const { +#if 0 try { +#endif if (node) { value_t context_node(node); xpath_t final(ptr->compile(&context_node, scope, true)); @@ -1893,6 +1891,7 @@ void xpath_t::calc(value_t& result, node_t * node, scope_t * scope) const xpath_t final(ptr->compile(&context_node, scope, true)); final->get_value(result); } +#if 0 } catch (error * err) { if (err->context.empty() || @@ -1908,8 +1907,10 @@ void xpath_t::calc(value_t& result, node_t * node, scope_t * scope) const #endif throw err; } +#endif } +#if 0 xpath_t::context::context(const xpath_t& _xpath, const op_t * _err_node, const string& desc) throw() @@ -1952,6 +1953,7 @@ void xpath_t::context::describe(std::ostream& out) const throw() out << std::endl; } } +#endif bool xpath_t::op_t::write(std::ostream& out, const bool relaxed, @@ -11,30 +11,11 @@ class xpath_t public: struct op_t; - class parse_error : public error { - public: - parse_error(const string& _reason, - error_context * _ctxt = NULL) throw() - : error(_reason, _ctxt) {} - virtual ~parse_error() throw() {} - }; - - class compile_error : public error { - public: - compile_error(const string& _reason, - error_context * _ctxt = NULL) throw() - : error(_reason, _ctxt) {} - virtual ~compile_error() throw() {} - }; - - class calc_error : public error { - public: - calc_error(const string& _reason, - error_context * _ctxt = NULL) throw() - : error(_reason, _ctxt) {} - virtual ~calc_error() throw() {} - }; + DECLARE_EXCEPTION(parse_exception); + DECLARE_EXCEPTION(compile_exception); + DECLARE_EXCEPTION(calc_exception); +#if 0 class context : public error_context { public: const xpath_t& xpath; @@ -47,6 +28,7 @@ public: virtual void describe(std::ostream& out) const throw(); }; +#endif public: class scope_t; @@ -439,21 +421,21 @@ public: } void release() const { - DEBUG_PRINT("ledger.xpath.memory", + DEBUG_("ledger.xpath.memory", "Releasing " << this << ", refc now " << refc - 1); assert(refc > 0); if (--refc == 0) delete this; } op_t * acquire() { - DEBUG_PRINT("ledger.xpath.memory", + DEBUG_("ledger.xpath.memory", "Acquiring " << this << ", refc now " << refc + 1); assert(refc >= 0); refc++; return this; } const op_t * acquire() const { - DEBUG_PRINT("ledger.xpath.memory", + DEBUG_("ledger.xpath.memory", "Acquiring " << this << ", refc now " << refc + 1); assert(refc >= 0); refc++; @@ -580,8 +562,11 @@ public: unsigned short tflags = XPATH_PARSE_RELAXED) const { std::istringstream stream(str); +#if 0 try { +#endif return parse_expr(stream, tflags); +#if 0 } catch (error * err) { err->context.push_back @@ -589,6 +574,7 @@ public: "While parsing value expression:")); throw err; } +#endif } op_t * parse_expr(const char * p, @@ -749,6 +735,11 @@ public: friend class scope_t; }; +inline std::ostream& operator<<(std::ostream& out, const xpath_t::op_t& op) { + op.write(out); + return out; +}; + } // namespace xml template <typename T> @@ -770,7 +761,6 @@ class xml_command : public xml::xpath_t::functor_t doc->write(*out); } - }; } // namespace ledger |