Merge branch 'next'
This commit is contained in:
commit
290cac7b84
31 changed files with 439 additions and 152 deletions
11
acprep
11
acprep
|
|
@ -124,7 +124,9 @@ class BoostInfo(object):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def locate_boost(self):
|
def locate_boost(self):
|
||||||
for path in map(lambda x: join(x, 'lib'), search_prefixes):
|
lib64_dirs = map(lambda x: join(x, 'lib64'), search_prefixes)
|
||||||
|
lib_dirs = map(lambda x: join(x, 'lib'), search_prefixes)
|
||||||
|
for path in lib64_dirs + lib_dirs:
|
||||||
self.log.info('Looking for Boost in %s...' % path)
|
self.log.info('Looking for Boost in %s...' % path)
|
||||||
self.suffix = self.find_boost_in_directory(path)
|
self.suffix = self.find_boost_in_directory(path)
|
||||||
if self.suffix is not None:
|
if self.suffix is not None:
|
||||||
|
|
@ -685,12 +687,16 @@ class PrepareBuild(CommandLineApp):
|
||||||
self.current_version())
|
self.current_version())
|
||||||
version_m4.close()
|
version_m4.close()
|
||||||
|
|
||||||
|
def copytimes(self, src, dest):
|
||||||
|
os.utime(dest, (os.stat(src)[ST_ATIME], os.stat(src)[ST_MTIME]))
|
||||||
|
|
||||||
def phase_autogen(self, *args):
|
def phase_autogen(self, *args):
|
||||||
self.log.info('Executing phase: autogen')
|
self.log.info('Executing phase: autogen')
|
||||||
|
|
||||||
if not exists('autogen.sh') or \
|
if not exists('autogen.sh') or \
|
||||||
self.isnewer('tools/autogen.sh', 'autogen.sh'):
|
self.isnewer('tools/autogen.sh', 'autogen.sh'):
|
||||||
shutil.copyfile('tools/autogen.sh', 'autogen.sh')
|
shutil.copyfile('tools/autogen.sh', 'autogen.sh')
|
||||||
|
self.copytimes('tools/autogen.sh', 'autogen.sh')
|
||||||
|
|
||||||
self.execute('sh', 'tools/autogen.sh')
|
self.execute('sh', 'tools/autogen.sh')
|
||||||
|
|
||||||
|
|
@ -704,10 +710,12 @@ class PrepareBuild(CommandLineApp):
|
||||||
if not exists('configure.ac') or \
|
if not exists('configure.ac') or \
|
||||||
self.isnewer('tools/configure.ac', 'configure.ac'):
|
self.isnewer('tools/configure.ac', 'configure.ac'):
|
||||||
shutil.copyfile('tools/configure.ac', 'configure.ac')
|
shutil.copyfile('tools/configure.ac', 'configure.ac')
|
||||||
|
self.copytimes('tools/configure.ac', 'configure.ac')
|
||||||
|
|
||||||
if not exists('Makefile.am') or \
|
if not exists('Makefile.am') or \
|
||||||
self.isnewer('tools/Makefile.am', 'Makefile.am'):
|
self.isnewer('tools/Makefile.am', 'Makefile.am'):
|
||||||
shutil.copyfile('tools/Makefile.am', 'Makefile.am')
|
shutil.copyfile('tools/Makefile.am', 'Makefile.am')
|
||||||
|
self.copytimes('tools/Makefile.am', 'Makefile.am')
|
||||||
|
|
||||||
reason = self.need_to_prepare_autotools()
|
reason = self.need_to_prepare_autotools()
|
||||||
if reason:
|
if reason:
|
||||||
|
|
@ -1159,6 +1167,7 @@ class PrepareBuild(CommandLineApp):
|
||||||
self.LDFLAGS.append('-g')
|
self.LDFLAGS.append('-g')
|
||||||
|
|
||||||
def setup_flavor_opt(self):
|
def setup_flavor_opt(self):
|
||||||
|
self.CPPFLAGS.append('-DNDEBUG=1')
|
||||||
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:
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,10 @@ namespace {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_t get_addr(account_t& account) {
|
||||||
|
return long(&account);
|
||||||
|
}
|
||||||
|
|
||||||
value_t get_depth_spacer(account_t& account)
|
value_t get_depth_spacer(account_t& account)
|
||||||
{
|
{
|
||||||
std::size_t depth = 0;
|
std::size_t depth = 0;
|
||||||
|
|
@ -296,6 +300,8 @@ expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_account>);
|
return WRAP_FUNCTOR(get_wrapper<&get_account>);
|
||||||
else if (name == "account_base")
|
else if (name == "account_base")
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_account_base>);
|
return WRAP_FUNCTOR(get_wrapper<&get_account_base>);
|
||||||
|
else if (name == "addr")
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_addr>);
|
||||||
else if (name == "any")
|
else if (name == "any")
|
||||||
return WRAP_FUNCTOR(&fn_any);
|
return WRAP_FUNCTOR(&fn_any);
|
||||||
else if (name == "all")
|
else if (name == "all")
|
||||||
|
|
|
||||||
|
|
@ -149,10 +149,6 @@ namespace {
|
||||||
mpfr_set_prec(tempfb, num_prec + den_prec);
|
mpfr_set_prec(tempfb, num_prec + den_prec);
|
||||||
mpfr_div(tempfb, tempfnum, tempfden, GMP_RNDN);
|
mpfr_div(tempfb, tempfnum, tempfden, GMP_RNDN);
|
||||||
|
|
||||||
char bigbuf[4096];
|
|
||||||
mpfr_sprintf(bigbuf, "%.RNf", tempfb);
|
|
||||||
DEBUG("amount.convert", "num/den = " << bigbuf);
|
|
||||||
|
|
||||||
if (mpfr_asprintf(&buf, "%.*RNf", precision, tempfb) < 0)
|
if (mpfr_asprintf(&buf, "%.*RNf", precision, tempfb) < 0)
|
||||||
throw_(amount_error,
|
throw_(amount_error,
|
||||||
_("Cannot output amount to a floating-point representation"));
|
_("Cannot output amount to a floating-point representation"));
|
||||||
|
|
@ -244,14 +240,18 @@ void amount_t::initialize()
|
||||||
// in terms of seconds, but reported as minutes or hours.
|
// in terms of seconds, but reported as minutes or hours.
|
||||||
if (commodity_t * commodity = commodity_pool_t::current_pool->create("s"))
|
if (commodity_t * commodity = commodity_pool_t::current_pool->create("s"))
|
||||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||||
|
#if !defined(NO_ASSERTS)
|
||||||
else
|
else
|
||||||
assert(false);
|
assert(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Add a "percentile" commodity
|
// Add a "percentile" commodity
|
||||||
if (commodity_t * commodity = commodity_pool_t::current_pool->create("%"))
|
if (commodity_t * commodity = commodity_pool_t::current_pool->create("%"))
|
||||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||||
|
#if !defined(NO_ASSERTS)
|
||||||
else
|
else
|
||||||
assert(false);
|
assert(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
is_initialized = true;
|
is_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
@ -472,7 +472,7 @@ amount_t& amount_t::operator-=(const amount_t& amt)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
amount_t& amount_t::operator*=(const amount_t& amt)
|
amount_t& amount_t::multiply(const amount_t& amt, bool ignore_commodity)
|
||||||
{
|
{
|
||||||
VERIFY(amt.valid());
|
VERIFY(amt.valid());
|
||||||
|
|
||||||
|
|
@ -491,7 +491,7 @@ amount_t& amount_t::operator*=(const amount_t& amt)
|
||||||
quantity->prec =
|
quantity->prec =
|
||||||
static_cast<precision_t>(quantity->prec + amt.quantity->prec);
|
static_cast<precision_t>(quantity->prec + amt.quantity->prec);
|
||||||
|
|
||||||
if (! has_commodity())
|
if (! has_commodity() && ! ignore_commodity)
|
||||||
commodity_ = amt.commodity_;
|
commodity_ = amt.commodity_;
|
||||||
|
|
||||||
if (has_commodity() && ! keep_precision()) {
|
if (has_commodity() && ! keep_precision()) {
|
||||||
|
|
@ -741,24 +741,33 @@ amount_t::value(const bool primary_only,
|
||||||
#endif
|
#endif
|
||||||
if (has_commodity() &&
|
if (has_commodity() &&
|
||||||
(! primary_only || ! commodity().has_flags(COMMODITY_PRIMARY))) {
|
(! primary_only || ! commodity().has_flags(COMMODITY_PRIMARY))) {
|
||||||
if (in_terms_of && commodity() == *in_terms_of) {
|
if (in_terms_of &&
|
||||||
|
commodity().referent() == in_terms_of->referent()) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
else if (has_annotation() && annotation().price &&
|
else if (has_annotation() && annotation().price &&
|
||||||
annotation().has_flags(ANNOTATION_PRICE_FIXATED)) {
|
annotation().has_flags(ANNOTATION_PRICE_FIXATED)) {
|
||||||
return (*annotation().price * number()).rounded();
|
amount_t price(*annotation().price);
|
||||||
|
price.multiply(*this, true);
|
||||||
|
price.in_place_round();
|
||||||
|
return price;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
optional<price_point_t> point =
|
optional<price_point_t> point =
|
||||||
commodity().find_price(in_terms_of, moment);
|
commodity().find_price(in_terms_of, moment);
|
||||||
|
|
||||||
// Whether a price was found or not, check whether we should attempt
|
// Whether a price was found or not, check whether we should
|
||||||
// to download a price from the Internet. This is done if (a) no
|
// attempt to download a price from the Internet. This is done
|
||||||
// price was found, or (b) the price is "stale" according to the
|
// if (a) no price was found, or (b) the price is "stale"
|
||||||
// setting of --price-exp.
|
// according to the setting of --price-exp.
|
||||||
point = commodity().check_for_updated_price(point, moment, in_terms_of);
|
point = commodity().check_for_updated_price(point, moment,
|
||||||
if (point)
|
in_terms_of);
|
||||||
return (point->price * number()).rounded();
|
if (point) {
|
||||||
|
amount_t price(point->price);
|
||||||
|
price.multiply(*this, true);
|
||||||
|
price.in_place_round();
|
||||||
|
return price;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,6 @@ namespace ledger {
|
||||||
class commodity_t;
|
class commodity_t;
|
||||||
class annotation_t;
|
class annotation_t;
|
||||||
class keep_details_t;
|
class keep_details_t;
|
||||||
class commodity_pool_t;
|
|
||||||
|
|
||||||
DECLARE_EXCEPTION(amount_error, std::runtime_error);
|
DECLARE_EXCEPTION(amount_error, std::runtime_error);
|
||||||
|
|
||||||
|
|
@ -275,7 +274,10 @@ public:
|
||||||
|
|
||||||
amount_t& operator+=(const amount_t& amt);
|
amount_t& operator+=(const amount_t& amt);
|
||||||
amount_t& operator-=(const amount_t& amt);
|
amount_t& operator-=(const amount_t& amt);
|
||||||
amount_t& operator*=(const amount_t& amt);
|
amount_t& operator*=(const amount_t& amt) {
|
||||||
|
return multiply(amt);
|
||||||
|
}
|
||||||
|
amount_t& multiply(const amount_t& amt, bool ignore_commodity = false);
|
||||||
|
|
||||||
/** Divide two amounts while extending the precision to preserve the
|
/** Divide two amounts while extending the precision to preserve the
|
||||||
accuracy of the result. For example, if \c 10 is divided by \c 3,
|
accuracy of the result. For example, if \c 10 is divided by \c 3,
|
||||||
|
|
@ -511,7 +513,7 @@ public:
|
||||||
amount's commodity:
|
amount's commodity:
|
||||||
|
|
||||||
commodity() returns an amount's commodity. If the amount has no
|
commodity() returns an amount's commodity. If the amount has no
|
||||||
commodity, the value returned is `current_pool->null_commodity'.
|
commodity, the value returned is the `null_commodity'.
|
||||||
|
|
||||||
has_commodity() returns true if the amount has a commodity.
|
has_commodity() returns true if the amount has a commodity.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep)
|
||||||
keep_date ? details.date : none,
|
keep_date ? details.date : none,
|
||||||
keep_tag ? details.tag : none));
|
keep_tag ? details.tag : none));
|
||||||
} else {
|
} else {
|
||||||
new_comm = pool().find_or_create(base_symbol());
|
new_comm = &referent();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(new_comm);
|
assert(new_comm);
|
||||||
|
|
|
||||||
203
src/commodity.cc
203
src/commodity.cc
|
|
@ -120,12 +120,16 @@ commodity_t::history_t::find_price(const optional<datetime_t>& moment,
|
||||||
price_point_t point;
|
price_point_t point;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
|
#if defined(DEBUG_ON)
|
||||||
#define DEBUG_INDENT(cat, indent) \
|
#define DEBUG_INDENT(cat, indent) \
|
||||||
do { \
|
do { \
|
||||||
if (SHOW_DEBUG(cat)) \
|
if (SHOW_DEBUG(cat)) \
|
||||||
for (int i = 0; i < indent; i++) \
|
for (int i = 0; i < indent; i++) \
|
||||||
ledger::_log_buffer << " "; \
|
ledger::_log_buffer << " "; \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
#else
|
||||||
|
#define DEBUG_INDENT(cat, indent)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(DEBUG_ON)
|
#if defined(DEBUG_ON)
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
|
|
@ -136,38 +140,34 @@ commodity_t::history_t::find_price(const optional<datetime_t>& moment,
|
||||||
|
|
||||||
if (oldest) {
|
if (oldest) {
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " but no older than: " << *oldest);
|
DEBUG("commodity.prices.find", "but no older than: " << *oldest);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (prices.size() == 0) {
|
if (prices.size() == 0) {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " there are no prices in this history");
|
DEBUG("commodity.prices.find", "there are no prices in this history");
|
||||||
#endif
|
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! moment) {
|
if (! moment) {
|
||||||
history_map::const_reverse_iterator r = prices.rbegin();
|
history_map::const_reverse_iterator r = prices.rbegin();
|
||||||
point.when = (*r).first;
|
point.when = (*r).first;
|
||||||
point.price = (*r).second;
|
point.price = (*r).second;
|
||||||
found = true;
|
found = true;
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " using most recent price");
|
DEBUG("commodity.prices.find", "using most recent price");
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
history_map::const_iterator i = prices.lower_bound(*moment);
|
history_map::const_iterator i = prices.upper_bound(*moment);
|
||||||
if (i == prices.end()) {
|
if (i == prices.end()) {
|
||||||
history_map::const_reverse_iterator r = prices.rbegin();
|
history_map::const_reverse_iterator r = prices.rbegin();
|
||||||
point.when = (*r).first;
|
point.when = (*r).first;
|
||||||
point.price = (*r).second;
|
point.price = (*r).second;
|
||||||
found = true;
|
found = true;
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " using last price");
|
DEBUG("commodity.prices.find", "using last price");
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
point.when = (*i).first;
|
point.when = (*i).first;
|
||||||
if (*moment < point.when) {
|
if (*moment < point.when) {
|
||||||
|
|
@ -181,40 +181,31 @@ commodity_t::history_t::find_price(const optional<datetime_t>& moment,
|
||||||
point.price = (*i).second;
|
point.price = (*i).second;
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " using found price");
|
DEBUG("commodity.prices.find", "using found price");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! found) {
|
if (! found) {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " could not find a price");
|
DEBUG("commodity.prices.find", "could not find a price");
|
||||||
#endif
|
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
else if (moment && point.when > *moment) {
|
else if (moment && point.when > *moment) {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " price is too young ");
|
DEBUG("commodity.prices.find", "price is too young ");
|
||||||
#endif
|
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
else if (oldest && point.when < *oldest) {
|
else if (oldest && point.when < *oldest) {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " price is too old ");
|
DEBUG("commodity.prices.find", "price is too old ");
|
||||||
#endif
|
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find",
|
DEBUG("commodity.prices.find",
|
||||||
" returning price: " << point.when << ", " << point.price);
|
"returning price: " << point.when << ", " << point.price);
|
||||||
#endif
|
|
||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +223,13 @@ commodity_t::varied_history_t::find_price(const commodity_t& source,
|
||||||
optional<price_point_t> point;
|
optional<price_point_t> point;
|
||||||
optional<datetime_t> limit = oldest;
|
optional<datetime_t> limit = oldest;
|
||||||
|
|
||||||
assert(! commodity || source != *commodity);
|
#if defined(VERIFY_ON)
|
||||||
|
if (commodity) {
|
||||||
|
VERIFY(source != *commodity);
|
||||||
|
VERIFY(! commodity->has_annotation());
|
||||||
|
VERIFY(source.referent() != commodity->referent());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(DEBUG_ON)
|
#if defined(DEBUG_ON)
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
|
|
@ -240,18 +237,18 @@ commodity_t::varied_history_t::find_price(const commodity_t& source,
|
||||||
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
if (commodity)
|
if (commodity)
|
||||||
DEBUG("commodity.prices.find", " looking for: commodity '" << *commodity << "'");
|
DEBUG("commodity.prices.find", "looking for: commodity '" << *commodity << "'");
|
||||||
else
|
else
|
||||||
DEBUG("commodity.prices.find", " looking for: any commodity");
|
DEBUG("commodity.prices.find", "looking for: any commodity");
|
||||||
|
|
||||||
if (moment) {
|
if (moment) {
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " time index: " << *moment);
|
DEBUG("commodity.prices.find", "time index: " << *moment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldest) {
|
if (oldest) {
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find", " only consider prices younger than: " << *oldest);
|
DEBUG("commodity.prices.find", "only consider prices younger than: " << *oldest);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -262,16 +259,18 @@ commodity_t::varied_history_t::find_price(const commodity_t& source,
|
||||||
price_point_t best;
|
price_point_t best;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
foreach (history_by_commodity_map::value_type hist, histories) {
|
foreach (const history_by_commodity_map::value_type& hist, histories) {
|
||||||
commodity_t& comm(*hist.first);
|
commodity_t& comm(*hist.first);
|
||||||
if (comm == source)
|
if (comm == source)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if defined(DEBUG_ON)
|
// 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 << "'");
|
||||||
#endif
|
|
||||||
|
|
||||||
point = hist.second.find_price(moment, limit
|
point = hist.second.find_price(moment, limit
|
||||||
#if defined(DEBUG_ON)
|
#if defined(DEBUG_ON)
|
||||||
|
|
@ -284,68 +283,59 @@ commodity_t::varied_history_t::find_price(const commodity_t& source,
|
||||||
optional<price_point_t> xlat;
|
optional<price_point_t> xlat;
|
||||||
|
|
||||||
if (commodity && comm != *commodity) {
|
if (commodity && comm != *commodity) {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||||
DEBUG("commodity.prices.find", " looking for translation price");
|
DEBUG("commodity.prices.find", "looking for translation price");
|
||||||
#endif
|
|
||||||
|
|
||||||
xlat = comm.find_price(commodity, moment, limit
|
xlat = comm.find_price(commodity, moment, limit, true
|
||||||
#if defined(DEBUG_ON)
|
#if defined(DEBUG_ON)
|
||||||
, indent + 2
|
, indent + 2
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
if (xlat) {
|
if (xlat) {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||||
DEBUG("commodity.prices.find", " found translated price "
|
DEBUG("commodity.prices.find", "found translated price "
|
||||||
<< xlat->price << " from " << xlat->when);
|
<< xlat->price << " from " << xlat->when);
|
||||||
#endif
|
|
||||||
|
|
||||||
point->price = xlat->price * point->price;
|
point->price = xlat->price * point->price;
|
||||||
if (xlat->when < point->when) {
|
if (xlat->when < point->when) {
|
||||||
point->when = xlat->when;
|
point->when = xlat->when;
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||||
DEBUG("commodity.prices.find",
|
DEBUG("commodity.prices.find",
|
||||||
" adjusting date of result back to " << point->when);
|
"adjusting date of result back to " << point->when);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||||
DEBUG("commodity.prices.find", " saw no translated price there");
|
DEBUG("commodity.prices.find", "saw no translated price there");
|
||||||
#endif
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(! commodity || point->price.commodity() == *commodity);
|
assert(! commodity || point->price.commodity() == *commodity);
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||||
DEBUG("commodity.prices.find",
|
DEBUG("commodity.prices.find",
|
||||||
" saw a price there: " << point->price << " from " << point->when);
|
"saw a price there: " << point->price << " from " << point->when);
|
||||||
#endif
|
|
||||||
if (! limit || point->when > *limit) {
|
if (! limit || point->when > *limit) {
|
||||||
limit = point->when;
|
limit = point->when;
|
||||||
best = *point;
|
best = *point;
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
|
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||||
|
DEBUG("commodity.prices.find",
|
||||||
|
"search limit adjusted to " << *limit);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||||
DEBUG("commodity.prices.find", " saw no price there");
|
DEBUG("commodity.prices.find", "saw no price there");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
DEBUG_INDENT("commodity.prices.find", indent);
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
DEBUG("commodity.prices.find",
|
|
||||||
" found price " << best.price << " from " << best.when);
|
|
||||||
DEBUG("commodity.download",
|
DEBUG("commodity.download",
|
||||||
"found price " << best.price << " from " << best.when);
|
"found price " << best.price << " from " << best.when);
|
||||||
#endif
|
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
return none;
|
return none;
|
||||||
|
|
@ -370,6 +360,97 @@ commodity_t::varied_history_t::history(const optional<commodity_t&>& commodity)
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional<price_point_t>
|
||||||
|
commodity_t::find_price(const optional<commodity_t&>& commodity,
|
||||||
|
const optional<datetime_t>& moment,
|
||||||
|
const optional<datetime_t>& oldest,
|
||||||
|
const bool nested
|
||||||
|
#if defined(DEBUG_ON)
|
||||||
|
, const int indent
|
||||||
|
#endif
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
if (! has_flags(COMMODITY_WALKED) && base->varied_history &&
|
||||||
|
(commodity || ! has_flags(COMMODITY_PRIMARY))) {
|
||||||
|
optional<base_t::time_and_commodity_t> pair;
|
||||||
|
#if defined(VERIFY_ON)
|
||||||
|
optional<price_point_t> checkpoint;
|
||||||
|
bool found = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (! nested) {
|
||||||
|
pair = base_t::time_and_commodity_t
|
||||||
|
(base_t::optional_time_pair_t(moment, oldest),
|
||||||
|
commodity ? &(*commodity) : NULL);
|
||||||
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
|
DEBUG("commodity.prices.find", "looking for memoized args: "
|
||||||
|
<< (moment ? format_datetime(*moment) : "NONE") << ", "
|
||||||
|
<< (oldest ? format_datetime(*oldest) : "NONE") << ", "
|
||||||
|
<< (commodity ? commodity->symbol() : "NONE"));
|
||||||
|
|
||||||
|
base_t::memoized_price_map::iterator i = base->price_map.find(*pair);
|
||||||
|
if (i != base->price_map.end()) {
|
||||||
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
|
DEBUG("commodity.prices.find", "found! returning: "
|
||||||
|
<< ((*i).second ? (*i).second->price : amount_t(0L)));
|
||||||
|
#if defined(VERIFY_ON)
|
||||||
|
IF_VERIFY() {
|
||||||
|
found = true;
|
||||||
|
checkpoint = (*i).second;
|
||||||
|
} else
|
||||||
|
#endif // defined(VERIFY_ON)
|
||||||
|
return (*i).second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<price_point_t> point;
|
||||||
|
|
||||||
|
const_cast<commodity_t&>(*this).add_flags(COMMODITY_WALKED);
|
||||||
|
try {
|
||||||
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
|
DEBUG("commodity.prices.find", "manually finding price...");
|
||||||
|
|
||||||
|
point = base->varied_history->find_price(*this, commodity,
|
||||||
|
moment, oldest
|
||||||
|
#if defined(DEBUG_ON)
|
||||||
|
, indent
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
const_cast<commodity_t&>(*this).drop_flags(COMMODITY_WALKED);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
const_cast<commodity_t&>(*this).drop_flags(COMMODITY_WALKED);
|
||||||
|
|
||||||
|
#if defined(VERIFY_ON)
|
||||||
|
if (DO_VERIFY() && found) {
|
||||||
|
VERIFY(checkpoint == point);
|
||||||
|
return checkpoint;
|
||||||
|
}
|
||||||
|
#endif // defined(VERIFY_ON)
|
||||||
|
|
||||||
|
if (! nested && pair) {
|
||||||
|
if (base->price_map.size() > base_t::max_price_map_size) {
|
||||||
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
|
DEBUG("commodity.prices.find",
|
||||||
|
"price map has grown too large, clearing it by half");
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < base_t::max_price_map_size >> 1; i++)
|
||||||
|
base->price_map.erase(base->price_map.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_INDENT("commodity.prices.find", indent);
|
||||||
|
DEBUG("commodity.prices.find",
|
||||||
|
"remembered: " << (point ? point->price : amount_t(0L)));
|
||||||
|
base->price_map.insert
|
||||||
|
(base_t::memoized_price_map::value_type(*pair, point));
|
||||||
|
}
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
optional<price_point_t>
|
optional<price_point_t>
|
||||||
commodity_t::check_for_updated_price(const optional<price_point_t>& point,
|
commodity_t::check_for_updated_price(const optional<price_point_t>& point,
|
||||||
const optional<datetime_t>& moment,
|
const optional<datetime_t>& moment,
|
||||||
|
|
@ -428,9 +509,7 @@ namespace {
|
||||||
{
|
{
|
||||||
switch (buf[0]) {
|
switch (buf[0]) {
|
||||||
case 'a':
|
case 'a':
|
||||||
return (std::strcmp(buf, "and") == 0 ||
|
return std::strcmp(buf, "and") == 0;
|
||||||
std::strcmp(buf, "any") == 0 ||
|
|
||||||
std::strcmp(buf, "all") == 0);
|
|
||||||
case 'd':
|
case 'd':
|
||||||
return std::strcmp(buf, "div") == 0;
|
return std::strcmp(buf, "div") == 0;
|
||||||
case 'e':
|
case 'e':
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
class keep_details_t;
|
class keep_details_t;
|
||||||
|
class commodity_pool_t;
|
||||||
|
|
||||||
DECLARE_EXCEPTION(commodity_error, std::runtime_error);
|
DECLARE_EXCEPTION(commodity_error, std::runtime_error);
|
||||||
|
|
||||||
|
|
@ -58,6 +59,10 @@ struct price_point_t
|
||||||
datetime_t when;
|
datetime_t when;
|
||||||
amount_t price;
|
amount_t price;
|
||||||
|
|
||||||
|
bool operator==(const price_point_t& other) const {
|
||||||
|
return when == other.when && price == other.price;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||||
private:
|
private:
|
||||||
/** Serialization. */
|
/** Serialization. */
|
||||||
|
|
@ -174,6 +179,16 @@ protected:
|
||||||
optional<amount_t> smaller;
|
optional<amount_t> smaller;
|
||||||
optional<amount_t> larger;
|
optional<amount_t> larger;
|
||||||
|
|
||||||
|
typedef std::pair<optional<datetime_t>,
|
||||||
|
optional<datetime_t> > optional_time_pair_t;
|
||||||
|
typedef std::pair<optional_time_pair_t,
|
||||||
|
commodity_t *> time_and_commodity_t;
|
||||||
|
typedef std::map<time_and_commodity_t,
|
||||||
|
optional<price_point_t> > memoized_price_map;
|
||||||
|
|
||||||
|
static const std::size_t max_price_map_size = 16;
|
||||||
|
mutable memoized_price_map price_map;
|
||||||
|
|
||||||
mutable bool searched;
|
mutable bool searched;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -333,36 +348,28 @@ public:
|
||||||
const bool reflexive = true) {
|
const bool reflexive = true) {
|
||||||
if (! base->varied_history)
|
if (! base->varied_history)
|
||||||
base->varied_history = varied_history_t();
|
base->varied_history = varied_history_t();
|
||||||
|
|
||||||
base->varied_history->add_price(*this, date, price, reflexive);
|
base->varied_history->add_price(*this, date, price, reflexive);
|
||||||
|
DEBUG("commodity.prices.find", "Price added, clearing price_map");
|
||||||
|
base->price_map.clear(); // a price was added, invalid the map
|
||||||
}
|
}
|
||||||
bool remove_price(const datetime_t& date, commodity_t& commodity) {
|
bool remove_price(const datetime_t& date, commodity_t& commodity) {
|
||||||
if (base->varied_history)
|
if (base->varied_history) {
|
||||||
base->varied_history->remove_price(date, commodity);
|
base->varied_history->remove_price(date, commodity);
|
||||||
|
DEBUG("commodity.prices.find", "Price removed, clearing price_map");
|
||||||
|
base->price_map.clear(); // a price was added, invalid the map
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<price_point_t>
|
optional<price_point_t>
|
||||||
find_price(const optional<commodity_t&>& commodity = none,
|
find_price(const optional<commodity_t&>& commodity = none,
|
||||||
const optional<datetime_t>& moment = none,
|
const optional<datetime_t>& moment = none,
|
||||||
const optional<datetime_t>& oldest = none
|
const optional<datetime_t>& oldest = none,
|
||||||
|
const bool nested = false
|
||||||
#if defined(DEBUG_ON)
|
#if defined(DEBUG_ON)
|
||||||
, const int indent = 0
|
, const int indent = 0
|
||||||
#endif
|
#endif
|
||||||
) const {
|
) const;
|
||||||
if (base->varied_history && ! has_flags(COMMODITY_WALKED)) {
|
|
||||||
const_cast<commodity_t&>(*this).add_flags(COMMODITY_WALKED);
|
|
||||||
optional<price_point_t> point =
|
|
||||||
base->varied_history->find_price(*this, commodity, moment, oldest
|
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
, indent
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
const_cast<commodity_t&>(*this).drop_flags(COMMODITY_WALKED);
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
return none;
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<price_point_t>
|
optional<price_point_t>
|
||||||
check_for_updated_price(const optional<price_point_t>& point,
|
check_for_updated_price(const optional<price_point_t>& point,
|
||||||
|
|
|
||||||
|
|
@ -155,17 +155,21 @@ public:
|
||||||
result_type calc(scope_t& scope)
|
result_type calc(scope_t& scope)
|
||||||
{
|
{
|
||||||
if (! compiled) {
|
if (! compiled) {
|
||||||
|
#if defined(DEBUG_ON)
|
||||||
if (SHOW_DEBUG("expr.compile")) {
|
if (SHOW_DEBUG("expr.compile")) {
|
||||||
DEBUG("expr.compile", "Before compilation:");
|
DEBUG("expr.compile", "Before compilation:");
|
||||||
dump(*_log_stream);
|
dump(*_log_stream);
|
||||||
}
|
}
|
||||||
|
#endif // defined(DEBUG_ON)
|
||||||
|
|
||||||
compile(scope);
|
compile(scope);
|
||||||
|
|
||||||
|
#if defined(DEBUG_ON)
|
||||||
if (SHOW_DEBUG("expr.compile")) {
|
if (SHOW_DEBUG("expr.compile")) {
|
||||||
DEBUG("expr.compile", "After compilation:");
|
DEBUG("expr.compile", "After compilation:");
|
||||||
dump(*_log_stream);
|
dump(*_log_stream);
|
||||||
}
|
}
|
||||||
|
#endif // defined(DEBUG_ON)
|
||||||
}
|
}
|
||||||
|
|
||||||
return real_calc(scope);
|
return real_calc(scope);
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ void post_splitter::print_title(const value_t& val)
|
||||||
|
|
||||||
void post_splitter::flush()
|
void post_splitter::flush()
|
||||||
{
|
{
|
||||||
foreach (value_to_posts_map::value_type pair, posts_map) {
|
foreach (value_to_posts_map::value_type& pair, posts_map) {
|
||||||
preflush_func(pair.first);
|
preflush_func(pair.first);
|
||||||
|
|
||||||
foreach (post_t * post, pair.second)
|
foreach (post_t * post, pair.second)
|
||||||
|
|
@ -256,6 +256,7 @@ void anonymize_posts::operator()(post_t& post)
|
||||||
create_temp_account_from_path(account_names, temps, xact.journal->master);
|
create_temp_account_from_path(account_names, temps, xact.journal->master);
|
||||||
post_t& temp = temps.copy_post(post, xact, new_account);
|
post_t& temp = temps.copy_post(post, xact, new_account);
|
||||||
temp.note = none;
|
temp.note = none;
|
||||||
|
temp.add_flags(POST_ANONYMIZED);
|
||||||
|
|
||||||
(*handler)(temp);
|
(*handler)(temp);
|
||||||
}
|
}
|
||||||
|
|
@ -894,7 +895,7 @@ void posts_as_equity::report_subtotal()
|
||||||
value_t total = 0L;
|
value_t total = 0L;
|
||||||
foreach (values_map::value_type& pair, values) {
|
foreach (values_map::value_type& pair, values) {
|
||||||
if (pair.second.value.is_balance()) {
|
if (pair.second.value.is_balance()) {
|
||||||
foreach (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(amount_pair.second, pair.second.account, &xact, temps,
|
handle_value(amount_pair.second, pair.second.account, &xact, temps,
|
||||||
handler);
|
handler);
|
||||||
|
|
@ -907,7 +908,7 @@ void posts_as_equity::report_subtotal()
|
||||||
values.clear();
|
values.clear();
|
||||||
|
|
||||||
if (total.is_balance()) {
|
if (total.is_balance()) {
|
||||||
foreach (balance_t::amounts_map::value_type pair,
|
foreach (const balance_t::amounts_map::value_type& pair,
|
||||||
total.as_balance().amounts) {
|
total.as_balance().amounts) {
|
||||||
post_t& balance_post = temps.create_post(xact, balance_account);
|
post_t& balance_post = temps.create_post(xact, balance_account);
|
||||||
balance_post.amount = - pair.second;
|
balance_post.amount = - pair.second;
|
||||||
|
|
@ -1166,8 +1167,10 @@ void forecast_posts::flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
date_t& begin = *(*least).first.start;
|
date_t& begin = *(*least).first.start;
|
||||||
|
#if !defined(NO_ASSERTS)
|
||||||
if ((*least).first.finish)
|
if ((*least).first.finish)
|
||||||
assert(begin < *(*least).first.finish);
|
assert(begin < *(*least).first.finish);
|
||||||
|
#endif
|
||||||
|
|
||||||
// If the next date in the series for this periodic posting is more than 5
|
// If the next date in the series for this periodic posting is more than 5
|
||||||
// years beyond the last valid post we generated, drop it from further
|
// years beyond the last valid post we generated, drop it from further
|
||||||
|
|
|
||||||
|
|
@ -226,16 +226,12 @@ class sort_posts : public item_handler<post_t>
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sort_posts(post_handler_ptr handler, const expr_t& _sort_order)
|
sort_posts(post_handler_ptr handler, const expr_t& _sort_order)
|
||||||
: item_handler<post_t>(handler),
|
: item_handler<post_t>(handler), sort_order(_sort_order) {
|
||||||
sort_order(_sort_order) {
|
TRACE_CTOR(sort_posts, "post_handler_ptr, const value_expr&");
|
||||||
TRACE_CTOR(sort_posts,
|
|
||||||
"post_handler_ptr, const value_expr&");
|
|
||||||
}
|
}
|
||||||
sort_posts(post_handler_ptr handler, const string& _sort_order)
|
sort_posts(post_handler_ptr handler, const string& _sort_order)
|
||||||
: item_handler<post_t>(handler),
|
: item_handler<post_t>(handler), sort_order(_sort_order) {
|
||||||
sort_order(_sort_order) {
|
TRACE_CTOR(sort_posts, "post_handler_ptr, const string&");
|
||||||
TRACE_CTOR(sort_posts,
|
|
||||||
"post_handler_ptr, const string&");
|
|
||||||
}
|
}
|
||||||
virtual ~sort_posts() {
|
virtual ~sort_posts() {
|
||||||
TRACE_DTOR(sort_posts);
|
TRACE_DTOR(sort_posts);
|
||||||
|
|
|
||||||
|
|
@ -391,11 +391,13 @@ global_scope_t::read_command_arguments(scope_t& scope, strings_list args)
|
||||||
|
|
||||||
void global_scope_t::normalize_session_options()
|
void global_scope_t::normalize_session_options()
|
||||||
{
|
{
|
||||||
|
#if defined(LOGGING_ON)
|
||||||
INFO("Initialization file is " << HANDLER(init_file_).str());
|
INFO("Initialization file is " << HANDLER(init_file_).str());
|
||||||
INFO("Price database is " << session().HANDLER(price_db_).str());
|
INFO("Price database is " << session().HANDLER(price_db_).str());
|
||||||
|
|
||||||
foreach (const path& pathname, session().HANDLER(file_).data_files)
|
foreach (const path& pathname, session().HANDLER(file_).data_files)
|
||||||
INFO("Journal file is " << pathname.string());
|
INFO("Journal file is " << pathname.string());
|
||||||
|
#endif // defined(LOGGING_ON)
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::func_t global_scope_t::look_for_precommand(scope_t& scope,
|
expr_t::func_t global_scope_t::look_for_precommand(scope_t& scope,
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,10 @@ namespace {
|
||||||
return item.pos ? long(item.pos->sequence) : 0L;
|
return item.pos ? long(item.pos->sequence) : 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_t get_addr(item_t& item) {
|
||||||
|
return long(&item);
|
||||||
|
}
|
||||||
|
|
||||||
value_t get_depth(item_t&) {
|
value_t get_depth(item_t&) {
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
@ -376,6 +380,8 @@ expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind,
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_actual>);
|
return WRAP_FUNCTOR(get_wrapper<&get_actual>);
|
||||||
else if (name == "actual_date")
|
else if (name == "actual_date")
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_actual_date>);
|
return WRAP_FUNCTOR(get_wrapper<&get_actual_date>);
|
||||||
|
else if (name == "addr")
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_addr>);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
|
|
|
||||||
|
|
@ -94,9 +94,9 @@ void posts_commodities_iterator::reset(journal_t& journal)
|
||||||
comm->varied_history()) {
|
comm->varied_history()) {
|
||||||
account_t * account = journal.master->find_account(comm->symbol());
|
account_t * account = journal.master->find_account(comm->symbol());
|
||||||
|
|
||||||
foreach (commodity_t::history_by_commodity_map::value_type pair,
|
foreach (commodity_t::history_by_commodity_map::value_type& pair,
|
||||||
history->histories) {
|
history->histories) {
|
||||||
foreach (commodity_t::history_map::value_type hpair,
|
foreach (commodity_t::history_map::value_type& hpair,
|
||||||
pair.second.prices) {
|
pair.second.prices) {
|
||||||
xact_t * xact;
|
xact_t * xact;
|
||||||
string symbol = hpair.second.commodity().symbol();
|
string symbol = hpair.second.commodity().symbol();
|
||||||
|
|
|
||||||
|
|
@ -78,10 +78,12 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
|
||||||
// Identifier references are first looked up at the point of
|
// Identifier references are first looked up at the point of
|
||||||
// definition, and then at the point of every use if they could
|
// definition, and then at the point of every use if they could
|
||||||
// not be found there.
|
// not be found there.
|
||||||
|
#if defined(DEBUG_ON)
|
||||||
if (SHOW_DEBUG("expr.compile")) {
|
if (SHOW_DEBUG("expr.compile")) {
|
||||||
DEBUG("expr.compile", "Found definition:");
|
DEBUG("expr.compile", "Found definition:");
|
||||||
def->dump(*_log_stream, 0);
|
def->dump(*_log_stream, 0);
|
||||||
}
|
}
|
||||||
|
#endif // defined(DEBUG_ON)
|
||||||
return copy(def);
|
return copy(def);
|
||||||
}
|
}
|
||||||
else if (left()) {
|
else if (left()) {
|
||||||
|
|
|
||||||
|
|
@ -61,10 +61,16 @@ class expr_t::parser_t : public noncopyable
|
||||||
return lookahead;
|
return lookahead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(NO_ASSERTS)
|
||||||
void push_token(const token_t& tok) const {
|
void push_token(const token_t& tok) const {
|
||||||
assert(&tok == &lookahead);
|
assert(&tok == &lookahead);
|
||||||
use_lookahead = true;
|
use_lookahead = true;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void push_token(const token_t&) const {
|
||||||
|
use_lookahead = true;
|
||||||
|
}
|
||||||
|
#endif // !defined(NO_ASSERTS)
|
||||||
void push_token() const {
|
void push_token() const {
|
||||||
use_lookahead = true;
|
use_lookahead = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
79
src/pool.cc
79
src/pool.cc
|
|
@ -122,8 +122,11 @@ string commodity_pool_t::make_qualified_name(const commodity_t& comm,
|
||||||
comm.print(name);
|
comm.print(name);
|
||||||
details.print(name, comm.pool().keep_base);
|
details.print(name, comm.pool().keep_base);
|
||||||
|
|
||||||
DEBUG("amounts.commodities", "make_qualified_name for "
|
#if defined(DEBUG_ON)
|
||||||
<< *comm.qualified_symbol << std::endl << details);
|
if (comm.qualified_symbol)
|
||||||
|
DEBUG("amounts.commodities", "make_qualified_name for "
|
||||||
|
<< *comm.qualified_symbol << std::endl << details);
|
||||||
|
#endif
|
||||||
DEBUG("amounts.commodities", "qualified_name is " << name.str());
|
DEBUG("amounts.commodities", "qualified_name is " << name.str());
|
||||||
|
|
||||||
return name.str();
|
return name.str();
|
||||||
|
|
@ -361,4 +364,76 @@ commodity_pool_t::parse_price_expression(const std::string& str,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void commodity_pool_t::print_pricemap(std::ostream& out,
|
||||||
|
const keep_details_t& keep,
|
||||||
|
const optional<datetime_t>& moment)
|
||||||
|
{
|
||||||
|
typedef std::map<commodity_t *, commodity_t *> comm_map_t;
|
||||||
|
|
||||||
|
comm_map_t comm_map;
|
||||||
|
|
||||||
|
foreach (const commodities_map::value_type& comm_pair, commodities) {
|
||||||
|
commodity_t * comm(&comm_pair.second->strip_annotations(keep));
|
||||||
|
comm_map.insert(comm_map_t::value_type(comm, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "digraph commodities {\n";
|
||||||
|
|
||||||
|
foreach (const comm_map_t::value_type& comm_pair, comm_map) {
|
||||||
|
commodity_t * comm(comm_pair.first);
|
||||||
|
if (comm->has_flags(COMMODITY_BUILTIN))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
out << " ";
|
||||||
|
if (commodity_t::symbol_needs_quotes(comm->symbol()))
|
||||||
|
out << comm->symbol() << ";\n";
|
||||||
|
else
|
||||||
|
out << "\"" << comm->symbol() << "\";\n";
|
||||||
|
|
||||||
|
if (! comm->has_flags(COMMODITY_NOMARKET) &&
|
||||||
|
(! commodity_pool_t::current_pool->default_commodity ||
|
||||||
|
comm != commodity_pool_t::current_pool->default_commodity)) {
|
||||||
|
if (optional<commodity_t::varied_history_t&> vhist =
|
||||||
|
comm->varied_history()) {
|
||||||
|
foreach (const commodity_t::history_by_commodity_map::value_type& pair,
|
||||||
|
vhist->histories) {
|
||||||
|
datetime_t most_recent;
|
||||||
|
amount_t most_recent_amt;
|
||||||
|
foreach (const commodity_t::history_map::value_type& inner_pair,
|
||||||
|
pair.second.prices) {
|
||||||
|
if ((most_recent.is_not_a_date_time() ||
|
||||||
|
inner_pair.first > most_recent) &&
|
||||||
|
(! moment || inner_pair.first <= moment)) {
|
||||||
|
most_recent = inner_pair.first;
|
||||||
|
most_recent_amt = inner_pair.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! most_recent.is_not_a_date_time()) {
|
||||||
|
out << " ";
|
||||||
|
if (commodity_t::symbol_needs_quotes(comm->symbol()))
|
||||||
|
out << comm->symbol();
|
||||||
|
else
|
||||||
|
out << "\"" << comm->symbol() << "\"";
|
||||||
|
|
||||||
|
out << " -> ";
|
||||||
|
|
||||||
|
if (commodity_t::symbol_needs_quotes(pair.first->symbol()))
|
||||||
|
out << pair.first->symbol();
|
||||||
|
else
|
||||||
|
out << "\"" << pair.first->symbol() << "\"";
|
||||||
|
|
||||||
|
out << " [label=\""
|
||||||
|
<< most_recent_amt.number() << "\\n"
|
||||||
|
<< format_date(most_recent.date(), FMT_WRITTEN)
|
||||||
|
<< "\" fontcolor=\"#008e28\"];\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ public:
|
||||||
|
|
||||||
virtual ~commodity_pool_t() {
|
virtual ~commodity_pool_t() {
|
||||||
TRACE_DTOR(commodity_pool_t);
|
TRACE_DTOR(commodity_pool_t);
|
||||||
foreach (commodities_map::value_type pair, commodities)
|
foreach (commodities_map::value_type& pair, commodities)
|
||||||
checked_delete(pair.second);
|
checked_delete(pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,6 +131,12 @@ public:
|
||||||
const bool add_prices = true,
|
const bool add_prices = true,
|
||||||
const optional<datetime_t>& moment = none);
|
const optional<datetime_t>& moment = none);
|
||||||
|
|
||||||
|
// Output the commodity price map for a given date as a DOT file
|
||||||
|
|
||||||
|
void print_pricemap(std::ostream& out,
|
||||||
|
const keep_details_t& keep,
|
||||||
|
const optional<datetime_t>& moment = none);
|
||||||
|
|
||||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||||
private:
|
private:
|
||||||
/** Serialization. */
|
/** Serialization. */
|
||||||
|
|
|
||||||
11
src/post.h
11
src/post.h
|
|
@ -52,11 +52,12 @@ class account_t;
|
||||||
class post_t : public item_t
|
class post_t : public item_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#define POST_VIRTUAL 0x08 // the account was specified with (parens)
|
#define POST_VIRTUAL 0x04 // the account was specified with (parens)
|
||||||
#define POST_MUST_BALANCE 0x10 // posting must balance in the transaction
|
#define POST_MUST_BALANCE 0x08 // posting must balance in the transaction
|
||||||
#define POST_CALCULATED 0x20 // posting's amount was calculated
|
#define POST_CALCULATED 0x10 // posting's amount was calculated
|
||||||
#define POST_COST_CALCULATED 0x40 // posting's cost was calculated
|
#define POST_COST_CALCULATED 0x20 // posting's cost was calculated
|
||||||
#define POST_COST_IN_FULL 0x80 // cost specified using @@
|
#define POST_COST_IN_FULL 0x40 // cost specified using @@
|
||||||
|
#define POST_ANONYMIZED 0x80 // a temporary, anonymous posting
|
||||||
|
|
||||||
xact_t * xact; // only set for posts of regular xacts
|
xact_t * xact; // only set for posts of regular xacts
|
||||||
account_t * account;
|
account_t * account;
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ namespace {
|
||||||
|
|
||||||
foreach (post_t * post, xact.posts) {
|
foreach (post_t * post, xact.posts) {
|
||||||
if (post->has_flags(ITEM_TEMP | ITEM_GENERATED) &&
|
if (post->has_flags(ITEM_TEMP | ITEM_GENERATED) &&
|
||||||
|
! post->has_flags(POST_ANONYMIZED) &&
|
||||||
! report.HANDLED(print_virtual))
|
! report.HANDLED(print_virtual))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,10 @@ struct string_from_python
|
||||||
utf8::unchecked::utf16to8(value, value + size, std::back_inserter(str));
|
utf8::unchecked::utf16to8(value, value + size, std::back_inserter(str));
|
||||||
else if (sizeof(Py_UNICODE) == 4) // UTF-32
|
else if (sizeof(Py_UNICODE) == 4) // UTF-32
|
||||||
utf8::unchecked::utf32to8(value, value + size, std::back_inserter(str));
|
utf8::unchecked::utf32to8(value, value + size, std::back_inserter(str));
|
||||||
|
#if !defined(NO_ASSERTS)
|
||||||
else
|
else
|
||||||
assert(! "Py_UNICODE has an unexpected size");
|
assert(! "Py_UNICODE has an unexpected size");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (value == 0) throw_error_already_set();
|
if (value == 0) throw_error_already_set();
|
||||||
void* storage =
|
void* storage =
|
||||||
|
|
|
||||||
|
|
@ -842,6 +842,18 @@ value_t report_t::echo_command(call_scope_t& scope)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_t report_t::pricemap_command(call_scope_t& scope)
|
||||||
|
{
|
||||||
|
interactive_t args(scope, "&s");
|
||||||
|
std::ostream& out(output_stream);
|
||||||
|
|
||||||
|
commodity_pool_t::current_pool->print_pricemap
|
||||||
|
(out, what_to_keep(), args.has(0) ?
|
||||||
|
optional<datetime_t>(datetime_t(parse_date(args.get<string>(0)))) : none);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
option_t<report_t> * report_t::lookup_option(const char * p)
|
option_t<report_t> * report_t::lookup_option(const char * p)
|
||||||
{
|
{
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
|
|
@ -1318,9 +1330,10 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
|
||||||
case symbol_t::COMMAND:
|
case symbol_t::COMMAND:
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'a':
|
case 'a':
|
||||||
if (is_eq(p, "accounts"))
|
if (is_eq(p, "accounts")) {
|
||||||
return WRAP_FUNCTOR(reporter<>(new report_accounts(*this), *this,
|
return WRAP_FUNCTOR(reporter<>(new report_accounts(*this), *this,
|
||||||
"#accounts"));
|
"#accounts"));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
|
|
@ -1381,48 +1394,60 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
|
||||||
HANDLER(print_virtual).on_only(string("#equity"));
|
HANDLER(print_virtual).on_only(string("#equity"));
|
||||||
return WRAP_FUNCTOR(reporter<>(new print_xacts(*this), *this, "#equity"));
|
return WRAP_FUNCTOR(reporter<>(new print_xacts(*this), *this, "#equity"));
|
||||||
}
|
}
|
||||||
else if (is_eq(p, "entry"))
|
else if (is_eq(p, "entry")) {
|
||||||
return WRAP_FUNCTOR(xact_command);
|
return WRAP_FUNCTOR(xact_command);
|
||||||
else if (is_eq(p, "emacs"))
|
}
|
||||||
|
else if (is_eq(p, "emacs")) {
|
||||||
return WRAP_FUNCTOR
|
return WRAP_FUNCTOR
|
||||||
(reporter<>(new format_emacs_posts(output_stream), *this, "#emacs"));
|
(reporter<>(new format_emacs_posts(output_stream), *this, "#emacs"));
|
||||||
else if (is_eq(p, "echo"))
|
}
|
||||||
|
else if (is_eq(p, "echo")) {
|
||||||
return MAKE_FUNCTOR(report_t::echo_command);
|
return MAKE_FUNCTOR(report_t::echo_command);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (*(p + 1) == '\0' || is_eq(p, "print"))
|
if (*(p + 1) == '\0' || is_eq(p, "print")) {
|
||||||
return WRAP_FUNCTOR
|
return WRAP_FUNCTOR
|
||||||
(reporter<>(new print_xacts(*this, HANDLED(raw)), *this, "#print"));
|
(reporter<>(new print_xacts(*this, HANDLED(raw)), *this, "#print"));
|
||||||
else if (is_eq(p, "prices"))
|
}
|
||||||
|
else if (is_eq(p, "prices")) {
|
||||||
return expr_t::op_t::wrap_functor
|
return expr_t::op_t::wrap_functor
|
||||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||||
(new format_posts(*this, report_format(HANDLER(prices_format_)),
|
(new format_posts(*this, report_format(HANDLER(prices_format_)),
|
||||||
maybe_format(HANDLER(prepend_format_)),
|
maybe_format(HANDLER(prepend_format_)),
|
||||||
HANDLER(prepend_width_).value.to_long()),
|
HANDLER(prepend_width_).value.to_long()),
|
||||||
*this, "#prices"));
|
*this, "#prices"));
|
||||||
else if (is_eq(p, "pricedb"))
|
}
|
||||||
|
else if (is_eq(p, "pricedb")) {
|
||||||
return expr_t::op_t::wrap_functor
|
return expr_t::op_t::wrap_functor
|
||||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||||
(new format_posts(*this, report_format(HANDLER(pricedb_format_)),
|
(new format_posts(*this, report_format(HANDLER(pricedb_format_)),
|
||||||
maybe_format(HANDLER(prepend_format_)),
|
maybe_format(HANDLER(prepend_format_)),
|
||||||
HANDLER(prepend_width_).value.to_long()),
|
HANDLER(prepend_width_).value.to_long()),
|
||||||
*this, "#pricedb"));
|
*this, "#pricedb"));
|
||||||
else if (is_eq(p, "payees"))
|
}
|
||||||
|
else if (is_eq(p, "pricemap")) {
|
||||||
|
return MAKE_FUNCTOR(report_t::pricemap_command);
|
||||||
|
}
|
||||||
|
else if (is_eq(p, "payees")) {
|
||||||
return WRAP_FUNCTOR(reporter<>(new report_payees(*this), *this,
|
return WRAP_FUNCTOR(reporter<>(new report_payees(*this), *this,
|
||||||
"#payees"));
|
"#payees"));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register"))
|
if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register")) {
|
||||||
return WRAP_FUNCTOR
|
return WRAP_FUNCTOR
|
||||||
(reporter<>
|
(reporter<>
|
||||||
(new format_posts(*this, report_format(HANDLER(register_format_)),
|
(new format_posts(*this, report_format(HANDLER(register_format_)),
|
||||||
maybe_format(HANDLER(prepend_format_)),
|
maybe_format(HANDLER(prepend_format_)),
|
||||||
HANDLER(prepend_width_).value.to_long()),
|
HANDLER(prepend_width_).value.to_long()),
|
||||||
*this, "#register"));
|
*this, "#register"));
|
||||||
else if (is_eq(p, "reload"))
|
}
|
||||||
|
else if (is_eq(p, "reload")) {
|
||||||
return MAKE_FUNCTOR(report_t::reload_command);
|
return MAKE_FUNCTOR(report_t::reload_command);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
|
|
@ -1448,6 +1473,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
|
||||||
case 'e':
|
case 'e':
|
||||||
if (is_eq(p, "eval"))
|
if (is_eq(p, "eval"))
|
||||||
return WRAP_FUNCTOR(eval_command);
|
return WRAP_FUNCTOR(eval_command);
|
||||||
|
else if (is_eq(p, "expr"))
|
||||||
|
return WRAP_FUNCTOR(parse_command);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
if (is_eq(p, "format"))
|
if (is_eq(p, "format"))
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,7 @@ public:
|
||||||
|
|
||||||
value_t reload_command(call_scope_t&);
|
value_t reload_command(call_scope_t&);
|
||||||
value_t echo_command(call_scope_t& scope);
|
value_t echo_command(call_scope_t& scope);
|
||||||
|
value_t pricemap_command(call_scope_t& scope);
|
||||||
|
|
||||||
keep_details_t what_to_keep() {
|
keep_details_t what_to_keep() {
|
||||||
bool lots = HANDLED(lots) || HANDLED(lots_actual);
|
bool lots = HANDLED(lots) || HANDLED(lots_actual);
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
class commodity_pool_t;
|
|
||||||
class xact_t;
|
class xact_t;
|
||||||
|
|
||||||
class session_t : public symbol_scope_t
|
class session_t : public symbol_scope_t
|
||||||
|
|
|
||||||
|
|
@ -695,8 +695,10 @@ void instance_t::master_account_directive(char * line)
|
||||||
{
|
{
|
||||||
if (account_t * acct = context.top_account()->find_account(line))
|
if (account_t * acct = context.top_account()->find_account(line))
|
||||||
context.state_stack.push_front(acct);
|
context.state_stack.push_front(acct);
|
||||||
|
#if !defined(NO_ASSERTS)
|
||||||
else
|
else
|
||||||
assert(! "Failed to create account");
|
assert(! "Failed to create account");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void instance_t::end_directive(char * kind)
|
void instance_t::end_directive(char * kind)
|
||||||
|
|
@ -763,8 +765,12 @@ void instance_t::payee_mapping_directive(char * line)
|
||||||
(payee_mapping_t(mask_t(regex), payee));
|
(payee_mapping_t(mask_t(regex), payee));
|
||||||
|
|
||||||
while (peek_whitespace_line()) {
|
while (peek_whitespace_line()) {
|
||||||
|
#if defined(NO_ASSERTS)
|
||||||
|
read_line(line);
|
||||||
|
#else
|
||||||
std::streamsize len = read_line(line);
|
std::streamsize len = read_line(line);
|
||||||
assert(len > 0);
|
assert(len > 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
regex = skip_ws(line);
|
regex = skip_ws(line);
|
||||||
if (! *regex)
|
if (! *regex)
|
||||||
|
|
@ -786,8 +792,12 @@ void instance_t::account_mapping_directive(char * line)
|
||||||
context.top_account()->find_account(account_name)));
|
context.top_account()->find_account(account_name)));
|
||||||
|
|
||||||
while (peek_whitespace_line()) {
|
while (peek_whitespace_line()) {
|
||||||
|
#if defined(NO_ASSERTS)
|
||||||
|
read_line(line);
|
||||||
|
#else
|
||||||
std::streamsize len = read_line(line);
|
std::streamsize len = read_line(line);
|
||||||
assert(len > 0);
|
assert(len > 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
payee_regex = skip_ws(line);
|
payee_regex = skip_ws(line);
|
||||||
if (! *payee_regex)
|
if (! *payee_regex)
|
||||||
|
|
|
||||||
|
|
@ -333,10 +333,12 @@ date_t date_specifier_t::begin(const optional_year& current_year) const
|
||||||
month_type the_month = month ? *month : date_t::month_type(1);
|
month_type the_month = month ? *month : date_t::month_type(1);
|
||||||
day_type the_day = day ? *day : date_t::day_type(1);
|
day_type the_day = day ? *day : date_t::day_type(1);
|
||||||
|
|
||||||
|
#if !defined(NO_ASSERTS)
|
||||||
if (day)
|
if (day)
|
||||||
assert(! wday);
|
assert(! wday);
|
||||||
else if (wday)
|
else if (wday)
|
||||||
assert(! day);
|
assert(! day);
|
||||||
|
#endif
|
||||||
|
|
||||||
// jww (2009-11-16): Handle wday. If a month is set, find the most recent
|
// jww (2009-11-16): Handle wday. If a month is set, find the most recent
|
||||||
// wday in that month; if the year is set, then in that year.
|
// wday in that month; if the year is set, then in that year.
|
||||||
|
|
|
||||||
14
src/utils.h
14
src/utils.h
|
|
@ -49,17 +49,17 @@
|
||||||
*/
|
*/
|
||||||
/*@{*/
|
/*@{*/
|
||||||
|
|
||||||
|
#define TIMERS_ON 1
|
||||||
|
|
||||||
#if defined(DEBUG_MODE)
|
#if defined(DEBUG_MODE)
|
||||||
#define VERIFY_ON 1
|
#define VERIFY_ON 1
|
||||||
#define TRACING_ON 1
|
#define TRACING_ON 1
|
||||||
#define DEBUG_ON 1
|
#define DEBUG_ON 1
|
||||||
#define TIMERS_ON 1
|
|
||||||
#elif defined(NDEBUG)
|
#elif defined(NDEBUG)
|
||||||
#define NO_ASSERTS 1
|
#define NO_ASSERTS 1
|
||||||
#define NO_LOGGING 1
|
//#define NO_LOGGING 1
|
||||||
#else
|
#else
|
||||||
#define TRACING_ON 1 // use --trace X to enable
|
#define TRACING_ON 1 // use --trace X to enable
|
||||||
#define TIMERS_ON 1
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
@ -434,8 +434,8 @@ void finish_timer(const char * name);
|
||||||
(SHOW_TRACE(lvl) ? ledger::finish_timer(#name) : ((void)0))
|
(SHOW_TRACE(lvl) ? ledger::finish_timer(#name) : ((void)0))
|
||||||
#else
|
#else
|
||||||
#define TRACE_START(name, lvl, msg)
|
#define TRACE_START(name, lvl, msg)
|
||||||
#define TRACE_STOP(name)
|
#define TRACE_STOP(name, lvl)
|
||||||
#define TRACE_FINISH(name)
|
#define TRACE_FINISH(name, lvl)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DEBUG_ON)
|
#if defined(DEBUG_ON)
|
||||||
|
|
@ -474,8 +474,8 @@ void finish_timer(const char * name);
|
||||||
#else // ! (LOGGING_ON && TIMERS_ON)
|
#else // ! (LOGGING_ON && TIMERS_ON)
|
||||||
|
|
||||||
#define TRACE_START(lvl, msg, name)
|
#define TRACE_START(lvl, msg, name)
|
||||||
#define TRACE_STOP(name)
|
#define TRACE_STOP(name, lvl)
|
||||||
#define TRACE_FINISH(name)
|
#define TRACE_FINISH(name, lvl)
|
||||||
|
|
||||||
#define DEBUG_START(name, msg)
|
#define DEBUG_START(name, msg)
|
||||||
#define DEBUG_START_(name, cat, msg)
|
#define DEBUG_START_(name, cat, msg)
|
||||||
|
|
|
||||||
28
src/value.cc
28
src/value.cc
|
|
@ -935,6 +935,20 @@ bool value_t::is_less_than(const value_t& val) const
|
||||||
}
|
}
|
||||||
return ! no_amounts;
|
return ! no_amounts;
|
||||||
}
|
}
|
||||||
|
case SEQUENCE: {
|
||||||
|
sequence_t::const_iterator i = as_sequence().begin();
|
||||||
|
sequence_t::const_iterator j = val.as_sequence().begin();
|
||||||
|
for (; (i != as_sequence().end() &&
|
||||||
|
j != val.as_sequence().end()); i++, j++) {
|
||||||
|
if (! ((*i) < (*j)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (i == as_sequence().end())
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1041,6 +1055,20 @@ bool value_t::is_greater_than(const value_t& val) const
|
||||||
}
|
}
|
||||||
return ! no_amounts;
|
return ! no_amounts;
|
||||||
}
|
}
|
||||||
|
case SEQUENCE: {
|
||||||
|
sequence_t::const_iterator i = as_sequence().begin();
|
||||||
|
sequence_t::const_iterator j = val.as_sequence().begin();
|
||||||
|
for (; (i != as_sequence().end() &&
|
||||||
|
j != val.as_sequence().end()); i++, j++) {
|
||||||
|
if (! ((*i) > (*j)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (i == as_sequence().end())
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -878,7 +878,6 @@ public:
|
||||||
sequence_t::iterator begin() {
|
sequence_t::iterator begin() {
|
||||||
return as_sequence_lval().begin();
|
return as_sequence_lval().begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
sequence_t::iterator end() {
|
sequence_t::iterator end() {
|
||||||
return as_sequence_lval().end();
|
return as_sequence_lval().end();
|
||||||
}
|
}
|
||||||
|
|
@ -886,7 +885,6 @@ public:
|
||||||
sequence_t::const_iterator begin() const {
|
sequence_t::const_iterator begin() const {
|
||||||
return as_sequence().begin();
|
return as_sequence().begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
sequence_t::const_iterator end() const {
|
sequence_t::const_iterator end() const {
|
||||||
return as_sequence().end();
|
return as_sequence().end();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,10 +62,12 @@ xact_base_t::~xact_base_t()
|
||||||
|
|
||||||
void xact_base_t::add_post(post_t * post)
|
void xact_base_t::add_post(post_t * post)
|
||||||
{
|
{
|
||||||
|
#if !defined(NO_ASSERTS)
|
||||||
// You can add temporary postings to transactions, but not real postings to
|
// You can add temporary postings to transactions, but not real postings to
|
||||||
// temporary transactions.
|
// temporary transactions.
|
||||||
if (! post->has_flags(ITEM_TEMP))
|
if (! post->has_flags(ITEM_TEMP))
|
||||||
assert(! has_flags(ITEM_TEMP));
|
assert(! has_flags(ITEM_TEMP));
|
||||||
|
#endif
|
||||||
|
|
||||||
posts.push_back(post);
|
posts.push_back(post);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,18 @@
|
||||||
<<<
|
<<<
|
||||||
>>>1
|
>>>1
|
||||||
>>>2
|
>>>2
|
||||||
While parsing file "$sourcepath/src/amount.h", line 67:
|
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 718:
|
While parsing file "$sourcepath/src/amount.h", line 720:
|
||||||
Error: Invalid date/time: line amount_t amoun
|
Error: Invalid date/time: line amount_t amoun
|
||||||
While parsing file "$sourcepath/src/amount.h", line 724:
|
While parsing file "$sourcepath/src/amount.h", line 726:
|
||||||
Error: Invalid date/time: line string amount_
|
Error: Invalid date/time: line string amount_
|
||||||
While parsing file "$sourcepath/src/amount.h", line 730:
|
While parsing file "$sourcepath/src/amount.h", line 732:
|
||||||
Error: Invalid date/time: line string amount_
|
Error: Invalid date/time: line string amount_
|
||||||
While parsing file "$sourcepath/src/amount.h", line 736:
|
While parsing file "$sourcepath/src/amount.h", line 738:
|
||||||
Error: Invalid date/time: line string amount_
|
Error: Invalid date/time: line string amount_
|
||||||
While parsing file "$sourcepath/src/amount.h", line 742:
|
While parsing file "$sourcepath/src/amount.h", line 744:
|
||||||
Error: Invalid date/time: line std::ostream&
|
Error: Invalid date/time: line std::ostream&
|
||||||
While parsing file "$sourcepath/src/amount.h", line 749:
|
While parsing file "$sourcepath/src/amount.h", line 751:
|
||||||
Error: Invalid date/time: line std::istream&
|
Error: Invalid date/time: line std::istream&
|
||||||
=== 7
|
=== 7
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ set -e
|
||||||
|
|
||||||
# Exit if it's not a branch we're interested in being thorough about
|
# Exit if it's not a branch we're interested in being thorough about
|
||||||
if echo $(git rev-parse --symbolic-full-name HEAD) | \
|
if echo $(git rev-parse --symbolic-full-name HEAD) | \
|
||||||
egrep -q '^refs/heads/(next|t/)'; then
|
egrep -q '^refs/heads/(t/)'; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -41,12 +41,12 @@ cd $TMPDIR
|
||||||
if [ ! -f Makefile -o \
|
if [ ! -f Makefile -o \
|
||||||
Makefile.in -nt Makefile -o \
|
Makefile.in -nt Makefile -o \
|
||||||
configure -nt Makefile -o \
|
configure -nt Makefile -o \
|
||||||
Makefile.am -nt Makefile.in -o \
|
tools/Makefile.am -nt Makefile.in -o \
|
||||||
configure.ac -nt configure -o \
|
tools/configure.ac -nt configure -o \
|
||||||
\( -f acprep -a acprep -nt Makefile \) ]
|
\( -f acprep -a acprep -nt Makefile \) ]
|
||||||
then
|
then
|
||||||
if [ -f acprep ]; then
|
if [ -f acprep ]; then
|
||||||
./acprep default --local
|
echo Will run acprep in a moment
|
||||||
elif [ -f autogen.sh ]; then
|
elif [ -f autogen.sh ]; then
|
||||||
sh autogen.sh && ./configure
|
sh autogen.sh && ./configure
|
||||||
else
|
else
|
||||||
|
|
@ -56,6 +56,10 @@ fi
|
||||||
|
|
||||||
# Finally, (re)build this proposed source tree and see if it passes
|
# Finally, (re)build this proposed source tree and see if it passes
|
||||||
# muster.
|
# muster.
|
||||||
nice -n 20 make check
|
if [ -f acprep ]; then
|
||||||
|
nice -n 20 ./acprep default --warn make check
|
||||||
|
else
|
||||||
|
nice -n 20 make check
|
||||||
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue