Cleared out all warnings; started work on getting Python up again.

This commit is contained in:
John Wiegley 2007-04-15 02:55:16 +00:00
parent 691c29a696
commit a087e6ea97
35 changed files with 1123 additions and 1004 deletions

View file

@ -1,6 +1,9 @@
lib_LTLIBRARIES = libledger.la lib_LTLIBRARIES = libledger.la
if HAVE_BOOST_PYTHON
lib_LTLIBRARIES += libpyledger.la
endif
libledger_la_CXXFLAGS = libledger_la_CXXFLAGS = $(WARNFLAGS)
libledger_la_SOURCES = \ libledger_la_SOURCES = \
amount.cc \ amount.cc \
quotes.cc \ quotes.cc \
@ -30,6 +33,7 @@ libledger_la_SOURCES = \
derive.cc \ derive.cc \
emacs.cc \ emacs.cc \
reconcile.cc reconcile.cc
if HAVE_EXPAT if HAVE_EXPAT
libledger_la_CXXFLAGS += -DHAVE_EXPAT=1 libledger_la_CXXFLAGS += -DHAVE_EXPAT=1
libledger_la_SOURCES += gnucash.cc libledger_la_SOURCES += gnucash.cc
@ -42,16 +46,29 @@ if HAVE_LIBOFX
libledger_la_CXXFLAGS += -DHAVE_LIBOFX=1 libledger_la_CXXFLAGS += -DHAVE_LIBOFX=1
libledger_la_SOURCES += ofx.cc libledger_la_SOURCES += ofx.cc
endif endif
if HAVE_BOOST_PYTHON
libledger_la_CXXFLAGS += -DUSE_BOOST_PYTHON=1
libledger_la_SOURCES += py_eval.cc
endif
if DEBUG if DEBUG
libledger_la_CXXFLAGS += -DDEBUG_LEVEL=4 libledger_la_CXXFLAGS += -DDEBUG_LEVEL=4
libledger_la_SOURCES += debug.cc libledger_la_SOURCES += debug.cc
endif endif
if HAVE_BOOST_PYTHON
libledger_la_CXXFLAGS += -DUSE_BOOST_PYTHON=1
endif
libledger_la_LDFLAGS = -release 3.0 libledger_la_LDFLAGS = -release 3.0
libpyledger_la_CXXFLAGS = -DUSE_BOOST_PYTHON=1
libpyledger_la_SOURCES = \
py_eval.cc \
py_amount.cc
if DEBUG
libpyledger_la_CXXFLAGS += -DDEBUG_LEVEL=4
endif
libpyledger_la_LDFLAGS = -release 3.0
pkginclude_HEADERS = \ pkginclude_HEADERS = \
acconf.h \ acconf.h \
amount.h \ amount.h \
@ -106,6 +123,7 @@ ledger_CXXFLAGS += -DHAVE_LIBOFX=1
endif endif
if HAVE_BOOST_PYTHON if HAVE_BOOST_PYTHON
ledger_CXXFLAGS += -DUSE_BOOST_PYTHON=1 ledger_CXXFLAGS += -DUSE_BOOST_PYTHON=1
ledger_LDADD += libpyledger.la
endif endif
if DEBUG if DEBUG
ledger_CXXFLAGS += -DDEBUG_LEVEL=4 ledger_CXXFLAGS += -DDEBUG_LEVEL=4
@ -125,7 +143,7 @@ if HAVE_BOOST_PYTHON
noinst_PROGRAMS = ledger.so noinst_PROGRAMS = ledger.so
ledger.so: pyledger.cc libledger.la ledger.so: pyledger.cc libledger.la libpyledger.la
CFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS) -L. -L.libs" \ CFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS) -L. -L.libs" \
python setup.py build --build-lib=. python setup.py build --build-lib=.
@ -142,12 +160,13 @@ TESTS = UnitTests
check_PROGRAMS = $(TESTS) check_PROGRAMS = $(TESTS)
UnitTests_SOURCES = tests/UnitTests.cc \ UnitTests_SOURCES = tests/UnitTests.cc \
\
tests/corelib/numerics/BasicAmountTest.cc tests/corelib/numerics/BasicAmountTest.cc
UnitTests_LDADD = $(lib_LTLIBRARIES) -lcppunit UnitTests_LDADD = $(lib_LTLIBRARIES) -lcppunit
UnitTests_LDFLAGS = $(LIBADD_DL) UnitTests_LDFLAGS = $(LIBADD_DL)
UnitTests_CXXFLAGS = -Itests UnitTests_CXXFLAGS = -I. -Itests
if HAVE_EXPAT if HAVE_EXPAT
UnitTests_CXXFLAGS += -DHAVE_EXPAT=1 UnitTests_CXXFLAGS += -DHAVE_EXPAT=1
endif endif
@ -165,6 +184,10 @@ endif
all: check all: check
check-syntax:
g++ -I. -Itests $(CPPFLAGS) $(UnitTests_CXXFLAGS) \
-o /dev/null -S $(CHK_SOURCES)
all-clean: maintainer-clean all-clean: maintainer-clean
rm -fr *~ .*~ .\#* *.html *.info *.pdf *.a *.so *.o *.lo *.la \ rm -fr *~ .*~ .\#* *.html *.info *.pdf *.a *.so *.o *.lo *.la \
*.elc *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr \ *.elc *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr \

36
acprep
View file

@ -23,7 +23,7 @@ INCDIRS="$INCDIRS -I/usr/include/httpd/xml"
INCDIRS="$INCDIRS -I/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5" INCDIRS="$INCDIRS -I/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5"
LIBDIRS="-L/usr/local/lib" LIBDIRS="-L/usr/local/lib"
LIBDIRS="$LIBDIRS -L/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5" LIBDIRS="$LIBDIRS -L/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/config"
SYSTEM=`uname -s` SYSTEM=`uname -s`
if [ $SYSTEM = Linux ]; then if [ $SYSTEM = Linux ]; then
@ -36,6 +36,12 @@ else
CXXFLAGS="" CXXFLAGS=""
fi fi
WARNFLAGS="-Wall -Wextra -Wfloat-equal -Wno-endif-labels -Wshadow"
WARNFLAGS="$WARNFLAGS -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion"
WARNFLAGS="$WARNFLAGS -Wconversion -Wshorten-64-to-32 -Wsign-compare"
WARNFLAGS="$WARNFLAGS -Wmissing-field-initializers -Wmissing-noreturn"
WARNFLAGS="$WARNFLAGS -pedantic-errors"
# Building the command-line tool as a shared library is a luxury, # Building the command-line tool as a shared library is a luxury,
# since there are no clients except a GUI tool which might use it (and # since there are no clients except a GUI tool which might use it (and
# that is built again anyway by Xcode). # that is built again anyway by Xcode).
@ -54,34 +60,34 @@ HERE="$PWD"
if [ "$1" = "--debug" ]; then if [ "$1" = "--debug" ]; then
shift 1 shift 1
"$HERE/configure" --srcdir="$HERE" \ "$HERE/configure" --srcdir="$HERE" \
CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="-g" $SWITCHES \ CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="$CXXFLAGS -ggdb3" \
--enable-debug "$@" WARNFLAGS="$WARNFLAGS" $SWITCHES --enable-debug "$@"
elif [ "$1" = "--python-debug" ]; then elif [ "$1" = "--python-debug" -o "$1" = "--debug-python" ]; then
shift 1 shift 1
"$HERE/configure" --srcdir="$HERE" \ "$HERE/configure" --srcdir="$HERE" \
CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="-g" $SWITCHES \ CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="$CXXFLAGS -ggdb3" \
--enable-debug --enable-python "$@" WARNFLAGS="$WARNFLAGS" $SWITCHES --enable-debug --enable-python "$@"
elif [ "$1" = "--opt" ]; then elif [ "$1" = "--opt" ]; then
shift 1 shift 1
"$HERE/configure" --srcdir="$HERE" \ "$HERE/configure" --srcdir="$HERE" \
CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \ CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" WARNFLAGS="$WARNFLAGS" \
CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450 -fPIC" "$@" $SWITCHES CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -O3 -fPIC" "$@" $SWITCHES
elif [ "$1" = "--flat-opt" ]; then elif [ "$1" = "--flat-opt" ]; then
shift 1 shift 1
"$HERE/configure" --srcdir="$HERE" \ "$HERE/configure" --srcdir="$HERE" \
CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \ CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" WARNFLAGS="$WARNFLAGS" \
CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450" "$@" $SWITCHES CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -O3" "$@" $SWITCHES
elif [ "$1" = "--safe-opt" ]; then elif [ "$1" = "--safe-opt" ]; then
shift 1 shift 1
"$HERE/configure" --srcdir="$HERE" \ "$HERE/configure" --srcdir="$HERE" \
CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \ CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" WARNFLAGS="$WARNFLAGS" \
CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450 -fPIC -DDEBUG_LEVEL=1" "$@" \ CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -O3 -fPIC -DDEBUG_LEVEL=1" "$@" \
$SWITCHES $SWITCHES
elif [ "$1" = "--perf" ]; then elif [ "$1" = "--perf" ]; then
shift 1 shift 1
"$HERE/configure" --srcdir="$HERE" \ "$HERE/configure" --srcdir="$HERE" WARNFLAGS="$WARNFLAGS" \
CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="-g -pg" "$@" \ CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
$SWITCHES CXXFLAGS="$CXXFLAGS -ggdb3 -pg" "$@" $SWITCHES
fi fi
rm AUTHORS COPYING rm AUTHORS COPYING

334
amount.cc
View file

@ -173,10 +173,10 @@ static void mpz_round(mpz_t out, mpz_t value, int value_prec, int round_prec)
mpz_tdiv_q(out, out, divisor); mpz_tdiv_q(out, out, divisor);
} }
amount_t::amount_t(const bool value) amount_t::amount_t(const bool val)
{ {
TRACE_CTOR("amount_t(const bool)"); TRACE_CTOR("amount_t(const bool)");
if (value) { if (val) {
quantity = &true_value; quantity = &true_value;
quantity->ref++; quantity->ref++;
} else { } else {
@ -185,24 +185,24 @@ amount_t::amount_t(const bool value)
commodity_ = NULL; commodity_ = NULL;
} }
amount_t::amount_t(const long value) amount_t::amount_t(const long val)
{ {
TRACE_CTOR("amount_t(const long)"); TRACE_CTOR("amount_t(const long)");
if (value != 0) { if (val != 0) {
quantity = new bigint_t; quantity = new bigint_t;
mpz_set_si(MPZ(quantity), value); mpz_set_si(MPZ(quantity), val);
} else { } else {
quantity = NULL; quantity = NULL;
} }
commodity_ = NULL; commodity_ = NULL;
} }
amount_t::amount_t(const unsigned long value) amount_t::amount_t(const unsigned long val)
{ {
TRACE_CTOR("amount_t(const unsigned long)"); TRACE_CTOR("amount_t(const unsigned long)");
if (value != 0) { if (val != 0) {
quantity = new bigint_t; quantity = new bigint_t;
mpz_set_ui(MPZ(quantity), value); mpz_set_ui(MPZ(quantity), val);
} else { } else {
quantity = NULL; quantity = NULL;
} }
@ -210,10 +210,10 @@ amount_t::amount_t(const unsigned long value)
} }
namespace { namespace {
unsigned char convert_double(mpz_t dest, double value) unsigned char convert_double(mpz_t dest, double val)
{ {
mpf_t temp; mpf_t temp;
mpf_init_set_d(temp, value); mpf_init_set_d(temp, val);
mp_exp_t exp; mp_exp_t exp;
char * buf = mpf_get_str(NULL, &exp, 10, 10, temp); char * buf = mpf_get_str(NULL, &exp, 10, 10, temp);
@ -231,15 +231,11 @@ namespace {
} }
} }
amount_t::amount_t(const double value) amount_t::amount_t(const double val)
{ {
TRACE_CTOR("amount_t(const double)"); TRACE_CTOR("amount_t(const double)");
if (value != 0.0) {
quantity = new bigint_t; quantity = new bigint_t;
quantity->prec = convert_double(MPZ(quantity), value); quantity->prec = convert_double(MPZ(quantity), val);
} else {
quantity = NULL;
}
commodity_ = NULL; commodity_ = NULL;
} }
@ -295,16 +291,16 @@ void amount_t::_copy(const amount_t& amt)
commodity_ = amt.commodity_; commodity_ = amt.commodity_;
} }
amount_t& amount_t::operator=(const std::string& value) amount_t& amount_t::operator=(const std::string& val)
{ {
std::istringstream str(value); std::istringstream str(val);
parse(str); parse(str);
return *this; return *this;
} }
amount_t& amount_t::operator=(const char * value) amount_t& amount_t::operator=(const char * val)
{ {
std::string valstr(value); std::string valstr(val);
std::istringstream str(valstr); std::istringstream str(valstr);
parse(str); parse(str);
return *this; return *this;
@ -322,9 +318,9 @@ amount_t& amount_t::operator=(const amount_t& amt)
return *this; return *this;
} }
amount_t& amount_t::operator=(const bool value) amount_t& amount_t::operator=(const bool val)
{ {
if (! value) { if (! val) {
if (quantity) if (quantity)
_clear(); _clear();
} else { } else {
@ -337,42 +333,37 @@ amount_t& amount_t::operator=(const bool value)
return *this; return *this;
} }
amount_t& amount_t::operator=(const long value) amount_t& amount_t::operator=(const long val)
{ {
if (value == 0) { if (val == 0) {
if (quantity) if (quantity)
_clear(); _clear();
} else { } else {
commodity_ = NULL; commodity_ = NULL;
_init(); _init();
mpz_set_si(MPZ(quantity), value); mpz_set_si(MPZ(quantity), val);
} }
return *this; return *this;
} }
amount_t& amount_t::operator=(const unsigned long value) amount_t& amount_t::operator=(const unsigned long val)
{ {
if (value == 0) { if (val == 0) {
if (quantity) if (quantity)
_clear(); _clear();
} else { } else {
commodity_ = NULL; commodity_ = NULL;
_init(); _init();
mpz_set_ui(MPZ(quantity), value); mpz_set_ui(MPZ(quantity), val);
} }
return *this; return *this;
} }
amount_t& amount_t::operator=(const double value) amount_t& amount_t::operator=(const double val)
{ {
if (value == 0.0) {
if (quantity)
_clear();
} else {
commodity_ = NULL; commodity_ = NULL;
_init(); _init();
quantity->prec = convert_double(MPZ(quantity), value); quantity->prec = convert_double(MPZ(quantity), val);
}
return *this; return *this;
} }
@ -436,9 +427,9 @@ amount_t& amount_t::operator+=(const amount_t& amt)
mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
} }
else { else {
amount_t temp = amt; amount_t t = amt;
temp._resize(quantity->prec); t._resize(quantity->prec);
mpz_add(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity)); mpz_add(MPZ(quantity), MPZ(quantity), MPZ(t.quantity));
} }
return *this; return *this;
@ -472,9 +463,9 @@ amount_t& amount_t::operator-=(const amount_t& amt)
mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
} }
else { else {
amount_t temp = amt; amount_t t = amt;
temp._resize(quantity->prec); t._resize(quantity->prec);
mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity)); mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(t.quantity));
} }
return *this; return *this;
@ -563,14 +554,14 @@ int amount_t::compare(const amount_t& amt) const
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)); return mpz_cmp(MPZ(quantity), MPZ(amt.quantity));
} }
else if (quantity->prec < amt.quantity->prec) { else if (quantity->prec < amt.quantity->prec) {
amount_t temp = *this; amount_t t = *this;
temp._resize(amt.quantity->prec); t._resize(amt.quantity->prec);
return mpz_cmp(MPZ(temp.quantity), MPZ(amt.quantity)); return mpz_cmp(MPZ(t.quantity), MPZ(amt.quantity));
} }
else { else {
amount_t temp = amt; amount_t t = amt;
temp._resize(quantity->prec); t._resize(quantity->prec);
return mpz_cmp(MPZ(quantity), MPZ(temp.quantity)); return mpz_cmp(MPZ(quantity), MPZ(t.quantity));
} }
} }
@ -663,43 +654,43 @@ amount_t amount_t::value(const datetime_t& moment) const
amount_t amount_t::round(unsigned int prec) const amount_t amount_t::round(unsigned int prec) const
{ {
amount_t temp = *this; amount_t t = *this;
if (! quantity || quantity->prec <= prec) { if (! quantity || quantity->prec <= prec) {
if (quantity && quantity->flags & BIGINT_KEEP_PREC) { if (quantity && quantity->flags & BIGINT_KEEP_PREC) {
temp._dup(); t._dup();
temp.quantity->flags &= ~BIGINT_KEEP_PREC; t.quantity->flags &= ~BIGINT_KEEP_PREC;
} }
return temp; return t;
} }
temp._dup(); t._dup();
mpz_round(MPZ(temp.quantity), MPZ(temp.quantity), temp.quantity->prec, prec); mpz_round(MPZ(t.quantity), MPZ(t.quantity), t.quantity->prec, prec);
temp.quantity->prec = prec; t.quantity->prec = prec;
temp.quantity->flags &= ~BIGINT_KEEP_PREC; t.quantity->flags &= ~BIGINT_KEEP_PREC;
return temp; return t;
} }
amount_t amount_t::unround() const amount_t amount_t::unround() const
{ {
if (! quantity) { if (! quantity) {
amount_t temp(0L); amount_t t(0L);
assert(temp.quantity); assert(t.quantity);
temp.quantity->flags |= BIGINT_KEEP_PREC; t.quantity->flags |= BIGINT_KEEP_PREC;
return temp; return t;
} }
else if (quantity->flags & BIGINT_KEEP_PREC) { else if (quantity->flags & BIGINT_KEEP_PREC) {
return *this; return *this;
} }
amount_t temp = *this; amount_t t = *this;
temp._dup(); t._dup();
temp.quantity->flags |= BIGINT_KEEP_PREC; t.quantity->flags |= BIGINT_KEEP_PREC;
return temp; return t;
} }
void amount_t::print_quantity(std::ostream& out) const void amount_t::print_quantity(std::ostream& out) const
@ -1117,8 +1108,8 @@ void amount_t::parse(std::istream& in, unsigned char flags)
std::string symbol; std::string symbol;
std::string quant; std::string quant;
amount_t price; amount_t tprice;
datetime_t date; datetime_t tdate;
std::string tag; std::string tag;
unsigned int comm_flags = COMMODITY_STYLE_DEFAULTS; unsigned int comm_flags = COMMODITY_STYLE_DEFAULTS;
bool negative = false; bool negative = false;
@ -1144,7 +1135,7 @@ void amount_t::parse(std::istream& in, unsigned char flags)
comm_flags |= COMMODITY_STYLE_SUFFIXED; comm_flags |= COMMODITY_STYLE_SUFFIXED;
if (! in.eof() && ((n = in.peek()) != '\n')) if (! in.eof() && ((n = in.peek()) != '\n'))
parse_annotations(in, price, date, tag); parse_annotations(in, tprice, tdate, tag);
} }
} else { } else {
parse_commodity(in, symbol); parse_commodity(in, symbol);
@ -1156,7 +1147,7 @@ void amount_t::parse(std::istream& in, unsigned char flags)
parse_quantity(in, quant); parse_quantity(in, quant);
if (! quant.empty() && ! in.eof() && ((n = in.peek()) != '\n')) if (! quant.empty() && ! in.eof() && ((n = in.peek()) != '\n'))
parse_annotations(in, price, date, tag); parse_annotations(in, tprice, tdate, tag);
} }
} }
@ -1180,9 +1171,9 @@ void amount_t::parse(std::istream& in, unsigned char flags)
} }
assert(commodity_); assert(commodity_);
if (! price.realzero() || date || ! tag.empty()) if (! tprice.realzero() || tdate || ! tag.empty())
commodity_ = commodity_ =
annotated_commodity_t::find_or_create(*commodity_, price, date, tag); annotated_commodity_t::find_or_create(*commodity_, tprice, tdate, tag);
} }
// Determine the precision of the amount, based on the usage of // Determine the precision of the amount, based on the usage of
@ -1456,8 +1447,8 @@ bool amount_t::valid() const
return true; return true;
} }
void amount_t::annotate_commodity(const amount_t& price, void amount_t::annotate_commodity(const amount_t& tprice,
const datetime_t& date, const datetime_t& tdate,
const std::string& tag) const std::string& tag)
{ {
const commodity_t * this_base; const commodity_t * this_base;
@ -1473,14 +1464,14 @@ void amount_t::annotate_commodity(const amount_t& price,
DEBUG_PRINT("amounts.commodities", "Annotating commodity for amount " DEBUG_PRINT("amounts.commodities", "Annotating commodity for amount "
<< *this << std::endl << *this << std::endl
<< " price " << price << " " << " price " << tprice << " "
<< " date " << date << " " << " date " << tdate << " "
<< " tag " << tag); << " tag " << tag);
commodity_t * ann_comm = commodity_t * ann_comm =
annotated_commodity_t::find_or_create annotated_commodity_t::find_or_create
(*this_base, ! price && this_ann ? this_ann->price : price, (*this_base, ! tprice && this_ann ? this_ann->price : tprice,
! date && this_ann ? this_ann->date : date, ! tdate && this_ann ? this_ann->date : tdate,
tag.empty() && this_ann ? this_ann->tag : tag); tag.empty() && this_ann ? this_ann->tag : tag);
if (ann_comm) if (ann_comm)
set_commodity(*ann_comm); set_commodity(*ann_comm);
@ -1521,22 +1512,21 @@ amount_t amount_t::strip_annotations(const bool _keep_price,
} }
assert(new_comm); assert(new_comm);
amount_t temp(*this); amount_t t(*this);
temp.set_commodity(*new_comm); t.set_commodity(*new_comm);
DEBUG_PRINT("amounts.commodities", " Reduced amount is " << t);
DEBUG_PRINT("amounts.commodities", " Reduced amount is " << temp); return t;
return temp;
} }
amount_t amount_t::price() const amount_t amount_t::price() const
{ {
if (commodity_ && commodity_->annotated) { if (commodity_ && commodity_->annotated) {
amount_t temp(((annotated_commodity_t *)commodity_)->price); amount_t t(((annotated_commodity_t *)commodity_)->price);
temp *= *this; t *= *this;
DEBUG_PRINT("amounts.commodities", DEBUG_PRINT("amounts.commodities",
"Returning price of " << *this << " = " << temp); "Returning price of " << *this << " = " << t);
return temp; return t;
} }
return *this; return *this;
} }
@ -1920,177 +1910,3 @@ bool compare_amount_commodities::operator()(const amount_t * left,
} }
} // namespace ledger } // namespace ledger
#ifdef USE_BOOST_PYTHON
#include <boost/python.hpp>
#include <Python.h>
using namespace boost::python;
using namespace ledger;
int py_amount_quantity(amount_t& amount)
{
std::ostringstream quant;
amount.print_quantity(quant);
return std::atol(quant.str().c_str());
}
void py_parse_1(amount_t& amount, const std::string& str,
unsigned char flags) {
amount.parse(str, flags);
}
void py_parse_2(amount_t& amount, const std::string& str) {
amount.parse(str);
}
struct commodity_updater_wrap : public commodity_base_t::updater_t
{
PyObject * self;
commodity_updater_wrap(PyObject * self_) : self(self_) {}
virtual void operator()(commodity_base_t& commodity,
const datetime_t& moment,
const datetime_t& date,
const datetime_t& last,
amount_t& price) {
call_method<void>(self, "__call__", commodity, moment, date, last, price);
}
};
commodity_t * py_find_commodity(const std::string& symbol)
{
return commodity_t::find(symbol);
}
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_RuntimeError, err.what()); \
}
EXC_TRANSLATOR(amount_error)
void export_amount()
{
scope().attr("AMOUNT_PARSE_NO_MIGRATE") = AMOUNT_PARSE_NO_MIGRATE;
scope().attr("AMOUNT_PARSE_NO_REDUCE") = AMOUNT_PARSE_NO_REDUCE;
class_< amount_t > ("Amount")
.def(init<amount_t>())
.def(init<std::string>())
.def(init<char *>())
.def(init<bool>())
.def(init<long>())
.def(init<unsigned long>())
.def(init<double>())
.def(self += self)
.def(self += long())
.def(self + self)
.def(self + long())
.def(self -= self)
.def(self -= long())
.def(self - self)
.def(self - long())
.def(self *= self)
.def(self *= long())
.def(self * self)
.def(self * long())
.def(self /= self)
.def(self /= long())
.def(self / self)
.def(self / long())
.def(- self)
.def(self < self)
.def(self < long())
.def(self <= self)
.def(self <= long())
.def(self > self)
.def(self > long())
.def(self >= self)
.def(self >= long())
.def(self == self)
.def(self == long())
.def(self != self)
.def(self != long())
.def(! self)
.def(self_ns::int_(self))
.def(self_ns::float_(self))
.def(self_ns::str(self))
.def(abs(self))
.add_property("commodity",
make_function(&amount_t::commodity,
return_value_policy<reference_existing_object>()),
make_function(&amount_t::set_commodity,
with_custodian_and_ward<1, 2>()))
.def("strip_annotations", &amount_t::strip_annotations)
.def("negate", &amount_t::negate)
.def("negated", &amount_t::negated)
.def("parse", py_parse_1)
.def("parse", py_parse_2)
.def("reduce", &amount_t::reduce)
.def("valid", &amount_t::valid)
;
class_< commodity_base_t::updater_t, commodity_updater_wrap,
boost::noncopyable >
("Updater")
;
scope().attr("COMMODITY_STYLE_DEFAULTS") = COMMODITY_STYLE_DEFAULTS;
scope().attr("COMMODITY_STYLE_SUFFIXED") = COMMODITY_STYLE_SUFFIXED;
scope().attr("COMMODITY_STYLE_SEPARATED") = COMMODITY_STYLE_SEPARATED;
scope().attr("COMMODITY_STYLE_EUROPEAN") = COMMODITY_STYLE_EUROPEAN;
scope().attr("COMMODITY_STYLE_THOUSANDS") = COMMODITY_STYLE_THOUSANDS;
scope().attr("COMMODITY_STYLE_NOMARKET") = COMMODITY_STYLE_NOMARKET;
scope().attr("COMMODITY_STYLE_BUILTIN") = COMMODITY_STYLE_BUILTIN;
class_< commodity_t > ("Commodity")
.add_property("symbol", &commodity_t::symbol)
.add_property("name", &commodity_t::name, &commodity_t::set_name)
.add_property("note", &commodity_t::note, &commodity_t::set_note)
.add_property("precision", &commodity_t::precision,
&commodity_t::set_precision)
.add_property("flags", &commodity_t::flags, &commodity_t::set_flags)
.add_property("add_flags", &commodity_t::add_flags)
.add_property("drop_flags", &commodity_t::drop_flags)
.add_property("updater", &commodity_t::updater)
.add_property("smaller",
make_getter(&commodity_t::smaller,
return_value_policy<reference_existing_object>()),
make_setter(&commodity_t::smaller,
return_value_policy<reference_existing_object>()))
.add_property("larger",
make_getter(&commodity_t::larger,
return_value_policy<reference_existing_object>()),
make_setter(&commodity_t::larger,
return_value_policy<reference_existing_object>()))
.def(self_ns::str(self))
.def("find", py_find_commodity,
return_value_policy<reference_existing_object>())
.staticmethod("find")
.def("add_price", &commodity_t::add_price)
.def("remove_price", &commodity_t::remove_price)
.def("value", &commodity_t::value)
.def("valid", &commodity_t::valid)
;
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
EXC_TRANSLATE(amount_error);
}
#endif // USE_BOOST_PYTHON

122
amount.h
View file

@ -54,18 +54,18 @@ class amount_t
else else
commodity_ = NULL; commodity_ = NULL;
} }
amount_t(const std::string& value) : quantity(NULL) { amount_t(const std::string& val) : quantity(NULL) {
TRACE_CTOR("amount_t(const std::string&)"); TRACE_CTOR("amount_t(const std::string&)");
parse(value); parse(val);
} }
amount_t(const char * value) : quantity(NULL) { amount_t(const char * val) : quantity(NULL) {
TRACE_CTOR("amount_t(const char *)"); TRACE_CTOR("amount_t(const char *)");
parse(value); parse(val);
} }
amount_t(const bool value); amount_t(const bool val);
amount_t(const long value); amount_t(const long val);
amount_t(const unsigned long value); amount_t(const unsigned long val);
amount_t(const double value); amount_t(const double val);
// destructor // destructor
~amount_t() { ~amount_t() {
@ -92,19 +92,19 @@ class amount_t
datetime_t date() const; datetime_t date() const;
bool null() const { bool null() const {
return ! quantity && ! commodity_; return ! quantity && ! has_commodity();
} }
std::string quantity_string() const; std::string quantity_string() const;
// assignment operator // assignment operator
amount_t& operator=(const amount_t& amt); amount_t& operator=(const amount_t& amt);
amount_t& operator=(const std::string& value); amount_t& operator=(const std::string& val);
amount_t& operator=(const char * value); amount_t& operator=(const char * val);
amount_t& operator=(const bool value); amount_t& operator=(const bool val);
amount_t& operator=(const long value); amount_t& operator=(const long val);
amount_t& operator=(const unsigned long value); amount_t& operator=(const unsigned long val);
amount_t& operator=(const double value); amount_t& operator=(const double val);
// general methods // general methods
amount_t round(unsigned int prec) const; amount_t round(unsigned int prec) const;
@ -118,20 +118,20 @@ class amount_t
amount_t& operator/=(const amount_t& amt); amount_t& operator/=(const amount_t& amt);
template <typename T> template <typename T>
amount_t& operator+=(T value) { amount_t& operator+=(T val) {
return *this += amount_t(value); return *this += amount_t(val);
} }
template <typename T> template <typename T>
amount_t& operator-=(T value) { amount_t& operator-=(T val) {
return *this -= amount_t(value); return *this -= amount_t(val);
} }
template <typename T> template <typename T>
amount_t& operator*=(T value) { amount_t& operator*=(T val) {
return *this *= amount_t(value); return *this *= amount_t(val);
} }
template <typename T> template <typename T>
amount_t& operator/=(T value) { amount_t& operator/=(T val) {
return *this /= amount_t(value); return *this /= amount_t(val);
} }
// simple arithmetic // simple arithmetic
@ -157,27 +157,27 @@ class amount_t
} }
template <typename T> template <typename T>
amount_t operator+(T value) const { amount_t operator+(T val) const {
amount_t temp = *this; amount_t temp = *this;
temp += value; temp += val;
return temp; return temp;
} }
template <typename T> template <typename T>
amount_t operator-(T value) const { amount_t operator-(T val) const {
amount_t temp = *this; amount_t temp = *this;
temp -= value; temp -= val;
return temp; return temp;
} }
template <typename T> template <typename T>
amount_t operator*(T value) const { amount_t operator*(T val) const {
amount_t temp = *this; amount_t temp = *this;
temp *= value; temp *= val;
return temp; return temp;
} }
template <typename T> template <typename T>
amount_t operator/(T value) const { amount_t operator/(T val) const {
amount_t temp = *this; amount_t temp = *this;
temp /= value; temp /= val;
return temp; return temp;
} }
@ -310,6 +310,64 @@ inline amount_t abs(const amount_t& amt) {
return amt < 0 ? amt.negated() : amt; return amt < 0 ? amt.negated() : amt;
} }
template <typename T>
inline amount_t operator+(const T val, const amount_t& amt) {
amount_t temp(val);
temp += amt;
return temp;
}
template <typename T>
inline amount_t operator-(const T val, const amount_t& amt) {
amount_t temp(val);
temp -= amt;
return temp;
}
template <typename T>
inline amount_t operator*(const T val, const amount_t& amt) {
amount_t temp(val);
temp *= amt;
return temp;
}
template <typename T>
inline amount_t operator/(const T val, const amount_t& amt) {
amount_t temp(val);
temp /= amt;
return temp;
}
template <typename T>
inline bool operator<(const T val, const amount_t& amt) {
return amount_t(val) < amt;
}
template <typename T>
inline bool operator<=(const T val, const amount_t& amt) {
return amount_t(val) <= amt;
}
template <typename T>
inline bool operator>(const T val, const amount_t& amt) {
return amount_t(val) > amt;
}
template <typename T>
inline bool operator>=(const T val, const amount_t& amt) {
return amount_t(val) >= amt;
}
template <typename T>
inline bool operator==(const T val, const amount_t& amt) {
return amount_t(val) == amt;
}
template <typename T>
inline bool operator!=(const T val, const amount_t& amt) {
return amount_t(val) != amt;
}
inline std::ostream& operator<<(std::ostream& out, const amount_t& amt) { inline std::ostream& operator<<(std::ostream& out, const amount_t& amt) {
amt.print(out); amt.print(out);
return out; return out;
@ -602,7 +660,7 @@ void parse_conversion(const std::string& larger_str,
class amount_error : public error { class amount_error : public error {
public: public:
amount_error(const std::string& reason) throw() : error(reason) {} amount_error(const std::string& _reason) throw() : error(_reason) {}
virtual ~amount_error() throw() {} virtual ~amount_error() throw() {}
}; };

View file

@ -64,10 +64,10 @@ datetime_t balance_t::date() const
for (amounts_map::const_iterator i = amounts.begin(); for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end(); i != amounts.end();
i++) { i++) {
datetime_t date = (*i).second.date(); datetime_t tdate = (*i).second.date();
if (! temp && date) if (! temp && tdate)
temp = date; temp = tdate;
else if (temp != date) else if (temp != tdate)
return datetime_t(); return datetime_t();
} }
@ -320,6 +320,7 @@ balance_t::operator amount_t() const
} // namespace ledger } // namespace ledger
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include <boost/python.hpp> #include <boost/python.hpp>
@ -528,3 +529,4 @@ void export_balance()
} }
#endif // USE_BOOST_PYTHON #endif // USE_BOOST_PYTHON
#endif

View file

@ -39,9 +39,9 @@ class balance_t
amounts.insert(amounts_pair(&amt.commodity(), amt)); amounts.insert(amounts_pair(&amt.commodity(), amt));
} }
template <typename T> template <typename T>
balance_t(T value) { balance_t(T val) {
TRACE_CTOR("balance_t(T)"); TRACE_CTOR("balance_t(T)");
amount_t amt(value); amount_t amt(val);
if (! amt.realzero()) if (! amt.realzero())
amounts.insert(amounts_pair(&amt.commodity(), amt)); amounts.insert(amounts_pair(&amt.commodity(), amt));
} }
@ -63,9 +63,9 @@ class balance_t
return *this; return *this;
} }
template <typename T> template <typename T>
balance_t& operator=(T value) { balance_t& operator=(T val) {
amounts.clear(); amounts.clear();
*this += value; *this += val;
return *this; return *this;
} }
@ -517,7 +517,7 @@ class balance_pair_t
TRACE_CTOR("balance_pair_t(const amount_t&)"); TRACE_CTOR("balance_pair_t(const amount_t&)");
} }
template <typename T> template <typename T>
balance_pair_t(T value) : quantity(value), cost(NULL) { balance_pair_t(T val) : quantity(val), cost(NULL) {
TRACE_CTOR("balance_pair_t(T)"); TRACE_CTOR("balance_pair_t(T)");
} }
@ -557,12 +557,12 @@ class balance_pair_t
return *this; return *this;
} }
template <typename T> template <typename T>
balance_pair_t& operator=(T value) { balance_pair_t& operator=(T val) {
if (cost) { if (cost) {
delete cost; delete cost;
cost = NULL; cost = NULL;
} }
quantity = value; quantity = val;
return *this; return *this;
} }
@ -902,13 +902,13 @@ class balance_pair_t
quantity.write(out, first_width, latter_width); quantity.write(out, first_width, latter_width);
} }
balance_pair_t& add(const amount_t& amount, balance_pair_t& add(const amount_t& amt,
const amount_t * a_cost = NULL) { const amount_t * a_cost = NULL) {
if (a_cost && ! cost) if (a_cost && ! cost)
cost = new balance_t(quantity); cost = new balance_t(quantity);
quantity += amount; quantity += amt;
if (cost) if (cost)
*cost += a_cost ? *a_cost : amount; *cost += a_cost ? *a_cost : amt;
return *this; return *this;
} }
@ -941,7 +941,7 @@ class balance_pair_t
}; };
inline balance_pair_t abs(const balance_pair_t& bal_pair) { inline balance_pair_t abs(const balance_pair_t& bal_pair) {
balance_pair_t temp; balance_pair_t temp(bal_pair);
temp.abs(); temp.abs();
return temp; return temp;
} }

View file

@ -117,9 +117,9 @@ void datetime_t::parse(std::istream& in)
istream_pos_type beg_pos = in.tellg(); istream_pos_type beg_pos = in.tellg();
int hour = 0; int thour = 0;
int min = 0; int tmin = 0;
int sec = 0; int tsec = 0;
// Now look for the (optional) time specifier. If no time is given, // Now look for the (optional) time specifier. If no time is given,
// we use midnight of the given day. // we use midnight of the given day.
@ -131,8 +131,8 @@ void datetime_t::parse(std::istream& in)
if (buf[0] == '\0') if (buf[0] == '\0')
goto abort; goto abort;
hour = std::atoi(buf); thour = std::atoi(buf);
if (hour > 23) if (thour > 23)
goto abort; goto abort;
if (in.peek() == ':') { if (in.peek() == ':') {
@ -141,8 +141,8 @@ void datetime_t::parse(std::istream& in)
if (buf[0] == '\0') if (buf[0] == '\0')
goto abort; goto abort;
min = std::atoi(buf); tmin = std::atoi(buf);
if (min > 59) if (tmin > 59)
goto abort; goto abort;
if (in.peek() == ':') { if (in.peek() == ':') {
@ -151,24 +151,24 @@ void datetime_t::parse(std::istream& in)
if (buf[0] == '\0') if (buf[0] == '\0')
goto abort; goto abort;
sec = std::atoi(buf); tsec = std::atoi(buf);
if (sec > 59) if (tsec > 59)
goto abort; goto abort;
} }
} }
c = peek_next_nonws(in); c = peek_next_nonws(in);
if (c == 'a' || c == 'p' || c == 'A' || c == 'P') { if (c == 'a' || c == 'p' || c == 'A' || c == 'P') {
if (hour > 12) if (thour > 12)
goto abort; goto abort;
in.get(c); in.get(c);
if (c == 'p' || c == 'P') { if (c == 'p' || c == 'P') {
if (hour != 12) if (thour != 12)
hour += 12; thour += 12;
} else { } else {
if (hour == 12) if (thour == 12)
hour = 0; thour = 0;
} }
c = in.peek(); c = in.peek();
@ -178,9 +178,9 @@ void datetime_t::parse(std::istream& in)
struct std::tm * desc = std::localtime(&when); struct std::tm * desc = std::localtime(&when);
desc->tm_hour = hour; desc->tm_hour = thour;
desc->tm_min = min; desc->tm_min = tmin;
desc->tm_sec = sec; desc->tm_sec = tsec;
desc->tm_isdst = -1; desc->tm_isdst = -1;
when = std::mktime(desc); when = std::mktime(desc);
@ -453,6 +453,7 @@ void interval_t::parse(std::istream& in)
} }
} }
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include <boost/python.hpp> #include <boost/python.hpp>
@ -571,3 +572,4 @@ void export_datetime()
} }
#endif // USE_BOOST_PYTHON #endif // USE_BOOST_PYTHON
#endif

View file

@ -8,7 +8,7 @@
class date_error : public error { class date_error : public error {
public: public:
date_error(const std::string& reason) throw() : error(reason) {} date_error(const std::string& _reason) throw() : error(_reason) {}
virtual ~date_error() throw() {} virtual ~date_error() throw() {}
}; };
@ -71,12 +71,11 @@ class date_t
virtual date_t& operator+=(const long days) { virtual date_t& operator+=(const long days) {
// jww (2006-03-26): This is not accurate enough when DST is in effect! // jww (2006-03-26): This is not accurate enough when DST is in effect!
assert(0);
when += days * 86400; when += days * 86400;
return *this; return *this;
} }
virtual date_t& operator-=(const long days) { virtual date_t& operator-=(const long days) {
assert(0); // jww (2006-03-26): This is not accurate enough when DST is in effect!
when -= days * 86400; when -= days * 86400;
return *this; return *this;
} }
@ -167,7 +166,7 @@ inline std::istream& operator>>(std::istream& in, date_t& moment) {
class datetime_error : public error { class datetime_error : public error {
public: public:
datetime_error(const std::string& reason) throw() : error(reason) {} datetime_error(const std::string& _reason) throw() : error(_reason) {}
virtual ~datetime_error() throw() {} virtual ~datetime_error() throw() {}
}; };
@ -176,7 +175,7 @@ class datetime_t : public date_t
public: public:
static datetime_t now; static datetime_t now;
datetime_t() : date_t() {} datetime_t() : date_t(now.when) {}
datetime_t(const datetime_t& _when) : date_t(_when.when) {} datetime_t(const datetime_t& _when) : date_t(_when.when) {}
datetime_t(const date_t& _when) : date_t(_when) {} datetime_t(const date_t& _when) : date_t(_when) {}

View file

@ -102,6 +102,7 @@ bool _debug_active(const char * const cls);
#include "trace.h" #include "trace.h"
#if 0
void * operator new(std::size_t) throw (std::bad_alloc); void * operator new(std::size_t) throw (std::bad_alloc);
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();
@ -110,6 +111,7 @@ void * operator new(std::size_t, const std::nothrow_t&) 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();
void operator delete[](void*, const std::nothrow_t&) throw(); void operator delete[](void*, const std::nothrow_t&) throw();
#endif
#else // DEBUG_LEVEL #else // DEBUG_LEVEL

20
error.h
View file

@ -27,8 +27,8 @@ class file_context : public error_context
unsigned long line; unsigned long line;
public: public:
file_context(const std::string& _file, unsigned long _line, file_context(const std::string& _file, unsigned long _line,
const std::string& desc = "") throw() const std::string& _desc = "") throw()
: error_context(desc), file(_file), line(_line) {} : error_context(_desc), file(_file), line(_line) {}
virtual ~file_context() throw() {} virtual ~file_context() throw() {}
virtual void describe(std::ostream& out) const throw() { virtual void describe(std::ostream& out) const throw() {
@ -45,8 +45,8 @@ class line_context : public error_context {
long pos; long pos;
line_context(const std::string& _line, long _pos, line_context(const std::string& _line, long _pos,
const std::string& desc = "") throw() const std::string& _desc = "") throw()
: error_context(desc), line(_line), pos(_pos) {} : error_context(_desc), line(_line), pos(_pos) {}
virtual ~line_context() throw() {} virtual ~line_context() throw() {}
virtual void describe(std::ostream& out) const throw() { virtual void describe(std::ostream& out) const throw() {
@ -103,22 +103,22 @@ class str_exception : public std::exception {
class error : public str_exception { class error : public str_exception {
public: public:
error(const std::string& reason, error_context * ctxt = NULL) throw() error(const std::string& _reason, error_context * _ctxt = NULL) throw()
: str_exception(reason, ctxt) {} : str_exception(_reason, _ctxt) {}
virtual ~error() throw() {} virtual ~error() throw() {}
}; };
class fatal : public str_exception { class fatal : public str_exception {
public: public:
fatal(const std::string& reason, error_context * ctxt = NULL) throw() fatal(const std::string& _reason, error_context * _ctxt = NULL) throw()
: str_exception(reason, ctxt) {} : str_exception(_reason, _ctxt) {}
virtual ~fatal() throw() {} virtual ~fatal() throw() {}
}; };
class fatal_assert : public fatal { class fatal_assert : public fatal {
public: public:
fatal_assert(const std::string& reason, error_context * ctxt = NULL) throw() fatal_assert(const std::string& _reason, error_context * _ctxt = NULL) throw()
: fatal(std::string("assertion failed '") + reason + "'", ctxt) {} : fatal(std::string("assertion failed '") + _reason + "'", _ctxt) {}
virtual ~fatal_assert() throw() {} virtual ~fatal_assert() throw() {}
}; };

View file

@ -1,9 +1,11 @@
#include "format.h" #include "format.h"
#include "error.h" #include "error.h"
#include "util.h" #include "util.h"
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include "py_eval.h" #include "py_eval.h"
#endif #endif
#endif
#include <cstdlib> #include <cstdlib>
@ -239,6 +241,7 @@ int format_t::format(std::ostream& out, xml::node_t * context,
} // namespace ledger } // namespace ledger
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include <boost/python.hpp> #include <boost/python.hpp>
@ -256,3 +259,4 @@ void export_format()
} }
#endif // USE_BOOST_PYTHON #endif // USE_BOOST_PYTHON
#endif

View file

@ -2,9 +2,11 @@
#include "datetime.h" #include "datetime.h"
#include "mask.h" #include "mask.h"
#include "format.h" #include "format.h"
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include "py_eval.h" #include "py_eval.h"
#endif #endif
#endif
#include "acconf.h" #include "acconf.h"
#include <fstream> #include <fstream>
@ -662,6 +664,7 @@ xact_context::xact_context(const ledger::transaction_t& _xact,
} // namespace ledger } // namespace ledger
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include <boost/python.hpp> #include <boost/python.hpp>
@ -1043,3 +1046,4 @@ void export_journal()
} }
#endif // USE_BOOST_PYTHON #endif // USE_BOOST_PYTHON
#endif

View file

@ -202,8 +202,8 @@ class entry_context : public error_context {
const entry_base_t& entry; const entry_base_t& entry;
entry_context(const entry_base_t& _entry, entry_context(const entry_base_t& _entry,
const std::string& desc = "") throw() const std::string& _desc = "") throw()
: error_context(desc), entry(_entry) {} : error_context(_desc), entry(_entry) {}
virtual ~entry_context() throw() {} virtual ~entry_context() throw() {}
virtual void describe(std::ostream& out) const throw(); virtual void describe(std::ostream& out) const throw();
@ -211,8 +211,9 @@ class entry_context : public error_context {
class balance_error : public error { class balance_error : public error {
public: public:
balance_error(const std::string& reason, error_context * ctxt = NULL) throw() balance_error(const std::string& _reason,
: error(reason, ctxt) {} error_context * _ctxt = NULL) throw()
: error(_reason, _ctxt) {}
virtual ~balance_error() throw() {} virtual ~balance_error() throw() {}
}; };
@ -342,7 +343,8 @@ struct func_finalizer_t : public entry_finalizer_t {
typedef bool (*func_t)(entry_t& entry, bool post); typedef bool (*func_t)(entry_t& entry, bool post);
func_t func; func_t func;
func_finalizer_t(func_t _func) : func(_func) {} func_finalizer_t(func_t _func) : func(_func) {}
func_finalizer_t(const func_finalizer_t& other) : func(other.func) {} func_finalizer_t(const func_finalizer_t& other) :
entry_finalizer_t(), func(other.func) {}
virtual bool operator()(entry_t& entry, bool post) { virtual bool operator()(entry_t& entry, bool post) {
return func(entry, post); return func(entry, post);
} }

2
mask.h
View file

@ -22,7 +22,7 @@ class mask_t
class mask_error : public error { class mask_error : public error {
public: public:
mask_error(const std::string& reason) throw() : error(reason) {} mask_error(const std::string& _reason) throw() : error(_reason) {}
virtual ~mask_error() throw() {} virtual ~mask_error() throw() {}
}; };

View file

@ -2,18 +2,22 @@
#include "report.h" #include "report.h"
#include "debug.h" #include "debug.h"
#include "error.h" #include "error.h"
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include "py_eval.h" #include "py_eval.h"
#endif #endif
#endif
#include <iostream> #include <iostream>
#include <cstdarg> #include <cstdarg>
#include "util.h" #include "util.h"
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
static ledger::option_t * find_option(const std::string& name); static ledger::option_t * find_option(const std::string& name);
#endif #endif
#endif
namespace ledger { namespace ledger {
@ -205,6 +209,7 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
} // namespace ledger } // namespace ledger
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include <boost/python.hpp> #include <boost/python.hpp>
@ -286,3 +291,4 @@ void export_option()
} }
#endif // USE_BOOST_PYTHON #endif // USE_BOOST_PYTHON
#endif

View file

@ -1,5 +1,6 @@
#include "parser.h" #include "parser.h"
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include <boost/python.hpp> #include <boost/python.hpp>
@ -47,3 +48,4 @@ void export_parser() {
} }
#endif // USE_BOOST_PYTHON #endif // USE_BOOST_PYTHON
#endif

View file

@ -26,8 +26,9 @@ class parser_t
class parse_error : public error { class parse_error : public error {
public: public:
parse_error(const std::string& reason, error_context * ctxt = NULL) throw() parse_error(const std::string& _reason,
: error(reason, ctxt) {} error_context * _ctxt = NULL) throw()
: error(_reason, _ctxt) {}
virtual ~parse_error() throw() {} virtual ~parse_error() throw() {}
}; };

226
py_amount.cc Normal file
View file

@ -0,0 +1,226 @@
#include <boost/python.hpp>
#include <Python.h>
#include "amount.h"
using namespace boost::python;
using namespace ledger;
int py_amount_quantity(amount_t& amount)
{
std::ostringstream quant;
amount.print_quantity(quant);
return std::atol(quant.str().c_str());
}
void py_parse_1(amount_t& amount, const std::string& str,
unsigned char flags) {
amount.parse(str, flags);
}
void py_parse_2(amount_t& amount, const std::string& str) {
amount.parse(str);
}
struct commodity_updater_wrap : public commodity_base_t::updater_t
{
PyObject * self;
commodity_updater_wrap(PyObject * self_) : self(self_) {}
virtual void operator()(commodity_base_t& commodity,
const datetime_t& moment,
const datetime_t& date,
const datetime_t& last,
amount_t& price) {
call_method<void>(self, "__call__", commodity, moment, date, last, price);
}
};
commodity_t * py_find_commodity(const std::string& symbol)
{
return commodity_t::find(symbol);
}
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_RuntimeError, err.what()); \
}
EXC_TRANSLATOR(amount_error)
void export_amount()
{
scope().attr("AMOUNT_PARSE_NO_MIGRATE") = AMOUNT_PARSE_NO_MIGRATE;
scope().attr("AMOUNT_PARSE_NO_REDUCE") = AMOUNT_PARSE_NO_REDUCE;
class_< amount_t > ("amount")
//.def(init<>())
.def(init<amount_t>())
.def(init<std::string>())
.def(init<char *>())
.def(init<bool>())
.def(init<long>())
.def(init<unsigned long>())
.def(init<double>())
.def(self += self)
.def(self += long())
.def(self += double())
.def(self + self)
.def(self + long())
.def(long() + self)
.def(self + double())
.def(double() + self)
.def(self -= self)
.def(self -= long())
.def(self -= double())
.def(self - self)
.def(self - long())
.def(long() - self)
.def(self - double())
.def(double() - self)
.def(self *= self)
.def(self *= long())
.def(self *= double())
.def(self * self)
.def(self * long())
.def(long() * self)
.def(self * double())
.def(double() * self)
.def(self /= self)
.def(self /= long())
.def(self /= double())
.def(self / self)
.def(self / long())
.def(long() / self)
.def(self / double())
.def(double() / self)
.def(- self)
.def(self < self)
.def(self < long())
.def(long() < self)
.def(self <= self)
.def(self <= long())
.def(long() <= self)
.def(self > self)
.def(self > long())
.def(long() > self)
.def(self >= self)
.def(self >= long())
.def(long() >= self)
.def(self == self)
.def(self == long())
.def(long() == self)
.def(self != self)
.def(self != long())
.def(long() != self)
.def(! self)
.def(self_ns::int_(self))
.def(self_ns::float_(self))
.def(self_ns::str(self))
.def(abs(self))
#if 0
.def("has_commodity", &amount_t::has_commodity)
.add_property("commodity",
make_function(&amount_t::commodity,
return_value_policy<reference_existing_object>()),
make_function(&amount_t::set_commodity,
with_custodian_and_ward<1, 2>()))
.def("annotate_commodity", &amount_t::annotate_commodity)
.def("strip_annotations", &amount_t::strip_annotations)
.def("clear_commodity", &amount_t::clear_commodity)
.def("quantity_string", &amount_t::quantity_string)
.def("abs", &amount_t::abs)
.def("compare", &amount_t::compare)
.def("date", &amount_t::date)
.def("negate", &amount_t::negate)
.def("negated", &amount_t::negated)
.def("null", &amount_t::null)
.def("parse", py_parse_1)
.def("parse", py_parse_2)
.def("price", &amount_t::price)
.def("reduce", &amount_t::reduce)
.def("reduced", &amount_t::reduced)
.def("sign", &amount_t::sign)
.def("value", &amount_t::value)
.def("valid", &amount_t::valid)
#endif
;
class_< commodity_base_t::updater_t, commodity_updater_wrap,
boost::noncopyable >
("updater")
;
scope().attr("COMMODITY_STYLE_DEFAULTS") = COMMODITY_STYLE_DEFAULTS;
scope().attr("COMMODITY_STYLE_SUFFIXED") = COMMODITY_STYLE_SUFFIXED;
scope().attr("COMMODITY_STYLE_SEPARATED") = COMMODITY_STYLE_SEPARATED;
scope().attr("COMMODITY_STYLE_EUROPEAN") = COMMODITY_STYLE_EUROPEAN;
scope().attr("COMMODITY_STYLE_THOUSANDS") = COMMODITY_STYLE_THOUSANDS;
scope().attr("COMMODITY_STYLE_NOMARKET") = COMMODITY_STYLE_NOMARKET;
scope().attr("COMMODITY_STYLE_BUILTIN") = COMMODITY_STYLE_BUILTIN;
class_< commodity_t > ("commodity")
#if 0
.add_property("symbol", &commodity_t::symbol)
.add_property("name", &commodity_t::name, &commodity_t::set_name)
.add_property("note", &commodity_t::note, &commodity_t::set_note)
.add_property("precision", &commodity_t::precision,
&commodity_t::set_precision)
.add_property("flags", &commodity_t::flags, &commodity_t::set_flags)
.add_property("add_flags", &commodity_t::add_flags)
.add_property("drop_flags", &commodity_t::drop_flags)
//.add_property("updater", &commodity_t::updater)
.add_property("smaller",
make_getter(&commodity_t::smaller,
return_value_policy<reference_existing_object>()),
make_setter(&commodity_t::smaller,
return_value_policy<reference_existing_object>()))
.add_property("larger",
make_getter(&commodity_t::larger,
return_value_policy<reference_existing_object>()),
make_setter(&commodity_t::larger,
return_value_policy<reference_existing_object>()))
.def(self_ns::str(self))
.def("find", py_find_commodity,
return_value_policy<reference_existing_object>())
.staticmethod("find")
.def("add_price", &commodity_t::add_price)
.def("remove_price", &commodity_t::remove_price)
.def("value", &commodity_t::value)
.def("valid", &commodity_t::valid)
#endif
;
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
EXC_TRANSLATE(amount_error);
}

View file

@ -5,6 +5,7 @@
#include <istream> #include <istream>
void export_amount(); void export_amount();
#if 0
void export_balance(); void export_balance();
void export_value(); void export_value();
void export_datetime(); void export_datetime();
@ -18,6 +19,7 @@ void export_format();
void export_valexpr(); void export_valexpr();
void shutdown_option(); void shutdown_option();
#endif
namespace ledger { namespace ledger {
@ -25,6 +27,7 @@ namespace {
void initialize_ledger_for_python() void initialize_ledger_for_python()
{ {
export_amount(); export_amount();
#if 0
export_balance(); export_balance();
export_value(); export_value();
export_datetime(); export_datetime();
@ -36,12 +39,15 @@ namespace {
export_format(); export_format();
export_report(); export_report();
export_valexpr(); export_valexpr();
#endif
} }
} }
void shutdown_ledger_for_python() void shutdown_ledger_for_python()
{ {
#if 0
shutdown_option(); shutdown_option();
#endif
} }
struct python_run struct python_run
@ -57,8 +63,8 @@ struct python_run
} }
}; };
python_interpreter_t::python_interpreter_t(valexpr_t::scope_t * parent) python_interpreter_t::python_interpreter_t(xml::xpath_t::scope_t * parent)
: valexpr_t::scope_t(parent), : xml::xpath_t::scope_t(parent),
mmodule(borrowed(PyImport_AddModule("__main__"))), mmodule(borrowed(PyImport_AddModule("__main__"))),
nspace(handle<>(borrowed(PyModule_GetDict(mmodule.get())))) nspace(handle<>(borrowed(PyModule_GetDict(mmodule.get()))))
{ {
@ -145,16 +151,18 @@ object python_interpreter_t::eval(const std::string& str, py_eval_mode_t mode)
} }
void python_interpreter_t::functor_t::operator()(value_t& result, void python_interpreter_t::functor_t::operator()(value_t& result,
valexpr_t::scope_t * locals) xml::xpath_t::scope_t * locals)
{ {
try { try {
if (! PyCallable_Check(func.ptr())) { if (! PyCallable_Check(func.ptr())) {
result = extract<value_t>(func.ptr()); result = static_cast<const value_t&>(extract<value_t>(func.ptr()));
} else { } else {
if (locals->arg_scope && locals->args.size() > 0) { assert(locals->args.type == value_t::SEQUENCE);
if (locals->args.to_sequence()->size() > 0) {
list arglist; list arglist;
for (valexpr_t::scope_t::args_list::iterator i = locals->args.begin(); for (value_t::sequence_t::iterator
i != locals->args.end(); i = locals->args.to_sequence()->begin();
i != locals->args.to_sequence()->end();
i++) i++)
arglist.append(*i); arglist.append(*i);
@ -165,7 +173,7 @@ void python_interpreter_t::functor_t::operator()(value_t& result,
} }
else if (PyObject * err = PyErr_Occurred()) { else if (PyObject * err = PyErr_Occurred()) {
PyErr_Print(); PyErr_Print();
throw new valexpr_t::calc_error throw new xml::xpath_t::calc_error
(std::string("While calling Python function '") + name() + "'"); (std::string("While calling Python function '") + name() + "'");
} else { } else {
assert(0); assert(0);
@ -177,24 +185,24 @@ void python_interpreter_t::functor_t::operator()(value_t& result,
} }
catch (const error_already_set&) { catch (const error_already_set&) {
PyErr_Print(); PyErr_Print();
throw new valexpr_t::calc_error throw new xml::xpath_t::calc_error
(std::string("While calling Python function '") + name() + "'"); (std::string("While calling Python function '") + name() + "'");
} }
} }
void python_interpreter_t::lambda_t::operator()(value_t& result, void python_interpreter_t::lambda_t::operator()(value_t& result,
valexpr_t::scope_t * locals) xml::xpath_t::scope_t * locals)
{ {
try { try {
assert(locals->arg_scope && locals->args.size() == 1); assert(locals->args.type == value_t::SEQUENCE);
assert(locals->args.to_sequence()->size() == 1);
value_t item = locals->args[0]; value_t item = locals->args[0];
assert(item.type == value_t::POINTER); assert(item.type == value_t::POINTER);
result = call<value_t>(func.ptr(), (repitem_t *)*(void **)item.data); result = call<value_t>(func.ptr(), (xml::node_t *)*(void **)item.data);
} }
catch (const error_already_set&) { catch (const error_already_set&) {
PyErr_Print(); PyErr_Print();
throw new valexpr_t::calc_error throw new xml::xpath_t::calc_error("While evaluating Python lambda expression");
("While evaluating Python lambda expression");
} }
} }

View file

@ -1,7 +1,7 @@
#ifndef _PY_EVAL_H #ifndef _PY_EVAL_H
#define _PY_EVAL_H #define _PY_EVAL_H
#include "valexpr.h" #include "xpath.h"
#include "pyfstream.h" #include "pyfstream.h"
#include <string> #include <string>
@ -15,13 +15,14 @@ namespace ledger {
void shutdown_ledger_for_python(); void shutdown_ledger_for_python();
class python_interpreter_t : public valexpr_t::scope_t class python_interpreter_t : public xml::xpath_t::scope_t
{ {
handle<> mmodule; handle<> mmodule;
dict nspace;
public: public:
python_interpreter_t(valexpr_t::scope_t * parent); dict nspace;
python_interpreter_t(xml::xpath_t::scope_t * parent);
virtual ~python_interpreter_t() { virtual ~python_interpreter_t() {
Py_Finalize(); Py_Finalize();
@ -42,35 +43,35 @@ class python_interpreter_t : public valexpr_t::scope_t
return eval(str, mode); return eval(str, mode);
} }
class functor_t : public valexpr_t::functor_t { class functor_t : public xml::xpath_t::functor_t {
protected: protected:
object func; object func;
public: public:
python_functor_t(const std::string& name, object _func) functor_t(const std::string& name, object _func)
: valexpr_t::functor_t(name), func(_func) {} : xml::xpath_t::functor_t(name), func(_func) {}
virtual void operator()(value_t& result, valexpr_t::scope_t * locals); virtual void operator()(value_t& result, xml::xpath_t::scope_t * locals);
}; };
virtual void define(const std::string& name, valexpr_t::node_t * def) { virtual void define(const std::string& name, xml::xpath_t::op_t * def) {
// Pass any definitions up to our parent // Pass any definitions up to our parent
parent->define(name, def); parent->define(name, def);
} }
virtual node_t * lookup(const std::string& name) { virtual xml::xpath_t::op_t * lookup(const std::string& name) {
object func = eval(name); object func = eval(name);
if (! func) if (! func)
return parent ? parent->lookup(name) : NULL; return parent ? parent->lookup(name) : NULL;
return valexpr_t::wrap_functor(new python_functor_t(name, func)); return xml::xpath_t::wrap_functor(new functor_t(name, func));
} }
class lambda_t : public functor_t { class lambda_t : public functor_t {
public: public:
python_lambda_t(object code) : python_functor_t("<lambda>"> code) {} lambda_t(object code) : functor_t("<lambda>", code) {}
virtual void operator()(value_t& result, valexpr_t::scope_t * locals); virtual void operator()(value_t& result, xml::xpath_t::scope_t * locals);
}; };
; };
} // namespace ledger } // namespace ledger

2
qif.cc
View file

@ -41,7 +41,7 @@ bool qif_parser_t::test(std::istream& in) const
unsigned int qif_parser_t::parse(std::istream& in, unsigned int qif_parser_t::parse(std::istream& in,
journal_t * journal, journal_t * journal,
account_t * master, account_t * master,
const std::string * original_file) const std::string *)
{ {
std::auto_ptr<entry_t> entry; std::auto_ptr<entry_t> entry;
std::auto_ptr<amount_t> amount; std::auto_ptr<amount_t> amount;

View file

@ -27,9 +27,9 @@ void quotes_by_script::operator()(commodity_base_t& commodity,
DEBUG_PRINT_("pricing_leeway is " << pricing_leeway); DEBUG_PRINT_("pricing_leeway is " << pricing_leeway);
if ((commodity.history && if ((commodity.history &&
(datetime_t::now - commodity.history->last_lookup) < pricing_leeway) || (datetime_t::now - commodity.history->last_lookup) < (long)pricing_leeway) ||
(datetime_t::now - last) < pricing_leeway || (datetime_t::now - last) < (long)pricing_leeway ||
(price && moment > date && (moment - date) <= pricing_leeway)) (price && moment > date && (moment - date) <= (long)pricing_leeway))
return; return;
using namespace std; using namespace std;

View file

@ -186,6 +186,7 @@ xml::xpath_t::op_t * report_t::lookup(const std::string& name)
} // namespace ledger } // namespace ledger
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include <boost/python.hpp> #include <boost/python.hpp>
@ -205,3 +206,4 @@ void export_report()
} }
#endif // USE_BOOST_PYTHON #endif // USE_BOOST_PYTHON
#endif

View file

@ -190,6 +190,7 @@ xml::xpath_t::op_t * session_t::lookup(const std::string& name)
} // namespace ledger } // namespace ledger
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include <boost/python.hpp> #include <boost/python.hpp>
@ -231,3 +232,4 @@ void export_session()
} }
#endif // USE_BOOST_PYTHON #endif // USE_BOOST_PYTHON
#endif

View file

@ -49,8 +49,8 @@ class session_t : public xml::xpath_t::scope_t
std::list<journal_t *> journals; std::list<journal_t *> journals;
std::list<parser_t *> parsers; std::list<parser_t *> parsers;
session_t(xml::xpath_t::scope_t * parent = NULL) : session_t(xml::xpath_t::scope_t * _parent = NULL) :
xml::xpath_t::scope_t(parent), xml::xpath_t::scope_t(_parent),
register_format register_format
("%((//entry)%{date} %-.20{payee}" ("%((//entry)%{date} %-.20{payee}"
@ -170,6 +170,7 @@ class session_t : public xml::xpath_t::scope_t
verbose_mode = true; verbose_mode = true;
} }
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
void option_import(value_t&) { void option_import(value_t&) {
python_import(optarg); python_import(optarg);
@ -178,6 +179,7 @@ class session_t : public xml::xpath_t::scope_t
python_eval(std::cin, PY_EVAL_MULTI); python_eval(std::cin, PY_EVAL_MULTI);
} }
#endif #endif
#endif
}; };
} // namespace ledger } // namespace ledger

View file

@ -4,7 +4,7 @@ from distutils.core import setup, Extension
import os import os
libs = ["ledger", "boost_python", "gmp", "pcre"] libs = ["ledger", "pyledger", "boost_python", "gmp", "pcre"]
if os.environ.has_key ("HAVE_EXPAT") and\ if os.environ.has_key ("HAVE_EXPAT") and\
os.environ["HAVE_EXPAT"] == "true": os.environ["HAVE_EXPAT"] == "true":

View file

@ -130,6 +130,7 @@ void BasicAmountTest::testIntegerAddition()
assertEquals(amount_t(579L), x1 + y1); assertEquals(amount_t(579L), x1 + y1);
assertEquals(amount_t(579L), x1 + 456L); assertEquals(amount_t(579L), x1 + 456L);
assertEquals(amount_t(579L), 456L + x1);
x1 += amount_t(456L); x1 += amount_t(456L);
assertEquals(amount_t(579L), x1); assertEquals(amount_t(579L), x1);
@ -154,6 +155,7 @@ void BasicAmountTest::testFractionalAddition()
assertEquals(amount_t(579.579), x1 + y1); assertEquals(amount_t(579.579), x1 + y1);
assertEquals(amount_t(579.579), x1 + 456.456); assertEquals(amount_t(579.579), x1 + 456.456);
assertEquals(amount_t(579.579), 456.456 + x1);
x1 += amount_t(456.456); x1 += amount_t(456.456);
assertEquals(amount_t(579.579), x1); assertEquals(amount_t(579.579), x1);
@ -174,6 +176,8 @@ void BasicAmountTest::testIntegerSubtraction()
assertEquals(amount_t(333L), y1 - x1); assertEquals(amount_t(333L), y1 - x1);
assertEquals(amount_t(-333L), x1 - y1); assertEquals(amount_t(-333L), x1 - y1);
assertEquals(amount_t(23L), x1 - 100L);
assertEquals(amount_t(-23L), 100L - x1);
x1 -= amount_t(456L); x1 -= amount_t(456L);
assertEquals(amount_t(-333L), x1); assertEquals(amount_t(-333L), x1);
@ -221,14 +225,18 @@ void BasicAmountTest::testIntegerMultiplication()
assertEquals(amount_t(0L), x1 * 0L); assertEquals(amount_t(0L), x1 * 0L);
assertEquals(amount_t(0L), amount_t(0L) * x1); assertEquals(amount_t(0L), amount_t(0L) * x1);
assertEquals(amount_t(0L), 0L * x1);
assertEquals(x1, x1 * 1L); assertEquals(x1, x1 * 1L);
assertEquals(x1, amount_t(1L) * x1); assertEquals(x1, amount_t(1L) * x1);
assertEquals(x1, 1L * x1);
assertEquals(- x1, x1 * -1L); assertEquals(- x1, x1 * -1L);
assertEquals(- x1, amount_t(-1L) * x1); assertEquals(- x1, amount_t(-1L) * x1);
assertEquals(- x1, -1L * x1);
assertEquals(amount_t(56088L), x1 * y1); assertEquals(amount_t(56088L), x1 * y1);
assertEquals(amount_t(56088L), y1 * x1); assertEquals(amount_t(56088L), y1 * x1);
assertEquals(amount_t(56088L), x1 * 456L); assertEquals(amount_t(56088L), x1 * 456L);
assertEquals(amount_t(56088L), amount_t(456L) * x1); assertEquals(amount_t(56088L), amount_t(456L) * x1);
assertEquals(amount_t(56088L), 456L * x1);
x1 *= amount_t(123L); x1 *= amount_t(123L);
assertEquals(amount_t(15129L), x1); assertEquals(amount_t(15129L), x1);
@ -253,14 +261,18 @@ void BasicAmountTest::testFractionalMultiplication()
assertEquals(amount_t(0L), x1 * 0L); assertEquals(amount_t(0L), x1 * 0L);
assertEquals(amount_t(0L), amount_t(0L) * x1); assertEquals(amount_t(0L), amount_t(0L) * x1);
assertEquals(amount_t(0L), 0L * x1);
assertEquals(x1, x1 * 1L); assertEquals(x1, x1 * 1L);
assertEquals(x1, amount_t(1L) * x1); assertEquals(x1, amount_t(1L) * x1);
assertEquals(x1, 1L * x1);
assertEquals(- x1, x1 * -1L); assertEquals(- x1, x1 * -1L);
assertEquals(- x1, amount_t(-1L) * x1); assertEquals(- x1, amount_t(-1L) * x1);
assertEquals(- x1, -1L * x1);
assertEquals(amount_t("56200.232088"), x1 * y1); assertEquals(amount_t("56200.232088"), x1 * y1);
assertEquals(amount_t("56200.232088"), y1 * x1); assertEquals(amount_t("56200.232088"), y1 * x1);
assertEquals(amount_t("56200.232088"), x1 * 456.456); assertEquals(amount_t("56200.232088"), x1 * 456.456);
assertEquals(amount_t("56200.232088"), amount_t(456.456) * x1); assertEquals(amount_t("56200.232088"), amount_t(456.456) * x1);
assertEquals(amount_t("56200.232088"), 456.456 * x1);
x1 *= amount_t(123.123); x1 *= amount_t(123.123);
assertEquals(amount_t("15159.273129"), x1); assertEquals(amount_t("15159.273129"), x1);
@ -282,14 +294,18 @@ void BasicAmountTest::testIntegerDivision()
assertThrow(x1 / 0L, amount_error *); assertThrow(x1 / 0L, amount_error *);
assertEquals(amount_t(0L), amount_t(0L) / x1); assertEquals(amount_t(0L), amount_t(0L) / x1);
assertEquals(amount_t(0L), 0L / x1);
assertEquals(x1, x1 / 1L); assertEquals(x1, x1 / 1L);
assertEquals(amount_t("0.008130"), amount_t(1L) / x1); assertEquals(amount_t("0.008130"), amount_t(1L) / x1);
assertEquals(amount_t("0.008130"), 1L / x1);
assertEquals(- x1, x1 / -1L); assertEquals(- x1, x1 / -1L);
assertEquals(- amount_t("0.008130"), amount_t(-1L) / x1); assertEquals(- amount_t("0.008130"), amount_t(-1L) / x1);
assertEquals(- amount_t("0.008130"), -1L / x1);
assertEquals(amount_t("0.269736"), x1 / y1); assertEquals(amount_t("0.269736"), x1 / y1);
assertEquals(amount_t("3.707317"), y1 / x1); assertEquals(amount_t("3.707317"), y1 / x1);
assertEquals(amount_t("0.269736"), x1 / 456L); assertEquals(amount_t("0.269736"), x1 / 456L);
assertEquals(amount_t("3.707317"), amount_t(456L) / x1); assertEquals(amount_t("3.707317"), amount_t(456L) / x1);
assertEquals(amount_t("3.707317"), 456L / x1);
x1 /= amount_t(456L); x1 /= amount_t(456L);
assertEquals(amount_t("0.269736"), x1); assertEquals(amount_t("0.269736"), x1);
@ -310,14 +326,18 @@ void BasicAmountTest::testFractionalDivision()
assertThrow(x1 / 0L, amount_error *); assertThrow(x1 / 0L, amount_error *);
assertEquals(amount_t("0.008121"), amount_t(1.0) / x1); assertEquals(amount_t("0.008121"), amount_t(1.0) / x1);
assertEquals(amount_t("0.008121"), 1.0 / x1);
assertEquals(x1, x1 / 1.0); assertEquals(x1, x1 / 1.0);
assertEquals(amount_t("0.008121"), amount_t(1.0) / x1); assertEquals(amount_t("0.008121"), amount_t(1.0) / x1);
assertEquals(amount_t("0.008121"), 1.0 / x1);
assertEquals(- x1, x1 / -1.0); assertEquals(- x1, x1 / -1.0);
assertEquals(- amount_t("0.008121"), amount_t(-1.0) / x1); assertEquals(- amount_t("0.008121"), amount_t(-1.0) / x1);
assertEquals(- amount_t("0.008121"), -1.0 / x1);
assertEquals(amount_t("0.269736842105"), x1 / y1); assertEquals(amount_t("0.269736842105"), x1 / y1);
assertEquals(amount_t("3.707317073170"), y1 / x1); assertEquals(amount_t("3.707317073170"), y1 / x1);
assertEquals(amount_t("0.269736842105"), x1 / 456.456); assertEquals(amount_t("0.269736842105"), x1 / 456.456);
assertEquals(amount_t("3.707317073170"), amount_t(456.456) / x1); assertEquals(amount_t("3.707317073170"), amount_t(456.456) / x1);
assertEquals(amount_t("3.707317073170"), 456.456 / x1);
x1 /= amount_t(456.456); x1 /= amount_t(456.456);
assertEquals(amount_t("0.269736842105"), x1); assertEquals(amount_t("0.269736842105"), x1);

View file

@ -10,6 +10,7 @@ namespace ledger {
class transform_t { class transform_t {
public: public:
virtual ~transform_t() {}
virtual void execute(xml::document_t * document) = 0; virtual void execute(xml::document_t * document) = 0;
}; };

View file

@ -73,7 +73,7 @@ std::string abbreviate(const std::string& str, unsigned int width,
elision_style_t elision_style, const bool is_account, elision_style_t elision_style, const bool is_account,
int abbrev_length) int abbrev_length)
{ {
const int len = str.length(); const unsigned int len = str.length();
if (len <= width) if (len <= width)
return str; return str;
@ -110,7 +110,7 @@ std::string abbreviate(const std::string& str, unsigned int width,
parts.push_back(std::string(str, beg)); parts.push_back(std::string(str, beg));
std::string result; std::string result;
int newlen = len; unsigned int newlen = len;
for (std::list<std::string>::iterator i = parts.begin(); for (std::list<std::string>::iterator i = parts.begin();
i != parts.end(); i != parts.end();
i++) { i++) {

488
value.cc

File diff suppressed because it is too large Load diff

239
value.h
View file

@ -49,62 +49,62 @@ class value_t
type = INTEGER; type = INTEGER;
} }
value_t(const value_t& value) : type(INTEGER) { value_t(const value_t& val) : type(INTEGER) {
TRACE_CTOR("value_t(copy)"); TRACE_CTOR("value_t(copy)");
*this = value; *this = val;
} }
value_t(const bool value) { value_t(const bool val) {
TRACE_CTOR("value_t(const bool)"); TRACE_CTOR("value_t(const bool)");
*((bool *) data) = value; *((bool *) data) = val;
type = BOOLEAN; type = BOOLEAN;
} }
value_t(const long value) { value_t(const long val) {
TRACE_CTOR("value_t(const long)"); TRACE_CTOR("value_t(const long)");
*((long *) data) = value; *((long *) data) = val;
type = INTEGER; type = INTEGER;
} }
value_t(const datetime_t value) { value_t(const datetime_t val) {
TRACE_CTOR("value_t(const datetime_t)"); TRACE_CTOR("value_t(const datetime_t)");
*((datetime_t *) data) = value; *((datetime_t *) data) = val;
type = DATETIME; type = DATETIME;
} }
value_t(const unsigned long value) { value_t(const unsigned long val) {
TRACE_CTOR("value_t(const unsigned long)"); TRACE_CTOR("value_t(const unsigned long)");
new((amount_t *) data) amount_t(value); new((amount_t *) data) amount_t(val);
type = AMOUNT; type = AMOUNT;
} }
value_t(const double value) { value_t(const double val) {
TRACE_CTOR("value_t(const double)"); TRACE_CTOR("value_t(const double)");
new((amount_t *) data) amount_t(value); new((amount_t *) data) amount_t(val);
type = AMOUNT; type = AMOUNT;
} }
value_t(const std::string& value, bool literal = false) { value_t(const std::string& val, bool literal = false) {
TRACE_CTOR("value_t(const std::string&, bool)"); TRACE_CTOR("value_t(const std::string&, bool)");
if (literal) { if (literal) {
type = INTEGER; type = INTEGER;
set_string(value); set_string(val);
} else { } else {
new((amount_t *) data) amount_t(value); new((amount_t *) data) amount_t(val);
type = AMOUNT; type = AMOUNT;
} }
} }
value_t(const char * value) { value_t(const char * val) {
TRACE_CTOR("value_t(const char *)"); TRACE_CTOR("value_t(const char *)");
new((amount_t *) data) amount_t(value); new((amount_t *) data) amount_t(val);
type = AMOUNT; type = AMOUNT;
} }
value_t(const amount_t& value) { value_t(const amount_t& val) {
TRACE_CTOR("value_t(const amount_t&)"); TRACE_CTOR("value_t(const amount_t&)");
new((amount_t *)data) amount_t(value); new((amount_t *)data) amount_t(val);
type = AMOUNT; type = AMOUNT;
} }
value_t(const balance_t& value) : type(INTEGER) { value_t(const balance_t& val) : type(INTEGER) {
TRACE_CTOR("value_t(const balance_t&)"); TRACE_CTOR("value_t(const balance_t&)");
*this = value; *this = val;
} }
value_t(const balance_pair_t& value) : type(INTEGER) { value_t(const balance_pair_t& val) : type(INTEGER) {
TRACE_CTOR("value_t(const balance_pair_t&)"); TRACE_CTOR("value_t(const balance_pair_t&)");
*this = value; *this = val;
} }
value_t(xml::node_t * xml_node) : type(INTEGER) { // gets set in = value_t(xml::node_t * xml_node) : type(INTEGER) { // gets set in =
TRACE_CTOR("value_t(xml::node_t *)"); TRACE_CTOR("value_t(xml::node_t *)");
@ -127,89 +127,89 @@ class value_t
void destroy(); void destroy();
void simplify(); void simplify();
value_t& operator=(const value_t& value); value_t& operator=(const value_t& val);
value_t& operator=(const bool value) { value_t& operator=(const bool val) {
if ((bool *) data != &value) { if ((bool *) data != &val) {
destroy(); destroy();
*((bool *) data) = value; *((bool *) data) = val;
type = BOOLEAN; type = BOOLEAN;
} }
return *this; return *this;
} }
value_t& operator=(const long value) { value_t& operator=(const long val) {
if ((long *) data != &value) { if ((long *) data != &val) {
destroy(); destroy();
*((long *) data) = value; *((long *) data) = val;
type = INTEGER; type = INTEGER;
} }
return *this; return *this;
} }
value_t& operator=(const datetime_t value) { value_t& operator=(const datetime_t val) {
if ((datetime_t *) data != &value) { if ((datetime_t *) data != &val) {
destroy(); destroy();
*((datetime_t *) data) = value; *((datetime_t *) data) = val;
type = DATETIME; type = DATETIME;
} }
return *this; return *this;
} }
value_t& operator=(const unsigned long value) { value_t& operator=(const unsigned long val) {
return *this = amount_t(value); return *this = amount_t(val);
} }
value_t& operator=(const double value) { value_t& operator=(const double val) {
return *this = amount_t(value); return *this = amount_t(val);
} }
value_t& operator=(const std::string& value) { value_t& operator=(const std::string& val) {
return *this = amount_t(value); return *this = amount_t(val);
} }
value_t& operator=(const char * value) { value_t& operator=(const char * val) {
return *this = amount_t(value); return *this = amount_t(val);
} }
value_t& operator=(const amount_t& value) { value_t& operator=(const amount_t& val) {
if (type == AMOUNT && if (type == AMOUNT &&
(amount_t *) data == &value) (amount_t *) data == &val)
return *this; return *this;
if (value.realzero()) { if (val.realzero()) {
return *this = 0L; return *this = 0L;
} else { } else {
destroy(); destroy();
new((amount_t *)data) amount_t(value); new((amount_t *)data) amount_t(val);
type = AMOUNT; type = AMOUNT;
} }
return *this; return *this;
} }
value_t& operator=(const balance_t& value) { value_t& operator=(const balance_t& val) {
if (type == BALANCE && if (type == BALANCE &&
(balance_t *) data == &value) (balance_t *) data == &val)
return *this; return *this;
if (value.realzero()) { if (val.realzero()) {
return *this = 0L; return *this = 0L;
} }
else if (value.amounts.size() == 1) { else if (val.amounts.size() == 1) {
return *this = (*value.amounts.begin()).second; return *this = (*val.amounts.begin()).second;
} }
else { else {
destroy(); destroy();
new((balance_t *)data) balance_t(value); new((balance_t *)data) balance_t(val);
type = BALANCE; type = BALANCE;
return *this; return *this;
} }
} }
value_t& operator=(const balance_pair_t& value) { value_t& operator=(const balance_pair_t& val) {
if (type == BALANCE_PAIR && if (type == BALANCE_PAIR &&
(balance_pair_t *) data == &value) (balance_pair_t *) data == &val)
return *this; return *this;
if (value.realzero()) { if (val.realzero()) {
return *this = 0L; return *this = 0L;
} }
else if (! value.cost) { else if (! val.cost) {
return *this = value.quantity; return *this = val.quantity;
} }
else { else {
destroy(); destroy();
new((balance_pair_t *)data) balance_pair_t(value); new((balance_pair_t *)data) balance_pair_t(val);
type = BALANCE_PAIR; type = BALANCE_PAIR;
return *this; return *this;
} }
@ -291,10 +291,10 @@ class value_t
return (*seq)[index]; return (*seq)[index];
} }
void push_back(const value_t& value) { void push_back(const value_t& val) {
sequence_t * seq = to_sequence(); sequence_t * seq = to_sequence();
assert(seq); assert(seq);
return seq->push_back(value); return seq->push_back(val);
} }
std::size_t size() const { std::size_t size() const {
@ -303,98 +303,98 @@ class value_t
return seq->size(); return seq->size();
} }
value_t& operator+=(const value_t& value); value_t& operator+=(const value_t& val);
value_t& operator-=(const value_t& value); value_t& operator-=(const value_t& val);
value_t& operator*=(const value_t& value); value_t& operator*=(const value_t& val);
value_t& operator/=(const value_t& value); value_t& operator/=(const value_t& val);
template <typename T> template <typename T>
value_t& operator+=(const T& value) { value_t& operator+=(const T& val) {
return *this += value_t(value); return *this += value_t(val);
} }
template <typename T> template <typename T>
value_t& operator-=(const T& value) { value_t& operator-=(const T& val) {
return *this -= value_t(value); return *this -= value_t(val);
} }
template <typename T> template <typename T>
value_t& operator*=(const T& value) { value_t& operator*=(const T& val) {
return *this *= value_t(value); return *this *= value_t(val);
} }
template <typename T> template <typename T>
value_t& operator/=(const T& value) { value_t& operator/=(const T& val) {
return *this /= value_t(value); return *this /= value_t(val);
} }
value_t operator+(const value_t& value) { value_t operator+(const value_t& val) {
value_t temp(*this); value_t temp(*this);
temp += value; temp += val;
return temp; return temp;
} }
value_t operator-(const value_t& value) { value_t operator-(const value_t& val) {
value_t temp(*this); value_t temp(*this);
temp -= value; temp -= val;
return temp; return temp;
} }
value_t operator*(const value_t& value) { value_t operator*(const value_t& val) {
value_t temp(*this); value_t temp(*this);
temp *= value; temp *= val;
return temp; return temp;
} }
value_t operator/(const value_t& value) { value_t operator/(const value_t& val) {
value_t temp(*this); value_t temp(*this);
temp /= value; temp /= val;
return temp; return temp;
} }
template <typename T> template <typename T>
value_t operator+(const T& value) { value_t operator+(const T& val) {
return *this + value_t(value); return *this + value_t(val);
} }
template <typename T> template <typename T>
value_t operator-(const T& value) { value_t operator-(const T& val) {
return *this - value_t(value); return *this - value_t(val);
} }
template <typename T> template <typename T>
value_t operator*(const T& value) { value_t operator*(const T& val) {
return *this * value_t(value); return *this * value_t(val);
} }
template <typename T> template <typename T>
value_t operator/(const T& value) { value_t operator/(const T& val) {
return *this / value_t(value); return *this / value_t(val);
} }
bool operator<(const value_t& value); bool operator<(const value_t& val);
bool operator<=(const value_t& value); bool operator<=(const value_t& val);
bool operator>(const value_t& value); bool operator>(const value_t& val);
bool operator>=(const value_t& value); bool operator>=(const value_t& val);
bool operator==(const value_t& value); bool operator==(const value_t& val);
bool operator!=(const value_t& value) { bool operator!=(const value_t& val) {
return ! (*this == value); return ! (*this == val);
} }
template <typename T> template <typename T>
bool operator<(const T& value) { bool operator<(const T& val) {
return *this < value_t(value); return *this < value_t(val);
} }
template <typename T> template <typename T>
bool operator<=(const T& value) { bool operator<=(const T& val) {
return *this <= value_t(value); return *this <= value_t(val);
} }
template <typename T> template <typename T>
bool operator>(const T& value) { bool operator>(const T& val) {
return *this > value_t(value); return *this > value_t(val);
} }
template <typename T> template <typename T>
bool operator>=(const T& value) { bool operator>=(const T& val) {
return *this >= value_t(value); return *this >= value_t(val);
} }
template <typename T> template <typename T>
bool operator==(const T& value) { bool operator==(const T& val) {
return *this == value_t(value); return *this == value_t(val);
} }
template <typename T> template <typename T>
bool operator!=(const T& value) { bool operator!=(const T& val) {
return ! (*this == value); return ! (*this == val);
} }
template <typename T> template <typename T>
@ -467,21 +467,21 @@ class value_t
}; };
#define DEF_VALUE_AUX_OP(OP) \ #define DEF_VALUE_AUX_OP(OP) \
inline value_t operator OP(const balance_pair_t& value, \ inline value_t operator OP(const balance_pair_t& val, \
const value_t& obj) { \ const value_t& obj) { \
return value_t(value) OP obj; \ return value_t(val) OP obj; \
} \ } \
inline value_t operator OP(const balance_t& value, \ inline value_t operator OP(const balance_t& val, \
const value_t& obj) { \ const value_t& obj) { \
return value_t(value) OP obj; \ return value_t(val) OP obj; \
} \ } \
inline value_t operator OP(const amount_t& value, \ inline value_t operator OP(const amount_t& val, \
const value_t& obj) { \ const value_t& obj) { \
return value_t(value) OP obj; \ return value_t(val) OP obj; \
} \ } \
template <typename T> \ template <typename T> \
inline value_t operator OP(T value, const value_t& obj) { \ inline value_t operator OP(T val, const value_t& obj) { \
return value_t(value) OP obj; \ return value_t(val) OP obj; \
} }
DEF_VALUE_AUX_OP(+) DEF_VALUE_AUX_OP(+)
@ -533,13 +533,13 @@ template <> value_t::operator datetime_t() const;
template <> value_t::operator double() const; template <> value_t::operator double() const;
template <> value_t::operator std::string() const; template <> value_t::operator std::string() const;
inline value_t abs(const value_t& value) { inline value_t abs(const value_t& val) {
value_t temp(value); value_t temp(val);
temp.abs(); temp.abs();
return temp; return temp;
} }
std::ostream& operator<<(std::ostream& out, const value_t& value); std::ostream& operator<<(std::ostream& out, const value_t& val);
class value_context : public error_context class value_context : public error_context
{ {
@ -554,8 +554,9 @@ class value_context : public error_context
class value_error : public error { class value_error : public error {
public: public:
value_error(const std::string& reason, error_context * ctxt = NULL) throw() value_error(const std::string& _reason,
: error(reason, ctxt) {} error_context * _ctxt = NULL) throw()
: error(_reason, _ctxt) {}
virtual ~value_error() throw() {} virtual ~value_error() throw() {}
}; };

11
xml.cc
View file

@ -10,7 +10,7 @@
namespace ledger { namespace ledger {
namespace xml { namespace xml {
document_t::document_t(node_t * _top, const char ** _builtins, document_t::document_t(node_t *, const char ** _builtins,
const int _builtins_size) const int _builtins_size)
: builtins(_builtins), builtins_size(_builtins_size), : builtins(_builtins), builtins_size(_builtins_size),
top(new terminal_node_t(this)) {} top(new terminal_node_t(this)) {}
@ -99,9 +99,8 @@ document_t * node_t::document;
node_t::node_t(document_t * _document, parent_node_t * _parent, node_t::node_t(document_t * _document, parent_node_t * _parent,
unsigned int _flags) unsigned int _flags)
: name_id(-1), : name_id(0), parent(_parent), next(NULL), prev(NULL),
parent(_parent), flags(_flags), info(NULL), attrs(NULL)
next(NULL), prev(NULL), flags(_flags), info(NULL), attrs(NULL)
{ {
TRACE_CTOR("node_t(document_t *, node_t *)"); TRACE_CTOR("node_t(document_t *, node_t *)");
#ifdef THREADSAFE #ifdef THREADSAFE
@ -144,9 +143,9 @@ void parent_node_t::clear()
{ {
node_t * child = _children; node_t * child = _children;
while (child) { while (child) {
node_t * next = child->next; node_t * tnext = child->next;
delete child; delete child;
child = next; child = tnext;
} }
} }

33
xml.h
View file

@ -63,7 +63,7 @@ class parent_node_t;
class node_t class node_t
{ {
public: public:
int name_id; unsigned int name_id;
#ifdef THREADSAFE #ifdef THREADSAFE
document_t * document; document_t * document;
#else #else
@ -210,6 +210,7 @@ class parser_t
parser_t() : document(NULL), pending(NULL), pending_attrs(NULL), parser_t() : document(NULL), pending(NULL), pending_attrs(NULL),
handled_data(false) {} handled_data(false) {}
virtual ~parser_t() {}
virtual bool test(std::istream& in) const; virtual bool test(std::istream& in) const;
virtual document_t * parse(std::istream& in, virtual document_t * parse(std::istream& in,
@ -219,8 +220,9 @@ class parser_t
class parse_error : public error { class parse_error : public error {
public: public:
parse_error(const std::string& reason, error_context * ctxt = NULL) throw() parse_error(const std::string& _reason,
: error(reason, ctxt) {} error_context * _ctxt = NULL) throw()
: error(_reason, _ctxt) {}
virtual ~parse_error() throw() {} virtual ~parse_error() throw() {}
}; };
@ -231,9 +233,10 @@ class transaction_node_t : public parent_node_t
transaction_t * transaction; transaction_t * transaction;
public: public:
transaction_node_t(document_t * document, transaction_t * _transaction, transaction_node_t(document_t * _document,
parent_node_t * parent = NULL) transaction_t * _transaction,
: parent_node_t(document, parent), transaction(_transaction) { parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), transaction(_transaction) {
TRACE_CTOR("transaction_node_t(document_t *, transaction_t *, parent_node_t *)"); TRACE_CTOR("transaction_node_t(document_t *, transaction_t *, parent_node_t *)");
set_name("transaction"); set_name("transaction");
} }
@ -249,9 +252,9 @@ class entry_node_t : public parent_node_t
entry_t * entry; entry_t * entry;
public: public:
entry_node_t(document_t * document, entry_t * _entry, entry_node_t(document_t * _document, entry_t * _entry,
parent_node_t * parent = NULL) parent_node_t * _parent = NULL)
: parent_node_t(document, parent), entry(_entry) { : parent_node_t(_document, _parent), entry(_entry) {
TRACE_CTOR("entry_node_t(document_t *, entry_t *, parent_node_t *)"); TRACE_CTOR("entry_node_t(document_t *, entry_t *, parent_node_t *)");
set_name("entry"); set_name("entry");
} }
@ -267,9 +270,9 @@ class account_node_t : public parent_node_t
account_t * account; account_t * account;
public: public:
account_node_t(document_t * document, account_t * _account, account_node_t(document_t * _document, account_t * _account,
parent_node_t * parent = NULL) parent_node_t * _parent = NULL)
: parent_node_t(document, parent), account(_account) { : parent_node_t(_document, _parent), account(_account) {
TRACE_CTOR("account_node_t(document_t *, account_t *, parent_node_t *)"); TRACE_CTOR("account_node_t(document_t *, account_t *, parent_node_t *)");
set_name("account"); set_name("account");
} }
@ -285,9 +288,9 @@ class journal_node_t : public parent_node_t
journal_t * journal; journal_t * journal;
public: public:
journal_node_t(document_t * document, journal_t * _journal, journal_node_t(document_t * _document, journal_t * _journal,
parent_node_t * parent = NULL) parent_node_t * _parent = NULL)
: parent_node_t(document, parent), journal(_journal) { : parent_node_t(_document, _parent), journal(_journal) {
TRACE_CTOR("journal_node_t(document_t *, journal_t *, parent_node_t *)"); TRACE_CTOR("journal_node_t(document_t *, journal_t *, parent_node_t *)");
set_name("journal"); set_name("journal");
} }

283
xpath.cc
View file

@ -397,7 +397,7 @@ void xpath_t::token_t::next(std::istream& in, unsigned short flags)
void xpath_t::token_t::rewind(std::istream& in) void xpath_t::token_t::rewind(std::istream& in)
{ {
for (int i = 0; i < length; i++) for (unsigned int i = 0; i < length; i++)
in.unget(); in.unget();
} }
@ -484,9 +484,9 @@ void xpath_t::scope_t::define(const std::string& name, op_t * def)
(*i).second->release(); (*i).second->release();
symbols.erase(i); symbols.erase(i);
std::pair<symbol_map::iterator, bool> result std::pair<symbol_map::iterator, bool> result2
= symbols.insert(symbol_pair(name, def)); = symbols.insert(symbol_pair(name, def));
if (! result.second) if (! result2.second)
throw new compile_error(std::string("Redefinition of '") + throw new compile_error(std::string("Redefinition of '") +
name + "' in same scope"); name + "' in same scope");
} }
@ -613,11 +613,11 @@ void xpath_t::op_t::get_value(value_t& result) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_value_term(std::istream& in, unsigned short flags) const xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node; std::auto_ptr<op_t> node;
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
switch (tok.kind) { switch (tok.kind) {
case token_t::VALUE: case token_t::VALUE:
@ -626,6 +626,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short flags) const
break; break;
case token_t::IDENT: { case token_t::IDENT: {
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
if (tok.value->to_string() == "lambda") // special if (tok.value->to_string() == "lambda") // special
try { try {
@ -649,6 +650,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short flags) const
catch(const boost::python::error_already_set&) { catch(const boost::python::error_already_set&) {
throw new parse_error("Error parsing lambda expression"); throw new parse_error("Error parsing lambda expression");
} }
#endif /* USE_BOOST_PYTHON */
#endif #endif
std::string ident = tok.value.to_string(); std::string ident = tok.value.to_string();
@ -661,16 +663,16 @@ xpath_t::parse_value_term(std::istream& in, unsigned short flags) const
} }
// An identifier followed by ( represents a function call // An identifier followed by ( represents a function call
tok = next_token(in, flags); tok = next_token(in, tflags);
if (tok.kind == token_t::LPAREN) { if (tok.kind == token_t::LPAREN) {
node->kind = op_t::FUNC_NAME; node->kind = op_t::FUNC_NAME;
std::auto_ptr<op_t> call_node; std::auto_ptr<op_t> call_node;
call_node.reset(new op_t(op_t::O_EVAL)); call_node.reset(new op_t(op_t::O_EVAL));
call_node->set_left(node.release()); call_node->set_left(node.release());
call_node->set_right(parse_value_expr(in, flags | XPATH_PARSE_PARTIAL)); call_node->set_right(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL));
tok = next_token(in, flags); tok = next_token(in, tflags);
if (tok.kind != token_t::RPAREN) if (tok.kind != token_t::RPAREN)
tok.unexpected(); // jww (2006-09-09): wanted ) tok.unexpected(); // jww (2006-09-09): wanted )
@ -682,7 +684,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short flags) const
} }
case token_t::AT_SYM: case token_t::AT_SYM:
tok = next_token(in, flags); tok = next_token(in, tflags);
if (tok.kind != token_t::IDENT) if (tok.kind != token_t::IDENT)
throw parse_error("@ symbol must be followed by attribute name"); throw parse_error("@ symbol must be followed by attribute name");
@ -692,7 +694,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short flags) const
#if 0 #if 0
case token_t::DOLLAR: case token_t::DOLLAR:
tok = next_token(in, flags); tok = next_token(in, tflags);
if (tok.kind != token_t::IDENT) if (tok.kind != token_t::IDENT)
throw parse_error("$ symbol must be followed by variable name"); throw parse_error("$ symbol must be followed by variable name");
@ -719,11 +721,11 @@ xpath_t::parse_value_term(std::istream& in, unsigned short flags) const
break; break;
case token_t::LPAREN: case token_t::LPAREN:
node.reset(parse_value_expr(in, flags | XPATH_PARSE_PARTIAL)); node.reset(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL));
if (! node.get()) if (! node.get())
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
tok = next_token(in, flags); tok = next_token(in, tflags);
if (tok.kind != token_t::RPAREN) if (tok.kind != token_t::RPAREN)
tok.unexpected(); // jww (2006-09-09): wanted ) tok.unexpected(); // jww (2006-09-09): wanted )
break; break;
@ -739,30 +741,34 @@ xpath_t::parse_value_term(std::istream& in, unsigned short flags) const
break; break;
} }
#if 0
#ifdef USE_BOOST_PYTHON
done: done:
#endif
#endif
return node.release(); return node.release();
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_predicate_expr(std::istream& in, unsigned short flags) const xpath_t::parse_predicate_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_value_term(in, flags)); std::auto_ptr<op_t> node(parse_value_term(in, tflags));
if (node.get()) { if (node.get()) {
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
while (tok.kind == token_t::LBRACKET) { while (tok.kind == token_t::LBRACKET) {
std::auto_ptr<op_t> prev(node.release()); std::auto_ptr<op_t> prev(node.release());
node.reset(new op_t(op_t::O_PRED)); node.reset(new op_t(op_t::O_PRED));
node->set_left(prev.release()); node->set_left(prev.release());
node->set_right(parse_value_expr(in, flags | XPATH_PARSE_PARTIAL)); node->set_right(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL));
if (! node->right) if (! node->right)
throw new parse_error("[ operator not followed by valid expression"); throw new parse_error("[ operator not followed by valid expression");
tok = next_token(in, flags); tok = next_token(in, tflags);
if (tok.kind != token_t::RBRACKET) if (tok.kind != token_t::RBRACKET)
tok.unexpected(); // jww (2006-09-09): wanted ] tok.unexpected(); // jww (2006-09-09): wanted ]
tok = next_token(in, flags); tok = next_token(in, tflags);
} }
push_token(tok); push_token(tok);
@ -772,9 +778,9 @@ xpath_t::parse_predicate_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_path_expr(std::istream& in, unsigned short flags) const xpath_t::parse_path_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_predicate_expr(in, flags)); std::auto_ptr<op_t> node(parse_predicate_expr(in, tflags));
if (node.get()) { if (node.get()) {
// If the beginning of the path was /, just put it back; this // If the beginning of the path was /, just put it back; this
@ -782,22 +788,22 @@ xpath_t::parse_path_expr(std::istream& in, unsigned short flags) const
if (node->kind == op_t::NODE_ID && node->name_id == document_t::ROOT) if (node->kind == op_t::NODE_ID && node->name_id == document_t::ROOT)
push_token(); push_token();
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
while (tok.kind == token_t::SLASH) { while (tok.kind == token_t::SLASH) {
std::auto_ptr<op_t> prev(node.release()); std::auto_ptr<op_t> prev(node.release());
tok = next_token(in, flags); tok = next_token(in, tflags);
node.reset(new op_t(tok.kind == token_t::SLASH ? node.reset(new op_t(tok.kind == token_t::SLASH ?
op_t::O_RFIND : op_t::O_FIND)); op_t::O_RFIND : op_t::O_FIND));
if (tok.kind != token_t::SLASH) if (tok.kind != token_t::SLASH)
push_token(tok); push_token(tok);
node->set_left(prev.release()); node->set_left(prev.release());
node->set_right(parse_predicate_expr(in, flags)); node->set_right(parse_predicate_expr(in, tflags));
if (! node->right) if (! node->right)
throw new parse_error("/ operator not followed by a valid term"); throw new parse_error("/ operator not followed by a valid term");
tok = next_token(in, flags); tok = next_token(in, tflags);
} }
push_token(tok); push_token(tok);
@ -807,59 +813,59 @@ xpath_t::parse_path_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_unary_expr(std::istream& in, unsigned short flags) const xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node; std::auto_ptr<op_t> node;
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
switch (tok.kind) { switch (tok.kind) {
case token_t::EXCLAM: { case token_t::EXCLAM: {
std::auto_ptr<op_t> expr(parse_path_expr(in, flags)); std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags));
if (! expr.get()) if (! texpr.get())
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
// A very quick optimization // A very quick optimization
if (expr->kind == op_t::VALUE) { if (texpr->kind == op_t::VALUE) {
*expr->valuep = ! *expr->valuep; *texpr->valuep = ! *texpr->valuep;
node.reset(expr.release()); node.reset(texpr.release());
} else { } else {
node.reset(new op_t(op_t::O_NOT)); node.reset(new op_t(op_t::O_NOT));
node->set_left(expr.release()); node->set_left(texpr.release());
} }
break; break;
} }
case token_t::MINUS: { case token_t::MINUS: {
std::auto_ptr<op_t> expr(parse_path_expr(in, flags)); std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags));
if (! expr.get()) if (! texpr.get())
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
// A very quick optimization // A very quick optimization
if (expr->kind == op_t::VALUE) { if (texpr->kind == op_t::VALUE) {
expr->valuep->negate(); texpr->valuep->negate();
node.reset(expr.release()); node.reset(texpr.release());
} else { } else {
node.reset(new op_t(op_t::O_NEG)); node.reset(new op_t(op_t::O_NEG));
node->set_left(expr.release()); node->set_left(texpr.release());
} }
break; break;
} }
#if 0 #if 0
case token_t::PERCENT: { case token_t::PERCENT: {
std::auto_ptr<op_t> expr(parse_path_expr(in, flags)); std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags));
if (! expr.get()) if (! texpr.get())
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
// A very quick optimization // A very quick optimization
if (expr->kind == op_t::VALUE) { if (texpr->kind == op_t::VALUE) {
static value_t perc("100.0%"); static value_t perc("100.0%");
*expr->valuep = perc * *expr->valuep; *texpr->valuep = perc * *texpr->valuep;
node.reset(expr.release()); node.reset(texpr.release());
} else { } else {
node.reset(new op_t(op_t::O_PERC)); node.reset(new op_t(op_t::O_PERC));
node->set_left(expr.release()); node->set_left(texpr.release());
} }
break; break;
} }
@ -867,7 +873,7 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short flags) const
default: default:
push_token(tok); push_token(tok);
node.reset(parse_path_expr(in, flags)); node.reset(parse_path_expr(in, tflags));
break; break;
} }
@ -875,17 +881,17 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_union_expr(std::istream& in, unsigned short flags) const xpath_t::parse_union_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_unary_expr(in, flags)); std::auto_ptr<op_t> node(parse_unary_expr(in, tflags));
if (node.get()) { if (node.get()) {
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::PIPE || tok.kind == token_t::KW_UNION) { if (tok.kind == token_t::PIPE || tok.kind == token_t::KW_UNION) {
std::auto_ptr<op_t> prev(node.release()); std::auto_ptr<op_t> prev(node.release());
node.reset(new op_t(op_t::O_UNION)); node.reset(new op_t(op_t::O_UNION));
node->set_left(prev.release()); node->set_left(prev.release());
node->set_right(parse_union_expr(in, flags)); node->set_right(parse_union_expr(in, tflags));
if (! node->right) if (! node->right)
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
@ -897,23 +903,23 @@ xpath_t::parse_union_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_mul_expr(std::istream& in, unsigned short flags) const xpath_t::parse_mul_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_union_expr(in, flags)); std::auto_ptr<op_t> node(parse_union_expr(in, tflags));
if (node.get()) { if (node.get()) {
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::STAR || tok.kind == token_t::KW_DIV) { if (tok.kind == token_t::STAR || tok.kind == token_t::KW_DIV) {
std::auto_ptr<op_t> prev(node.release()); std::auto_ptr<op_t> prev(node.release());
node.reset(new op_t(tok.kind == token_t::STAR ? node.reset(new op_t(tok.kind == token_t::STAR ?
op_t::O_MUL : op_t::O_DIV)); op_t::O_MUL : op_t::O_DIV));
node->set_left(prev.release()); node->set_left(prev.release());
node->set_right(parse_mul_expr(in, flags)); node->set_right(parse_mul_expr(in, tflags));
if (! node->right) if (! node->right)
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
tok = next_token(in, flags); tok = next_token(in, tflags);
} }
push_token(tok); push_token(tok);
} }
@ -922,24 +928,24 @@ xpath_t::parse_mul_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_add_expr(std::istream& in, unsigned short flags) const xpath_t::parse_add_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_mul_expr(in, flags)); std::auto_ptr<op_t> node(parse_mul_expr(in, tflags));
if (node.get()) { if (node.get()) {
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::PLUS || if (tok.kind == token_t::PLUS ||
tok.kind == token_t::MINUS) { tok.kind == token_t::MINUS) {
std::auto_ptr<op_t> prev(node.release()); std::auto_ptr<op_t> prev(node.release());
node.reset(new op_t(tok.kind == token_t::PLUS ? node.reset(new op_t(tok.kind == token_t::PLUS ?
op_t::O_ADD : op_t::O_SUB)); op_t::O_ADD : op_t::O_SUB));
node->set_left(prev.release()); node->set_left(prev.release());
node->set_right(parse_add_expr(in, flags)); node->set_right(parse_add_expr(in, tflags));
if (! node->right) if (! node->right)
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
tok = next_token(in, flags); tok = next_token(in, tflags);
} }
push_token(tok); push_token(tok);
} }
@ -948,16 +954,16 @@ xpath_t::parse_add_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_logic_expr(std::istream& in, unsigned short flags) const xpath_t::parse_logic_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_add_expr(in, flags)); std::auto_ptr<op_t> node(parse_add_expr(in, tflags));
if (node.get()) { if (node.get()) {
op_t::kind_t kind = op_t::LAST; op_t::kind_t kind = op_t::LAST;
unsigned short _flags = flags; unsigned short _flags = tflags;
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
switch (tok.kind) { switch (tok.kind) {
case token_t::ASSIGN: case token_t::ASSIGN:
kind = op_t::O_DEFINE; kind = op_t::O_DEFINE;
@ -1000,7 +1006,7 @@ xpath_t::parse_logic_expr(std::istream& in, unsigned short flags) const
node.reset(new op_t(kind)); node.reset(new op_t(kind));
node->set_left(prev.release()); node->set_left(prev.release());
if (kind == op_t::O_DEFINE) if (kind == op_t::O_DEFINE)
node->set_right(parse_querycolon_expr(in, flags)); node->set_right(parse_querycolon_expr(in, tflags));
else else
node->set_right(parse_add_expr(in, _flags)); node->set_right(parse_add_expr(in, _flags));
@ -1019,17 +1025,17 @@ xpath_t::parse_logic_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_and_expr(std::istream& in, unsigned short flags) const xpath_t::parse_and_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_logic_expr(in, flags)); std::auto_ptr<op_t> node(parse_logic_expr(in, tflags));
if (node.get()) { if (node.get()) {
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::KW_AND) { if (tok.kind == token_t::KW_AND) {
std::auto_ptr<op_t> prev(node.release()); std::auto_ptr<op_t> prev(node.release());
node.reset(new op_t(op_t::O_AND)); node.reset(new op_t(op_t::O_AND));
node->set_left(prev.release()); node->set_left(prev.release());
node->set_right(parse_and_expr(in, flags)); node->set_right(parse_and_expr(in, tflags));
if (! node->right) if (! node->right)
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
@ -1041,17 +1047,17 @@ xpath_t::parse_and_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_or_expr(std::istream& in, unsigned short flags) const xpath_t::parse_or_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_and_expr(in, flags)); std::auto_ptr<op_t> node(parse_and_expr(in, tflags));
if (node.get()) { if (node.get()) {
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::KW_OR) { if (tok.kind == token_t::KW_OR) {
std::auto_ptr<op_t> prev(node.release()); std::auto_ptr<op_t> prev(node.release());
node.reset(new op_t(op_t::O_OR)); node.reset(new op_t(op_t::O_OR));
node->set_left(prev.release()); node->set_left(prev.release());
node->set_right(parse_or_expr(in, flags)); node->set_right(parse_or_expr(in, tflags));
if (! node->right) if (! node->right)
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
@ -1063,25 +1069,25 @@ xpath_t::parse_or_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_querycolon_expr(std::istream& in, unsigned short flags) const xpath_t::parse_querycolon_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_or_expr(in, flags)); std::auto_ptr<op_t> node(parse_or_expr(in, tflags));
if (node.get()) { if (node.get()) {
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::QUESTION) { if (tok.kind == token_t::QUESTION) {
std::auto_ptr<op_t> prev(node.release()); std::auto_ptr<op_t> prev(node.release());
node.reset(new op_t(op_t::O_QUES)); node.reset(new op_t(op_t::O_QUES));
node->set_left(prev.release()); node->set_left(prev.release());
node->set_right(new op_t(op_t::O_COLON)); node->set_right(new op_t(op_t::O_COLON));
node->right->set_left(parse_querycolon_expr(in, flags)); node->right->set_left(parse_querycolon_expr(in, tflags));
if (! node->right) if (! node->right)
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
tok = next_token(in, flags); tok = next_token(in, tflags);
if (tok.kind != token_t::COLON) if (tok.kind != token_t::COLON)
tok.unexpected(); // jww (2006-09-09): wanted : tok.unexpected(); // jww (2006-09-09): wanted :
node->right->set_right(parse_querycolon_expr(in, flags)); node->right->set_right(parse_querycolon_expr(in, tflags));
if (! node->right) if (! node->right)
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
@ -1093,31 +1099,31 @@ xpath_t::parse_querycolon_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_value_expr(std::istream& in, unsigned short flags) const xpath_t::parse_value_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_querycolon_expr(in, flags)); std::auto_ptr<op_t> node(parse_querycolon_expr(in, tflags));
if (node.get()) { if (node.get()) {
token_t& tok = next_token(in, flags); token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::COMMA) { if (tok.kind == token_t::COMMA) {
std::auto_ptr<op_t> prev(node.release()); std::auto_ptr<op_t> prev(node.release());
node.reset(new op_t(op_t::O_COMMA)); node.reset(new op_t(op_t::O_COMMA));
node->set_left(prev.release()); node->set_left(prev.release());
node->set_right(parse_value_expr(in, flags)); node->set_right(parse_value_expr(in, tflags));
if (! node->right) if (! node->right)
throw new parse_error(std::string(tok.symbol) + throw new parse_error(std::string(tok.symbol) +
" operator not followed by argument"); " operator not followed by argument");
tok = next_token(in, flags); tok = next_token(in, tflags);
} }
if (tok.kind != token_t::TOK_EOF) { if (tok.kind != token_t::TOK_EOF) {
if (flags & XPATH_PARSE_PARTIAL) if (tflags & XPATH_PARSE_PARTIAL)
push_token(tok); push_token(tok);
else else
tok.unexpected(); tok.unexpected();
} }
} }
else if (! (flags & XPATH_PARSE_PARTIAL)) { else if (! (tflags & XPATH_PARSE_PARTIAL)) {
throw new parse_error(std::string("Failed to parse value expression")); throw new parse_error(std::string("Failed to parse value expression"));
} }
@ -1125,9 +1131,9 @@ xpath_t::parse_value_expr(std::istream& in, unsigned short flags) const
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::parse_expr(std::istream& in, unsigned short flags) const xpath_t::parse_expr(std::istream& in, unsigned short tflags) const
{ {
std::auto_ptr<op_t> node(parse_value_expr(in, flags)); std::auto_ptr<op_t> node(parse_value_expr(in, tflags));
if (use_lookahead) { if (use_lookahead) {
use_lookahead = false; use_lookahead = false;
@ -1150,13 +1156,13 @@ xpath_t::op_t::new_node(kind_t kind, op_t * left, op_t * right)
} }
xpath_t::op_t * xpath_t::op_t *
xpath_t::op_t::copy(op_t * left, op_t * right) const xpath_t::op_t::copy(op_t * tleft, op_t * tright) const
{ {
std::auto_ptr<op_t> node(new op_t(kind)); std::auto_ptr<op_t> node(new op_t(kind));
if (left) if (tleft)
node->set_left(left); node->set_left(tleft);
if (right) if (tright)
node->set_right(right); node->set_right(tright);
return node.release(); return node.release();
} }
@ -1239,17 +1245,17 @@ xpath_t::op_t * xpath_t::op_t::defer_sequence(value_t::sequence_t& result_seq)
return lit_seq.release(); return lit_seq.release();
} }
void xpath_t::op_t::append_value(value_t& value, void xpath_t::op_t::append_value(value_t& val,
value_t::sequence_t& result_seq) value_t::sequence_t& result_seq)
{ {
if (value.type == value_t::SEQUENCE) { if (val.type == value_t::SEQUENCE) {
value_t::sequence_t * subseq = value.to_sequence(); value_t::sequence_t * subseq = val.to_sequence();
for (value_t::sequence_t::iterator i = subseq->begin(); for (value_t::sequence_t::iterator i = subseq->begin();
i != subseq->end(); i != subseq->end();
i++) i++)
result_seq.push_back(*i); result_seq.push_back(*i);
} else { } else {
result_seq.push_back(value); result_seq.push_back(val);
} }
} }
@ -2380,6 +2386,7 @@ void xpath_t::op_t::dump(std::ostream& out, const int depth) const
} // namespace xml } // namespace xml
} // namespace ledger } // namespace ledger
#if 0
#ifdef USE_BOOST_PYTHON #ifdef USE_BOOST_PYTHON
#include <boost/python.hpp> #include <boost/python.hpp>
@ -2465,88 +2472,4 @@ void export_xpath()
} }
#endif // USE_BOOST_PYTHON #endif // USE_BOOST_PYTHON
#ifdef TEST
#if ! defined(HAVE_EXPAT) && ! defined(HAVE_XMLPARSE)
#error No XML parser library was found during configure
#endif #endif
#if 0
#include "session.h"
#include "format.h"
#endif
int main(int argc, char *argv[])
{
using namespace ledger;
using namespace ledger::xml;
try {
parser_t parser;
std::auto_ptr<document_t> doc;
std::ifstream input(argv[1]);
if (parser.test(input)) {
doc.reset(parser.parse(input));
doc->write(std::cout);
} else {
std::cerr << "Could not parse XML file: " << argv[1] << std::endl;
return 1;
}
xpath_t expr(argv[2]);
if (expr) {
std::cout << "Parsed:" << std::endl;
expr.dump(std::cout);
std::cout << std::endl;
expr.compile(doc.get());
std::cout << "Compiled:" << std::endl;
expr.dump(std::cout);
std::cout << std::endl;
value_t temp;
expr.calc(temp, doc->top);
std::cout << "Calculated value: " << temp << std::endl;
} else {
std::cerr << "Failed to parse value expression!" << std::endl;
}
#if 0
{
ledger::session_t session;
std::auto_ptr<xpath_t::scope_t>
locals(new xpath_t::scope_t(&session.globals));
ledger::format_t fmt(std::string("%20|%40{") + argv[1] + "}\n");
fmt.format(std::cout, locals.get());
}
#endif
}
catch (error * err) {
std::cout.flush();
if (err->context.empty())
err->context.push_front(new error_context(""));
err->reveal_context(std::cerr, "Error");
std::cerr << err->what() << std::endl;
delete err;
return 1;
}
catch (fatal * err) {
std::cout.flush();
if (err->context.empty())
err->context.push_front(new error_context(""));
err->reveal_context(std::cerr, "Fatal");
std::cerr << err->what() << std::endl;
delete err;
return 1;
}
catch (const std::exception& err) {
std::cout.flush();
std::cerr << "Error: " << err.what() << std::endl;
return 1;
}
}
#endif // TEST

62
xpath.h
View file

@ -20,25 +20,25 @@ public:
class parse_error : public error { class parse_error : public error {
public: public:
parse_error(const std::string& reason, parse_error(const std::string& _reason,
error_context * ctxt = NULL) throw() error_context * _ctxt = NULL) throw()
: error(reason, ctxt) {} : error(_reason, _ctxt) {}
virtual ~parse_error() throw() {} virtual ~parse_error() throw() {}
}; };
class compile_error : public error { class compile_error : public error {
public: public:
compile_error(const std::string& reason, compile_error(const std::string& _reason,
error_context * ctxt = NULL) throw() error_context * _ctxt = NULL) throw()
: error(reason, ctxt) {} : error(_reason, _ctxt) {}
virtual ~compile_error() throw() {} virtual ~compile_error() throw() {}
}; };
class calc_error : public error { class calc_error : public error {
public: public:
calc_error(const std::string& reason, calc_error(const std::string& _reason,
error_context * ctxt = NULL) throw() error_context * _ctxt = NULL) throw()
: error(reason, ctxt) {} : error(_reason, _ctxt) {}
virtual ~calc_error() throw() {} virtual ~calc_error() throw() {}
}; };
@ -78,8 +78,8 @@ public:
T * ptr; T * ptr;
U T::*dptr; U T::*dptr;
member_functor_t(const std::string& name, T * _ptr, U T::*_dptr) member_functor_t(const std::string& _name, T * _ptr, U T::*_dptr)
: functor_t(name, false), ptr(_ptr), dptr(_dptr) {} : functor_t(_name, false), ptr(_ptr), dptr(_dptr) {}
virtual void operator()(value_t& result, scope_t * locals) { virtual void operator()(value_t& result, scope_t * locals) {
assert(ptr); assert(ptr);
@ -94,8 +94,8 @@ public:
T * ptr; T * ptr;
std::string T::*dptr; std::string T::*dptr;
member_functor_t(const std::string& name, T * _ptr, std::string T::*_dptr) member_functor_t(const std::string& _name, T * _ptr, std::string T::*_dptr)
: functor_t(name, false), ptr(_ptr), dptr(_dptr) {} : functor_t(_name, false), ptr(_ptr), dptr(_dptr) {}
virtual void operator()(value_t& result, scope_t * locals) { virtual void operator()(value_t& result, scope_t * locals) {
assert(ptr); assert(ptr);
@ -110,13 +110,15 @@ public:
T * ptr; T * ptr;
void (T::*mptr)(value_t& result); void (T::*mptr)(value_t& result);
memfun_functor_t(const std::string& name, T * _ptr, memfun_functor_t(const std::string& _name, T * _ptr,
void (T::*_mptr)(value_t& result)) void (T::*_mptr)(value_t& result))
: functor_t(name, false), ptr(_ptr), mptr(_mptr) {} : functor_t(_name, false), ptr(_ptr), mptr(_mptr) {}
virtual void operator()(value_t& result, scope_t * locals = NULL) { virtual void operator()(value_t& result,
scope_t * locals = NULL) {
assert(ptr); assert(ptr);
assert(mptr); assert(mptr);
assert(locals || locals == NULL);
(ptr->*mptr)(result); (ptr->*mptr)(result);
} }
}; };
@ -127,9 +129,9 @@ public:
T * ptr; T * ptr;
void (T::*mptr)(value_t& result, scope_t * locals); void (T::*mptr)(value_t& result, scope_t * locals);
memfun_args_functor_t(const std::string& name, T * _ptr, memfun_args_functor_t(const std::string& _name, T * _ptr,
void (T::*_mptr)(value_t& result, scope_t * locals)) void (T::*_mptr)(value_t& result, scope_t * locals))
: functor_t(name, true), ptr(_ptr), mptr(_mptr) {} : functor_t(_name, true), ptr(_ptr), mptr(_mptr) {}
virtual void operator()(value_t& result, scope_t * locals) { virtual void operator()(value_t& result, scope_t * locals) {
assert(ptr); assert(ptr);
@ -221,8 +223,8 @@ public:
public: public:
function_scope_t(value_t::sequence_t * _sequence, value_t * _value, function_scope_t(value_t::sequence_t * _sequence, value_t * _value,
int _index, scope_t * parent = NULL) int _index, scope_t * _parent = NULL)
: scope_t(parent, STATIC), : scope_t(_parent, STATIC),
sequence(_sequence), value(_value), index(_index) {} sequence(_sequence), value(_value), index(_index) {}
virtual bool resolve(const std::string& name, value_t& result, virtual bool resolve(const std::string& name, value_t& result,
@ -549,11 +551,11 @@ public:
#endif #endif
mutable bool use_lookahead; mutable bool use_lookahead;
token_t& next_token(std::istream& in, unsigned short flags) const { token_t& next_token(std::istream& in, unsigned short tflags) const {
if (use_lookahead) if (use_lookahead)
use_lookahead = false; use_lookahead = false;
else else
lookahead.next(in, flags); lookahead.next(in, tflags);
return lookahead; return lookahead;
} }
void push_token(const token_t& tok) const { void push_token(const token_t& tok) const {
@ -581,11 +583,11 @@ public:
unsigned short flags = XPATH_PARSE_RELAXED) const; unsigned short flags = XPATH_PARSE_RELAXED) const;
op_t * parse_expr(const std::string& str, op_t * parse_expr(const std::string& str,
unsigned short flags = XPATH_PARSE_RELAXED) const unsigned short tflags = XPATH_PARSE_RELAXED) const
{ {
std::istringstream stream(str); std::istringstream stream(str);
try { try {
return parse_expr(stream, flags); return parse_expr(stream, tflags);
} }
catch (error * err) { catch (error * err) {
err->context.push_back err->context.push_back
@ -596,8 +598,8 @@ public:
} }
op_t * parse_expr(const char * p, op_t * parse_expr(const char * p,
unsigned short flags = XPATH_PARSE_RELAXED) const { unsigned short tflags = XPATH_PARSE_RELAXED) const {
return parse_expr(std::string(p), flags); return parse_expr(std::string(p), tflags);
} }
bool write(std::ostream& out, bool write(std::ostream& out,
@ -721,11 +723,11 @@ public:
calc(temp, document ? document->top : NULL, scope); calc(temp, document ? document->top : NULL, scope);
return temp; return temp;
} }
virtual value_t calc(node_t * context, scope_t * scope = NULL) const { virtual value_t calc(node_t * tcontext, scope_t * scope = NULL) const {
if (! ptr) if (! ptr)
return 0L; return 0L;
value_t temp; value_t temp;
calc(temp, context, scope); calc(temp, tcontext, scope);
return temp; return temp;
} }
@ -749,7 +751,7 @@ public:
} // namespace xml } // namespace xml
template <typename T> template <typename T>
inline T * get_ptr(xml::xpath_t::scope_t * locals, int idx) { inline T * get_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
assert(locals->args.size() > idx); assert(locals->args.size() > idx);
T * ptr = static_cast<T *>(locals->args[idx].to_pointer()); T * ptr = static_cast<T *>(locals->args[idx].to_pointer());
assert(ptr); assert(ptr);
@ -761,7 +763,7 @@ class xml_command : public xml::xpath_t::functor_t
public: public:
xml_command() : xml::xpath_t::functor_t("xml") {} xml_command() : xml::xpath_t::functor_t("xml") {}
virtual void operator()(value_t& result, xml::xpath_t::scope_t * locals) { virtual void operator()(value_t&, xml::xpath_t::scope_t * locals) {
std::ostream * out = get_ptr<std::ostream>(locals, 0); std::ostream * out = get_ptr<std::ostream>(locals, 0);
xml::document_t * doc = get_ptr<xml::document_t>(locals, 1); xml::document_t * doc = get_ptr<xml::document_t>(locals, 1);