Restructured the code to use the new utility code in utils.h.
This commit is contained in:
parent
d016291483
commit
0eb597a681
45 changed files with 1277 additions and 1163 deletions
30
COPYRIGHT
Normal file
30
COPYRIGHT
Normal file
|
|
@ -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.
|
||||
*/
|
||||
166
amount.cc
166
amount.cc
|
|
@ -1,33 +1,44 @@
|
|||
// amount.cc
|
||||
/**
|
||||
* @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.
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
|
|
|||
8
amount.h
8
amount.h
|
|
@ -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;
|
||||
|
|
|
|||
25
balance.cc
25
balance.cc
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
15
error.h
15
error.h
|
|
@ -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);
|
||||
|
|
|
|||
7
format.h
7
format.h
|
|
@ -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;
|
||||
|
|
|
|||
38
journal.cc
38
journal.cc
|
|
@ -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
|
||||
|
||||
|
|
|
|||
12
journal.h
12
journal.h
|
|
@ -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
|
||||
|
|
|
|||
73
main.cc
73
main.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
6
mask.h
6
mask.h
|
|
@ -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
|
||||
|
|
|
|||
8
ofx.cc
8
ofx.cc
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
35
option.cc
35
option.cc
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
6
option.h
6
option.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
60
parser.h
60
parser.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
10
py_amount.cc
10
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);
|
||||
}
|
||||
|
|
|
|||
19
py_eval.cc
19
py_eval.cc
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
10
qif.cc
10
qif.cc
|
|
@ -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':
|
||||
|
|
|
|||
27
quotes.cc
27
quotes.cc
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
89
register.cc
89
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))
|
||||
|
|
|
|||
13
register.h
13
register.h
|
|
@ -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
session.cc
27
session.cc
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
117
textual.cc
117
textual.cc
|
|
@ -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
|
||||
|
||||
|
|
|
|||
2
times.cc
2
times.cc
|
|
@ -46,4 +46,4 @@ moment_t datetime_range_from_stream(std::istream& in)
|
|||
{
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace ledger
|
||||
|
|
|
|||
14
times.h
14
times.h
|
|
@ -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
|
||||
|
||||
#endif /* _TIMES_H */
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _TIMES_H
|
||||
|
|
|
|||
146
util.cc
146
util.cc
|
|
@ -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
|
||||
88
util.h
88
util.h
|
|
@ -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
|
||||
240
utils.cc
240
utils.cc
|
|
@ -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
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // LOGGING_ON && TIMERS_ON
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Exception handling
|
||||
*/
|
||||
|
||||
namespace ledger {
|
||||
|
||||
std::ostringstream _exc_buffer;
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* General utility functions
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#endif // TIMERS_ON
|
||||
|
||||
#if defined(LOGGING_ON) && defined(DEBUG_ON)
|
||||
|
||||
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;
|
||||
}
|
||||
_set_debug_regex = true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
~init_streams() {
|
||||
if (_free_debug_stream && _debug_stream) {
|
||||
delete _debug_stream;
|
||||
_debug_stream = NULL;
|
||||
}
|
||||
}
|
||||
} _debug_init;
|
||||
|
||||
#endif // LOGGING_ON && DEBUG_ON
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
315
utils.h
315
utils.h
|
|
@ -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);
|
||||
|
||||
bool logger(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)
|
||||
|
||||
#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 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)
|
||||
|
||||
} // 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)
|
||||
|
|
@ -326,32 +387,46 @@ void finish_timer(const char * name);
|
|||
|
||||
#endif // TIMERS_ON
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Debug macros
|
||||
*/
|
||||
|
||||
#if defined(DEBUG_ON)
|
||||
|
||||
#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
|
||||
|
||||
#define if_debug(cat) if (false)
|
||||
|
||||
#endif // DEBUG_ON
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Exception handling
|
||||
*/
|
||||
|
||||
#import "error.h"
|
||||
#include "error.h"
|
||||
|
||||
// } namespace ledger
|
||||
namespace ledger {
|
||||
|
||||
extern std::ostringstream _exc_buffer;
|
||||
|
||||
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
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* General utility functions
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
#endif // _UTILS_H
|
||||
|
|
|
|||
10
value.h
10
value.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
23
xml.cc
23
xml.cc
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
19
xml.h
19
xml.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
152
xpath.cc
152
xpath.cc
|
|
@ -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,
|
||||
|
|
|
|||
44
xpath.h
44
xpath.h
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue