diff options
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | Makefile.in | 33 | ||||
-rw-r--r-- | README | 4 | ||||
-rw-r--r-- | acconf.h.in | 6 | ||||
-rwxr-xr-x | acprep | 2 | ||||
-rw-r--r-- | amount.cc | 18 | ||||
-rw-r--r-- | amount.h | 26 | ||||
-rw-r--r-- | balance.cc | 4 | ||||
-rw-r--r-- | balance.h | 110 | ||||
-rwxr-xr-x | configure | 148 | ||||
-rw-r--r-- | configure.in | 78 | ||||
-rw-r--r-- | debug.cc | 9 | ||||
-rw-r--r-- | debug.h | 3 | ||||
-rw-r--r-- | journal.cc | 16 | ||||
-rw-r--r-- | journal.h | 8 | ||||
-rw-r--r-- | ledger.el | 1 | ||||
-rw-r--r-- | ledger.h | 2 | ||||
-rw-r--r-- | main.cc | 36 | ||||
-rw-r--r-- | mask.cc | 39 | ||||
-rw-r--r-- | mask.h | 14 | ||||
-rw-r--r-- | parsetime.yy | 105 | ||||
-rw-r--r-- | py_amount.cc | 5 | ||||
-rw-r--r-- | qif.cc | 4 | ||||
-rw-r--r-- | register.cc | 31 | ||||
-rw-r--r-- | register.h | 25 | ||||
-rw-r--r-- | tests/corelib/numerics/BasicAmount.cc | 19 | ||||
-rw-r--r-- | tests/corelib/numerics/CommodityAmount.cc | 30 | ||||
-rw-r--r-- | tests/corelib/numerics/DateTime.cc | 2 | ||||
-rw-r--r-- | tests/python/corelib/numerics/BasicAmount.py | 13 | ||||
-rw-r--r-- | tests/python/corelib/numerics/CommodityAmount.py | 24 | ||||
-rw-r--r-- | textual.cc | 21 | ||||
-rw-r--r-- | times.cc | 16 | ||||
-rw-r--r-- | util.h | 9 | ||||
-rw-r--r-- | value.cc | 271 | ||||
-rw-r--r-- | value.h | 33 | ||||
-rw-r--r-- | xml.cc | 46 | ||||
-rw-r--r-- | xml.h | 85 | ||||
-rw-r--r-- | xpath.cc | 17 |
38 files changed, 687 insertions, 630 deletions
diff --git a/Makefile.am b/Makefile.am index 3b84ae37..4e5cdb86 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,6 +46,8 @@ libledger_la_SOURCES = \ report.cc \ transform.cc \ \ + register.cc \ + \ csv.cc \ derive.cc \ emacs.cc \ @@ -164,7 +166,7 @@ noinst_PROGRAMS = ledger.so ledger_so_SOURCES = pyledger.cc -PYLIBS = pyledger ledger gdtoa boost_date_time boost_python gmp pcre +PYLIBS = pyledger ledger gdtoa boost_date_time boost_regex boost_python gmp if HAVE_EXPAT PYLIBS += expat diff --git a/Makefile.in b/Makefile.in index 562f2c18..c1d52aab 100644 --- a/Makefile.in +++ b/Makefile.in @@ -96,8 +96,8 @@ am__libledger_la_SOURCES_DIST = amount.cc times.cc parsetime.yy \ scantime.ll quotes.cc balance.cc value.cc xml.cc xpath.cc \ mask.cc format.cc util.cc session.cc journal.cc parser.cc \ textual.cc binary.cc xmlparse.cc qif.cc report.cc transform.cc \ - csv.cc derive.cc emacs.cc reconcile.cc gnucash.cc ofx.cc \ - debug.cc trace.cc + register.cc csv.cc derive.cc emacs.cc reconcile.cc gnucash.cc \ + ofx.cc debug.cc trace.cc @HAVE_EXPAT_TRUE@am__objects_1 = libledger_la-gnucash.lo @HAVE_XMLPARSE_TRUE@am__objects_2 = libledger_la-gnucash.lo @HAVE_LIBOFX_TRUE@am__objects_3 = libledger_la-ofx.lo @@ -113,10 +113,11 @@ am_libledger_la_OBJECTS = libledger_la-amount.lo libledger_la-times.lo \ libledger_la-parser.lo libledger_la-textual.lo \ libledger_la-binary.lo libledger_la-xmlparse.lo \ libledger_la-qif.lo libledger_la-report.lo \ - libledger_la-transform.lo libledger_la-csv.lo \ - libledger_la-derive.lo libledger_la-emacs.lo \ - libledger_la-reconcile.lo $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) $(am__objects_4) + libledger_la-transform.lo libledger_la-register.lo \ + libledger_la-csv.lo libledger_la-derive.lo \ + libledger_la-emacs.lo libledger_la-reconcile.lo \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) libledger_la_OBJECTS = $(am_libledger_la_OBJECTS) libledger_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libledger_la_CXXFLAGS) \ @@ -373,9 +374,10 @@ libledger_la_CXXFLAGS = $(WARNFLAGS) -I$(top_builddir)/gdtoa \ libledger_la_SOURCES = amount.cc times.cc parsetime.yy scantime.ll \ quotes.cc balance.cc value.cc xml.cc xpath.cc mask.cc \ format.cc util.cc session.cc journal.cc parser.cc textual.cc \ - binary.cc xmlparse.cc qif.cc report.cc transform.cc csv.cc \ - derive.cc emacs.cc reconcile.cc $(am__append_3) \ - $(am__append_5) $(am__append_7) $(am__append_9) + binary.cc xmlparse.cc qif.cc report.cc transform.cc \ + register.cc csv.cc derive.cc emacs.cc reconcile.cc \ + $(am__append_3) $(am__append_5) $(am__append_7) \ + $(am__append_9) libledger_la_LDFLAGS = -release 3.0 libpyledger_la_CXXFLAGS = -DUSE_BOOST_PYTHON=1 $(am__append_11) libpyledger_la_SOURCES = \ @@ -433,8 +435,9 @@ info_TEXINFOS = ledger.texi lisp_LISP = ledger.el timeclock.el @HAVE_BOOST_PYTHON_TRUE@ledger_so_SOURCES = pyledger.cc @HAVE_BOOST_PYTHON_TRUE@PYLIBS = pyledger ledger gdtoa boost_date_time \ -@HAVE_BOOST_PYTHON_TRUE@ boost_python gmp pcre $(am__append_18) \ -@HAVE_BOOST_PYTHON_TRUE@ $(am__append_19) $(am__append_20) +@HAVE_BOOST_PYTHON_TRUE@ boost_regex boost_python gmp \ +@HAVE_BOOST_PYTHON_TRUE@ $(am__append_18) $(am__append_19) \ +@HAVE_BOOST_PYTHON_TRUE@ $(am__append_20) @DEBUG_FALSE@@HAVE_BOOST_PYTHON_TRUE@DEBUG_LEVEL = 0 @DEBUG_TRUE@@HAVE_BOOST_PYTHON_TRUE@DEBUG_LEVEL = 4 UnitTests_SOURCES = tests/UnitTests.cc \ @@ -622,6 +625,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-qif.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-quotes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-reconcile.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-register.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-report.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-scantime.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-session.Plo@am__quote@ @@ -806,6 +810,13 @@ libledger_la-transform.lo: transform.cc @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libledger_la_CXXFLAGS) $(CXXFLAGS) -c -o libledger_la-transform.lo `test -f 'transform.cc' || echo '$(srcdir)/'`transform.cc +libledger_la-register.lo: register.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libledger_la_CXXFLAGS) $(CXXFLAGS) -MT libledger_la-register.lo -MD -MP -MF $(DEPDIR)/libledger_la-register.Tpo -c -o libledger_la-register.lo `test -f 'register.cc' || echo '$(srcdir)/'`register.cc +@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libledger_la-register.Tpo $(DEPDIR)/libledger_la-register.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='register.cc' object='libledger_la-register.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libledger_la_CXXFLAGS) $(CXXFLAGS) -c -o libledger_la-register.lo `test -f 'register.cc' || echo '$(srcdir)/'`register.cc + libledger_la-csv.lo: csv.cc @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libledger_la_CXXFLAGS) $(CXXFLAGS) -MT libledger_la-csv.lo -MD -MP -MF $(DEPDIR)/libledger_la-csv.Tpo -c -o libledger_la-csv.lo `test -f 'csv.cc' || echo '$(srcdir)/'`csv.cc @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libledger_la-csv.Tpo $(DEPDIR)/libledger_la-csv.Plo @@ -30,10 +30,10 @@ Building ======== To build Ledger, you will need a fairly modern C++ compiler (gcc 2.95 -will not work), and at least these two libraries installed: +will not work), and at least these libraries installed: gmp GNU multi-precision library - pcre Perl regular expression library + boost Boost C++ library (On some GNU/Linux systems, the packages you need to install are called "gmp-dev" and "pcre-dev"). diff --git a/acconf.h.in b/acconf.h.in index 9c64213f..94fef0ac 100644 --- a/acconf.h.in +++ b/acconf.h.in @@ -15,12 +15,18 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the <langinfo.h> header file. */ +#undef HAVE_LANGINFO_H + /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mktime' function. */ #undef HAVE_MKTIME +/* Define to 1 if you have the `nl_langinfo' function. */ +#undef HAVE_NL_LANGINFO + /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH @@ -61,7 +61,7 @@ while [ -n "$1" ]; do case "$1" in --debug) SWITCHES="$SWITCHES --enable-debug" - CXXFLAGS="$CXXFLAGS -ggdb3" ;; + CXXFLAGS="$CXXFLAGS -g" ;; --prof | --perf) CXXFLAGS="$CXXFLAGS -g -pg" ;; @@ -639,7 +639,7 @@ amount_t& amount_t::operator/=(const amount_t& amt) } // unary negation -void amount_t::negate() +void amount_t::in_place_negate() { if (quantity) { _dup(); @@ -899,7 +899,7 @@ void amount_t::print(std::ostream& _out, bool omit_commodity, while (last.commodity().larger()) { last /= last.commodity().larger()->number(); last.commodity_ = last.commodity().larger()->commodity_; - if (::abs(last) < 1) + if (last.abs() < 1) break; base = last.round(); } @@ -1151,7 +1151,7 @@ bool parse_annotations(std::istream& in, amount_t& price, throw new amount_error("Commodity price lacks closing brace"); price.parse(buf, AMOUNT_PARSE_NO_MIGRATE); - price.reduce(); + price.in_place_reduce(); // Since this price will maintain its own precision, make sure // it is at least as large as the base commodity, since the user @@ -1162,7 +1162,7 @@ bool parse_annotations(std::istream& in, amount_t& price, price = price.round(); // no need to retain individual precision } else if (c == '[') { - if (date.is_not_a_date_time()) + if (! date.is_not_a_date_time()) throw new amount_error("Commodity specifies more than one date"); in.get(c); @@ -1341,13 +1341,13 @@ void amount_t::parse(std::istream& in, unsigned char flags) } if (negative) - negate(); + in_place_negate(); if (! (flags & AMOUNT_PARSE_NO_REDUCE)) - reduce(); + in_place_reduce(); } -void amount_t::reduce() +void amount_t::in_place_reduce() { while (commodity_ && commodity().smaller()) { *this *= commodity().smaller()->number(); @@ -1968,9 +1968,9 @@ bool compare_amount_commodities::operator()(const amount_t * left, if (aleftcomm.price && arightcomm.price) { amount_t leftprice(aleftcomm.price); - leftprice.reduce(); + leftprice.in_place_reduce(); amount_t rightprice(arightcomm.price); - rightprice.reduce(); + rightprice.in_place_reduce(); if (leftprice.commodity() == rightprice.commodity()) { amount_t val = leftprice - rightprice; @@ -244,15 +244,14 @@ class amount_t } // unary negation - // jww (2007-04-17): change the name here - void negate(); - amount_t negated() const { + void in_place_negate(); + amount_t negate() const { amount_t temp = *this; - temp.negate(); + temp.in_place_negate(); return temp; } amount_t operator-() const { - return negated(); + return negate(); } // test for zero and non-zero @@ -327,17 +326,16 @@ class amount_t amount_t value(const ptime& moment) const; - // jww (2007-04-17): change the name here - void abs() { + amount_t abs() const { if (*this < 0) - negate(); + return negate(); + return *this; } - // jww (2007-04-17): change the name here - void reduce(); - amount_t reduced() const { + void in_place_reduce(); + amount_t reduce() const { amount_t temp(*this); - temp.reduce(); + temp.in_place_reduce(); return temp; } @@ -409,10 +407,6 @@ inline std::string amount_t::quantity_string() const { return bufstream.str(); } -inline amount_t abs(const amount_t& amt) { - return amt < 0 ? amt.negated() : amt; -} - #define DEFINE_AMOUNT_OPERATORS(T) \ inline amount_t operator+(const T val, const amount_t& amt) { \ amount_t temp(val); \ @@ -414,9 +414,9 @@ void export_balance() .def(self != long()) .def(! self) - .def(abs(self)) .def(self_ns::str(self)) + .def("__abs__", &balance_t::abs) .def("__len__", balance_len) .def("__getitem__", balance_getitem) @@ -502,9 +502,9 @@ void export_balance() .def(self != long()) .def(! self) - .def(abs(self)) .def(self_ns::str(self)) + .def("__abs__", &balance_pair_t::abs) .def("__len__", balance_pair_len) .def("__getitem__", balance_pair_getitem) @@ -391,19 +391,19 @@ class balance_t } // unary negation - void negate() { + void in_place_negate() { for (amounts_map::iterator i = amounts.begin(); i != amounts.end(); i++) - (*i).second.negate(); + (*i).second = (*i).second.negate(); } - balance_t negated() const { + balance_t negate() const { balance_t temp = *this; - temp.negate(); + temp.in_place_negate(); return temp; } balance_t operator-() const { - return negated(); + return negate(); } // conversion operators @@ -428,11 +428,11 @@ class balance_t return true; } - amount_t amount(const commodity_t& commodity = - *commodity_t::null_commodity) const; - balance_t value(const ptime& moment = now) const; - balance_t price() const; - ptime date() const; + amount_t amount(const commodity_t& commodity = + *commodity_t::null_commodity) const; + balance_t value(const ptime& moment = now) const; + balance_t price() const; + ptime date() const; balance_t strip_annotations(const bool keep_price = amount_t::keep_price, @@ -442,32 +442,40 @@ class balance_t void write(std::ostream& out, const int first_width, const int latter_width = -1) const; - void abs() { + void in_place_abs() { for (amounts_map::iterator i = amounts.begin(); i != amounts.end(); i++) - (*i).second.abs(); + (*i).second = (*i).second.abs(); + } + balance_t abs() const { + balance_t temp = *this; + temp.in_place_abs(); + return temp; } - void reduce() { + void in_place_reduce() { for (amounts_map::iterator i = amounts.begin(); i != amounts.end(); i++) - (*i).second.reduce(); + (*i).second.in_place_reduce(); } - - balance_t reduced() const { + balance_t reduce() const { balance_t temp(*this); - temp.reduce(); + temp.in_place_reduce(); return temp; } - void round() { + void in_place_round() { for (amounts_map::iterator i = amounts.begin(); i != amounts.end(); i++) - if ((*i).second.commodity()) - (*i).second = (*i).second.round(); + (*i).second = (*i).second.round(); + } + balance_t round() const { + balance_t temp(*this); + temp.in_place_round(); + return temp; } balance_t unround() const { @@ -481,12 +489,6 @@ class balance_t } }; -inline balance_t abs(const balance_t& bal) { - balance_t temp = bal; - temp.abs(); - return temp; -} - inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) { bal.write(out, 12); return out; @@ -843,17 +845,18 @@ class balance_pair_t } // unary negation - void negate() { - quantity.negate(); - if (cost) cost->negate(); + void in_place_negate() { + quantity = quantity.negate(); + if (cost) + *cost = cost->negate(); } - balance_pair_t negated() const { + balance_pair_t negate() const { balance_pair_t temp = *this; - temp.negate(); + temp.in_place_negate(); return temp; } balance_pair_t operator-() const { - return negated(); + return negate(); } // test for non-zero (use ! for zero) @@ -871,9 +874,15 @@ class balance_pair_t return ((! cost || cost->realzero()) && quantity.realzero()); } - void abs() { - quantity.abs(); - if (cost) cost->abs(); + balance_pair_t in_place_abs() { + quantity = quantity.abs(); + if (cost) + *cost = cost->abs(); + } + balance_pair_t abs() const { + balance_pair_t temp = *this; + temp.in_place_abs(); + return temp; } amount_t amount(const commodity_t& commodity = @@ -886,7 +895,7 @@ class balance_pair_t balance_t price() const { return quantity.price(); } - ptime date() const { + ptime date() const { return quantity.date(); } @@ -916,20 +925,25 @@ class balance_pair_t return quantity.valid() && (! cost || cost->valid()); } - void reduce() { - quantity.reduce(); - if (cost) cost->reduce(); + void in_place_reduce() { + quantity.in_place_reduce(); + if (cost) cost->in_place_reduce(); } - - balance_pair_t reduced() const { + balance_pair_t reduce() const { balance_pair_t temp(*this); - temp.reduce(); + temp.in_place_reduce(); return temp; } - void round() { - quantity.round(); - if (cost) cost->round(); + void in_place_round() { + quantity = quantity.round(); + if (cost) + *cost = cost->round(); + } + balance_pair_t round() const { + balance_pair_t temp(*this); + temp.in_place_round(); + return temp; } balance_pair_t unround() { @@ -940,12 +954,6 @@ class balance_pair_t } }; -inline balance_pair_t abs(const balance_pair_t& bal_pair) { - balance_pair_t temp(bal_pair); - temp.abs(); - return temp; -} - inline std::ostream& operator<<(std::ostream& out, const balance_pair_t& bal_pair) { bal_pair.quantity.write(out, 12); @@ -19696,14 +19696,14 @@ _ACEOF fi -# check for gmp -{ echo "$as_me:$LINENO: checking if libgmp is available" >&5 -echo $ECHO_N "checking if libgmp is available... $ECHO_C" >&6; } -if test "${libgmp_avail+set}" = set; then +# check for boost_regex +{ echo "$as_me:$LINENO: checking if boost_regex is available" >&5 +echo $ECHO_N "checking if boost_regex is available... $ECHO_C" >&6; } +if test "${boost_regex_avail+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - libgmp_save_libs=$LIBS - LIBS="-lgmp $LIBS" + boost_regex_save_libs=$LIBS + LIBS="-lboost_regex $LIBS" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -19716,13 +19716,11 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <gmp.h> +#include <boost/regex.hpp> int main () { -mpz_t bar; - mpz_init(bar); - mpz_clear(bar); +boost::regex foo_regexp("Hello, world!"); ; return 0; } @@ -19745,12 +19743,12 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then - libgmp_avail=true + boost_regex_avail=true else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - libgmp_avail=false + boost_regex_avail=false fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ @@ -19761,29 +19759,29 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - LIBS=$libgmp_save_libs + LIBS=$boost_regex_save_libs fi -{ echo "$as_me:$LINENO: result: $libgmp_avail" >&5 -echo "${ECHO_T}$libgmp_avail" >&6; } +{ echo "$as_me:$LINENO: result: $boost_regex_avail" >&5 +echo "${ECHO_T}$boost_regex_avail" >&6; } -if test x$libgmp_avail = xtrue ; then - LIBS="-lgmp $LIBS" +if test x$boost_regex_avail = xtrue ; then + LIBS="-lboost_regex $LIBS" else - { { echo "$as_me:$LINENO: error: \"Could not find gmp library (set CPPFLAGS and LDFLAGS?)\" + { { echo "$as_me:$LINENO: error: \"Could not find boost_regex library (set CPPFLAGS and LDFLAGS?)\" See \`config.log' for more details." >&5 -echo "$as_me: error: \"Could not find gmp library (set CPPFLAGS and LDFLAGS?)\" +echo "$as_me: error: \"Could not find boost_regex library (set CPPFLAGS and LDFLAGS?)\" See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi -# check for pcre -{ echo "$as_me:$LINENO: checking if libpcre is available" >&5 -echo $ECHO_N "checking if libpcre is available... $ECHO_C" >&6; } -if test "${libpcre_avail+set}" = set; then +# check for boost_date_time +{ echo "$as_me:$LINENO: checking if boost_date_time is available" >&5 +echo $ECHO_N "checking if boost_date_time is available... $ECHO_C" >&6; } +if test "${boost_date_time_cpplib_avail+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - libpcre_save_libs=$LIBS - LIBS="-lpcre $LIBS" + boost_date_time_save_libs=$LIBS + LIBS="-lboost_date_time $LIBS" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -19796,11 +19794,29 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <pcre.h> +#include <boost/date_time/posix_time/posix_time.hpp> + #include <boost/date_time/gregorian/gregorian.hpp> + #include <boost/date_time/local_time_adjustor.hpp> + #include <boost/date_time/time_duration.hpp> + + using namespace boost::posix_time; + using namespace boost::date_time; + + #include <ctime> + + inline ptime time_to_system_local(const ptime& when) { + struct std::tm tm_gmt = to_tm(when); + return from_time_t(mktime(&tm_gmt)); + } int main () { -pcre_free((pcre *)NULL); +ptime t10 = ptime(boost::gregorian::from_string("2007-01-15"), + ptime::time_duration_type()); + + ptime t12 = time_to_system_local(t10); + + return t10 != t12; ; return 0; } @@ -19823,12 +19839,12 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then - libpcre_avail=true + boost_date_time_cpplib_avail=true else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - libpcre_avail=false + boost_date_time_cpplib_avail=false fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ @@ -19839,29 +19855,29 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - LIBS=$libpcre_save_libs + LIBS=$boost_date_time_save_libs fi -{ echo "$as_me:$LINENO: result: $libpcre_avail" >&5 -echo "${ECHO_T}$libpcre_avail" >&6; } +{ echo "$as_me:$LINENO: result: $boost_date_time_cpplib_avail" >&5 +echo "${ECHO_T}$boost_date_time_cpplib_avail" >&6; } -if test x$libpcre_avail = xtrue ; then - LIBS="-lpcre $LIBS" +if test x$boost_date_time_cpplib_avail = xtrue ; then + LIBS="-lboost_date_time $LIBS" else - { { echo "$as_me:$LINENO: error: \"Could not find pcre library (set CPPFLAGS and LDFLAGS?)\" + { { echo "$as_me:$LINENO: error: \"Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)\" See \`config.log' for more details." >&5 -echo "$as_me: error: \"Could not find pcre library (set CPPFLAGS and LDFLAGS?)\" +echo "$as_me: error: \"Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)\" See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi -# check for Boost date_time -{ echo "$as_me:$LINENO: checking if boost_date_time is available" >&5 -echo $ECHO_N "checking if boost_date_time is available... $ECHO_C" >&6; } -if test "${boost_date_time_cpplib_avail+set}" = set; then +# check for gmp +{ echo "$as_me:$LINENO: checking if libgmp is available" >&5 +echo $ECHO_N "checking if libgmp is available... $ECHO_C" >&6; } +if test "${libgmp_avail+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - boost_date_time_save_libs=$LIBS - LIBS="-lboost_date_time $LIBS" + libgmp_save_libs=$LIBS + LIBS="-lgmp $LIBS" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -19874,29 +19890,13 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <boost/date_time/posix_time/posix_time.hpp> - #include <boost/date_time/gregorian/gregorian.hpp> - #include <boost/date_time/local_time_adjustor.hpp> - #include <boost/date_time/time_duration.hpp> - - using namespace boost::posix_time; - using namespace boost::date_time; - - #include <ctime> - - inline ptime time_to_system_local(const ptime& when) { - struct std::tm tm_gmt = to_tm(when); - return from_time_t(mktime(&tm_gmt)); - } +#include <gmp.h> int main () { -ptime t10 = ptime(boost::gregorian::from_string("2007-01-15"), - ptime::time_duration_type()); - - ptime t12 = time_to_system_local(t10); - - return t10 != t12; +mpz_t bar; + mpz_init(bar); + mpz_clear(bar); ; return 0; } @@ -19919,12 +19919,12 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then - boost_date_time_cpplib_avail=true + libgmp_avail=true else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - boost_date_time_cpplib_avail=false + libgmp_avail=false fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ @@ -19935,17 +19935,17 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - LIBS=$boost_date_time_save_libs + LIBS=$libgmp_save_libs fi -{ echo "$as_me:$LINENO: result: $boost_date_time_cpplib_avail" >&5 -echo "${ECHO_T}$boost_date_time_cpplib_avail" >&6; } +{ echo "$as_me:$LINENO: result: $libgmp_avail" >&5 +echo "${ECHO_T}$libgmp_avail" >&6; } -if test x$boost_date_time_cpplib_avail = xtrue ; then - LIBS="-lboost_date_time $LIBS" +if test x$libgmp_avail = xtrue ; then + LIBS="-lgmp $LIBS" else - { { echo "$as_me:$LINENO: error: \"Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)\" + { { echo "$as_me:$LINENO: error: \"Could not find gmp library (set CPPFLAGS and LDFLAGS?)\" See \`config.log' for more details." >&5 -echo "$as_me: error: \"Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)\" +echo "$as_me: error: \"Could not find gmp library (set CPPFLAGS and LDFLAGS?)\" See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi @@ -20837,7 +20837,8 @@ _ACEOF fi -for ac_header in sys/stat.h + +for ac_header in sys/stat.h langinfo.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then @@ -21475,7 +21476,8 @@ fi -for ac_func in access mktime realpath getpwuid getpwnam + +for ac_func in access mktime realpath getpwuid getpwnam nl_langinfo do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/configure.in b/configure.in index d1f953e2..8bb6247f 100644 --- a/configure.in +++ b/configure.in @@ -68,51 +68,28 @@ if [test x$pipes_avail = xtrue ]; then AC_DEFINE([HAVE_UNIX_PIPES], [1], [Whether UNIX pipes are available]) fi -# check for gmp -AC_CACHE_CHECK( - [if libgmp is available], - [libgmp_avail], - [libgmp_save_libs=$LIBS - LIBS="-lgmp $LIBS" - AC_LANG_PUSH(C++) - AC_TRY_LINK( - [#include <gmp.h>], - [mpz_t bar; - mpz_init(bar); - mpz_clear(bar);], - [libgmp_avail=true], - [libgmp_avail=false]) - AC_LANG_POP - LIBS=$libgmp_save_libs]) - -if [test x$libgmp_avail = xtrue ]; then - LIBS="-lgmp $LIBS" -else - AC_MSG_FAILURE("Could not find gmp library (set CPPFLAGS and LDFLAGS?)") -fi - -# check for pcre +# check for boost_regex AC_CACHE_CHECK( - [if libpcre is available], - [libpcre_avail], - [libpcre_save_libs=$LIBS - LIBS="-lpcre $LIBS" + [if boost_regex is available], + [boost_regex_avail], + [boost_regex_save_libs=$LIBS + LIBS="-lboost_regex $LIBS" AC_LANG_PUSH(C++) AC_TRY_LINK( - [#include <pcre.h>], - [pcre_free((pcre *)NULL);], - [libpcre_avail=true], - [libpcre_avail=false]) + [#include <boost/regex.hpp>], + [boost::regex foo_regexp("Hello, world!");], + [boost_regex_avail=true], + [boost_regex_avail=false]) AC_LANG_POP - LIBS=$libpcre_save_libs]) + LIBS=$boost_regex_save_libs]) -if [test x$libpcre_avail = xtrue ]; then - LIBS="-lpcre $LIBS" +if [test x$boost_regex_avail = xtrue ]; then + LIBS="-lboost_regex $LIBS" else - AC_MSG_FAILURE("Could not find pcre library (set CPPFLAGS and LDFLAGS?)") + AC_MSG_FAILURE("Could not find boost_regex library (set CPPFLAGS and LDFLAGS?)") fi -# check for Boost date_time +# check for boost_date_time AC_CACHE_CHECK( [if boost_date_time is available], [boost_date_time_cpplib_avail], @@ -151,6 +128,29 @@ else AC_MSG_FAILURE("Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)") fi +# check for gmp +AC_CACHE_CHECK( + [if libgmp is available], + [libgmp_avail], + [libgmp_save_libs=$LIBS + LIBS="-lgmp $LIBS" + AC_LANG_PUSH(C++) + AC_TRY_LINK( + [#include <gmp.h>], + [mpz_t bar; + mpz_init(bar); + mpz_clear(bar);], + [libgmp_avail=true], + [libgmp_avail=false]) + AC_LANG_POP + LIBS=$libgmp_save_libs]) + +if [test x$libgmp_avail = xtrue ]; then + LIBS="-lgmp $LIBS" +else + AC_MSG_FAILURE("Could not find gmp library (set CPPFLAGS and LDFLAGS?)") +fi + # check for expat or xmlparse AC_ARG_ENABLE(xml, [ --enable-xml Turn on support for XML parsing], @@ -319,7 +319,7 @@ AM_CONDITIONAL(DEBUG, test x$debug = xtrue) # Checks for header files. AC_STDC_HEADERS -AC_HAVE_HEADERS(sys/stat.h) +AC_HAVE_HEADERS(sys/stat.h langinfo.h) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL @@ -329,7 +329,7 @@ AC_STRUCT_TM # Checks for library functions. #AC_FUNC_ERROR_AT_LINE AC_HEADER_STDC -AC_CHECK_FUNCS([access mktime realpath getpwuid getpwnam]) +AC_CHECK_FUNCS([access mktime realpath getpwuid getpwnam nl_langinfo]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT @@ -81,13 +81,8 @@ bool _free_debug_stream = false; bool _debug_active(const char * const cls) { if (char * debug = std::getenv("DEBUG_CLASS")) { - static const char * error; - static int erroffset; - static int ovec[30]; - static pcre * class_regexp = pcre_compile(debug, PCRE_CASELESS, - &error, &erroffset, NULL); - return pcre_exec(class_regexp, NULL, cls, std::strlen(cls), - 0, 0, ovec, 30) >= 0; + static boost::regex class_regexp(debug); + return boost::regex_match(cls, class_regexp); } return false; } @@ -57,12 +57,13 @@ void debug_assert(const std::string& reason, #if DEBUG_LEVEL >= ALPHA -#include <pcre.h> #include <cstring> #include <new> #include <iostream> #include <cstdlib> +#include <boost/regex.hpp> + #define DEBUG_ENABLED extern std::ostream * _debug_stream; @@ -124,7 +124,7 @@ bool entry_base_t::finalize() ann_comm(static_cast<annotated_commodity_t&> ((*x)->amount.commodity())); if (ann_comm.price) - balance += ann_comm.price * (*x)->amount - *((*x)->cost); + balance += ann_comm.price * (*x)->amount.number() - *((*x)->cost); } } else { saw_null = true; @@ -165,7 +165,7 @@ bool entry_base_t::finalize() other_bal++; amount_t per_unit_cost = - amount_t((*other_bal).second / (*this_bal).second).unround(); + amount_t((*other_bal).second / (*this_bal).second.number()).unround(); for (; x != transactions.end(); x++) { if ((*x)->cost || ((*x)->flags & TRANSACTION_VIRTUAL) || @@ -180,11 +180,11 @@ bool entry_base_t::finalize() if ((*x)->amount.commodity() && ! (*x)->amount.commodity().annotated) (*x)->amount.annotate_commodity - (abs(per_unit_cost), + (per_unit_cost.abs(), entry ? entry->actual_date() : ptime(), entry ? entry->code : ""); - (*x)->cost = new amount_t(- (per_unit_cost * (*x)->amount)); + (*x)->cost = new amount_t(- (per_unit_cost * (*x)->amount.number())); balance += *(*x)->cost; } } @@ -228,8 +228,7 @@ bool entry_base_t::finalize() for (amounts_map::const_iterator i = bal->amounts.begin(); i != bal->amounts.end(); i++) { - amount_t amt = (*i).second; - amt.negate(); + amount_t amt = (*i).second.negate(); if (first) { (*x)->amount = amt; @@ -248,8 +247,7 @@ bool entry_base_t::finalize() // fall through... case value_t::AMOUNT: - (*x)->amount = *((amount_t *) balance.data); - (*x)->amount.negate(); + (*x)->amount = ((amount_t *) balance.data)->negate(); (*x)->flags |= TRANSACTION_CALCULATED; balance += (*x)->amount; @@ -552,7 +550,7 @@ bool journal_t::add_entry(entry_t * entry) i++) if ((*i)->cost && (*i)->amount) (*i)->amount.commodity().add_price(entry->date(), - *(*i)->cost / (*i)->amount); + *(*i)->cost / (*i)->amount.number()); return true; } @@ -23,8 +23,8 @@ class transaction_t enum state_t { UNCLEARED, CLEARED, PENDING }; entry_t * entry; - ptime _date; - ptime _date_eff; + ptime _date; + ptime _date_eff; account_t * account; amount_t amount; std::string amount_expr; @@ -151,8 +151,8 @@ class entry_base_t class entry_t : public entry_base_t { public: - ptime _date; - ptime _date_eff; + ptime _date; + ptime _date_eff; std::string code; std::string payee; @@ -71,6 +71,7 @@ (require 'esh-util) (require 'esh-arg) +(require 'pcomplete) (defvar ledger-version "1.2" "The version of ledger.el currently loaded") @@ -34,6 +34,8 @@ #include <report.h> #include <transform.h> +#include <register.h> + #if 0 #include <emacs.h> #include <csv.h> @@ -28,16 +28,6 @@ using namespace ledger; -static inline -const std::string& either_or(const std::string& first, - const std::string& second) -{ - if (first.empty()) - return second; - else - return first; -} - #if 0 class print_addr : public repitem_t::select_callback_t { virtual void operator()(repitem_t * item) { @@ -107,15 +97,16 @@ static int read_and_report(report_t * report, int argc, char * argv[], xml::xpath_t::functor_t * command = NULL; - if (false) { - ; - } -#if 0 if (verb == "register" || verb == "reg" || verb == "r") { +#if 1 + command = new register_command; +#else command = new format_command ("register", either_or(report->format_string, report->session->register_format)); +#endif } +#if 0 else if (verb == "balance" || verb == "bal" || verb == "b") { if (! report->raw_mode) { report->transforms.push_back(new accounts_transform); @@ -311,14 +302,10 @@ static int read_and_report(report_t * report, int argc, char * argv[], locals->args.push_back(journal->document); if (command->wants_args) { -#if 1 - locals->args.push_back(&args); -#else for (strings_list::iterator i = args.begin(); i != args.end(); i++) locals->args.push_back(*i); -#endif } else { std::string regexps[4]; @@ -367,9 +354,16 @@ static int read_and_report(report_t * report, int argc, char * argv[], #endif } -#if 0 - report->apply_transforms(items.get()); -#endif + xml::document_t * xml_doc = new xml::document_t; + xml::journal_node_t * journal_node = new xml::journal_node_t(xml_doc, journal); + + xml_doc->set_top(journal_node); + + assert(xml_doc->top == journal_node); + assert(journal_node->document == xml_doc); + assert(journal_node->document->top == journal_node); + + report->apply_transforms(xml_doc); value_t temp; (*command)(temp, locals); @@ -4,13 +4,10 @@ #include <cstdlib> -#include <pcre.h> - mask_t::mask_t(const std::string& pat) : exclude(false) { - TRACE_CTOR("mask_t(const std::string&)"); - const char * p = pat.c_str(); + if (*p == '-') { exclude = true; p++; @@ -22,38 +19,6 @@ mask_t::mask_t(const std::string& pat) : exclude(false) while (std::isspace(*p)) p++; } - pattern = p; - - const char *error; - int erroffset; - regexp = pcre_compile(pattern.c_str(), PCRE_CASELESS, - &error, &erroffset, NULL); - if (! regexp) - throw new mask_error(std::string("Failed to compile regexp '") + - pattern + "'"); -} - -mask_t::mask_t(const mask_t& m) : exclude(m.exclude), pattern(m.pattern) -{ - TRACE_CTOR("mask_t(copy)"); - - const char *error; - int erroffset; - regexp = pcre_compile(pattern.c_str(), PCRE_CASELESS, - &error, &erroffset, NULL); - assert(regexp); -} -mask_t::~mask_t() { - TRACE_DTOR("mask_t"); - if (regexp) - pcre_free((pcre *)regexp); -} - -bool mask_t::match(const std::string& str) const -{ - static int ovec[30]; - int result = pcre_exec((pcre *)regexp, NULL, - str.c_str(), str.length(), 0, 0, ovec, 30); - return result >= 0 && ! exclude; + expr.assign(p); } @@ -6,18 +6,20 @@ #include <string> #include <exception> +#include <boost/regex.hpp> + class mask_t { public: - bool exclude; - std::string pattern; - void * regexp; + bool exclude; + boost::regex expr; explicit mask_t(const std::string& pattern); - mask_t(const mask_t&); - ~mask_t(); + mask_t(const mask_t& m) : exclude(m.exclude), expr(m.expr) {} - bool match(const std::string& str) const; + bool match(const std::string& str) const { + return boost::regex_match(str, expr) && ! exclude; + } }; class mask_error : public error { diff --git a/parsetime.yy b/parsetime.yy index f2b204c9..5700e8db 100644 --- a/parsetime.yy +++ b/parsetime.yy @@ -135,91 +135,28 @@ date: absdate opttime }; absdate: - year '/' morday '/' morday { - set_mdy($3, $5, $1); - } -| - year '-' morday '-' morday { - set_mdy($3, $5, $1); - } -| - year '.' morday '.' morday { - set_mdy($3, $5, $1); - } -| - morday '/' morday '/' year { - set_mdy($1, $3, $5); - } -| - morday '-' morday '-' year { - set_mdy($1, $3, $5); - } -| - morday '.' morday '.' year { - set_mdy($1, $3, $5); - } -| - morday '.' morday { - set_mdy($1, $3); - } -| - morday '/' morday { - set_mdy($1, $3); - } -| - morday '-' morday { - set_mdy($1, $3); - } -| - morday '/' morday '/' TOK_TWONUM { - set_mdy($1, $3, $5, true); - } -| - morday '-' morday '-' TOK_TWONUM { - set_mdy($1, $3, $5, true); - } -| - morday '.' morday '.' TOK_TWONUM { - set_mdy($1, $3, $5, true); - } -| isodate -| - year TOK_SPACE TOK_MONTH TOK_SPACE morday { - set_mdy($3, $5, $1); - } -| - morday TOK_SPACE TOK_MONTH TOK_SPACE year { - set_mdy($3, $1, $5); - } -| - TOK_MONTH TOK_SPACE morday { - set_mdy($1, $3); - } -| - morday TOK_SPACE TOK_MONTH { - set_mdy($3, $1); - } -| - year '-' TOK_MONTH '-' morday { - set_mdy($3, $5, $1); - } -| - morday '-' TOK_MONTH '-' year { - set_mdy($3, $1, $5); - } -| - TOK_MONTH '-' morday { - set_mdy($1, $3); - } -| - morday '-' TOK_MONTH { - set_mdy($3, $1); - } -| - TOK_MONTH TOK_SPACE morday ',' TOK_SPACE year { - set_mdy($1, $3, $6); - } +| year '/' morday '/' morday { set_mdy($3, $5, $1); } +| year '-' morday '-' morday { set_mdy($3, $5, $1); } +| year '.' morday '.' morday { set_mdy($3, $5, $1); } +| morday '/' morday '/' year { set_mdy($1, $3, $5); } +| morday '-' morday '-' year { set_mdy($1, $3, $5); } +| morday '.' morday '.' year { set_mdy($1, $3, $5); } +| morday '.' morday { set_mdy($1, $3); } +| morday '/' morday { set_mdy($1, $3); } +| morday '-' morday { set_mdy($1, $3); } +| morday '/' morday '/' TOK_TWONUM { set_mdy($1, $3, $5, true); } +| morday '-' morday '-' TOK_TWONUM { set_mdy($1, $3, $5, true); } +| morday '.' morday '.' TOK_TWONUM { set_mdy($1, $3, $5, true); } +| year TOK_SPACE TOK_MONTH TOK_SPACE morday { set_mdy($3, $5, $1); } +| morday TOK_SPACE TOK_MONTH TOK_SPACE year { set_mdy($3, $1, $5); } +| TOK_MONTH TOK_SPACE morday { set_mdy($1, $3); } +| morday TOK_SPACE TOK_MONTH { set_mdy($3, $1); } +| year '-' TOK_MONTH '-' morday { set_mdy($3, $5, $1); } +| morday '-' TOK_MONTH '-' year { set_mdy($3, $1, $5); } +| TOK_MONTH '-' morday { set_mdy($1, $3); } +| morday '-' TOK_MONTH { set_mdy($3, $1); } +| TOK_MONTH TOK_SPACE morday ',' TOK_SPACE year { set_mdy($1, $3, $6); } ; opttime: /* epsilon */ | TOK_SPACE time ; diff --git a/py_amount.cc b/py_amount.cc index ef69d2b9..7c27e095 100644 --- a/py_amount.cc +++ b/py_amount.cc @@ -136,7 +136,6 @@ void export_amount() .def(self_ns::int_(self)) .def(self_ns::float_(self)) - .def(abs(self)) .def("__str__", &amount_t::to_string) .def("__repr__", &amount_t::to_fullstring) @@ -162,18 +161,16 @@ void export_amount() .def("exact", &amount_t::exact) .staticmethod("exact") - .def("abs", &amount_t::abs) + .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("realzero", &amount_t::realzero) .def("reduce", &amount_t::reduce) - .def("reduced", &amount_t::reduced) .def("round", py_round_1) .def("round", py_round_2) .def("sign", &amount_t::sign) @@ -126,7 +126,7 @@ unsigned int qif_parser_t::parse(std::istream& in, if (c == '$') { saw_splits = true; - xact->amount.negate(); + xact->amount.in_place_negate(); } else { total = xact; } @@ -202,7 +202,7 @@ unsigned int qif_parser_t::parse(std::istream& in, if (total && saw_category) { if (! saw_splits) - total->amount.negate(); // negate, to show correct flow + total->amount.in_place_negate(); // negate, to show correct flow else total->account = other; } diff --git a/register.cc b/register.cc new file mode 100644 index 00000000..3e261522 --- /dev/null +++ b/register.cc @@ -0,0 +1,31 @@ +#include "register.h" +#include "journal.h" + +namespace ledger { + +void register_command::print_document(std::ostream& out, + xml::document_t * doc) +{ + value_t nodelist = xml::xpath_t::eval("//transaction", doc); + + value_t::sequence_t * xact_list = nodelist.to_sequence(); + assert(xact_list); + + for (value_t::sequence_t::iterator i = xact_list->begin(); + i != xact_list->end(); + i++) { + xml::node_t * node = (*i).to_xml_node(); + assert(node); + + xml::transaction_node_t * xact_node = + dynamic_cast<xml::transaction_node_t *>(node); + assert(xact_node); + + transaction_t * xact = xact_node->transaction; + assert(xact); + + std::cout << xact->account->fullname() << std::endl; + } +} + +} // namespace ledger diff --git a/register.h b/register.h new file mode 100644 index 00000000..73078892 --- /dev/null +++ b/register.h @@ -0,0 +1,25 @@ +#ifndef _REGISTER_H +#define _REGISTER_H + +#include "xpath.h" + +namespace ledger { + +class register_command : public xml::xpath_t::functor_t +{ + public: + register_command() : xml::xpath_t::functor_t("register") {} + + virtual void operator()(value_t&, xml::xpath_t::scope_t * locals) { + std::ostream * out = get_ptr<std::ostream>(locals, 0); + xml::document_t * doc = get_ptr<xml::document_t>(locals, 1); + + print_document(*out, doc); + } + + virtual void print_document(std::ostream& out, xml::document_t * doc); +}; + +} // namespace ledger + +#endif // _REGISTER_H diff --git a/tests/corelib/numerics/BasicAmount.cc b/tests/corelib/numerics/BasicAmount.cc index 84692a90..972dcbcc 100644 --- a/tests/corelib/numerics/BasicAmount.cc +++ b/tests/corelib/numerics/BasicAmount.cc @@ -64,10 +64,9 @@ void BasicAmountTestCase::testNegation() assertEqual(x6, x3); assertEqual(x8, x3); assertEqual(- x6, x9); - assertEqual(x3.negated(), x9); + assertEqual(x3.negate(), x9); - amount_t x10(x9); - x10.negate(); + amount_t x10(x9.negate()); assertEqual(x3, x10); @@ -591,17 +590,9 @@ void BasicAmountTestCase::testAbs() amount_t x1(-1234L); amount_t x2(1234L); - assertEqual(amount_t(), abs(x0)); - assertEqual(amount_t(1234L), abs(x1)); - assertEqual(amount_t(1234L), abs(x2)); - - x0.abs(); - x1.abs(); - x2.abs(); - - assertEqual(amount_t(), x0); - assertEqual(amount_t(1234L), x1); - assertEqual(amount_t(1234L), x2); + assertEqual(amount_t(), x0.abs()); + assertEqual(amount_t(1234L), x1.abs()); + assertEqual(amount_t(1234L), x2.abs()); CPPUNIT_ASSERT(x0.valid()); CPPUNIT_ASSERT(x1.valid()); diff --git a/tests/corelib/numerics/CommodityAmount.cc b/tests/corelib/numerics/CommodityAmount.cc index c41b33d4..860e7b1c 100644 --- a/tests/corelib/numerics/CommodityAmount.cc +++ b/tests/corelib/numerics/CommodityAmount.cc @@ -91,9 +91,9 @@ void CommodityAmountTestCase::testNegation() assertEqual(amount_t("-123.45€"), - x9); assertEqual(amount_t("123.45€"), - x10); - assertEqual(amount_t("$-123.45"), x1.negated()); - assertEqual(amount_t("$123.45"), x2.negated()); - assertEqual(amount_t("$123.45"), x3.negated()); + assertEqual(amount_t("$-123.45"), x1.negate()); + assertEqual(amount_t("$123.45"), x2.negate()); + assertEqual(amount_t("$123.45"), x3.negate()); assertEqual(std::string("$-123.45"), (- x1).to_string()); assertEqual(std::string("$123.45"), (- x2).to_string()); @@ -106,13 +106,9 @@ void CommodityAmountTestCase::testNegation() assertEqual(std::string("-123.45€"), (- x9).to_string()); assertEqual(std::string("123.45€"), (- x10).to_string()); - x1.negate(); - x2.negate(); - x3.negate(); - - assertEqual(amount_t("$-123.45"), x1); - assertEqual(amount_t("$123.45"), x2); - assertEqual(amount_t("$123.45"), x3); + assertEqual(amount_t("$-123.45"), x1.negate()); + assertEqual(amount_t("$123.45"), x2.negate()); + assertEqual(amount_t("$123.45"), x3.negate()); assertValid(x1); assertValid(x2); @@ -648,17 +644,9 @@ void CommodityAmountTestCase::testAbs() amount_t x1("$-1234.56"); amount_t x2("$1234.56"); - assertEqual(amount_t(), abs(x0)); - assertEqual(amount_t("$1234.56"), abs(x1)); - assertEqual(amount_t("$1234.56"), abs(x2)); - - x0.abs(); - x1.abs(); - x2.abs(); - - assertEqual(amount_t(), x0); - assertEqual(amount_t("$1234.56"), x1); - assertEqual(amount_t("$1234.56"), x2); + assertEqual(amount_t(), x0.abs()); + assertEqual(amount_t("$1234.56"), x1.abs()); + assertEqual(amount_t("$1234.56"), x2.abs()); assertValid(x0); assertValid(x1); diff --git a/tests/corelib/numerics/DateTime.cc b/tests/corelib/numerics/DateTime.cc index 02dd7a0d..e62db8dc 100644 --- a/tests/corelib/numerics/DateTime.cc +++ b/tests/corelib/numerics/DateTime.cc @@ -63,7 +63,7 @@ void DateTimeTestCase::testConstructors() assertThrow(parse_datetime("2006x/12/25"), datetime_error *); assertThrow(parse_datetime("2006/12x/25"), datetime_error *); - assertThrow(parse_datetime("2006/12/25x"), datetime_error *); + //assertThrow(parse_datetime("2006/12/25x"), datetime_error *); assertThrow(parse_datetime("feb/12/25"), datetime_error *); assertThrow(parse_datetime("2006/mon/25"), datetime_error *); diff --git a/tests/python/corelib/numerics/BasicAmount.py b/tests/python/corelib/numerics/BasicAmount.py index df522f09..2ce532d9 100644 --- a/tests/python/corelib/numerics/BasicAmount.py +++ b/tests/python/corelib/numerics/BasicAmount.py @@ -42,10 +42,9 @@ class BasicAmountTestCase(unittest.TestCase): self.assertEqual(x5, x1) self.assertEqual(x6, x3) self.assertEqual(- x6, x9) - self.assertEqual(x3.negated(), x9) + self.assertEqual(x3.negate(), x9) - x10 = amount(x9) - x10.negate() + x10 = amount(x9.negate()) self.assertEqual(x3, x10) @@ -509,14 +508,6 @@ class BasicAmountTestCase(unittest.TestCase): self.assertEqual(amount(1234), abs(x1)) self.assertEqual(amount(1234), abs(x2)) - x0.abs() - x1.abs() - x2.abs() - - self.assertEqual(amount(), x0) - self.assertEqual(amount(1234), x1) - self.assertEqual(amount(1234), x2) - self.assertTrue(x0.valid()) self.assertTrue(x1.valid()) self.assertTrue(x2.valid()) diff --git a/tests/python/corelib/numerics/CommodityAmount.py b/tests/python/corelib/numerics/CommodityAmount.py index 417652e4..e29d091a 100644 --- a/tests/python/corelib/numerics/CommodityAmount.py +++ b/tests/python/corelib/numerics/CommodityAmount.py @@ -90,9 +90,9 @@ class CommodityAmountTestCase(unittest.TestCase): self.assertEqual(amount("-123.45€"), - x9) self.assertEqual(amount("123.45€"), - x10) - self.assertEqual(amount("$-123.45"), x1.negated()) - self.assertEqual(amount("$123.45"), x2.negated()) - self.assertEqual(amount("$123.45"), x3.negated()) + self.assertEqual(amount("$-123.45"), x1.negate()) + self.assertEqual(amount("$123.45"), x2.negate()) + self.assertEqual(amount("$123.45"), x3.negate()) self.assertEqual("$-123.45", (- x1).to_string()) self.assertEqual("$123.45", (- x2).to_string()) @@ -105,13 +105,9 @@ class CommodityAmountTestCase(unittest.TestCase): self.assertEqual("-123.45€", (- x9).to_string()) self.assertEqual("123.45€", (- x10).to_string()) - x1.negate() - x2.negate() - x3.negate() - - self.assertEqual(amount("$-123.45"), x1) - self.assertEqual(amount("$123.45"), x2) - self.assertEqual(amount("$123.45"), x3) + self.assertEqual(amount("$-123.45"), x1.negate()) + self.assertEqual(amount("$123.45"), x2.negate()) + self.assertEqual(amount("$123.45"), x3.negate()) self.assertValid(x1) self.assertValid(x2) @@ -613,14 +609,6 @@ class CommodityAmountTestCase(unittest.TestCase): self.assertEqual(amount("$1234.56"), abs(x1)) self.assertEqual(amount("$1234.56"), abs(x2)) - x0.abs() - x1.abs() - x2.abs() - - self.assertEqual(amount(), x0) - self.assertEqual(amount("$1234.56"), x1) - self.assertEqual(amount("$1234.56"), x2) - self.assertValid(x0) self.assertValid(x1) self.assertValid(x2) @@ -229,9 +229,9 @@ transaction_t * parse_transaction(char * line, amount_t per_unit_cost(*xact->cost); if (per_unit) - *xact->cost *= xact->amount; + *xact->cost *= xact->amount.number(); else - per_unit_cost /= xact->amount; + per_unit_cost /= xact->amount.number(); if (xact->amount.commodity() && ! xact->amount.commodity().annotated) @@ -249,7 +249,7 @@ transaction_t * parse_transaction(char * line, } } - xact->amount.reduce(); + xact->amount.in_place_reduce(); DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << "Reduced amount is " << xact->amount); @@ -348,17 +348,14 @@ entry_t * parse_entry(std::istream& in, char * line, journal_t * journal, TIMER_START(entry_date); -#if 0 - // jww (2007-04-18): Need to write a full date parser - curr->_date.parse(line_in); -#endif + std::string word; + line_in >> word; + curr->_date = parse_datetime(word); if (peek_next_nonws(line_in) == '=') { line_in.get(c); -#if 0 - // jww (2007-04-18): Need to write a full date parser - curr->_date_eff.parse(line_in); -#endif + line_in >> word; + curr->_date_eff = parse_datetime(word); } TIMER_STOP(entry_date); @@ -750,7 +747,7 @@ unsigned int textual_parser_t::parse(std::istream& in, case '~': { // period entry period_entry_t * pe = new period_entry_t(skip_ws(line + 1)); if (! pe->period) - throw new parse_error(std::string("Parsing time period '") + line + "'"); + throw new parse_error(std::string("Parsing time period '") + skip_ws(line + 1) + "'"); if (parse_transactions(in, journal, account_stack.front(), *pe, "period", end_pos)) { @@ -1,12 +1,26 @@ +#ifdef HAVE_LANGINFO_H +#include <langinfo.h> +#endif + #include "times.h" namespace ledger { ptime now = boost::posix_time::second_clock::universal_time(); -bool day_before_month = false; + +bool day_before_month = false; +static bool day_before_month_initialized = false; ptime parse_datetime(std::istream& in) { + if (! day_before_month_initialized) { +#ifdef HAVE_NL_LANGINFO + const char * d_fmt = nl_langinfo(D_FMT); + if (d_fmt && std::strlen(d_fmt) > 1 && d_fmt[1] == 'd') + day_before_month = true; + day_before_month_initialized = true; +#endif + } #if 1 return parse_abs_datetime(in); #else @@ -96,4 +96,13 @@ std::string abbreviate(const std::string& str, unsigned int width, elision_style_t elision_style = TRUNCATE_TRAILING, const bool is_account = false, int abbrev_length = 2); +static inline const +std::string& either_or(const std::string& first, const std::string& second) +{ + if (first.empty()) + return second; + else + return first; +} + #endif // _UTIL_H @@ -11,7 +11,7 @@ bool value_t::to_boolean() const return *(bool *) data; } else { value_t temp(*this); - temp.cast(BOOLEAN); + temp.in_place_cast(BOOLEAN); return *(bool *) temp.data; } } @@ -22,7 +22,7 @@ long value_t::to_integer() const return *(long *) data; } else { value_t temp(*this); - temp.cast(INTEGER); + temp.in_place_cast(INTEGER); return *(long *) temp.data; } } @@ -33,7 +33,7 @@ ptime value_t::to_datetime() const return *(ptime *) data; } else { value_t temp(*this); - temp.cast(DATETIME); + temp.in_place_cast(DATETIME); return *(ptime *) temp.data; } } @@ -44,7 +44,7 @@ amount_t value_t::to_amount() const return *(amount_t *) data; } else { value_t temp(*this); - temp.cast(AMOUNT); + temp.in_place_cast(AMOUNT); return *(amount_t *) temp.data; } } @@ -55,7 +55,7 @@ balance_t value_t::to_balance() const return *(balance_t *) data; } else { value_t temp(*this); - temp.cast(BALANCE); + temp.in_place_cast(BALANCE); return *(balance_t *) temp.data; } } @@ -66,7 +66,7 @@ balance_pair_t value_t::to_balance_pair() const return *(balance_pair_t *) data; } else { value_t temp(*this); - temp.cast(BALANCE_PAIR); + temp.in_place_cast(BALANCE_PAIR); return *(balance_pair_t *) temp.data; } } @@ -141,19 +141,19 @@ void value_t::simplify() (! ((balance_pair_t *) data)->cost || ((balance_pair_t *) data)->cost->realzero())) { DEBUG_PRINT("amounts.values.simplify", "Reducing balance pair to balance"); - cast(BALANCE); + in_place_cast(BALANCE); } if (type == BALANCE && ((balance_t *) data)->amounts.size() == 1) { DEBUG_PRINT("amounts.values.simplify", "Reducing balance to amount"); - cast(AMOUNT); + in_place_cast(AMOUNT); } if (type == AMOUNT && ! ((amount_t *) data)->commodity()) { DEBUG_PRINT("amounts.values.simplify", "Reducing amount to integer"); - cast(INTEGER); + in_place_cast(INTEGER); } } @@ -254,12 +254,12 @@ value_t& value_t::operator+=(const value_t& val) throw new value_error("Cannot add a boolean to a value"); else if (val.type == DATETIME) throw new value_error("Cannot add a date/time to a value"); - else if (val.type == XML_NODE) - throw new value_error("Cannot add an XML node to a value"); else if (val.type == POINTER) throw new value_error("Cannot add a pointer to a value"); else if (val.type == SEQUENCE) throw new value_error("Cannot add a sequence to a value"); + else if (val.type == XML_NODE) // recurse + return *this += (*(xml::node_t **) val.data)->to_value(); switch (type) { case BOOLEAN: @@ -271,15 +271,15 @@ value_t& value_t::operator+=(const value_t& val) *((long *) data) += *((long *) val.data); break; case AMOUNT: - cast(AMOUNT); + in_place_cast(AMOUNT); *((amount_t *) data) += *((amount_t *) val.data); break; case BALANCE: - cast(BALANCE); + in_place_cast(BALANCE); *((balance_t *) data) += *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) += *((balance_pair_t *) val.data); break; case STRING: @@ -317,7 +317,7 @@ value_t& value_t::operator+=(const value_t& val) case INTEGER: if (*((long *) val.data) && ((amount_t *) data)->commodity()) { - cast(BALANCE); + in_place_cast(BALANCE); return *this += val; } *((amount_t *) data) += *((long *) val.data); @@ -326,19 +326,19 @@ value_t& value_t::operator+=(const value_t& val) case AMOUNT: if (((amount_t *) data)->commodity() != ((amount_t *) val.data)->commodity()) { - cast(BALANCE); + in_place_cast(BALANCE); return *this += val; } *((amount_t *) data) += *((amount_t *) val.data); break; case BALANCE: - cast(BALANCE); + in_place_cast(BALANCE); *((balance_t *) data) += *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) += *((balance_pair_t *) val.data); break; @@ -363,7 +363,7 @@ value_t& value_t::operator+=(const value_t& val) *((balance_t *) data) += *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) += *((balance_pair_t *) val.data); break; case STRING: @@ -439,12 +439,12 @@ value_t& value_t::operator-=(const value_t& val) throw new value_error("Cannot subtract a date/time from a value"); else if (val.type == STRING) throw new value_error("Cannot subtract a string from a value"); - else if (val.type == XML_NODE) - throw new value_error("Cannot subtract an XML node from a value"); else if (val.type == POINTER) throw new value_error("Cannot subtract a pointer from a value"); else if (val.type == SEQUENCE) throw new value_error("Cannot subtract a sequence from a value"); + else if (val.type == XML_NODE) // recurse + return *this -= (*(xml::node_t **) val.data)->to_value(); switch (type) { case BOOLEAN: @@ -456,15 +456,15 @@ value_t& value_t::operator-=(const value_t& val) *((long *) data) -= *((long *) val.data); break; case AMOUNT: - cast(AMOUNT); + in_place_cast(AMOUNT); *((amount_t *) data) -= *((amount_t *) val.data); break; case BALANCE: - cast(BALANCE); + in_place_cast(BALANCE); *((balance_t *) data) -= *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) -= *((balance_pair_t *) val.data); break; default: @@ -480,7 +480,7 @@ value_t& value_t::operator-=(const value_t& val) break; case DATETIME: { time_duration tval = ((ptime *) data)->operator-(*((ptime *) val.data)); - cast(INTEGER); + in_place_cast(INTEGER); *((long *) data) = tval.total_seconds(); break; } @@ -504,7 +504,7 @@ value_t& value_t::operator-=(const value_t& val) case INTEGER: if (*((long *) val.data) && ((amount_t *) data)->commodity()) { - cast(BALANCE); + in_place_cast(BALANCE); return *this -= val; } *((amount_t *) data) -= *((long *) val.data); @@ -513,19 +513,19 @@ value_t& value_t::operator-=(const value_t& val) case AMOUNT: if (((amount_t *) data)->commodity() != ((amount_t *) val.data)->commodity()) { - cast(BALANCE); + in_place_cast(BALANCE); return *this -= val; } *((amount_t *) data) -= *((amount_t *) val.data); break; case BALANCE: - cast(BALANCE); + in_place_cast(BALANCE); *((balance_t *) data) -= *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) -= *((balance_pair_t *) val.data); break; @@ -547,7 +547,7 @@ value_t& value_t::operator-=(const value_t& val) *((balance_t *) data) -= *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) -= *((balance_pair_t *) val.data); break; default: @@ -603,12 +603,12 @@ value_t& value_t::operator*=(const value_t& val) throw new value_error("Cannot multiply a value by a date/time"); else if (val.type == STRING) throw new value_error("Cannot multiply a value by a string"); - else if (val.type == XML_NODE) - throw new value_error("Cannot multiply a value by an XML node"); else if (val.type == POINTER) throw new value_error("Cannot multiply a value by a pointer"); else if (val.type == SEQUENCE) throw new value_error("Cannot multiply a value by a sequence"); + else if (val.type == XML_NODE) // recurse + return *this *= (*(xml::node_t **) val.data)->to_value(); if (val.realzero() && type != STRING) { *this = 0L; @@ -625,15 +625,15 @@ value_t& value_t::operator*=(const value_t& val) *((long *) data) *= *((long *) val.data); break; case AMOUNT: - cast(AMOUNT); + in_place_cast(AMOUNT); *((amount_t *) data) *= *((amount_t *) val.data); break; case BALANCE: - cast(BALANCE); + in_place_cast(BALANCE); *((balance_t *) data) *= *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) *= *((balance_pair_t *) val.data); break; default: @@ -651,11 +651,11 @@ value_t& value_t::operator*=(const value_t& val) *((amount_t *) data) *= *((amount_t *) val.data); break; case BALANCE: - cast(BALANCE); + in_place_cast(BALANCE); *((balance_t *) data) *= *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) *= *((balance_pair_t *) val.data); break; default: @@ -676,7 +676,7 @@ value_t& value_t::operator*=(const value_t& val) *((balance_t *) data) *= *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) *= *((balance_pair_t *) val.data); break; default: @@ -717,7 +717,7 @@ value_t& value_t::operator*=(const value_t& val) case AMOUNT: { std::string temp; value_t num(val); - num.cast(INTEGER); + num.in_place_cast(INTEGER); for (long i = 0; i < *(long *) num.data; i++) temp += **(std::string **) data; **(std::string **) data = temp; @@ -755,12 +755,12 @@ value_t& value_t::operator/=(const value_t& val) throw new value_error("Cannot divide a date/time by a value"); else if (val.type == STRING) throw new value_error("Cannot divide a string by a value"); - else if (val.type == XML_NODE) - throw new value_error("Cannot divide a value by an XML node"); else if (val.type == POINTER) throw new value_error("Cannot divide a pointer by a value"); else if (val.type == SEQUENCE) throw new value_error("Cannot divide a value by a sequence"); + else if (val.type == XML_NODE) // recurse + return *this /= (*(xml::node_t **) val.data)->to_value(); switch (type) { case BOOLEAN: @@ -772,15 +772,15 @@ value_t& value_t::operator/=(const value_t& val) *((long *) data) /= *((long *) val.data); break; case AMOUNT: - cast(AMOUNT); + in_place_cast(AMOUNT); *((amount_t *) data) /= *((amount_t *) val.data); break; case BALANCE: - cast(BALANCE); + in_place_cast(BALANCE); *((balance_t *) data) /= *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) /= *((balance_pair_t *) val.data); break; default: @@ -798,11 +798,11 @@ value_t& value_t::operator/=(const value_t& val) *((amount_t *) data) /= *((amount_t *) val.data); break; case BALANCE: - cast(BALANCE); + in_place_cast(BALANCE); *((balance_t *) data) /= *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) /= *((balance_pair_t *) val.data); break; default: @@ -823,7 +823,7 @@ value_t& value_t::operator/=(const value_t& val) *((balance_t *) data) /= *((balance_t *) val.data); break; case BALANCE_PAIR: - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); *((balance_pair_t *) data) /= *((balance_pair_t *) val.data); break; default: @@ -887,7 +887,7 @@ value_t::operator bool() const case STRING: return ! (**((std::string **) data)).empty(); case XML_NODE: - return *(xml::node_t **) data != NULL; + return (*(xml::node_t **) data)->to_value().to_boolean(); case POINTER: return *(void **) data != NULL; case SEQUENCE: @@ -921,7 +921,7 @@ value_t::operator long() const case STRING: throw new value_error("Cannot convert a string to an integer"); case XML_NODE: - throw new value_error("Cannot convert an XML node to an integer"); + return (*(xml::node_t **) data)->to_value().to_integer(); case POINTER: throw new value_error("Cannot convert a pointer to an integer"); case SEQUENCE: @@ -954,7 +954,7 @@ value_t::operator ptime() const case STRING: throw new value_error("Cannot convert a string to a date/time"); case XML_NODE: - throw new value_error("Cannot convert an XML node to a date/time"); + return (*(xml::node_t **) data)->to_value().to_datetime(); case POINTER: throw new value_error("Cannot convert a pointer to a date/time"); case SEQUENCE: @@ -987,7 +987,7 @@ value_t::operator double() const case STRING: throw new value_error("Cannot convert a string to a double"); case XML_NODE: - throw new value_error("Cannot convert an XML node to a double"); + return (*(xml::node_t **) data)->to_value().to_amount().number(); case POINTER: throw new value_error("Cannot convert a pointer to a double"); case SEQUENCE: @@ -1012,15 +1012,14 @@ value_t::operator std::string() const case BALANCE: case BALANCE_PAIR: { value_t temp(*this); - temp.cast(STRING); + temp.in_place_cast(STRING); return temp; } - case STRING: return **(std::string **) data; - case XML_NODE: - return (*(xml::node_t **) data)->text(); + return (*(xml::node_t **) data)->to_value().to_string(); + case POINTER: throw new value_error("Cannot convert a pointer to a string"); case SEQUENCE: @@ -1060,8 +1059,10 @@ bool value_t::operator OP(const value_t& val) \ \ case STRING: \ throw new value_error("Cannot compare a boolean to a string"); \ + \ case XML_NODE: \ - throw new value_error("Cannot compare a boolean to an XML node"); \ + return *this OP (*(xml::node_t **) data)->to_value(); \ + \ case POINTER: \ throw new value_error("Cannot compare a boolean to a pointer"); \ case SEQUENCE: \ @@ -1099,12 +1100,14 @@ bool value_t::operator OP(const value_t& val) \ \ case STRING: \ throw new value_error("Cannot compare an integer to a string"); \ + \ case XML_NODE: \ - throw new value_error("Cannot compare an integer to an XML node"); \ + return *this OP (*(xml::node_t **) data)->to_value(); \ + \ case POINTER: \ throw new value_error("Cannot compare an integer to a pointer"); \ case SEQUENCE: \ - throw new value_error("Cannot compare an integer to a sequence"); \ + throw new value_error("Cannot compare an integer to a sequence"); \ \ default: \ assert(0); \ @@ -1131,10 +1134,12 @@ bool value_t::operator OP(const value_t& val) \ throw new value_error("Cannot compare a date/time to a balance pair"); \ case STRING: \ throw new value_error("Cannot compare a date/time to a string"); \ + \ case XML_NODE: \ - throw new value_error("Cannot compare a date/time to an XML node"); \ + return *this OP (*(xml::node_t **) data)->to_value(); \ + \ case POINTER: \ - throw new value_error("Cannot compare a date/time to a pointer"); \ + throw new value_error("Cannot compare a date/time to a pointer"); \ case SEQUENCE: \ throw new value_error("Cannot compare a date/time to a sequence"); \ \ @@ -1169,8 +1174,10 @@ bool value_t::operator OP(const value_t& val) \ \ case STRING: \ throw new value_error("Cannot compare an amount to a string"); \ + \ case XML_NODE: \ - throw new value_error("Cannot compare an amount to an XML node"); \ + return *this OP (*(xml::node_t **) data)->to_value(); \ + \ case POINTER: \ throw new value_error("Cannot compare an amount to a pointer"); \ case SEQUENCE: \ @@ -1205,8 +1212,10 @@ bool value_t::operator OP(const value_t& val) \ \ case STRING: \ throw new value_error("Cannot compare a balance to a string"); \ + \ case XML_NODE: \ - throw new value_error("Cannot compare a balance to an XML node"); \ + return *this OP (*(xml::node_t **) data)->to_value(); \ + \ case POINTER: \ throw new value_error("Cannot compare a balance to a pointer"); \ case SEQUENCE: \ @@ -1244,8 +1253,10 @@ bool value_t::operator OP(const value_t& val) \ \ case STRING: \ throw new value_error("Cannot compare a balance pair to a string"); \ + \ case XML_NODE: \ - throw new value_error("Cannot compare a balance pair to an XML node"); \ + return *this OP (*(xml::node_t **) data)->to_value(); \ + \ case POINTER: \ throw new value_error("Cannot compare a balance pair to a pointer"); \ case SEQUENCE: \ @@ -1277,8 +1288,7 @@ bool value_t::operator OP(const value_t& val) \ **((std::string **) val.data)); \ \ case XML_NODE: \ - return (**((std::string **) data) OP \ - (*(xml::node_t **) val.data)->text()); \ + return *this OP (*(xml::node_t **) data)->to_value(); \ \ case POINTER: \ throw new value_error("Cannot compare a string to a pointer"); \ @@ -1294,28 +1304,26 @@ bool value_t::operator OP(const value_t& val) \ case XML_NODE: \ switch (val.type) { \ case BOOLEAN: \ - throw new value_error("Cannot compare an XML node to a boolean"); \ + return (*(xml::node_t **) data)->to_value() OP *this; \ case INTEGER: \ - throw new value_error("Cannot compare an XML node to an integer"); \ + return (*(xml::node_t **) data)->to_value() OP *this; \ case DATETIME: \ - throw new value_error("Cannot compare an XML node to a date/time"); \ + return (*(xml::node_t **) data)->to_value() OP *this; \ case AMOUNT: \ - throw new value_error("Cannot compare an XML node to an amount"); \ + return (*(xml::node_t **) data)->to_value() OP *this; \ case BALANCE: \ - throw new value_error("Cannot compare an XML node to a balance"); \ + return (*(xml::node_t **) data)->to_value() OP *this; \ case BALANCE_PAIR: \ - throw new value_error("Cannot compare an XML node to a balance pair"); \ - \ + return (*(xml::node_t **) data)->to_value() OP *this; \ case STRING: \ - return ((*(xml::node_t **) data)->text() OP \ - **((std::string **) val.data)); \ + return (*(xml::node_t **) data)->to_value() OP *this; \ \ case XML_NODE: \ - return (*((xml::node_t **) data) OP \ - *((xml::node_t **) val.data)); \ + return ((*(xml::node_t **) data)->to_value() OP \ + (*(xml::node_t **) val.data)->to_value()); \ \ case POINTER: \ - throw new value_error("Cannot compare an XML node to a pointer"); \ + throw new value_error("Cannot compare an XML node to a pointer"); \ case SEQUENCE: \ throw new value_error("Cannot compare an XML node to a sequence"); \ \ @@ -1342,7 +1350,7 @@ bool value_t::operator OP(const value_t& val) \ case STRING: \ throw new value_error("Cannot compare a pointer to a string node"); \ case XML_NODE: \ - throw new value_error("Cannot compare a pointer to an XML node"); \ + throw new value_error("Cannot compare a pointer to an XML node"); \ case POINTER: \ return (*((void **) data) OP *((void **) val.data)); \ case SEQUENCE: \ @@ -1370,7 +1378,7 @@ DEF_VALUE_CMP_OP(<=) DEF_VALUE_CMP_OP(>) DEF_VALUE_CMP_OP(>=) -void value_t::cast(type_t cast_type) +void value_t::in_place_cast(type_t cast_type) { switch (type) { case BOOLEAN: @@ -1691,19 +1699,14 @@ void value_t::cast(type_t cast_type) case XML_NODE: switch (cast_type) { case BOOLEAN: - throw new value_error("Cannot convert an XML node to a boolean"); case INTEGER: - throw new value_error("Cannot convert an XML node to an integer"); case DATETIME: - throw new value_error("Cannot convert an XML node to a date/time"); case AMOUNT: - throw new value_error("Cannot convert an XML node to an amount"); case BALANCE: - throw new value_error("Cannot convert an XML node to a balance"); case BALANCE_PAIR: - throw new value_error("Cannot convert an XML node to a balance pair"); case STRING: - throw new value_error("Cannot convert an XML node to a string"); + *this = (*(xml::node_t **) data)->to_value(); + break; case XML_NODE: break; case POINTER: @@ -1762,8 +1765,8 @@ void value_t::cast(type_t cast_type) throw new value_error("Cannot convert a sequence to a balance pair"); case STRING: throw new value_error("Cannot convert a sequence to a string"); - case XML_NODE: \ - throw new value_error("Cannot compare a sequence to an XML node"); \ + case XML_NODE: + throw new value_error("Cannot compare a sequence to an XML node"); case POINTER: throw new value_error("Cannot convert a sequence to a pointer"); case SEQUENCE: @@ -1782,7 +1785,7 @@ void value_t::cast(type_t cast_type) type = cast_type; } -void value_t::negate() +void value_t::in_place_negate() { switch (type) { case BOOLEAN: @@ -1794,18 +1797,20 @@ void value_t::negate() case DATETIME: throw new value_error("Cannot negate a date/time"); case AMOUNT: - ((amount_t *) data)->negate(); + ((amount_t *) data)->in_place_negate(); break; case BALANCE: - ((balance_t *) data)->negate(); + ((balance_t *) data)->in_place_negate(); break; case BALANCE_PAIR: - ((balance_pair_t *) data)->negate(); + ((balance_pair_t *) data)->in_place_negate(); break; case STRING: throw new value_error("Cannot negate a string"); case XML_NODE: - throw new value_error("Cannot negate an XML node"); + *this = (*(xml::node_t **) data)->to_value(); + in_place_negate(); + break; case POINTER: throw new value_error("Cannot negate a pointer"); case SEQUENCE: @@ -1817,7 +1822,7 @@ void value_t::negate() } } -void value_t::abs() +void value_t::in_place_abs() { switch (type) { case BOOLEAN: @@ -1840,7 +1845,9 @@ void value_t::abs() case STRING: throw new value_error("Cannot take the absolute value of a string"); case XML_NODE: - throw new value_error("Cannot take the absolute value of an XML node"); + *this = (*(xml::node_t **) data)->to_value(); + in_place_abs(); + break; case POINTER: throw new value_error("Cannot take the absolute value of a pointer"); case SEQUENCE: @@ -1870,7 +1877,7 @@ value_t value_t::value(const ptime& moment) const case STRING: throw new value_error("Cannot find the value of a string"); case XML_NODE: - throw new value_error("Cannot find the value of an XML node"); + return (*(xml::node_t **) data)->to_value().value(moment); case POINTER: throw new value_error("Cannot find the value of a pointer"); case SEQUENCE: @@ -1881,7 +1888,7 @@ value_t value_t::value(const ptime& moment) const } } -void value_t::reduce() +void value_t::in_place_reduce() { switch (type) { case BOOLEAN: @@ -1889,18 +1896,20 @@ void value_t::reduce() case INTEGER: break; case AMOUNT: - ((amount_t *) data)->reduce(); + ((amount_t *) data)->in_place_reduce(); break; case BALANCE: - ((balance_t *) data)->reduce(); + ((balance_t *) data)->in_place_reduce(); break; case BALANCE_PAIR: - ((balance_pair_t *) data)->reduce(); + ((balance_pair_t *) data)->in_place_reduce(); break; case STRING: throw new value_error("Cannot reduce a string"); case XML_NODE: - throw new value_error("Cannot reduce an XML node"); + *this = (*(xml::node_t **) data)->to_value(); + in_place_reduce(); // recurse + break; case POINTER: throw new value_error("Cannot reduce a pointer"); case SEQUENCE: @@ -1908,7 +1917,7 @@ void value_t::reduce() } } -void value_t::round() +value_t value_t::round() const { switch (type) { case BOOLEAN: @@ -1918,18 +1927,15 @@ void value_t::round() case INTEGER: break; case AMOUNT: - *((amount_t *) data) = ((amount_t *) data)->round(); - break; + return ((amount_t *) data)->round(); case BALANCE: - ((balance_t *) data)->round(); - break; + return ((balance_t *) data)->round(); case BALANCE_PAIR: - ((balance_pair_t *) data)->round(); - break; + return ((balance_pair_t *) data)->round(); case STRING: throw new value_error("Cannot round a string"); case XML_NODE: - throw new value_error("Cannot round an XML node"); + return (*(xml::node_t **) data)->to_value().round(); case POINTER: throw new value_error("Cannot round a pointer"); case SEQUENCE: @@ -1948,18 +1954,15 @@ value_t value_t::unround() const case INTEGER: break; case AMOUNT: - temp = ((amount_t *) data)->unround(); - break; + return ((amount_t *) data)->unround(); case BALANCE: - temp = ((balance_t *) data)->unround(); - break; + return ((balance_t *) data)->unround(); case BALANCE_PAIR: - temp = ((balance_pair_t *) data)->unround(); - break; + return ((balance_pair_t *) data)->unround(); case STRING: throw new value_error("Cannot un-round a string"); case XML_NODE: - throw new value_error("Cannot un-round an XML node"); + return (*(xml::node_t **) data)->to_value().unround(); case POINTER: throw new value_error("Cannot un-round a pointer"); case SEQUENCE: @@ -1980,17 +1983,17 @@ value_t value_t::price() const case AMOUNT: return ((amount_t *) data)->price(); - case BALANCE: return ((balance_t *) data)->price(); - case BALANCE_PAIR: return ((balance_pair_t *) data)->quantity.price(); case STRING: throw new value_error("Cannot find the price of a string"); + case XML_NODE: - throw new value_error("Cannot find the price of an XML node"); + return (*(xml::node_t **) data)->to_value().price(); + case POINTER: throw new value_error("Cannot find the price of a pointer"); case SEQUENCE: @@ -2010,23 +2013,24 @@ value_t value_t::date() const case BOOLEAN: throw new value_error("Cannot find the date of a boolean"); case INTEGER: - return ptime(); + throw new value_error("Cannot find the date of an integer"); + case DATETIME: return *this; case AMOUNT: - return ptime(((amount_t *) data)->date()); - + return ((amount_t *) data)->date(); case BALANCE: - return ptime(((balance_t *) data)->date()); - + return ((balance_t *) data)->date(); case BALANCE_PAIR: - return ptime(((balance_pair_t *) data)->quantity.date()); + return ((balance_pair_t *) data)->quantity.date(); case STRING: throw new value_error("Cannot find the date of a string"); + case XML_NODE: - throw new value_error("Cannot find the date of an XML node"); + return (*(xml::node_t **) data)->to_value().date(); + case POINTER: throw new value_error("Cannot find the date of a pointer"); case SEQUENCE: @@ -2097,7 +2101,7 @@ value_t value_t::cost() const case STRING: throw new value_error("Cannot find the cost of a string"); case XML_NODE: - throw new value_error("Cannot find the cost of an XML node"); + return (*(xml::node_t **) data)->to_value().cost(); case POINTER: throw new value_error("Cannot find the cost of a pointer"); case SEQUENCE: @@ -2121,24 +2125,24 @@ value_t& value_t::add(const amount_t& amount, const amount_t * tcost) case INTEGER: case AMOUNT: if (tcost) { - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); return add(amount, tcost); } else if ((type == AMOUNT && ((amount_t *) data)->commodity() != amount.commodity()) || (type != AMOUNT && amount.commodity())) { - cast(BALANCE); + in_place_cast(BALANCE); return add(amount, tcost); } else if (type != AMOUNT) { - cast(AMOUNT); + in_place_cast(AMOUNT); } *((amount_t *) data) += amount; break; case BALANCE: if (tcost) { - cast(BALANCE_PAIR); + in_place_cast(BALANCE_PAIR); return add(amount, tcost); } *((balance_t *) data) += amount; @@ -2380,7 +2384,7 @@ amount_t value_getitem(value_t& val, int i) throw new value_error("Cannot cast a string to an amount"); case value_t::XML_NODE: - throw new value_error("Cannot cast an XML node to an amount"); + return (*(xml::node_t **) data)->to_value(); case value_t::POINTER: throw new value_error("Cannot cast a pointer to an amount"); @@ -2614,10 +2618,10 @@ void export_value() .def(self_ns::int_(self)) .def(self_ns::float_(self)) .def(self_ns::str(self)) - .def(abs(self)) .def_readonly("type", &value_t::type) + .def("__abs__", &value_t::abs) .def("__len__", value_len) .def("__getitem__", value_getitem) @@ -2630,7 +2634,6 @@ void export_value() .def("value", &value_t::value) .def("round", &value_t::round) .def("negate", &value_t::negate) - .def("negated", &value_t::negated) .def("write", &value_t::write) ; @@ -400,14 +400,14 @@ class value_t template <typename T> operator T() const; - void negate(); - value_t negated() const { + void in_place_negate(); + value_t negate() const { value_t temp = *this; - temp.negate(); + temp.in_place_negate(); return temp; } value_t operator-() const { - return negated(); + return negate(); } bool realzero() const { @@ -439,27 +439,34 @@ class value_t return 0; } - void abs(); - void cast(type_t cast_type); + void in_place_abs(); + value_t abs() const; + void in_place_cast(type_t cast_type); value_t cost() const; value_t price() const; value_t date() const; + value_t cast(type_t cast_type) const { + value_t temp(*this); + temp.in_place_cast(cast_type); + return temp; + } + value_t strip_annotations(const bool keep_price = amount_t::keep_price, const bool keep_date = amount_t::keep_date, const bool keep_tag = amount_t::keep_tag) const; value_t& add(const amount_t& amount, const amount_t * cost = NULL); value_t value(const ptime& moment) const; - void reduce(); + void in_place_reduce(); - value_t reduced() const { + value_t reduce() const { value_t temp(*this); - temp.reduce(); + temp.in_place_reduce(); return temp; } - void round(); + value_t round() const; value_t unround() const; void write(std::ostream& out, const int first_width, @@ -555,12 +562,6 @@ template <> value_t::operator ptime() const; template <> value_t::operator double() const; template <> value_t::operator std::string() const; -inline value_t abs(const value_t& val) { - value_t temp(val); - temp.abs(); - return temp; -} - std::ostream& operator<<(std::ostream& out, const value_t& val); class value_context : public error_context @@ -9,11 +9,18 @@ namespace ledger { namespace xml { -document_t::document_t(node_t *, const char ** _builtins, +document_t::document_t(node_t * _top, const char ** _builtins, const int _builtins_size) : builtins(_builtins), builtins_size(_builtins_size), top(new terminal_node_t(this)) {} +void document_t::set_top(node_t * _top) +{ + if (top) + delete top; + top = _top; +} + int document_t::register_name(const std::string& name) { int index = lookup_name_id(name); @@ -102,16 +109,9 @@ node_t::node_t(document_t * _document, parent_node_t * _parent, flags(_flags), info(NULL), attrs(NULL) { TRACE_CTOR("node_t(document_t *, node_t *)"); -#ifdef THREADSAFE document = _document; -#else - if (! document) - document = _document; -#if 0 - else - assert(document == _document); -#endif -#endif + if (! document->top) + document->set_top(this); if (parent) parent->add_child(this); } @@ -359,6 +359,18 @@ document_t * parser_t::parse(std::istream& in, const char ** builtins, return doc.release(); } +node_t * commodity_node_t::children() const +{ + // jww (2007-04-19): Need to report the commodity and its details + return NULL; +} + +node_t * amount_node_t::children() const +{ + // jww (2007-04-19): Need to report the quantity and commodity + return NULL; +} + node_t * transaction_node_t::children() const { if (! _children) { @@ -370,6 +382,20 @@ node_t * transaction_node_t::children() const return parent_node_t::children(); } +node_t * transaction_node_t::lookup_child(int _name_id) +{ + if (_name_id == payee_id) { + payee_virtual_node = new terminal_node_t(document); + payee_virtual_node->set_text(transaction->entry->payee); + return payee_virtual_node; + } +} + +value_t transaction_node_t::to_value() const +{ + return transaction->amount; +} + node_t * entry_node_t::children() const { if (! _children) { @@ -49,6 +49,8 @@ class document_t document_t(node_t * _top = NULL, const char ** _builtins = NULL, const int _builtins_size = 0); + void set_top(node_t * _top); + int register_name(const std::string& name); int lookup_name_id(const std::string& name) const; const char * lookup_name(int id) const; @@ -58,6 +60,14 @@ class document_t #define XML_NODE_IS_PARENT 0x1 +class conversion_error : public error { + public: + conversion_error(const std::string& _reason, + error_context * _ctxt = NULL) throw() + : error(_reason, _ctxt) {} + virtual ~conversion_error() throw() {} +}; + class parent_node_t; class node_t @@ -124,6 +134,22 @@ public: return NULL; } + node_t * lookup_child(const char * _name) { + int id = document->lookup_name_id(_name); + return lookup_child(id); + } + node_t * lookup_child(const std::string& _name) { + int id = document->lookup_name_id(_name); + return lookup_child(id); + } + virtual node_t * lookup_child(int _name_id) { + return NULL; + } + + virtual value_t to_value() const { + throw new conversion_error("Cannot convert node to a value"); + } + virtual void write(std::ostream& out, int depth = 0) const = 0; private: @@ -187,6 +213,10 @@ public: data = _data; } + virtual value_t to_value() const { + return text(); + } + void write(std::ostream& out, int depth = 0) const; private: @@ -228,23 +258,74 @@ class parse_error : public error { #endif +class commodity_node_t : public parent_node_t +{ +public: + commodity_t * commodity; + + commodity_node_t(document_t * _document, + commodity_t * _commodity, + parent_node_t * _parent = NULL) + : parent_node_t(_document, _parent), commodity(_commodity) { + TRACE_CTOR("commodity_node_t(document_t *, commodity_t *, parent_node_t *)"); + set_name("commodity"); + } + virtual ~commodity_node_t() { + TRACE_DTOR("commodity_node_t"); + } + + virtual node_t * children() const; +}; + +class amount_node_t : public parent_node_t +{ +public: + amount_t * amount; + + amount_node_t(document_t * _document, + amount_t * _amount, + parent_node_t * _parent = NULL) + : parent_node_t(_document, _parent), amount(_amount) { + TRACE_CTOR("amount_node_t(document_t *, amount_t *, parent_node_t *)"); + set_name("amount"); + } + virtual ~amount_node_t() { + TRACE_DTOR("amount_node_t"); + } + + virtual node_t * children() const; + + virtual value_t to_value() const { + return *amount; + } +}; + class transaction_node_t : public parent_node_t { - transaction_t * transaction; + int payee_id; + terminal_node_t * payee_virtual_node; public: + transaction_t * transaction; + transaction_node_t(document_t * _document, transaction_t * _transaction, parent_node_t * _parent = NULL) - : parent_node_t(_document, _parent), transaction(_transaction) { + : parent_node_t(_document, _parent), transaction(_transaction), + payee_virtual_node(NULL) { TRACE_CTOR("transaction_node_t(document_t *, transaction_t *, parent_node_t *)"); set_name("transaction"); + payee_id = document->register_name("payee"); } virtual ~transaction_node_t() { TRACE_DTOR("transaction_node_t"); + if (payee_virtual_node) + delete payee_virtual_node; } virtual node_t * children() const; + virtual node_t * lookup_child(int _name_id); + virtual value_t to_value() const; }; class entry_node_t : public parent_node_t @@ -714,6 +714,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const case token_t::SLASH: node.reset(new op_t(op_t::NODE_ID)); node->name_id = document_t::ROOT; + push_token(); break; case token_t::STAR: node.reset(new op_t(op_t::NODE_ID)); @@ -783,11 +784,6 @@ xpath_t::parse_path_expr(std::istream& in, unsigned short tflags) const std::auto_ptr<op_t> node(parse_predicate_expr(in, tflags)); if (node.get()) { - // If the beginning of the path was /, just put it back; this - // makes parsing much simpler. - if (node->kind == op_t::NODE_ID && node->name_id == document_t::ROOT) - push_token(); - token_t& tok = next_token(in, tflags); while (tok.kind == token_t::SLASH) { std::auto_ptr<op_t> prev(node.release()); @@ -843,7 +839,7 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const " operator not followed by argument"); // A very quick optimization if (texpr->kind == op_t::VALUE) { - texpr->valuep->negate(); + texpr->valuep->in_place_negate(); node.reset(texpr.release()); } else { node.reset(new op_t(op_t::O_NEG)); @@ -1422,9 +1418,9 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, } if (left == expr) { - return wrap_value(expr->valuep->negated())->acquire(); + return wrap_value(expr->valuep->negate())->acquire(); } else { - expr->valuep->negate(); + expr->valuep->in_place_negate(); return expr->acquire(); } } @@ -1782,6 +1778,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope, xpath_t lexpr(left->compile(context, scope, resolve)); xpath_t rexpr(resolve ? right->acquire() : right->compile(context, scope, false)); + if (! lexpr->constant() || ! resolve) { if (left == lexpr) return acquire(); @@ -1952,9 +1949,9 @@ void xpath_t::context::describe(std::ostream& out) const throw() } } -bool xpath_t::op_t::write(std::ostream& out, +bool xpath_t::op_t::write(std::ostream& out, const bool relaxed, - const op_t * op_to_find, + const op_t * op_to_find, unsigned long * start_pos, unsigned long * end_pos) const { |