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):
"Base class for building command line applications."
force_exit = True # If true, always ends run() with sys.exit()
log_handler = None
darwin_gcc = False
force_exit = True # If true, always ends run() with sys.exit()
log_handler = None
darwin_gcc = False
boost_version = "1_43"
gcc_version = "45"
options = {
'debug': False,
@ -459,6 +461,9 @@ class PrepareBuild(CommandLineApp):
op.add_option('', '--universal', action='store_true',
dest='universal', default=False,
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",
callback=self.option_output,
help='Build in the specified directory')
@ -909,13 +914,17 @@ class PrepareBuild(CommandLineApp):
def setup_for_johnw(self):
if self.current_flavor == 'debug' or self.current_flavor == 'gcov':
if exists('/usr/local/stow/cppunit/include'):
self.sys_include_dirs.insert(0, '/usr/local/stow/cppunit/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/cppunit/lib')
if exists('/usr/local/stow/cppunit-gcc%s/include' % self.gcc_version):
self.sys_include_dirs.insert(
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'):
self.sys_include_dirs.insert(0, '/usr/local/stow/icu/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/icu/lib')
if exists('/usr/local/stow/icu-gcc%s/include' % self.gcc_version):
self.sys_include_dirs.insert(
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.configure_args.append('--disable-shared')
@ -955,11 +964,16 @@ class PrepareBuild(CommandLineApp):
elif system == 'Darwin':
if (self.current_flavor == 'opt' or \
self.current_flavor == 'default') and \
not self.options.gcc45 and \
exists('/usr/bin/g++-4.2'):
self.envvars['CC'] = '/usr/bin/gcc-4.2'
self.envvars['CXX'] = '/usr/bin/g++-4.2'
self.envvars['LD'] = '/usr/bin/g++-4.2'
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'):
self.envvars['CC'] = '/opt/local/bin/gcc-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.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1')
if self.boost_info.configure(home_path = '/usr/local/stow/boost_1_43_0',
suffix = '-xgcc44-sd-1_43',
include_path = 'include/boost-1_43'):
if self.boost_info.configure(
home_path = '/usr/local/stow/boost_%s_0-gcc%s' % \
(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
elif self.boost_info.configure(home_path = '/usr/local/stow/boost_1_43_0',
suffix = '-xgcc44-d-1_43',
include_path = 'include/boost-1_43'):
elif self.boost_info.configure(
home_path = '/usr/local/stow/boost_%s_0-gcc%s' % \
(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
elif self.boost_info.configure(suffix = '-d'):
pass
@ -1147,13 +1167,19 @@ class PrepareBuild(CommandLineApp):
else:
if self.boost_info.configure():
pass
elif self.boost_info.configure(home_path = '/usr/local/stow/boost_1_43_0',
suffix = '-xgcc44-s-1_43',
include_path = 'include/boost-1_43'):
elif self.boost_info.configure(
home_path = '/usr/local/stow/boost_%s_0-gcc%s' % \
(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
elif self.boost_info.configure(home_path = '/usr/local/stow/boost_1_43_0',
suffix = '-xgcc44-1_43',
include_path = 'include/boost-1_43'):
elif self.boost_info.configure(
home_path = '/usr/local/stow/boost_%s_0-gcc%s' % \
(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
def setup_flavor_default(self):
@ -1168,25 +1194,29 @@ class PrepareBuild(CommandLineApp):
def setup_flavor_opt(self):
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:
self.option_no_pch()
if '--disable-shared' in self.configure_args:
self.configure_args.remove('--disable-shared')
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:
for i in ['-fast']:
self.CXXFLAGS.append(i)
self.CFLAGS.append(i)
self.LDFLAGS.append(i)
for i in ['-arch', 'i386', '-arch', 'x86_64']:
self.CXXFLAGS.append(i)
self.CFLAGS.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):
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
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.
The transaction might look like this:
Such a transaction might look like this:
@smallexample
9/29 BAL Pacific Bell $-200.00 $-200.00
Equity:Opening Balances $200.00
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
9/29 Pacific Bell $23.00 $23.00
Checking $-23.00 0
@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
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
@ -174,16 +160,8 @@ formatting as the ledger program wishes to see them:
@smallexample
2004/09/29 Pacific Bell
Payable:Pacific Bell $-200.00
Equity:Opening Balances
2004/09/29 Checking
Accounts:Checking $100.00
Equity:Opening Balances
2004/09/29 Pacific Bell
Payable:Pacific Bell $23.00
Accounts:Checking
Expenses:Pacific Bell $23.00
Assets:Checking
@end smallexample
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
# installation.
STOW_ROOT = /usr/local/stow
PRODUCTS = $(HOME)/Products
STOW_ROOT = /usr/local/stow
PRODUCTS = $(HOME)/Products
CC = gcc-mp-4.4
CXX = g++-mp-4.4
LD = gcc-mp-4.4
CPPFLAGS = -D_GLIBCXX_DEBUG=1 -D_GLIBCXX_FULLY_DYNAMIC_STRING=1
CFLAGS = $(CPPFLAGS) -g
LDFLAGS = -g
CC = gcc-mp-4.5
CXX = g++-mp-4.5
LD = gcc-mp-4.5
CXX_VERSION = 45
CPPFLAGS = -D_GLIBCXX_DEBUG=1 -D_GLIBCXX_FULLY_DYNAMIC_STRING=1
CFLAGS = $(CPPFLAGS) -g
LDFLAGS = -g
BOOST_VERSION = 1_43_0
BOOST_SOURCE = boost_$(BOOST_VERSION)
BOOST_TOOLSET = darwin
BOOST_DEFINES = define=_GLIBCXX_DEBUG=1 define=_GLIBCXX_FULLY_DYNAMIC_STRING=1
#BOOST_FLAGS = --architecture=x86 --address_model=32_64
BOOST_FLAGS = --toolset=$(BOOST_TOOLSET) \
--build-type=complete --layout=versioned \
$(BOOST_DEFINES)
ICU_FLAGS = -sHAVE_ICU=1 -sICU_PATH=$(STOW_ROOT)/icu
BOOST_VERSION = 1_43_0
BOOST_SOURCE = boost_$(BOOST_VERSION)
BOOST_TOOLSET = darwin
BOOST_DEFINES = define=_GLIBCXX_DEBUG=1 define=_GLIBCXX_FULLY_DYNAMIC_STRING=1
#BOOST_FLAGS = --architecture=x86 --address_model=32_64
BOOST_FLAGS = --toolset=$(BOOST_TOOLSET) \
--build-type=complete --layout=versioned \
$(BOOST_DEFINES)
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:
(cd $(BOOST_SOURCE) && \
bjam debug --prefix=$(STOW_ROOT)/boost_$(BOOST_VERSION) \
--build-dir=$(PRODUCTS)/boost_$(BOOST_VERSION) \
bjam debug --prefix=$(BOOST_STOW) --build-dir=$(BOOST_BUILD) \
$(BOOST_FLAGS) install)
cppunit-build:
@ -37,23 +43,30 @@ cppunit-build:
CFLAGS="$(CFLAGS)" \
LDFLAGS="$(LDFLAGS)" \
CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \
--prefix=$(STOW_ROOT)/cppunit \
--prefix=$(STOW_ROOT)/cppunit-gcc$(CXX_VERSION) \
--disable-doxygen --disable-dot && \
make install)
icu-build:
-(cd icu/source; make distclean)
(cd icu/source; sh autogen.sh; \
./configure CPPFLAGS="$(CPPFLAGS)" \
CFLAGS="$(CFLAGS)" \
LDFLAGS="$(LDFLAGS)" \
CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \
--enable-static --enable-debug \
--prefix=$(STOW_ROOT)/icu && \
make install)
#icu-build:
# -(cd icu/source; make distclean)
# (cd icu/source; sh autogen.sh; \
# ./configure CPPFLAGS="$(CPPFLAGS)" \
# CFLAGS="$(CFLAGS)" \
# LDFLAGS="$(LDFLAGS)" \
# CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \
# --enable-static --enable-debug \
# --prefix=$(STOW_ROOT)/icu-gcc$(CXX_VERSION) && \
# 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:
(cd $(BOOST_SOURCE) && \
bjam debug --prefix=$(STOW_ROOT)/boost_$(BOOST_VERSION)-icu \
--build-dir=$(PRODUCTS)/boost_$(BOOST_VERSION)-icu \
$(BOOST_FLAGS) $(ICU_FLAGS) install)
clean:
-rm -fr $(BOOST_STOW) $(BOOST_BUILD)
-rm -fr $(BOOST_ICU_STOW) $(BOOST_ICU_BUILD)
-rm -fr $(STOW_ROOT)/cppunit-gcc$(CXX_VERSION)
-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>
amount_t::value(const bool primary_only,
const optional<datetime_t>& moment,
amount_t::value(const optional<datetime_t>& moment,
const optional<commodity_t&>& in_terms_of) const
{
if (quantity) {
@ -740,35 +739,39 @@ amount_t::value(const bool primary_only,
"amount_t::value: in_terms_of = " << in_terms_of->symbol());
#endif
if (has_commodity() &&
(! primary_only || ! commodity().has_flags(COMMODITY_PRIMARY))) {
if (in_terms_of &&
commodity().referent() == in_terms_of->referent()) {
(in_terms_of || ! commodity().has_flags(COMMODITY_PRIMARY))) {
optional<price_point_t> point;
optional<commodity_t&> comm(in_terms_of);
if (comm && commodity().referent() == comm->referent()) {
return *this;
}
else if (has_annotation() && annotation().price &&
annotation().has_flags(ANNOTATION_PRICE_FIXATED)) {
amount_t price(*annotation().price);
else if (has_annotation() && annotation().price) {
if (annotation().has_flags(ANNOTATION_PRICE_FIXATED)) {
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.in_place_round();
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 {
throw_(amount_error,
@ -1216,7 +1219,7 @@ void amount_t::parse_conversion(const string& larger_str,
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());
@ -1246,7 +1249,7 @@ void amount_t::print(std::ostream& _out) const
// If there are any annotations associated with this commodity, output them
// 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
// width or fill for _out, it will be applied to the entire amount string,

View file

@ -399,8 +399,7 @@ public:
$100.00.
*/
optional<amount_t>
value(const bool primary_only = true,
const optional<datetime_t>& moment = none,
value(const optional<datetime_t>& moment = none,
const optional<commodity_t&>& in_terms_of = none) const;
amount_t price() const;
@ -677,7 +676,13 @@ public:
true, the full internal precision of the amount is displayed, regardless
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);
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;
}
else if (c == '[') {
@ -118,18 +109,22 @@ void annotation_t::parse(std::istream& in)
#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 << " {"
<< (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) << ']';
if (tag)
if (tag &&
(! no_computed_annotations || ! has_flags(ANNOTATION_TAG_CALCULATED)))
out << " (" << *tag << ')';
}
@ -197,9 +192,10 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep)
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

View file

@ -87,7 +87,8 @@ struct annotation_t : public supports_flags<>,
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 {
assert(*this);
@ -230,7 +231,8 @@ public:
}
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)
private:

View file

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

View file

@ -384,9 +384,8 @@ public:
}
optional<balance_t>
value(const bool primary_only = false,
const optional<datetime_t>& moment = none,
const optional<commodity_t&>& in_terms_of = none) const;
value(const optional<datetime_t>& moment = none,
const optional<commodity_t&>& in_terms_of = none) const;
balance_t price() const;
@ -530,11 +529,10 @@ public:
* relative amounts of those commodities. There is no option to
* change this behavior.
*/
void print(std::ostream& out,
const int first_width = -1,
const int latter_width = -1,
const bool right_justify = false,
const bool colorize = false) const;
void print(std::ostream& out,
const int first_width = -1,
const int latter_width = -1,
const uint_least8_t flags = AMOUNT_PRINT_NO_FLAGS) const;
/**
* 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);
predicate_t display_predicate;
predicate_t only_predicate;
rounding_error_posts * rounding_handler = NULL;
display_filter_posts * display_filter = NULL;
assert(report.HANDLED(amount_));
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
// in market value of commodities, which otherwise would affect the running
// total unpredictably.
if (report.HANDLED(revalued) && ! report.HANDLED(no_rounding)) {
rounding_handler = new rounding_error_posts(handler, report);
handler.reset(rounding_handler);
}
display_filter = new display_filter_posts(handler, report,
report.HANDLED(revalued) &&
! report.HANDLED(no_rounding));
handler.reset(display_filter);
// filter_posts will only pass through posts matching the
// `display_predicate'.
@ -162,7 +162,7 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler,
(! for_accounts_report || report.HANDLED(unrealized)))
handler.reset(new changed_value_posts(handler, report, for_accounts_report,
report.HANDLED(unrealized),
rounding_handler));
display_filter));
// calc_posts computes the running total. When this appears will determine,
// 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)
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("commodity.prices.find",
"searching for price via commodity '" << comm << "'");
@ -370,8 +366,7 @@ commodity_t::find_price(const optional<commodity_t&>& commodity,
#endif
) const
{
if (! has_flags(COMMODITY_WALKED) && base->varied_history &&
(commodity || ! has_flags(COMMODITY_PRIMARY))) {
if (! has_flags(COMMODITY_WALKED) && base->varied_history) {
optional<base_t::time_and_commodity_t> pair;
#if defined(VERIFY_ON)
optional<price_point_t> checkpoint;

View file

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

View file

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

View file

@ -289,18 +289,16 @@ void calc_posts::operator()(post_t& post)
}
namespace {
typedef function<void (post_t&)> post_functor_t;
void handle_value(const value_t& value,
account_t * account,
xact_t * xact,
temporaries_t& temps,
post_handler_ptr handler,
const date_t& date = date_t(),
const value_t& total = value_t(),
const bool direct_amount = false,
const bool mark_visited = false,
const optional<post_functor_t>& functor = none)
void handle_value(const value_t& value,
account_t * account,
xact_t * xact,
temporaries_t& temps,
post_handler_ptr handler,
const date_t& date = date_t(),
const bool act_date_p = true,
const value_t& total = value_t(),
const bool direct_amount = false,
const bool mark_visited = false)
{
post_t& post = temps.create_post(*xact, account);
post.add_flags(ITEM_GENERATED);
@ -319,8 +317,12 @@ namespace {
post_t::xdata_t& xdata(post.xdata());
if (is_valid(date))
xdata.date = date;
if (is_valid(date)) {
if (act_date_p)
xdata.date = date;
else
xdata.value_date = date;
}
value_t temp(value);
@ -353,9 +355,6 @@ namespace {
if (direct_amount)
xdata.add_flags(POST_EXT_DIRECT_AMT);
if (functor)
(*functor)(post);
DEBUG("filters.changed_value.rounding", "post.amount = " << post.amount);
(*handler)(post);
@ -388,12 +387,15 @@ void collapse_posts::report_subtotal()
}
else {
date_t earliest_date;
date_t latest_date;
foreach (post_t * post, component_posts) {
date_t reported = post->date();
if (! is_valid(earliest_date) ||
reported < earliest_date)
earliest_date = reported;
date_t date = post->date();
date_t value_date = post->value_date();
if (! is_valid(earliest_date) || date < earliest_date)
earliest_date = date;
if (! is_valid(latest_date) || value_date > latest_date)
latest_date = value_date;
}
xact_t& xact = temps.create_xact();
@ -401,12 +403,16 @@ void collapse_posts::report_subtotal()
xact._date = (is_valid(earliest_date) ?
earliest_date : last_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,
/* account= */ &totals_account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler);
handle_value(/* value= */ subtotal,
/* account= */ &totals_account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler,
/* date= */ latest_date,
/* act_date_p= */ false);
}
component_posts.clear();
@ -466,27 +472,46 @@ void related_posts::flush()
item_handler<post_t>::flush();
}
rounding_error_posts::rounding_error_posts(post_handler_ptr handler,
report_t& _report)
display_filter_posts::display_filter_posts(post_handler_ptr handler,
report_t& _report,
bool _show_rounding)
: 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_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);
value_t new_display_total(display_total_expr.calc(bound_scope));
value_t new_display_total;
DEBUG("filters.changed_value.rounding",
"rounding.new_display_total = " << new_display_total);
if (show_rounding) {
new_display_total = display_total_expr.calc(bound_scope);
if (! last_display_total.is_null()) {
if (value_t repriced_amount = display_amount_expr.calc(bound_scope)) {
DEBUG("filters.changed_value.rounding",
"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",
"rounding.repriced_amount = " << repriced_amount);
@ -502,29 +527,29 @@ void rounding_error_posts::output_rounding(post_t& post)
DEBUG("filters.changed_value.rounding",
"rounding.diff = " << diff);
xact_t& xact = temps.create_xact();
xact.payee = _("Commodity rounding");
xact._date = post.date();
handle_value(/* value= */ diff,
/* account= */ &rounding_account,
/* xact= */ &xact,
/* xact= */ post.xact,
/* temps= */ temps,
/* handler= */ handler,
/* date= */ *xact._date,
/* date= */ date_t(),
/* act_date_p= */ true,
/* total= */ precise_display_total,
/* 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);
item_handler<post_t>::operator()(post);
if (output_rounding(post))
item_handler<post_t>::operator()(post);
}
changed_value_posts::changed_value_posts
@ -532,12 +557,13 @@ changed_value_posts::changed_value_posts
report_t& _report,
bool _for_accounts_report,
bool _show_unrealized,
rounding_error_posts * _rounding_handler)
display_filter_posts * _display_filter)
: item_handler<post_t>(handler), report(_report),
for_accounts_report(_for_accounts_report),
show_unrealized(_show_unrealized), last_post(NULL),
revalued_account(temps.create_account(_("<Revalued>"))),
rounding_handler(_rounding_handler)
revalued_account(_display_filter ? _display_filter->revalued_account :
temps.create_account(_("<Revalued>"))),
display_filter(_display_filter)
{
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.payee = _("Commodities revalued");
xact._date = is_valid(date) ? date : post.date();
xact._date = is_valid(date) ? date : post.value_date();
if (! for_accounts_report) {
handle_value
@ -614,6 +640,7 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
/* temps= */ temps,
/* handler= */ handler,
/* date= */ *xact._date,
/* act_date_p= */ true,
/* total= */ repriced_total);
}
else if (show_unrealized) {
@ -626,6 +653,7 @@ void changed_value_posts::output_revaluation(post_t& post, const date_t& date)
/* temps= */ temps,
/* handler= */ handler,
/* date= */ *xact._date,
/* act_date_p= */ true,
/* total= */ value_t(),
/* direct_amount= */ false,
/* mark_visited= */ true);
@ -649,7 +677,7 @@ void changed_value_posts::output_intermediate_prices(post_t& post,
xact_t& xact(temps.create_xact());
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));
temp.add_flags(ITEM_GENERATED);
@ -711,9 +739,9 @@ void changed_value_posts::output_intermediate_prices(post_t& post,
hist->histories) {
foreach (const commodity_t::history_map::value_type& price,
comm_hist.second.prices) {
if (price.first.date() > post.date() &&
if (price.first.date() > post.value_date() &&
price.first.date() < current) {
DEBUG("filters.revalued", post.date() << " < "
DEBUG("filters.revalued", post.value_date() << " < "
<< price.first.date() << " < " << current);
DEBUG("filters.revalued", "inserting "
<< price.second << " at " << price.first.date());
@ -755,8 +783,8 @@ void changed_value_posts::operator()(post_t& post)
{
if (last_post) {
if (! for_accounts_report)
output_intermediate_prices(*last_post, post.date());
output_revaluation(*last_post, post.date());
output_intermediate_prices(*last_post, post.value_date());
output_revaluation(*last_post, post.value_date());
}
if (changed_values_only)
@ -780,11 +808,12 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
if (! range_start || ! range_finish) {
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)
range_start = date;
if (! range_finish || date > *range_finish)
range_finish = date;
if (! range_finish || value_date > *range_finish)
range_finish = value_date;
}
}
component_posts.clear();
@ -806,11 +835,13 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
xact._date = *range_start;
foreach (values_map::value_type& pair, values)
handle_value(/* value= */ pair.second.value,
/* account= */ pair.second.account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler);
handle_value(/* value= */ pair.second.value,
/* account= */ pair.second.account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler,
/* date= */ *range_finish,
/* act_date_p= */ false);
values.clear();
}
@ -919,17 +950,21 @@ void posts_as_equity::report_subtotal()
if (pair.second.value.is_balance()) {
foreach (const balance_t::amounts_map::value_type& amount_pair,
pair.second.value.as_balance().amounts)
handle_value(/* value= */ amount_pair.second,
/* account= */ pair.second.account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler);
handle_value(/* value= */ amount_pair.second,
/* account= */ pair.second.account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler,
/* date= */ finish,
/* act_date_p= */ false);
} else {
handle_value(/* value= */ pair.second.value,
/* account= */ pair.second.account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler);
handle_value(/* value= */ pair.second.value,
/* account= */ pair.second.account,
/* xact= */ &xact,
/* temps= */ temps,
/* handler= */ handler,
/* date= */ finish,
/* act_date_p= */ false);
}
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
// 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_total_expr;
report_t& report;
bool show_rounding;
value_t last_display_total;
temporaries_t temps;
account_t& rounding_account;
rounding_error_posts();
display_filter_posts();
public:
rounding_error_posts(post_handler_ptr handler,
report_t& _report);
account_t& revalued_account;
virtual ~rounding_error_posts() {
TRACE_DTOR(rounding_error_posts);
display_filter_posts(post_handler_ptr handler,
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);
@ -538,7 +542,7 @@ class changed_value_posts : public item_handler<post_t>
account_t * gains_equity_account;
account_t * losses_equity_account;
rounding_error_posts * rounding_handler;
display_filter_posts * display_filter;
changed_value_posts();
@ -547,7 +551,7 @@ public:
report_t& _report,
bool _for_accounts_report,
bool _show_unrealized,
rounding_error_posts * _rounding_handler);
display_filter_posts * _display_filter);
virtual ~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>);
break;
case 'v':
if (name == "value_date")
return WRAP_FUNCTOR(get_wrapper<&get_date>);
break;
case 'L':
if (name[1] == '\0')
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 &&
(account.has_xflags(ACCOUNT_EXT_VISITED) || (! flat && visited > 0))) {
bind_scope_t bound_scope(report, account);
call_scope_t call_scope(bound_scope);
if ((! flat && to_display > 1) ||
((flat || to_display != 1 ||
account.has_xflags(ACCOUNT_EXT_VISITED)) &&
(report.HANDLED(empty) || report.fn_display_total(call_scope)) &&
disp_pred(bound_scope))) {
account.xdata().add_flags(ACCOUNT_EXT_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;
}
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
{
if (xdata_ && is_valid(xdata_->date))
@ -319,6 +326,14 @@ namespace {
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) {
return post.xdata().datetime;
}
@ -479,6 +494,8 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
case 'v':
if (name == "virtual")
return WRAP_FUNCTOR(get_wrapper<&get_virtual>);
else if (name == "value_date")
return WRAP_FUNCTOR(get_wrapper<&get_value_date>);
break;
case 'x':

View file

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

View file

@ -172,13 +172,14 @@ namespace {
if (post->amount_expr) {
amt = post->amount_expr->text();
} else {
std::size_t amount_width =
int amount_width =
(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;
report.scrub(post->amount)
.print(amt_str, static_cast<int>(amount_width), -1, true);
value_t(post->amount).print(amt_str, amount_width, -1,
AMOUNT_PRINT_RIGHT_JUSTIFY |
AMOUNT_PRINT_NO_COMPUTED_ANNOTATIONS);
amt = amt_str.str();
}
@ -190,15 +191,17 @@ namespace {
amtbuf << string(2 - (slip + amt_slip), ' ');
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))
amtbuf << " @@ " << report.scrub(post->cost->abs());
amtbuf << " @@ " << post->cost->abs();
else
amtbuf << " @ " << report.scrub((*post->cost / post->amount).abs());
amtbuf << " @ "
<< (*post->cost / post->amount).abs();
}
if (post->assigned_amount)
amtbuf << " = " << report.scrub(*post->assigned_amount);
amtbuf << " = " << post->assigned_amount;
string trailer = amtbuf.str();
out << trailer;

View file

@ -45,16 +45,16 @@ using namespace boost::python;
namespace {
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,
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,
commodity_t& in_terms_of,
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) {

View file

@ -45,16 +45,16 @@ using namespace boost::python;
namespace {
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,
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,
commodity_t& in_terms_of,
datetime_t& moment) {
return balance.value(false, moment, in_terms_of);
return balance.value(moment, in_terms_of);
}
boost::optional<amount_t>

View file

@ -48,16 +48,16 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(set_string_overloads, set_string, 0, 2)
namespace {
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,
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,
commodity_t& in_terms_of,
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)

View file

@ -140,11 +140,6 @@ void report_t::normalize_options(const string& verb)
if (verb == "print")
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')
HANDLER(base).on_only(string("?normalize"));
@ -471,7 +466,7 @@ value_t report_t::fn_market(call_scope_t& scope)
/* add_prices= */ false,
moment);
else
result = args.value_at(0).value(true, moment);
result = args.value_at(0).value(moment);
if (! result.is_null())
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)
{
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;
args.value_at(0)
.print(out, args.get<int>(1),
args.has(2) ? args.get<int>(2) : -1,
args.has(3) ? args.get<bool>(3) : false,
args.has(4) ? args.get<bool>(4) : false);
.print(out, args.get<int>(1), args.has(2) ? args.get<int>(2) : -1, flags);
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);
break;
case 'v':
if (is_eq(p, "value_date"))
return MAKE_FUNCTOR(report_t::fn_now);
break;
case 'w':
if (is_eq(p, "white"))
return WRAP_FUNCTOR(fn_white);

View file

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

View file

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

View file

@ -476,8 +476,7 @@ public:
void in_place_unreduce(); // exists for efficiency's sake
// Return the "market value" of a given value at a specific time.
value_t value(const bool primary_only = false,
const optional<datetime_t>& moment = none,
value_t value(const optional<datetime_t>& moment = none,
const optional<commodity_t&>& in_terms_of = none) const;
value_t price() const;
@ -942,11 +941,11 @@ public:
/**
* Printing methods.
*/
void print(std::ostream& out,
const int first_width = -1,
const int latter_width = -1,
const bool right_justify = false,
const bool colorize = false) const;
void print(std::ostream& out,
const int first_width = -1,
const int latter_width = -1,
const uint_least8_t flags = AMOUNT_PRINT_NO_FLAGS) 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)));
if (post->amount.has_annotation() &&
breakdown.basis_cost.commodity() ==
breakdown.final_cost.commodity()) {
if (amount_t gain_loss = (breakdown.basis_cost -
breakdown.final_cost).rounded()) {
breakdown.basis_cost.commodity() == breakdown.final_cost.commodity()) {
if (amount_t gain_loss = breakdown.basis_cost - breakdown.final_cost) {
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());
@ -293,6 +293,8 @@ bool xact_base_t::finalize()
p->set_state(post->state());
add_post(p);
DEBUG("xact.finalize", "added gain_loss, balance = " << balance);
} else {
DEBUG("xact.finalize", "gain_loss would have display as zero");
}
} else {
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}
Equity:Gold -5000000s
>>>1
1339829c {1.8659s} [2006/03/14]
1339829c {1.8659s} [2006/03/14]
248720c {10.0515s}
1339829c {1.8659s} [2006/03/14]
248720c {10.0515s}
1339829c {1.86590975416s} [2006/03/14]
1339829c {1.86590975416s} [2006/03/14]
248720c {10.051463493s}
1339829c {1.86590975416s} [2006/03/14]
248720c {10.051463493s}
-1388.9h
>>>2
=== 0
@ -19,9 +19,9 @@ reg --format '%(justify(scrub(total_expr), 40, 40, true))\n' --lots-actual
>>>1
1339829c
1339829c
248720c {10.0515s}
248720c {10.051463493s}
1339829c
248720c {10.0515s}
248720c {10.051463493s}
-1388.9h
>>>2
=== 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 €
>>>1
1999/11/01 * Achat
Actif:SSB 125,0000 STK @ 13,37936 $
Actif:SSB 125,0000 STK
Actif:SSB -1672,42 $
1999/11/04 * Vente
Actif:SSB -125,0000 STK @ 15,01288 $
Actif:SSB -125,0000 STK
Dépense:SSB:Commissions 55,07 $
Actif:SSB 1821,54 $

View file

@ -4,16 +4,16 @@
>>>2
While parsing file "$sourcepath/src/amount.h", line 66:
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
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_
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_
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_
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&
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&
=== 7

View file

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

View file

@ -529,4 +529,13 @@ report: all
genhtml -o doc/report doc/report/ledger_cov.info
@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