Merge branch 'next'

This commit is contained in:
John Wiegley 2010-06-09 05:44:06 -04:00
commit 14476a63f4
36 changed files with 33709 additions and 887 deletions

90
acprep
View file

@ -214,9 +214,11 @@ class BoostInfo(object):
class CommandLineApp(object): class CommandLineApp(object):
"Base class for building command line applications." "Base class for building command line applications."
force_exit = True # If true, always ends run() with sys.exit() force_exit = True # If true, always ends run() with sys.exit()
log_handler = None log_handler = None
darwin_gcc = False darwin_gcc = False
boost_version = "1_43"
gcc_version = "45"
options = { options = {
'debug': False, 'debug': False,
@ -459,6 +461,9 @@ class PrepareBuild(CommandLineApp):
op.add_option('', '--universal', action='store_true', op.add_option('', '--universal', action='store_true',
dest='universal', default=False, dest='universal', default=False,
help='Attempt to build universal binaries') help='Attempt to build universal binaries')
op.add_option('', '--gcc45', action='store_true',
dest='gcc45', default=False,
help='Require the use of gcc 4.5')
op.add_option('', '--output', metavar='DIR', action="callback", op.add_option('', '--output', metavar='DIR', action="callback",
callback=self.option_output, callback=self.option_output,
help='Build in the specified directory') help='Build in the specified directory')
@ -909,13 +914,17 @@ class PrepareBuild(CommandLineApp):
def setup_for_johnw(self): def setup_for_johnw(self):
if self.current_flavor == 'debug' or self.current_flavor == 'gcov': if self.current_flavor == 'debug' or self.current_flavor == 'gcov':
if exists('/usr/local/stow/cppunit/include'): if exists('/usr/local/stow/cppunit-gcc%s/include' % self.gcc_version):
self.sys_include_dirs.insert(0, '/usr/local/stow/cppunit/include') self.sys_include_dirs.insert(
self.sys_library_dirs.insert(0, '/usr/local/stow/cppunit/lib') 0, '/usr/local/stow/cppunit-gcc%s/include' % self.gcc_version)
self.sys_library_dirs.insert(
0, '/usr/local/stow/cppunit-gcc%s/lib' % self.gcc_version)
if exists('/usr/local/stow/icu/include'): if exists('/usr/local/stow/icu-gcc%s/include' % self.gcc_version):
self.sys_include_dirs.insert(0, '/usr/local/stow/icu/include') self.sys_include_dirs.insert(
self.sys_library_dirs.insert(0, '/usr/local/stow/icu/lib') 0, '/usr/local/stow/icu-gcc%s/include' % self.gcc_version)
self.sys_library_dirs.insert(
0, '/usr/local/stow/icu-gcc%s/lib' % self.gcc_version)
self.CPPFLAGS.append('-D_GLIBCXX_FULLY_DYNAMIC_STRING=1') self.CPPFLAGS.append('-D_GLIBCXX_FULLY_DYNAMIC_STRING=1')
self.configure_args.append('--disable-shared') self.configure_args.append('--disable-shared')
@ -955,11 +964,16 @@ class PrepareBuild(CommandLineApp):
elif system == 'Darwin': elif system == 'Darwin':
if (self.current_flavor == 'opt' or \ if (self.current_flavor == 'opt' or \
self.current_flavor == 'default') and \ self.current_flavor == 'default') and \
not self.options.gcc45 and \
exists('/usr/bin/g++-4.2'): exists('/usr/bin/g++-4.2'):
self.envvars['CC'] = '/usr/bin/gcc-4.2' self.envvars['CC'] = '/usr/bin/gcc-4.2'
self.envvars['CXX'] = '/usr/bin/g++-4.2' self.envvars['CXX'] = '/usr/bin/g++-4.2'
self.envvars['LD'] = '/usr/bin/g++-4.2' self.envvars['LD'] = '/usr/bin/g++-4.2'
self.darwin_gcc = True self.darwin_gcc = True
elif exists('/opt/local/bin/g++-mp-4.5'):
self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.5'
self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.5'
self.envvars['LD'] = '/opt/local/bin/g++-mp-4.5'
elif exists('/opt/local/bin/g++-mp-4.4'): elif exists('/opt/local/bin/g++-mp-4.4'):
self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.4' self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.4'
self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.4' self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.4'
@ -1133,13 +1147,19 @@ class PrepareBuild(CommandLineApp):
self.log.debug('We are using GLIBCXX_DEBUG, so setting up flags') self.log.debug('We are using GLIBCXX_DEBUG, so setting up flags')
self.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1') self.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1')
if self.boost_info.configure(home_path = '/usr/local/stow/boost_1_43_0', if self.boost_info.configure(
suffix = '-xgcc44-sd-1_43', home_path = '/usr/local/stow/boost_%s_0-gcc%s' % \
include_path = 'include/boost-1_43'): (self.boost_version, self.gcc_version),
suffix = '-xgcc%s-sd-%s' % \
(self.gcc_version, self.boost_version),
include_path = 'include/boost-%s' % self.boost_version):
pass pass
elif self.boost_info.configure(home_path = '/usr/local/stow/boost_1_43_0', elif self.boost_info.configure(
suffix = '-xgcc44-d-1_43', home_path = '/usr/local/stow/boost_%s_0-gcc%s' % \
include_path = 'include/boost-1_43'): (self.boost_version, self.gcc_version),
suffix = '-xgcc%s-d-%s' % \
(self.gcc_version, self.boost_version),
include_path = 'include/boost-%s' % self.boost_version):
pass pass
elif self.boost_info.configure(suffix = '-d'): elif self.boost_info.configure(suffix = '-d'):
pass pass
@ -1147,13 +1167,19 @@ class PrepareBuild(CommandLineApp):
else: else:
if self.boost_info.configure(): if self.boost_info.configure():
pass pass
elif self.boost_info.configure(home_path = '/usr/local/stow/boost_1_43_0', elif self.boost_info.configure(
suffix = '-xgcc44-s-1_43', home_path = '/usr/local/stow/boost_%s_0-gcc%s' % \
include_path = 'include/boost-1_43'): (self.boost_version, self.gcc_version),
suffix = '-xgcc%s-s-%s' % \
(self.gcc_version, self.boost_version),
include_path = 'include/boost-%s' % self.boost_version):
pass pass
elif self.boost_info.configure(home_path = '/usr/local/stow/boost_1_43_0', elif self.boost_info.configure(
suffix = '-xgcc44-1_43', home_path = '/usr/local/stow/boost_%s_0-gcc%s' % \
include_path = 'include/boost-1_43'): (self.boost_version, self.gcc_version),
suffix = '-xgcc%s-%s' % \
(self.gcc_version, self.boost_version),
include_path = 'include/boost-%s' % self.boost_version):
pass pass
def setup_flavor_default(self): def setup_flavor_default(self):
@ -1168,25 +1194,29 @@ class PrepareBuild(CommandLineApp):
def setup_flavor_opt(self): def setup_flavor_opt(self):
self.CPPFLAGS.append('-DNDEBUG=1') self.CPPFLAGS.append('-DNDEBUG=1')
for i in ['-O3', '-fomit-frame-pointer']:
self.CXXFLAGS.append(i)
self.CFLAGS.append(i)
self.LDFLAGS.append(i)
#if self.options.gcc45:
# for i in ['-flto']:
# self.CXXFLAGS.append(i)
# self.CFLAGS.append(i)
# self.LDFLAGS.append(i)
if self.darwin_gcc: if self.darwin_gcc:
self.option_no_pch() self.option_no_pch()
if '--disable-shared' in self.configure_args: if '--disable-shared' in self.configure_args:
self.configure_args.remove('--disable-shared') self.configure_args.remove('--disable-shared')
self.configure_args.append('--disable-dependency-tracking') self.configure_args.append('--disable-dependency-tracking')
for i in ['-fast']:
self.CXXFLAGS.append(i)
self.CFLAGS.append(i)
self.LDFLAGS.append(i)
if self.options.universal: if self.options.universal:
for i in ['-fast']:
self.CXXFLAGS.append(i)
self.CFLAGS.append(i)
self.LDFLAGS.append(i)
for i in ['-arch', 'i386', '-arch', 'x86_64']: for i in ['-arch', 'i386', '-arch', 'x86_64']:
self.CXXFLAGS.append(i) self.CXXFLAGS.append(i)
self.CFLAGS.append(i) self.CFLAGS.append(i)
self.LDFLAGS.append(i) self.LDFLAGS.append(i)
else:
for i in ['-O3', '-fomit-frame-pointer']:
self.CXXFLAGS.append(i)
self.CFLAGS.append(i)
self.LDFLAGS.append(i)
def setup_flavor_gcov(self): def setup_flavor_gcov(self):
self.CXXFLAGS.append('-g') self.CXXFLAGS.append('-g')

View file

@ -122,27 +122,13 @@ general ledger you need to record a payment to Pacific Bell for your
monthly phone bill. The cost is $23.00, let's say, and you want to monthly phone bill. The cost is $23.00, let's say, and you want to
pay it from your checking account. In the general ledger you need to pay it from your checking account. In the general ledger you need to
say where the money came from, in addition to where it's going to. say where the money came from, in addition to where it's going to.
The transaction might look like this: Such a transaction might look like this:
@smallexample @smallexample
9/29 BAL Pacific Bell $-200.00 $-200.00 9/29 Pacific Bell $23.00 $23.00
Equity:Opening Balances $200.00 Checking $-23.00 0
9/29 BAL Checking $100.00 $100.00
Equity:Opening Balances $-100.00
9/29 100 Pacific Bell $23.00 $223.00
Checking $-23.00 $77.00
@end smallexample @end smallexample
The first line shows a payment to Pacific Bell for $23.00. Because
there is no ``balance'' in a general ledger---it's always zero---we
write in the total balance of all payments to ``Pacific Bell'', which
now is $223.00 (previously the balance was $200.00). This is done by
looking at the last transaction for ``Pacific Bell'' in the ledger, adding
$23.00 to that amount, and writing the total in the balance column.
And the money came from ``Checking''---a withdrawal of $23.00---which
leaves the ending balance in ``Checking'' at $77.00. This is a very
manual procedure; but that's where computers come in...
The posting must balance to $0: $23 went to Pacific Bell, $23 came The posting must balance to $0: $23 went to Pacific Bell, $23 came
from Checking. There is nothing left over to be accounted for, since from Checking. There is nothing left over to be accounted for, since
the money has simply moved from one account to another. This is the the money has simply moved from one account to another. This is the
@ -174,16 +160,8 @@ formatting as the ledger program wishes to see them:
@smallexample @smallexample
2004/09/29 Pacific Bell 2004/09/29 Pacific Bell
Payable:Pacific Bell $-200.00 Expenses:Pacific Bell $23.00
Equity:Opening Balances Assets:Checking
2004/09/29 Checking
Accounts:Checking $100.00
Equity:Opening Balances
2004/09/29 Pacific Bell
Payable:Pacific Bell $23.00
Accounts:Checking
@end smallexample @end smallexample
The account balances and registers in this file, if saved as The account balances and registers in this file, if saved as

View file

@ -2,32 +2,38 @@
# This is only important if you intend to produce a Ledger binary for # This is only important if you intend to produce a Ledger binary for
# installation. # installation.
STOW_ROOT = /usr/local/stow STOW_ROOT = /usr/local/stow
PRODUCTS = $(HOME)/Products PRODUCTS = $(HOME)/Products
CC = gcc-mp-4.4 CC = gcc-mp-4.5
CXX = g++-mp-4.4 CXX = g++-mp-4.5
LD = gcc-mp-4.4 LD = gcc-mp-4.5
CPPFLAGS = -D_GLIBCXX_DEBUG=1 -D_GLIBCXX_FULLY_DYNAMIC_STRING=1 CXX_VERSION = 45
CFLAGS = $(CPPFLAGS) -g CPPFLAGS = -D_GLIBCXX_DEBUG=1 -D_GLIBCXX_FULLY_DYNAMIC_STRING=1
LDFLAGS = -g CFLAGS = $(CPPFLAGS) -g
LDFLAGS = -g
BOOST_VERSION = 1_43_0 BOOST_VERSION = 1_43_0
BOOST_SOURCE = boost_$(BOOST_VERSION) BOOST_SOURCE = boost_$(BOOST_VERSION)
BOOST_TOOLSET = darwin BOOST_TOOLSET = darwin
BOOST_DEFINES = define=_GLIBCXX_DEBUG=1 define=_GLIBCXX_FULLY_DYNAMIC_STRING=1 BOOST_DEFINES = define=_GLIBCXX_DEBUG=1 define=_GLIBCXX_FULLY_DYNAMIC_STRING=1
#BOOST_FLAGS = --architecture=x86 --address_model=32_64 #BOOST_FLAGS = --architecture=x86 --address_model=32_64
BOOST_FLAGS = --toolset=$(BOOST_TOOLSET) \ BOOST_FLAGS = --toolset=$(BOOST_TOOLSET) \
--build-type=complete --layout=versioned \ --build-type=complete --layout=versioned \
$(BOOST_DEFINES) $(BOOST_DEFINES)
ICU_FLAGS = -sHAVE_ICU=1 -sICU_PATH=$(STOW_ROOT)/icu BOOST_DIR = boost_$(BOOST_VERSION)-gcc$(CXX_VERSION)
BOOST_STOW = $(STOW_ROOT)/$(BOOST_DIR)
BOOST_BUILD = $(PRODUCTS)/$(BOOST_DIR)
ICU_FLAGS = -sHAVE_ICU=1 -sICU_PATH=$(STOW_ROOT)/icu
BOOST_ICU_DIR = boost_$(BOOST_VERSION)-icu-gcc$(CXX_VERSION)
BOOST_ICU_STOW = $(STOW_ROOT)/$(BOOST_ICU_DIR)
BOOST_ICU_BUILD = $(PRODUCTS)/$(BOOST_ICU_DIR)
all: boost-build cppunit-build icu-build boost-icu-build all: boost-build cppunit-build #icu-build boost-icu-build
boost-build: boost-build:
(cd $(BOOST_SOURCE) && \ (cd $(BOOST_SOURCE) && \
bjam debug --prefix=$(STOW_ROOT)/boost_$(BOOST_VERSION) \ bjam debug --prefix=$(BOOST_STOW) --build-dir=$(BOOST_BUILD) \
--build-dir=$(PRODUCTS)/boost_$(BOOST_VERSION) \
$(BOOST_FLAGS) install) $(BOOST_FLAGS) install)
cppunit-build: cppunit-build:
@ -37,23 +43,30 @@ cppunit-build:
CFLAGS="$(CFLAGS)" \ CFLAGS="$(CFLAGS)" \
LDFLAGS="$(LDFLAGS)" \ LDFLAGS="$(LDFLAGS)" \
CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \ CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \
--prefix=$(STOW_ROOT)/cppunit \ --prefix=$(STOW_ROOT)/cppunit-gcc$(CXX_VERSION) \
--disable-doxygen --disable-dot && \ --disable-doxygen --disable-dot && \
make install) make install)
icu-build: #icu-build:
-(cd icu/source; make distclean) # -(cd icu/source; make distclean)
(cd icu/source; sh autogen.sh; \ # (cd icu/source; sh autogen.sh; \
./configure CPPFLAGS="$(CPPFLAGS)" \ # ./configure CPPFLAGS="$(CPPFLAGS)" \
CFLAGS="$(CFLAGS)" \ # CFLAGS="$(CFLAGS)" \
LDFLAGS="$(LDFLAGS)" \ # LDFLAGS="$(LDFLAGS)" \
CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \ # CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \
--enable-static --enable-debug \ # --enable-static --enable-debug \
--prefix=$(STOW_ROOT)/icu && \ # --prefix=$(STOW_ROOT)/icu-gcc$(CXX_VERSION) && \
make install) # make install)
#
#boost-icu-build:
# (cd $(BOOST_SOURCE) && \
# bjam debug --prefix=$(BOOST_ICU_STOW) --build-dir=$(BOOST_ICU_BUILD) \
# $(BOOST_FLAGS) $(ICU_FLAGS) install)
boost-icu-build: clean:
(cd $(BOOST_SOURCE) && \ -rm -fr $(BOOST_STOW) $(BOOST_BUILD)
bjam debug --prefix=$(STOW_ROOT)/boost_$(BOOST_VERSION)-icu \ -rm -fr $(BOOST_ICU_STOW) $(BOOST_ICU_BUILD)
--build-dir=$(PRODUCTS)/boost_$(BOOST_VERSION)-icu \ -rm -fr $(STOW_ROOT)/cppunit-gcc$(CXX_VERSION)
$(BOOST_FLAGS) $(ICU_FLAGS) install) -rm -fr $(STOW_ROOT)/icu-gcc$(CXX_VERSION)
-(cd cppunit; make distclean)
-(cd icu/source; make distclean)

View file

@ -724,8 +724,7 @@ void amount_t::in_place_unreduce()
} }
optional<amount_t> optional<amount_t>
amount_t::value(const bool primary_only, amount_t::value(const optional<datetime_t>& moment,
const optional<datetime_t>& moment,
const optional<commodity_t&>& in_terms_of) const const optional<commodity_t&>& in_terms_of) const
{ {
if (quantity) { if (quantity) {
@ -740,35 +739,39 @@ amount_t::value(const bool primary_only,
"amount_t::value: in_terms_of = " << in_terms_of->symbol()); "amount_t::value: in_terms_of = " << in_terms_of->symbol());
#endif #endif
if (has_commodity() && if (has_commodity() &&
(! primary_only || ! commodity().has_flags(COMMODITY_PRIMARY))) { (in_terms_of || ! commodity().has_flags(COMMODITY_PRIMARY))) {
if (in_terms_of && optional<price_point_t> point;
commodity().referent() == in_terms_of->referent()) { optional<commodity_t&> comm(in_terms_of);
if (comm && commodity().referent() == comm->referent()) {
return *this; return *this;
} }
else if (has_annotation() && annotation().price && else if (has_annotation() && annotation().price) {
annotation().has_flags(ANNOTATION_PRICE_FIXATED)) { if (annotation().has_flags(ANNOTATION_PRICE_FIXATED)) {
amount_t price(*annotation().price); point = price_point_t();
point->price = *annotation().price;
}
else if (! in_terms_of) {
comm = annotation().price->commodity();
}
}
if (! point) {
point = commodity().find_price(comm, moment);
// Whether a price was found or not, check whether we should attempt
// to download a price from the Internet. This is done if (a) no
// price was found, or (b) the price is "stale" according to the
// setting of --price-exp.
if (point)
point = commodity().check_for_updated_price(point, moment, comm);
}
if (point) {
amount_t price(point->price);
price.multiply(*this, true); price.multiply(*this, true);
price.in_place_round(); price.in_place_round();
return price; return price;
} }
else {
optional<price_point_t> point =
commodity().find_price(in_terms_of, moment);
// Whether a price was found or not, check whether we should
// attempt to download a price from the Internet. This is done
// if (a) no price was found, or (b) the price is "stale"
// according to the setting of --price-exp.
point = commodity().check_for_updated_price(point, moment,
in_terms_of);
if (point) {
amount_t price(point->price);
price.multiply(*this, true);
price.in_place_round();
return price;
}
}
} }
} else { } else {
throw_(amount_error, throw_(amount_error,
@ -1216,7 +1219,7 @@ void amount_t::parse_conversion(const string& larger_str,
smaller.commodity().set_larger(larger); smaller.commodity().set_larger(larger);
} }
void amount_t::print(std::ostream& _out) const void amount_t::print(std::ostream& _out, const uint_least8_t flags) const
{ {
VERIFY(valid()); VERIFY(valid());
@ -1246,7 +1249,7 @@ void amount_t::print(std::ostream& _out) const
// If there are any annotations associated with this commodity, output them // If there are any annotations associated with this commodity, output them
// now. // now.
comm.write_annotations(out); comm.write_annotations(out, flags & AMOUNT_PRINT_NO_COMPUTED_ANNOTATIONS);
// Things are output to a string first, so that if anyone has specified a // Things are output to a string first, so that if anyone has specified a
// width or fill for _out, it will be applied to the entire amount string, // width or fill for _out, it will be applied to the entire amount string,

View file

@ -399,8 +399,7 @@ public:
$100.00. $100.00.
*/ */
optional<amount_t> optional<amount_t>
value(const bool primary_only = true, value(const optional<datetime_t>& moment = none,
const optional<datetime_t>& moment = none,
const optional<commodity_t&>& in_terms_of = none) const; const optional<commodity_t&>& in_terms_of = none) const;
amount_t price() const; amount_t price() const;
@ -677,7 +676,13 @@ public:
true, the full internal precision of the amount is displayed, regardless true, the full internal precision of the amount is displayed, regardless
of its commodity's display precision. of its commodity's display precision.
*/ */
void print(std::ostream& out) const; #define AMOUNT_PRINT_NO_FLAGS 0x00
#define AMOUNT_PRINT_RIGHT_JUSTIFY 0x01
#define AMOUNT_PRINT_COLORIZE 0x02
#define AMOUNT_PRINT_NO_COMPUTED_ANNOTATIONS 0x04
void print(std::ostream& out,
const uint_least8_t flags = AMOUNT_PRINT_NO_FLAGS) const;
/*@}*/ /*@}*/

View file

@ -66,15 +66,6 @@ void annotation_t::parse(std::istream& in)
temp.parse(buf, PARSE_NO_MIGRATE); temp.parse(buf, PARSE_NO_MIGRATE);
DEBUG("commodity.annotations", "Parsed annotation price: " << temp); DEBUG("commodity.annotations", "Parsed annotation price: " << temp);
// Since this price will maintain its own precision, make sure
// it is at least as large as the base commodity, since the user
// may have only specified {$1} or something similar.
if (temp.has_commodity() &&
temp.precision() > temp.commodity().precision())
temp = temp.rounded(); // no need to retain individual precision
price = temp; price = temp;
} }
else if (c == '[') { else if (c == '[') {
@ -118,18 +109,22 @@ void annotation_t::parse(std::istream& in)
#endif #endif
} }
void annotation_t::print(std::ostream& out, bool keep_base) const void annotation_t::print(std::ostream& out, bool keep_base,
bool no_computed_annotations) const
{ {
if (price) if (price &&
(! no_computed_annotations || ! has_flags(ANNOTATION_PRICE_CALCULATED)))
out << " {" out << " {"
<< (has_flags(ANNOTATION_PRICE_FIXATED) ? "=" : "") << (has_flags(ANNOTATION_PRICE_FIXATED) ? "=" : "")
<< (keep_base ? *price : price->unreduced()).rounded() << (keep_base ? *price : price->unreduced())
<< '}'; << '}';
if (date) if (date &&
(! no_computed_annotations || ! has_flags(ANNOTATION_DATE_CALCULATED)))
out << " [" << format_date(*date, FMT_WRITTEN) << ']'; out << " [" << format_date(*date, FMT_WRITTEN) << ']';
if (tag) if (tag &&
(! no_computed_annotations || ! has_flags(ANNOTATION_TAG_CALCULATED)))
out << " (" << *tag << ')'; out << " (" << *tag << ')';
} }
@ -197,9 +192,10 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep)
return *new_comm; return *new_comm;
} }
void annotated_commodity_t::write_annotations(std::ostream& out) const void annotated_commodity_t::write_annotations
(std::ostream& out, bool no_computed_annotations) const
{ {
details.print(out, pool().keep_base); details.print(out, pool().keep_base, no_computed_annotations);
} }
} // namespace ledger } // namespace ledger

View file

@ -87,7 +87,8 @@ struct annotation_t : public supports_flags<>,
void parse(std::istream& in); void parse(std::istream& in);
void print(std::ostream& out, bool keep_base = false) const; void print(std::ostream& out, bool keep_base = false,
bool no_computed_annotations = false) const;
bool valid() const { bool valid() const {
assert(*this); assert(*this);
@ -230,7 +231,8 @@ public:
} }
virtual commodity_t& strip_annotations(const keep_details_t& what_to_keep); virtual commodity_t& strip_annotations(const keep_details_t& what_to_keep);
virtual void write_annotations(std::ostream& out) const; virtual void write_annotations(std::ostream& out,
bool no_computed_annotations = false) const;
#if defined(HAVE_BOOST_SERIALIZATION) #if defined(HAVE_BOOST_SERIALIZATION)
private: private:

View file

@ -185,16 +185,14 @@ balance_t& balance_t::operator/=(const amount_t& amt)
} }
optional<balance_t> optional<balance_t>
balance_t::value(const bool primary_only, balance_t::value(const optional<datetime_t>& moment,
const optional<datetime_t>& moment,
const optional<commodity_t&>& in_terms_of) const const optional<commodity_t&>& in_terms_of) const
{ {
balance_t temp; balance_t temp;
bool resolved = false; bool resolved = false;
foreach (const amounts_map::value_type& pair, amounts) { foreach (const amounts_map::value_type& pair, amounts) {
if (optional<amount_t> val = pair.second.value(primary_only, moment, if (optional<amount_t> val = pair.second.value(moment, in_terms_of)) {
in_terms_of)) {
temp += *val; temp += *val;
resolved = true; resolved = true;
} else { } else {
@ -252,11 +250,10 @@ balance_t::strip_annotations(const keep_details_t& what_to_keep) const
return temp; return temp;
} }
void balance_t::print(std::ostream& out, void balance_t::print(std::ostream& out,
const int first_width, const int first_width,
const int latter_width, const int latter_width,
const bool right_justify, const uint_least8_t flags) const
const bool colorize) const
{ {
bool first = true; bool first = true;
int lwidth = latter_width; int lwidth = latter_width;
@ -285,14 +282,14 @@ void balance_t::print(std::ostream& out,
} }
std::ostringstream buf; std::ostringstream buf;
buf << *amount; amount->print(buf, flags);
justify(out, buf.str(), width, right_justify, justify(out, buf.str(), width, flags & AMOUNT_PRINT_RIGHT_JUSTIFY,
colorize && amount->sign() < 0); flags & AMOUNT_PRINT_COLORIZE && amount->sign() < 0);
} }
if (first) { if (first) {
out.width(first_width); out.width(first_width);
if (right_justify) if (flags & AMOUNT_PRINT_RIGHT_JUSTIFY)
out << std::right; out << std::right;
else else
out << std::left; out << std::left;

View file

@ -384,9 +384,8 @@ public:
} }
optional<balance_t> optional<balance_t>
value(const bool primary_only = false, value(const optional<datetime_t>& moment = none,
const optional<datetime_t>& moment = none, const optional<commodity_t&>& in_terms_of = none) const;
const optional<commodity_t&>& in_terms_of = none) const;
balance_t price() const; balance_t price() const;
@ -530,11 +529,10 @@ public:
* relative amounts of those commodities. There is no option to * relative amounts of those commodities. There is no option to
* change this behavior. * change this behavior.
*/ */
void print(std::ostream& out, void print(std::ostream& out,
const int first_width = -1, const int first_width = -1,
const int latter_width = -1, const int latter_width = -1,
const bool right_justify = false, const uint_least8_t flags = AMOUNT_PRINT_NO_FLAGS) const;
const bool colorize = false) const;
/** /**
* Debugging methods. There are two methods defined to help with * Debugging methods. There are two methods defined to help with

View file

@ -113,7 +113,7 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler,
post_handler_ptr handler(base_handler); post_handler_ptr handler(base_handler);
predicate_t display_predicate; predicate_t display_predicate;
predicate_t only_predicate; predicate_t only_predicate;
rounding_error_posts * rounding_handler = NULL; display_filter_posts * display_filter = NULL;
assert(report.HANDLED(amount_)); assert(report.HANDLED(amount_));
expr_t& expr(report.HANDLER(amount_).expr); expr_t& expr(report.HANDLER(amount_).expr);
@ -141,10 +141,10 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler,
// changed_value_posts adds virtual posts to the list to account for changes // changed_value_posts adds virtual posts to the list to account for changes
// in market value of commodities, which otherwise would affect the running // in market value of commodities, which otherwise would affect the running
// total unpredictably. // total unpredictably.
if (report.HANDLED(revalued) && ! report.HANDLED(no_rounding)) { display_filter = new display_filter_posts(handler, report,
rounding_handler = new rounding_error_posts(handler, report); report.HANDLED(revalued) &&
handler.reset(rounding_handler); ! report.HANDLED(no_rounding));
} handler.reset(display_filter);
// filter_posts will only pass through posts matching the // filter_posts will only pass through posts matching the
// `display_predicate'. // `display_predicate'.
@ -162,7 +162,7 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler,
(! for_accounts_report || report.HANDLED(unrealized))) (! for_accounts_report || report.HANDLED(unrealized)))
handler.reset(new changed_value_posts(handler, report, for_accounts_report, handler.reset(new changed_value_posts(handler, report, for_accounts_report,
report.HANDLED(unrealized), report.HANDLED(unrealized),
rounding_handler)); display_filter));
// calc_posts computes the running total. When this appears will determine, // calc_posts computes the running total. When this appears will determine,
// for example, whether filtered posts are included or excluded from the // for example, whether filtered posts are included or excluded from the

View file

@ -264,10 +264,6 @@ commodity_t::varied_history_t::find_price(const commodity_t& source,
if (comm == source) if (comm == source)
continue; continue;
// Only value secondary commodities in terms of primary ones
if (! commodity && ! comm.has_flags(COMMODITY_PRIMARY))
continue;
DEBUG_INDENT("commodity.prices.find", indent + 1); DEBUG_INDENT("commodity.prices.find", indent + 1);
DEBUG("commodity.prices.find", DEBUG("commodity.prices.find",
"searching for price via commodity '" << comm << "'"); "searching for price via commodity '" << comm << "'");
@ -370,8 +366,7 @@ commodity_t::find_price(const optional<commodity_t&>& commodity,
#endif #endif
) const ) const
{ {
if (! has_flags(COMMODITY_WALKED) && base->varied_history && if (! has_flags(COMMODITY_WALKED) && base->varied_history) {
(commodity || ! has_flags(COMMODITY_PRIMARY))) {
optional<base_t::time_and_commodity_t> pair; optional<base_t::time_and_commodity_t> pair;
#if defined(VERIFY_ON) #if defined(VERIFY_ON)
optional<price_point_t> checkpoint; optional<price_point_t> checkpoint;

View file

@ -59,6 +59,10 @@ struct price_point_t
datetime_t when; datetime_t when;
amount_t price; amount_t price;
price_point_t() {}
price_point_t(datetime_t _when, amount_t _price)
: when(_when), price(_price) {}
bool operator==(const price_point_t& other) const { bool operator==(const price_point_t& other) const {
return when == other.when && price == other.price; return when == other.when && price == other.price;
} }
@ -273,7 +277,7 @@ public:
virtual commodity_t& strip_annotations(const keep_details_t&) { virtual commodity_t& strip_annotations(const keep_details_t&) {
return *this; return *this;
} }
virtual void write_annotations(std::ostream&) const {} virtual void write_annotations(std::ostream&, bool) const {}
commodity_pool_t& pool() const { commodity_pool_t& pool() const {
return *parent_; return *parent_;

View file

@ -162,6 +162,7 @@ public:
} }
#endif // defined(DEBUG_ON) #endif // defined(DEBUG_ON)
DEBUG("expr.calc.when", "Compiling: " << str);
compile(scope); compile(scope);
#if defined(DEBUG_ON) #if defined(DEBUG_ON)
@ -172,6 +173,7 @@ public:
#endif // defined(DEBUG_ON) #endif // defined(DEBUG_ON)
} }
DEBUG("expr.calc.when", "Calculating: " << str);
return real_calc(scope); return real_calc(scope);
} }

View file

@ -289,18 +289,16 @@ void calc_posts::operator()(post_t& post)
} }
namespace { namespace {
typedef function<void (post_t&)> post_functor_t; void handle_value(const value_t& value,
account_t * account,
void handle_value(const value_t& value, xact_t * xact,
account_t * account, temporaries_t& temps,
xact_t * xact, post_handler_ptr handler,
temporaries_t& temps, const date_t& date = date_t(),
post_handler_ptr handler, const bool act_date_p = true,
const date_t& date = date_t(), const value_t& total = value_t(),
const value_t& total = value_t(), const bool direct_amount = false,
const bool direct_amount = false, const bool mark_visited = false)
const bool mark_visited = false,
const optional<post_functor_t>& functor = none)
{ {
post_t& post = temps.create_post(*xact, account); post_t& post = temps.create_post(*xact, account);
post.add_flags(ITEM_GENERATED); post.add_flags(ITEM_GENERATED);
@ -319,8 +317,12 @@ namespace {
post_t::xdata_t& xdata(post.xdata()); post_t::xdata_t& xdata(post.xdata());
if (is_valid(date)) if (is_valid(date)) {
xdata.date = date; if (act_date_p)
xdata.date = date;
else
xdata.value_date = date;
}
value_t temp(value); value_t temp(value);
@ -353,9 +355,6 @@ namespace {
if (direct_amount) if (direct_amount)
xdata.add_flags(POST_EXT_DIRECT_AMT); xdata.add_flags(POST_EXT_DIRECT_AMT);
if (functor)
(*functor)(post);
DEBUG("filters.changed_value.rounding", "post.amount = " << post.amount); DEBUG("filters.changed_value.rounding", "post.amount = " << post.amount);
(*handler)(post); (*handler)(post);
@ -388,12 +387,15 @@ void collapse_posts::report_subtotal()
} }
else { else {
date_t earliest_date; date_t earliest_date;
date_t latest_date;
foreach (post_t * post, component_posts) { foreach (post_t * post, component_posts) {
date_t reported = post->date(); date_t date = post->date();
if (! is_valid(earliest_date) || date_t value_date = post->value_date();
reported < earliest_date) if (! is_valid(earliest_date) || date < earliest_date)
earliest_date = reported; earliest_date = date;
if (! is_valid(latest_date) || value_date > latest_date)
latest_date = value_date;
} }
xact_t& xact = temps.create_xact(); xact_t& xact = temps.create_xact();
@ -401,12 +403,16 @@ void collapse_posts::report_subtotal()
xact._date = (is_valid(earliest_date) ? xact._date = (is_valid(earliest_date) ?
earliest_date : last_xact->_date); earliest_date : last_xact->_date);
DEBUG("filters.collapse", "Pseudo-xact date = " << *xact._date); DEBUG("filters.collapse", "Pseudo-xact date = " << *xact._date);
DEBUG("filters.collapse", "earliest date = " << earliest_date);
DEBUG("filters.collapse", "latest date = " << latest_date);
handle_value(/* value= */ subtotal, handle_value(/* value= */ subtotal,
/* account= */ &totals_account, /* account= */ &totals_account,
/* xact= */ &xact, /* xact= */ &xact,
/* temps= */ temps, /* temps= */ temps,
/* handler= */ handler); /* handler= */ handler,
/* date= */ latest_date,
/* act_date_p= */ false);
} }
component_posts.clear(); component_posts.clear();
@ -466,27 +472,46 @@ void related_posts::flush()
item_handler<post_t>::flush(); item_handler<post_t>::flush();
} }
rounding_error_posts::rounding_error_posts(post_handler_ptr handler, display_filter_posts::display_filter_posts(post_handler_ptr handler,
report_t& _report) report_t& _report,
bool _show_rounding)
: item_handler<post_t>(handler), report(_report), : item_handler<post_t>(handler), report(_report),
rounding_account(temps.create_account(_("<Rounding>"))) show_rounding(_show_rounding),
rounding_account(temps.create_account(_("<Rounding>"))),
revalued_account(temps.create_account(_("<Revalued>")))
{ {
TRACE_CTOR(rounding_error_posts, "post_handler_ptr, report_t&"); TRACE_CTOR(display_filter_posts,
"post_handler_ptr, report_t&, account_t&, bool");
display_amount_expr = report.HANDLER(display_amount_).expr; display_amount_expr = report.HANDLER(display_amount_).expr;
display_total_expr = report.HANDLER(display_total_).expr; display_total_expr = report.HANDLER(display_total_).expr;
} }
void rounding_error_posts::output_rounding(post_t& post) bool display_filter_posts::output_rounding(post_t& post)
{ {
bind_scope_t bound_scope(report, post); bind_scope_t bound_scope(report, post);
value_t new_display_total(display_total_expr.calc(bound_scope)); value_t new_display_total;
DEBUG("filters.changed_value.rounding", if (show_rounding) {
"rounding.new_display_total = " << new_display_total); new_display_total = display_total_expr.calc(bound_scope);
if (! last_display_total.is_null()) { DEBUG("filters.changed_value.rounding",
if (value_t repriced_amount = display_amount_expr.calc(bound_scope)) { "rounding.new_display_total = " << new_display_total);
}
// Allow the posting to be displayed if:
// 1. It's display_amount would display as non-zero
// 2. The --empty option was specified
// 3. The account of the posting is <Revalued>
if (post.account == &revalued_account) {
if (show_rounding)
last_display_total = new_display_total;
return true;
}
if (value_t repriced_amount = display_amount_expr.calc(bound_scope)) {
if (! last_display_total.is_null()) {
DEBUG("filters.changed_value.rounding", DEBUG("filters.changed_value.rounding",
"rounding.repriced_amount = " << repriced_amount); "rounding.repriced_amount = " << repriced_amount);
@ -502,29 +527,29 @@ void rounding_error_posts::output_rounding(post_t& post)
DEBUG("filters.changed_value.rounding", DEBUG("filters.changed_value.rounding",
"rounding.diff = " << diff); "rounding.diff = " << diff);
xact_t& xact = temps.create_xact();
xact.payee = _("Commodity rounding");
xact._date = post.date();
handle_value(/* value= */ diff, handle_value(/* value= */ diff,
/* account= */ &rounding_account, /* account= */ &rounding_account,
/* xact= */ &xact, /* xact= */ post.xact,
/* temps= */ temps, /* temps= */ temps,
/* handler= */ handler, /* handler= */ handler,
/* date= */ *xact._date, /* date= */ date_t(),
/* act_date_p= */ true,
/* total= */ precise_display_total, /* total= */ precise_display_total,
/* direct_amount= */ true); /* direct_amount= */ true);
} }
} }
if (show_rounding)
last_display_total = new_display_total;
return true;
} else {
return report.HANDLED(empty);
} }
last_display_total = new_display_total;
} }
void rounding_error_posts::operator()(post_t& post) void display_filter_posts::operator()(post_t& post)
{ {
output_rounding(post); if (output_rounding(post))
item_handler<post_t>::operator()(post);
item_handler<post_t>::operator()(post);
} }
changed_value_posts::changed_value_posts changed_value_posts::changed_value_posts
@ -532,12 +557,13 @@ changed_value_posts::changed_value_posts
report_t& _report, report_t& _report,
bool _for_accounts_report, bool _for_accounts_report,
bool _show_unrealized, bool _show_unrealized,
rounding_error_posts * _rounding_handler) display_filter_posts * _display_filter)
: item_handler<post_t>(handler), report(_report), : item_handler<post_t>(handler), report(_report),
for_accounts_report(_for_accounts_report), for_accounts_report(_for_accounts_report),
show_unrealized(_show_unrealized), last_post(NULL), show_unrealized(_show_unrealized), last_post(NULL),
revalued_account(temps.create_account(_("<Revalued>"))), revalued_account(_display_filter ? _display_filter->revalued_account :
rounding_handler(_rounding_handler) temps.create_account(_("<Revalued>"))),
display_filter(_display_filter)
{ {
TRACE_CTOR(changed_value_posts, "post_handler_ptr, report_t&, bool"); TRACE_CTOR(changed_value_posts, "post_handler_ptr, report_t&, bool");
@ -604,7 +630,7 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
xact_t& xact = temps.create_xact(); xact_t& xact = temps.create_xact();
xact.payee = _("Commodities revalued"); xact.payee = _("Commodities revalued");
xact._date = is_valid(date) ? date : post.date(); xact._date = is_valid(date) ? date : post.value_date();
if (! for_accounts_report) { if (! for_accounts_report) {
handle_value handle_value
@ -614,6 +640,7 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
/* temps= */ temps, /* temps= */ temps,
/* handler= */ handler, /* handler= */ handler,
/* date= */ *xact._date, /* date= */ *xact._date,
/* act_date_p= */ true,
/* total= */ repriced_total); /* total= */ repriced_total);
} }
else if (show_unrealized) { else if (show_unrealized) {
@ -626,6 +653,7 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
/* temps= */ temps, /* temps= */ temps,
/* handler= */ handler, /* handler= */ handler,
/* date= */ *xact._date, /* date= */ *xact._date,
/* act_date_p= */ true,
/* total= */ value_t(), /* total= */ value_t(),
/* direct_amount= */ false, /* direct_amount= */ false,
/* mark_visited= */ true); /* mark_visited= */ true);
@ -649,7 +677,7 @@ void changed_value_posts::output_intermediate_prices(post_t& post,
xact_t& xact(temps.create_xact()); xact_t& xact(temps.create_xact());
xact.payee = _("Commodities revalued"); xact.payee = _("Commodities revalued");
xact._date = is_valid(current) ? current : post.date(); xact._date = is_valid(current) ? current : post.value_date();
post_t& temp(temps.copy_post(post, xact)); post_t& temp(temps.copy_post(post, xact));
temp.add_flags(ITEM_GENERATED); temp.add_flags(ITEM_GENERATED);
@ -711,9 +739,9 @@ void changed_value_posts::output_intermediate_prices(post_t& post,
hist->histories) { hist->histories) {
foreach (const commodity_t::history_map::value_type& price, foreach (const commodity_t::history_map::value_type& price,
comm_hist.second.prices) { comm_hist.second.prices) {
if (price.first.date() > post.date() && if (price.first.date() > post.value_date() &&
price.first.date() < current) { price.first.date() < current) {
DEBUG("filters.revalued", post.date() << " < " DEBUG("filters.revalued", post.value_date() << " < "
<< price.first.date() << " < " << current); << price.first.date() << " < " << current);
DEBUG("filters.revalued", "inserting " DEBUG("filters.revalued", "inserting "
<< price.second << " at " << price.first.date()); << price.second << " at " << price.first.date());
@ -755,8 +783,8 @@ void changed_value_posts::operator()(post_t& post)
{ {
if (last_post) { if (last_post) {
if (! for_accounts_report) if (! for_accounts_report)
output_intermediate_prices(*last_post, post.date()); output_intermediate_prices(*last_post, post.value_date());
output_revaluation(*last_post, post.date()); output_revaluation(*last_post, post.value_date());
} }
if (changed_values_only) if (changed_values_only)
@ -780,11 +808,12 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
if (! range_start || ! range_finish) { if (! range_start || ! range_finish) {
foreach (post_t * post, component_posts) { foreach (post_t * post, component_posts) {
date_t date = post->date(); date_t date = post->date();
date_t value_date = post->value_date();
if (! range_start || date < *range_start) if (! range_start || date < *range_start)
range_start = date; range_start = date;
if (! range_finish || date > *range_finish) if (! range_finish || value_date > *range_finish)
range_finish = date; range_finish = value_date;
} }
} }
component_posts.clear(); component_posts.clear();
@ -806,11 +835,13 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
xact._date = *range_start; xact._date = *range_start;
foreach (values_map::value_type& pair, values) foreach (values_map::value_type& pair, values)
handle_value(/* value= */ pair.second.value, handle_value(/* value= */ pair.second.value,
/* account= */ pair.second.account, /* account= */ pair.second.account,
/* xact= */ &xact, /* xact= */ &xact,
/* temps= */ temps, /* temps= */ temps,
/* handler= */ handler); /* handler= */ handler,
/* date= */ *range_finish,
/* act_date_p= */ false);
values.clear(); values.clear();
} }
@ -919,17 +950,21 @@ void posts_as_equity::report_subtotal()
if (pair.second.value.is_balance()) { if (pair.second.value.is_balance()) {
foreach (const balance_t::amounts_map::value_type& amount_pair, foreach (const balance_t::amounts_map::value_type& amount_pair,
pair.second.value.as_balance().amounts) pair.second.value.as_balance().amounts)
handle_value(/* value= */ amount_pair.second, handle_value(/* value= */ amount_pair.second,
/* account= */ pair.second.account, /* account= */ pair.second.account,
/* xact= */ &xact, /* xact= */ &xact,
/* temps= */ temps, /* temps= */ temps,
/* handler= */ handler); /* handler= */ handler,
/* date= */ finish,
/* act_date_p= */ false);
} else { } else {
handle_value(/* value= */ pair.second.value, handle_value(/* value= */ pair.second.value,
/* account= */ pair.second.account, /* account= */ pair.second.account,
/* xact= */ &xact, /* xact= */ &xact,
/* temps= */ temps, /* temps= */ temps,
/* handler= */ handler); /* handler= */ handler,
/* date= */ finish,
/* act_date_p= */ false);
} }
total += pair.second.value; total += pair.second.value;
} }

View file

@ -481,7 +481,7 @@ public:
} }
}; };
class rounding_error_posts : public item_handler<post_t> class display_filter_posts : public item_handler<post_t>
{ {
// This filter requires that calc_posts be used at some point // This filter requires that calc_posts be used at some point
// later in the chain. // later in the chain.
@ -489,21 +489,25 @@ class rounding_error_posts : public item_handler<post_t>
expr_t display_amount_expr; expr_t display_amount_expr;
expr_t display_total_expr; expr_t display_total_expr;
report_t& report; report_t& report;
bool show_rounding;
value_t last_display_total; value_t last_display_total;
temporaries_t temps; temporaries_t temps;
account_t& rounding_account; account_t& rounding_account;
rounding_error_posts(); display_filter_posts();
public: public:
rounding_error_posts(post_handler_ptr handler, account_t& revalued_account;
report_t& _report);
virtual ~rounding_error_posts() { display_filter_posts(post_handler_ptr handler,
TRACE_DTOR(rounding_error_posts); report_t& _report,
bool _show_rounding);
virtual ~display_filter_posts() {
TRACE_DTOR(display_filter_posts);
} }
void output_rounding(post_t& post); bool output_rounding(post_t& post);
virtual void operator()(post_t& post); virtual void operator()(post_t& post);
@ -538,7 +542,7 @@ class changed_value_posts : public item_handler<post_t>
account_t * gains_equity_account; account_t * gains_equity_account;
account_t * losses_equity_account; account_t * losses_equity_account;
rounding_error_posts * rounding_handler; display_filter_posts * display_filter;
changed_value_posts(); changed_value_posts();
@ -547,7 +551,7 @@ public:
report_t& _report, report_t& _report,
bool _for_accounts_report, bool _for_accounts_report,
bool _show_unrealized, bool _show_unrealized,
rounding_error_posts * _rounding_handler); display_filter_posts * _display_filter);
virtual ~changed_value_posts() { virtual ~changed_value_posts() {
TRACE_DTOR(changed_value_posts); TRACE_DTOR(changed_value_posts);

View file

@ -465,6 +465,11 @@ expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind,
return WRAP_FUNCTOR(get_wrapper<&get_uncleared>); return WRAP_FUNCTOR(get_wrapper<&get_uncleared>);
break; break;
case 'v':
if (name == "value_date")
return WRAP_FUNCTOR(get_wrapper<&get_date>);
break;
case 'L': case 'L':
if (name[1] == '\0') if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_actual>); return WRAP_FUNCTOR(get_wrapper<&get_actual>);

View file

@ -224,9 +224,11 @@ format_accounts::mark_accounts(account_t& account, const bool flat)
if (account.parent && if (account.parent &&
(account.has_xflags(ACCOUNT_EXT_VISITED) || (! flat && visited > 0))) { (account.has_xflags(ACCOUNT_EXT_VISITED) || (! flat && visited > 0))) {
bind_scope_t bound_scope(report, account); bind_scope_t bound_scope(report, account);
call_scope_t call_scope(bound_scope);
if ((! flat && to_display > 1) || if ((! flat && to_display > 1) ||
((flat || to_display != 1 || ((flat || to_display != 1 ||
account.has_xflags(ACCOUNT_EXT_VISITED)) && account.has_xflags(ACCOUNT_EXT_VISITED)) &&
(report.HANDLED(empty) || report.fn_display_total(call_scope)) &&
disp_pred(bound_scope))) { disp_pred(bound_scope))) {
account.xdata().add_flags(ACCOUNT_EXT_TO_DISPLAY); account.xdata().add_flags(ACCOUNT_EXT_TO_DISPLAY);
DEBUG("account.display", "Marking account as TO_DISPLAY"); DEBUG("account.display", "Marking account as TO_DISPLAY");

View file

@ -78,6 +78,13 @@ optional<string> post_t::get_tag(const mask_t& tag_mask,
return none; return none;
} }
date_t post_t::value_date() const
{
if (xdata_ && is_valid(xdata_->value_date))
return xdata_->value_date;
return date();
}
date_t post_t::date() const date_t post_t::date() const
{ {
if (xdata_ && is_valid(xdata_->date)) if (xdata_ && is_valid(xdata_->date))
@ -319,6 +326,14 @@ namespace {
return long(post.reported_account()->depth); return long(post.reported_account()->depth);
} }
value_t get_value_date(post_t& post) {
if (post.has_xdata()) {
post_t::xdata_t& xdata(post.xdata());
if (! xdata.value_date.is_not_a_date())
return xdata.value_date;
}
return post.date();
}
value_t get_datetime(post_t& post) { value_t get_datetime(post_t& post) {
return post.xdata().datetime; return post.xdata().datetime;
} }
@ -479,6 +494,8 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
case 'v': case 'v':
if (name == "virtual") if (name == "virtual")
return WRAP_FUNCTOR(get_wrapper<&get_virtual>); return WRAP_FUNCTOR(get_wrapper<&get_virtual>);
else if (name == "value_date")
return WRAP_FUNCTOR(get_wrapper<&get_value_date>);
break; break;
case 'x': case 'x':

View file

@ -106,6 +106,7 @@ public:
virtual optional<string> get_tag(const mask_t& tag_mask, virtual optional<string> get_tag(const mask_t& tag_mask,
const optional<mask_t>& value_mask = none) const; const optional<mask_t>& value_mask = none) const;
virtual date_t value_date() const;
virtual date_t date() const; virtual date_t date() const;
virtual date_t actual_date() const; virtual date_t actual_date() const;
virtual optional<date_t> effective_date() const; virtual optional<date_t> effective_date() const;
@ -141,6 +142,7 @@ public:
value_t total; value_t total;
std::size_t count; std::size_t count;
date_t date; date_t date;
date_t value_date;
datetime_t datetime; datetime_t datetime;
account_t * account; account_t * account;

View file

@ -172,13 +172,14 @@ namespace {
if (post->amount_expr) { if (post->amount_expr) {
amt = post->amount_expr->text(); amt = post->amount_expr->text();
} else { } else {
std::size_t amount_width = int amount_width =
(report.HANDLER(amount_width_).specified ? (report.HANDLER(amount_width_).specified ?
report.HANDLER(amount_width_).value.to_long() : 12); report.HANDLER(amount_width_).value.to_int() : 12);
std::ostringstream amt_str; std::ostringstream amt_str;
report.scrub(post->amount) value_t(post->amount).print(amt_str, amount_width, -1,
.print(amt_str, static_cast<int>(amount_width), -1, true); AMOUNT_PRINT_RIGHT_JUSTIFY |
AMOUNT_PRINT_NO_COMPUTED_ANNOTATIONS);
amt = amt_str.str(); amt = amt_str.str();
} }
@ -190,15 +191,17 @@ namespace {
amtbuf << string(2 - (slip + amt_slip), ' '); amtbuf << string(2 - (slip + amt_slip), ' ');
amtbuf << amt; amtbuf << amt;
if (post->cost && ! post->has_flags(POST_CALCULATED)) { if (post->cost &&
! post->has_flags(POST_CALCULATED | POST_COST_CALCULATED)) {
if (post->has_flags(POST_COST_IN_FULL)) if (post->has_flags(POST_COST_IN_FULL))
amtbuf << " @@ " << report.scrub(post->cost->abs()); amtbuf << " @@ " << post->cost->abs();
else else
amtbuf << " @ " << report.scrub((*post->cost / post->amount).abs()); amtbuf << " @ "
<< (*post->cost / post->amount).abs();
} }
if (post->assigned_amount) if (post->assigned_amount)
amtbuf << " = " << report.scrub(*post->assigned_amount); amtbuf << " = " << post->assigned_amount;
string trailer = amtbuf.str(); string trailer = amtbuf.str();
out << trailer; out << trailer;

View file

@ -45,16 +45,16 @@ using namespace boost::python;
namespace { namespace {
boost::optional<amount_t> py_value_0(const amount_t& amount) { boost::optional<amount_t> py_value_0(const amount_t& amount) {
return amount.value(false, CURRENT_TIME()); return amount.value(CURRENT_TIME());
} }
boost::optional<amount_t> py_value_1(const amount_t& amount, boost::optional<amount_t> py_value_1(const amount_t& amount,
commodity_t& in_terms_of) { commodity_t& in_terms_of) {
return amount.value(false, CURRENT_TIME(), in_terms_of); return amount.value(CURRENT_TIME(), in_terms_of);
} }
boost::optional<amount_t> py_value_2(const amount_t& amount, boost::optional<amount_t> py_value_2(const amount_t& amount,
commodity_t& in_terms_of, commodity_t& in_terms_of,
datetime_t& moment) { datetime_t& moment) {
return amount.value(false, moment, in_terms_of); return amount.value(moment, in_terms_of);
} }
void py_parse_2(amount_t& amount, object in, unsigned char flags) { void py_parse_2(amount_t& amount, object in, unsigned char flags) {

View file

@ -45,16 +45,16 @@ using namespace boost::python;
namespace { namespace {
boost::optional<balance_t> py_value_0(const balance_t& balance) { boost::optional<balance_t> py_value_0(const balance_t& balance) {
return balance.value(false, CURRENT_TIME()); return balance.value(CURRENT_TIME());
} }
boost::optional<balance_t> py_value_1(const balance_t& balance, boost::optional<balance_t> py_value_1(const balance_t& balance,
commodity_t& in_terms_of) { commodity_t& in_terms_of) {
return balance.value(false, CURRENT_TIME(), in_terms_of); return balance.value(CURRENT_TIME(), in_terms_of);
} }
boost::optional<balance_t> py_value_2(const balance_t& balance, boost::optional<balance_t> py_value_2(const balance_t& balance,
commodity_t& in_terms_of, commodity_t& in_terms_of,
datetime_t& moment) { datetime_t& moment) {
return balance.value(false, moment, in_terms_of); return balance.value(moment, in_terms_of);
} }
boost::optional<amount_t> boost::optional<amount_t>

View file

@ -48,16 +48,16 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(set_string_overloads, set_string, 0, 2)
namespace { namespace {
boost::optional<value_t> py_value_0(const value_t& value) { boost::optional<value_t> py_value_0(const value_t& value) {
return value.value(false, CURRENT_TIME()); return value.value(CURRENT_TIME());
} }
boost::optional<value_t> py_value_1(const value_t& value, boost::optional<value_t> py_value_1(const value_t& value,
commodity_t& in_terms_of) { commodity_t& in_terms_of) {
return value.value(false, CURRENT_TIME(), in_terms_of); return value.value(CURRENT_TIME(), in_terms_of);
} }
boost::optional<value_t> py_value_2(const value_t& value, boost::optional<value_t> py_value_2(const value_t& value,
commodity_t& in_terms_of, commodity_t& in_terms_of,
datetime_t& moment) { datetime_t& moment) {
return value.value(false, moment, in_terms_of); return value.value(moment, in_terms_of);
} }
PyObject * py_base_type(value_t& value) PyObject * py_base_type(value_t& value)

View file

@ -140,11 +140,6 @@ void report_t::normalize_options(const string& verb)
if (verb == "print") if (verb == "print")
HANDLER(limit_).on(string("?normalize"), "actual"); HANDLER(limit_).on(string("?normalize"), "actual");
if (! HANDLED(empty))
HANDLER(display_).on(string("?normalize"),
string("(post?(display_amount|account=\"") +
_("<Revalued>") + "\"):display_total)");
if (verb[0] != 'b' && verb[0] != 'r') if (verb[0] != 'b' && verb[0] != 'r')
HANDLER(base).on_only(string("?normalize")); HANDLER(base).on_only(string("?normalize"));
@ -471,7 +466,7 @@ value_t report_t::fn_market(call_scope_t& scope)
/* add_prices= */ false, /* add_prices= */ false,
moment); moment);
else else
result = args.value_at(0).value(true, moment); result = args.value_at(0).value(moment);
if (! result.is_null()) if (! result.is_null())
return result; return result;
@ -602,12 +597,17 @@ value_t report_t::fn_truncated(call_scope_t& scope)
value_t report_t::fn_justify(call_scope_t& scope) value_t report_t::fn_justify(call_scope_t& scope)
{ {
interactive_t args(scope, "vl&lbb"); interactive_t args(scope, "vl&lbb");
uint_least8_t flags(AMOUNT_PRINT_NO_FLAGS);
if (args.has(3) && args.get<bool>(3))
flags |= AMOUNT_PRINT_RIGHT_JUSTIFY;
if (args.has(4) && args.get<bool>(4))
flags |= AMOUNT_PRINT_COLORIZE;
std::ostringstream out; std::ostringstream out;
args.value_at(0) args.value_at(0)
.print(out, args.get<int>(1), .print(out, args.get<int>(1), args.has(2) ? args.get<int>(2) : -1, flags);
args.has(2) ? args.get<int>(2) : -1,
args.has(3) ? args.get<bool>(3) : false,
args.has(4) ? args.get<bool>(4) : false);
return string_value(out.str()); return string_value(out.str());
} }
@ -1308,6 +1308,11 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
return MAKE_FUNCTOR(report_t::fn_unrounded); return MAKE_FUNCTOR(report_t::fn_unrounded);
break; break;
case 'v':
if (is_eq(p, "value_date"))
return MAKE_FUNCTOR(report_t::fn_now);
break;
case 'w': case 'w':
if (is_eq(p, "white")) if (is_eq(p, "white"))
return WRAP_FUNCTOR(fn_white); return WRAP_FUNCTOR(fn_white);

View file

@ -586,16 +586,16 @@ public:
"use_direct_amount ? amount :" "use_direct_amount ? amount :"
" (is_seq(get_at(amount_expr, 0)) ?" " (is_seq(get_at(amount_expr, 0)) ?"
" get_at(get_at(amount_expr, 0), 0) :" " get_at(get_at(amount_expr, 0), 0) :"
" market(get_at(amount_expr, 0), date, exchange)" " market(get_at(amount_expr, 0), value_date, exchange)"
" - get_at(amount_expr, 1))"); " - get_at(amount_expr, 1))");
parent->HANDLER(revalued_total_) parent->HANDLER(revalued_total_)
.set_expr(string("--gain"), .set_expr(string("--gain"),
"(market(get_at(total_expr, 0), date, exchange), " "(market(get_at(total_expr, 0), value_date, exchange), "
"get_at(total_expr, 1))"); "get_at(total_expr, 1))");
parent->HANDLER(display_total_) parent->HANDLER(display_total_)
.set_expr(string("--gain"), .set_expr(string("--gain"),
"use_direct_amount ? total_expr :" "use_direct_amount ? total_expr :"
" market(get_at(total_expr, 0), date, exchange)" " market(get_at(total_expr, 0), value_date, exchange)"
" - get_at(total_expr, 1)"); " - get_at(total_expr, 1)");
}); });
@ -642,9 +642,11 @@ public:
OPTION_(report_t, market, DO() { // -V OPTION_(report_t, market, DO() { // -V
parent->HANDLER(revalued).on_only(string("--market")); parent->HANDLER(revalued).on_only(string("--market"));
parent->HANDLER(display_amount_) parent->HANDLER(display_amount_)
.set_expr(string("--market"), "market(amount_expr, date, exchange)"); .set_expr(string("--market"),
"market(amount_expr, value_date, exchange)");
parent->HANDLER(display_total_) parent->HANDLER(display_total_)
.set_expr(string("--market"), "market(total_expr, date, exchange)"); .set_expr(string("--market"),
"market(total_expr, value_date, exchange)");
}); });
OPTION(report_t, meta_); OPTION(report_t, meta_);

View file

@ -1401,8 +1401,7 @@ bool value_t::is_zero() const
return false; return false;
} }
value_t value_t::value(const bool primary_only, value_t value_t::value(const optional<datetime_t>& moment,
const optional<datetime_t>& moment,
const optional<commodity_t&>& in_terms_of) const const optional<commodity_t&>& in_terms_of) const
{ {
switch (type()) { switch (type()) {
@ -1411,13 +1410,13 @@ value_t value_t::value(const bool primary_only,
case AMOUNT: case AMOUNT:
if (optional<amount_t> val = if (optional<amount_t> val =
as_amount().value(primary_only, moment, in_terms_of)) as_amount().value(moment, in_terms_of))
return *val; return *val;
return NULL_VALUE; return NULL_VALUE;
case BALANCE: case BALANCE:
if (optional<balance_t> bal = if (optional<balance_t> bal =
as_balance().value(primary_only, moment, in_terms_of)) as_balance().value(moment, in_terms_of))
return *bal; return *bal;
return NULL_VALUE; return NULL_VALUE;
@ -1455,7 +1454,7 @@ value_t value_t::exchange_commodities(const std::string& commodities,
if (commodity_t * commodity = if (commodity_t * commodity =
commodity_pool_t::current_pool->parse_price_expression(p, add_prices, commodity_pool_t::current_pool->parse_price_expression(p, add_prices,
moment)) { moment)) {
value_t result = value(false, moment, *commodity); value_t result = value(moment, *commodity);
if (! result.is_null()) if (! result.is_null())
return result; return result;
} }
@ -1681,18 +1680,17 @@ value_t value_t::strip_annotations(const keep_details_t& what_to_keep) const
return NULL_VALUE; return NULL_VALUE;
} }
void value_t::print(std::ostream& out, void value_t::print(std::ostream& out,
const int first_width, const int first_width,
const int latter_width, const int latter_width,
const bool right_justify, const uint_least8_t flags) const
const bool colorize) const
{ {
if (first_width > 0 && if (first_width > 0 &&
(! is_amount() || as_amount().is_zero()) && (! is_amount() || as_amount().is_zero()) &&
! is_balance() && ! is_string()) { ! is_balance() && ! is_string()) {
out.width(first_width); out.width(first_width);
if (right_justify) if (flags & AMOUNT_PRINT_RIGHT_JUSTIFY)
out << std::right; out << std::right;
else else
out << std::left; out << std::left;
@ -1716,8 +1714,9 @@ void value_t::print(std::ostream& out,
break; break;
case INTEGER: case INTEGER:
if (colorize && as_long() < 0) if (flags & AMOUNT_PRINT_COLORIZE && as_long() < 0)
justify(out, to_string(), first_width, right_justify, true); justify(out, to_string(), first_width,
flags & AMOUNT_PRINT_RIGHT_JUSTIFY, true);
else else
out << as_long(); out << as_long();
break; break;
@ -1727,21 +1726,20 @@ void value_t::print(std::ostream& out,
out << 0; out << 0;
} else { } else {
std::ostringstream buf; std::ostringstream buf;
buf << as_amount(); as_amount().print(buf, flags & AMOUNT_PRINT_NO_COMPUTED_ANNOTATIONS);
justify(out, buf.str(), first_width, right_justify, justify(out, buf.str(), first_width, flags & AMOUNT_PRINT_RIGHT_JUSTIFY,
colorize && as_amount().sign() < 0); flags & AMOUNT_PRINT_COLORIZE && as_amount().sign() < 0);
} }
break; break;
} }
case BALANCE: case BALANCE:
as_balance().print(out, first_width, latter_width, right_justify, as_balance().print(out, first_width, latter_width, flags);
colorize);
break; break;
case STRING: case STRING:
if (first_width > 0) if (first_width > 0)
justify(out, as_string(), first_width, right_justify); justify(out, as_string(), first_width, flags & AMOUNT_PRINT_RIGHT_JUSTIFY);
else else
out << as_string(); out << as_string();
break; break;
@ -1759,8 +1757,7 @@ void value_t::print(std::ostream& out,
else else
out << ", "; out << ", ";
value.print(out, first_width, latter_width, right_justify, value.print(out, first_width, latter_width, flags);
colorize);
} }
out << ')'; out << ')';
break; break;

View file

@ -476,8 +476,7 @@ public:
void in_place_unreduce(); // exists for efficiency's sake void in_place_unreduce(); // exists for efficiency's sake
// Return the "market value" of a given value at a specific time. // Return the "market value" of a given value at a specific time.
value_t value(const bool primary_only = false, value_t value(const optional<datetime_t>& moment = none,
const optional<datetime_t>& moment = none,
const optional<commodity_t&>& in_terms_of = none) const; const optional<commodity_t&>& in_terms_of = none) const;
value_t price() const; value_t price() const;
@ -942,11 +941,11 @@ public:
/** /**
* Printing methods. * Printing methods.
*/ */
void print(std::ostream& out, void print(std::ostream& out,
const int first_width = -1, const int first_width = -1,
const int latter_width = -1, const int latter_width = -1,
const bool right_justify = false, const uint_least8_t flags = AMOUNT_PRINT_NO_FLAGS) const;
const bool colorize = false) const;
void dump(std::ostream& out, const bool relaxed = true) const; void dump(std::ostream& out, const bool relaxed = true) const;
/** /**

View file

@ -275,11 +275,11 @@ bool xact_base_t::finalize()
datetime_t(date(), time_duration(0, 0, 0, 0))); datetime_t(date(), time_duration(0, 0, 0, 0)));
if (post->amount.has_annotation() && if (post->amount.has_annotation() &&
breakdown.basis_cost.commodity() == breakdown.basis_cost.commodity() == breakdown.final_cost.commodity()) {
breakdown.final_cost.commodity()) { if (amount_t gain_loss = breakdown.basis_cost - breakdown.final_cost) {
if (amount_t gain_loss = (breakdown.basis_cost -
breakdown.final_cost).rounded()) {
DEBUG("xact.finalize", "gain_loss = " << gain_loss); DEBUG("xact.finalize", "gain_loss = " << gain_loss);
gain_loss.in_place_round();
DEBUG("xact.finalize", "gain_loss rounds to = " << gain_loss);
add_or_set_value(balance, gain_loss.reduced()); add_or_set_value(balance, gain_loss.reduced());
@ -293,6 +293,8 @@ bool xact_base_t::finalize()
p->set_state(post->state()); p->set_state(post->state());
add_post(p); add_post(p);
DEBUG("xact.finalize", "added gain_loss, balance = " << balance); DEBUG("xact.finalize", "added gain_loss, balance = " << balance);
} else {
DEBUG("xact.finalize", "gain_loss would have display as zero");
} }
} else { } else {
post->amount = breakdown.amount; post->amount = breakdown.amount;

File diff suppressed because it is too large Load diff

View file

@ -7,11 +7,11 @@ D 1.0000s
Assets:Gruulmorg 248720c {10.051463493s} Assets:Gruulmorg 248720c {10.051463493s}
Equity:Gold -5000000s Equity:Gold -5000000s
>>>1 >>>1
1339829c {1.8659s} [2006/03/14] 1339829c {1.86590975416s} [2006/03/14]
1339829c {1.8659s} [2006/03/14] 1339829c {1.86590975416s} [2006/03/14]
248720c {10.0515s} 248720c {10.051463493s}
1339829c {1.8659s} [2006/03/14] 1339829c {1.86590975416s} [2006/03/14]
248720c {10.0515s} 248720c {10.051463493s}
-1388.9h -1388.9h
>>>2 >>>2
=== 0 === 0
@ -19,9 +19,9 @@ reg --format '%(justify(scrub(total_expr), 40, 40, true))\n' --lots-actual
>>>1 >>>1
1339829c 1339829c
1339829c 1339829c
248720c {10.0515s} 248720c {10.051463493s}
1339829c 1339829c
248720c {10.0515s} 248720c {10.051463493s}
-1388.9h -1388.9h
>>>2 >>>2
=== 0 === 0

File diff suppressed because it is too large Load diff

32717
test/input/speed-test.dat Normal file

File diff suppressed because it is too large Load diff

View file

@ -89,11 +89,11 @@ D 1.200,40 €
Actif:SV 14,89 € Actif:SV 14,89 €
>>>1 >>>1
1999/11/01 * Achat 1999/11/01 * Achat
Actif:SSB 125,0000 STK @ 13,37936 $ Actif:SSB 125,0000 STK
Actif:SSB -1672,42 $ Actif:SSB -1672,42 $
1999/11/04 * Vente 1999/11/04 * Vente
Actif:SSB -125,0000 STK @ 15,01288 $ Actif:SSB -125,0000 STK
Dépense:SSB:Commissions 55,07 $ Dépense:SSB:Commissions 55,07 $
Actif:SSB 1821,54 $ Actif:SSB 1821,54 $

View file

@ -4,16 +4,16 @@
>>>2 >>>2
While parsing file "$sourcepath/src/amount.h", line 66: While parsing file "$sourcepath/src/amount.h", line 66:
Error: No quantity specified for amount Error: No quantity specified for amount
While parsing file "$sourcepath/src/amount.h", line 720: While parsing file "$sourcepath/src/amount.h", line 725:
Error: Invalid date/time: line amount_t amoun Error: Invalid date/time: line amount_t amoun
While parsing file "$sourcepath/src/amount.h", line 726: While parsing file "$sourcepath/src/amount.h", line 731:
Error: Invalid date/time: line string amount_ Error: Invalid date/time: line string amount_
While parsing file "$sourcepath/src/amount.h", line 732: While parsing file "$sourcepath/src/amount.h", line 737:
Error: Invalid date/time: line string amount_ Error: Invalid date/time: line string amount_
While parsing file "$sourcepath/src/amount.h", line 738: While parsing file "$sourcepath/src/amount.h", line 743:
Error: Invalid date/time: line string amount_ Error: Invalid date/time: line string amount_
While parsing file "$sourcepath/src/amount.h", line 744: While parsing file "$sourcepath/src/amount.h", line 749:
Error: Invalid date/time: line std::ostream& Error: Invalid date/time: line std::ostream&
While parsing file "$sourcepath/src/amount.h", line 751: While parsing file "$sourcepath/src/amount.h", line 756:
Error: Invalid date/time: line std::istream& Error: Invalid date/time: line std::istream&
=== 7 === 7

View file

@ -73,11 +73,11 @@ void CommodityTestCase::testPriceHistory()
cad.add_price(jan17_06, amount_t("$1.11")); cad.add_price(jan17_06, amount_t("$1.11"));
#ifndef NOT_FOR_PYTHON #ifndef NOT_FOR_PYTHON
optional<amount_t> amt = x1.value(false, feb28_07sbm); optional<amount_t> amt = x1.value(feb28_07sbm);
assertTrue(amt); assertTrue(amt);
assertEqual(amount_t("$1831.83"), *amt); assertEqual(amount_t("$1831.83"), *amt);
amt = x1.value(false, CURRENT_TIME()); amt = x1.value(CURRENT_TIME());
assertTrue(amt); assertTrue(amt);
assertEqual(string("$2124.12"), amt->to_string()); assertEqual(string("$2124.12"), amt->to_string());
#ifdef INTEGER_MATH #ifdef INTEGER_MATH
@ -86,18 +86,18 @@ void CommodityTestCase::testPriceHistory()
assertEqual(string("$2124.122"), amt->to_fullstring()); assertEqual(string("$2124.122"), amt->to_fullstring());
#endif #endif
amt = x1.value(false, CURRENT_TIME(), euro); amt = x1.value(CURRENT_TIME(), euro);
assertTrue(amt); assertTrue(amt);
assertEqual(string("EUR 1366.87"), amt->rounded().to_string()); assertEqual(string("EUR 1366.87"), amt->rounded().to_string());
// Add a newer Euro pricing // Add a newer Euro pricing
aapl.add_price(jan17_07, amount_t("EUR 23.00")); aapl.add_price(jan17_07, amount_t("EUR 23.00"));
amt = x1.value(false, CURRENT_TIME(), euro); amt = x1.value(CURRENT_TIME(), euro);
assertTrue(amt); assertTrue(amt);
assertEqual(string("EUR 2302.30"), amt->to_string()); assertEqual(string("EUR 2302.30"), amt->to_string());
amt = x1.value(false, CURRENT_TIME(), cad); amt = x1.value(CURRENT_TIME(), cad);
assertTrue(amt); assertTrue(amt);
assertEqual(string("CAD 3223.22"), amt->to_string()); assertEqual(string("CAD 3223.22"), amt->to_string());
#endif // NOT_FOR_PYTHON #endif // NOT_FOR_PYTHON

View file

@ -529,4 +529,13 @@ report: all
genhtml -o doc/report doc/report/ledger_cov.info genhtml -o doc/report doc/report/ledger_cov.info
@echo Coverage reported generated\; now open doc/report/index.html @echo Coverage reported generated\; now open doc/report/index.html
LEDGER_BINARY = $(top_builddir)/ledger$(EXEEXT)
SPEEDTEST_DAT = $(srcdir)/test/input/speed-test.dat
SPEEDTEST_ARGS = -v --decimal-comma -o /dev/null reg 2eb75f84 1eede0cb
speedtest:
@$(LEDGER_BINARY) -f $(SPEEDTEST_DAT) $(SPEEDTEST_ARGS)
@$(LEDGER_BINARY) -f $(SPEEDTEST_DAT) $(SPEEDTEST_ARGS) -V
@$(LEDGER_BINARY) -f $(SPEEDTEST_DAT) $(SPEEDTEST_ARGS) -X €
# Makefile.am ends here # Makefile.am ends here