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
|
||||
|
||||
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.suffix = self.find_boost_in_directory(path)
|
||||
if self.suffix is not None:
|
||||
|
|
@ -685,12 +687,16 @@ class PrepareBuild(CommandLineApp):
|
|||
self.current_version())
|
||||
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):
|
||||
self.log.info('Executing phase: autogen')
|
||||
|
||||
if not exists('autogen.sh') or \
|
||||
self.isnewer('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')
|
||||
|
||||
|
|
@ -704,10 +710,12 @@ class PrepareBuild(CommandLineApp):
|
|||
if not exists('configure.ac') or \
|
||||
self.isnewer('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 \
|
||||
self.isnewer('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()
|
||||
if reason:
|
||||
|
|
@ -1159,6 +1167,7 @@ class PrepareBuild(CommandLineApp):
|
|||
self.LDFLAGS.append('-g')
|
||||
|
||||
def setup_flavor_opt(self):
|
||||
self.CPPFLAGS.append('-DNDEBUG=1')
|
||||
if self.darwin_gcc:
|
||||
self.option_no_pch()
|
||||
if '--disable-shared' in self.configure_args:
|
||||
|
|
|
|||
|
|
@ -218,6 +218,10 @@ namespace {
|
|||
return true;
|
||||
}
|
||||
|
||||
value_t get_addr(account_t& account) {
|
||||
return long(&account);
|
||||
}
|
||||
|
||||
value_t get_depth_spacer(account_t& account)
|
||||
{
|
||||
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>);
|
||||
else if (name == "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")
|
||||
return WRAP_FUNCTOR(&fn_any);
|
||||
else if (name == "all")
|
||||
|
|
|
|||
|
|
@ -149,10 +149,6 @@ namespace {
|
|||
mpfr_set_prec(tempfb, num_prec + den_prec);
|
||||
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)
|
||||
throw_(amount_error,
|
||||
_("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.
|
||||
if (commodity_t * commodity = commodity_pool_t::current_pool->create("s"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
#if !defined(NO_ASSERTS)
|
||||
else
|
||||
assert(false);
|
||||
#endif
|
||||
|
||||
// Add a "percentile" commodity
|
||||
if (commodity_t * commodity = commodity_pool_t::current_pool->create("%"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
#if !defined(NO_ASSERTS)
|
||||
else
|
||||
assert(false);
|
||||
#endif
|
||||
|
||||
is_initialized = true;
|
||||
}
|
||||
|
|
@ -472,7 +472,7 @@ amount_t& amount_t::operator-=(const amount_t& amt)
|
|||
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());
|
||||
|
||||
|
|
@ -491,7 +491,7 @@ amount_t& amount_t::operator*=(const amount_t& amt)
|
|||
quantity->prec =
|
||||
static_cast<precision_t>(quantity->prec + amt.quantity->prec);
|
||||
|
||||
if (! has_commodity())
|
||||
if (! has_commodity() && ! ignore_commodity)
|
||||
commodity_ = amt.commodity_;
|
||||
|
||||
if (has_commodity() && ! keep_precision()) {
|
||||
|
|
@ -741,24 +741,33 @@ amount_t::value(const bool primary_only,
|
|||
#endif
|
||||
if (has_commodity() &&
|
||||
(! 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;
|
||||
}
|
||||
else if (has_annotation() && annotation().price &&
|
||||
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 {
|
||||
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)
|
||||
return (point->price * number()).rounded();
|
||||
// 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 {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ namespace ledger {
|
|||
class commodity_t;
|
||||
class annotation_t;
|
||||
class keep_details_t;
|
||||
class commodity_pool_t;
|
||||
|
||||
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) {
|
||||
return multiply(amt);
|
||||
}
|
||||
amount_t& multiply(const amount_t& amt, bool ignore_commodity = false);
|
||||
|
||||
/** Divide two amounts while extending the precision to preserve the
|
||||
accuracy of the result. For example, if \c 10 is divided by \c 3,
|
||||
|
|
@ -511,7 +513,7 @@ public:
|
|||
amount's commodity:
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep)
|
|||
keep_date ? details.date : none,
|
||||
keep_tag ? details.tag : none));
|
||||
} else {
|
||||
new_comm = pool().find_or_create(base_symbol());
|
||||
new_comm = &referent();
|
||||
}
|
||||
|
||||
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;
|
||||
bool found = false;
|
||||
|
||||
#if defined(DEBUG_ON)
|
||||
#define DEBUG_INDENT(cat, indent) \
|
||||
do { \
|
||||
if (SHOW_DEBUG(cat)) \
|
||||
for (int i = 0; i < indent; i++) \
|
||||
ledger::_log_buffer << " "; \
|
||||
} while (false)
|
||||
#else
|
||||
#define DEBUG_INDENT(cat, indent)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
|
|
@ -136,38 +140,34 @@ commodity_t::history_t::find_price(const optional<datetime_t>& moment,
|
|||
|
||||
if (oldest) {
|
||||
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
|
||||
|
||||
if (prices.size() == 0) {
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find", " there are no prices in this history");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "there are no prices in this history");
|
||||
return none;
|
||||
}
|
||||
|
||||
if (! moment) {
|
||||
history_map::const_reverse_iterator r = prices.rbegin();
|
||||
point.when = (*r).first;
|
||||
point.when = (*r).first;
|
||||
point.price = (*r).second;
|
||||
found = true;
|
||||
#if defined(DEBUG_ON)
|
||||
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find", " using most recent price");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "using most recent price");
|
||||
} else {
|
||||
history_map::const_iterator i = prices.lower_bound(*moment);
|
||||
history_map::const_iterator i = prices.upper_bound(*moment);
|
||||
if (i == prices.end()) {
|
||||
history_map::const_reverse_iterator r = prices.rbegin();
|
||||
point.when = (*r).first;
|
||||
point.price = (*r).second;
|
||||
found = true;
|
||||
#if defined(DEBUG_ON)
|
||||
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find", " using last price");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "using last price");
|
||||
} else {
|
||||
point.when = (*i).first;
|
||||
if (*moment < point.when) {
|
||||
|
|
@ -181,40 +181,31 @@ commodity_t::history_t::find_price(const optional<datetime_t>& moment,
|
|||
point.price = (*i).second;
|
||||
found = true;
|
||||
}
|
||||
#if defined(DEBUG_ON)
|
||||
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find", " using found price");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "using found price");
|
||||
}
|
||||
}
|
||||
|
||||
if (! found) {
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find", " could not find a price");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "could not find a price");
|
||||
return none;
|
||||
}
|
||||
else if (moment && point.when > *moment) {
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find", " price is too young ");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "price is too young ");
|
||||
return none;
|
||||
}
|
||||
else if (oldest && point.when < *oldest) {
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find", " price is too old ");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "price is too old ");
|
||||
return none;
|
||||
}
|
||||
else {
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find",
|
||||
" returning price: " << point.when << ", " << point.price);
|
||||
#endif
|
||||
"returning price: " << point.when << ", " << point.price);
|
||||
return point;
|
||||
}
|
||||
}
|
||||
|
|
@ -232,7 +223,13 @@ commodity_t::varied_history_t::find_price(const commodity_t& source,
|
|||
optional<price_point_t> point;
|
||||
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)
|
||||
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);
|
||||
if (commodity)
|
||||
DEBUG("commodity.prices.find", " looking for: commodity '" << *commodity << "'");
|
||||
DEBUG("commodity.prices.find", "looking for: commodity '" << *commodity << "'");
|
||||
else
|
||||
DEBUG("commodity.prices.find", " looking for: any commodity");
|
||||
DEBUG("commodity.prices.find", "looking for: any commodity");
|
||||
|
||||
if (moment) {
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find", " time index: " << *moment);
|
||||
DEBUG("commodity.prices.find", "time index: " << *moment);
|
||||
}
|
||||
|
||||
if (oldest) {
|
||||
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
|
||||
|
||||
|
|
@ -262,16 +259,18 @@ commodity_t::varied_history_t::find_price(const commodity_t& source,
|
|||
price_point_t best;
|
||||
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);
|
||||
if (comm == source)
|
||||
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("commodity.prices.find",
|
||||
" searching for price via commodity '" << comm << "'");
|
||||
#endif
|
||||
"searching for price via commodity '" << comm << "'");
|
||||
|
||||
point = hist.second.find_price(moment, limit
|
||||
#if defined(DEBUG_ON)
|
||||
|
|
@ -284,68 +283,59 @@ commodity_t::varied_history_t::find_price(const commodity_t& source,
|
|||
optional<price_point_t> xlat;
|
||||
|
||||
if (commodity && comm != *commodity) {
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||
DEBUG("commodity.prices.find", " looking for translation price");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "looking for translation price");
|
||||
|
||||
xlat = comm.find_price(commodity, moment, limit
|
||||
xlat = comm.find_price(commodity, moment, limit, true
|
||||
#if defined(DEBUG_ON)
|
||||
, indent + 2
|
||||
#endif
|
||||
);
|
||||
if (xlat) {
|
||||
#if defined(DEBUG_ON)
|
||||
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);
|
||||
#endif
|
||||
|
||||
point->price = xlat->price * point->price;
|
||||
if (xlat->when < point->when) {
|
||||
point->when = xlat->when;
|
||||
#if defined(DEBUG_ON)
|
||||
|
||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||
DEBUG("commodity.prices.find",
|
||||
" adjusting date of result back to " << point->when);
|
||||
#endif
|
||||
"adjusting date of result back to " << point->when);
|
||||
}
|
||||
} else {
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||
DEBUG("commodity.prices.find", " saw no translated price there");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "saw no translated price there");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
assert(! commodity || point->price.commodity() == *commodity);
|
||||
#if defined(DEBUG_ON)
|
||||
|
||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||
DEBUG("commodity.prices.find",
|
||||
" saw a price there: " << point->price << " from " << point->when);
|
||||
#endif
|
||||
"saw a price there: " << point->price << " from " << point->when);
|
||||
|
||||
if (! limit || point->when > *limit) {
|
||||
limit = point->when;
|
||||
best = *point;
|
||||
found = true;
|
||||
|
||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||
DEBUG("commodity.prices.find",
|
||||
"search limit adjusted to " << *limit);
|
||||
}
|
||||
} else {
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||
DEBUG("commodity.prices.find", " saw no price there");
|
||||
#endif
|
||||
DEBUG("commodity.prices.find", "saw no price there");
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
#if defined(DEBUG_ON)
|
||||
DEBUG_INDENT("commodity.prices.find", indent);
|
||||
DEBUG("commodity.prices.find",
|
||||
" found price " << best.price << " from " << best.when);
|
||||
DEBUG("commodity.download",
|
||||
"found price " << best.price << " from " << best.when);
|
||||
#endif
|
||||
return best;
|
||||
}
|
||||
return none;
|
||||
|
|
@ -370,6 +360,97 @@ commodity_t::varied_history_t::history(const optional<commodity_t&>& commodity)
|
|||
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>
|
||||
commodity_t::check_for_updated_price(const optional<price_point_t>& point,
|
||||
const optional<datetime_t>& moment,
|
||||
|
|
@ -428,9 +509,7 @@ namespace {
|
|||
{
|
||||
switch (buf[0]) {
|
||||
case 'a':
|
||||
return (std::strcmp(buf, "and") == 0 ||
|
||||
std::strcmp(buf, "any") == 0 ||
|
||||
std::strcmp(buf, "all") == 0);
|
||||
return std::strcmp(buf, "and") == 0;
|
||||
case 'd':
|
||||
return std::strcmp(buf, "div") == 0;
|
||||
case 'e':
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
namespace ledger {
|
||||
|
||||
class keep_details_t;
|
||||
class commodity_pool_t;
|
||||
|
||||
DECLARE_EXCEPTION(commodity_error, std::runtime_error);
|
||||
|
||||
|
|
@ -58,6 +59,10 @@ struct price_point_t
|
|||
datetime_t when;
|
||||
amount_t price;
|
||||
|
||||
bool operator==(const price_point_t& other) const {
|
||||
return when == other.when && price == other.price;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
|
@ -174,6 +179,16 @@ protected:
|
|||
optional<amount_t> smaller;
|
||||
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;
|
||||
|
||||
public:
|
||||
|
|
@ -333,36 +348,28 @@ public:
|
|||
const bool reflexive = true) {
|
||||
if (! base->varied_history)
|
||||
base->varied_history = varied_history_t();
|
||||
|
||||
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) {
|
||||
if (base->varied_history)
|
||||
if (base->varied_history) {
|
||||
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;
|
||||
}
|
||||
|
||||
optional<price_point_t>
|
||||
find_price(const optional<commodity_t&>& commodity = 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)
|
||||
, const int indent = 0
|
||||
#endif
|
||||
) 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;
|
||||
}
|
||||
) const;
|
||||
|
||||
optional<price_point_t>
|
||||
check_for_updated_price(const optional<price_point_t>& point,
|
||||
|
|
|
|||
|
|
@ -155,17 +155,21 @@ public:
|
|||
result_type calc(scope_t& scope)
|
||||
{
|
||||
if (! compiled) {
|
||||
#if defined(DEBUG_ON)
|
||||
if (SHOW_DEBUG("expr.compile")) {
|
||||
DEBUG("expr.compile", "Before compilation:");
|
||||
dump(*_log_stream);
|
||||
}
|
||||
#endif // defined(DEBUG_ON)
|
||||
|
||||
compile(scope);
|
||||
|
||||
#if defined(DEBUG_ON)
|
||||
if (SHOW_DEBUG("expr.compile")) {
|
||||
DEBUG("expr.compile", "After compilation:");
|
||||
dump(*_log_stream);
|
||||
}
|
||||
#endif // defined(DEBUG_ON)
|
||||
}
|
||||
|
||||
return real_calc(scope);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ void post_splitter::print_title(const value_t& val)
|
|||
|
||||
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);
|
||||
|
||||
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);
|
||||
post_t& temp = temps.copy_post(post, xact, new_account);
|
||||
temp.note = none;
|
||||
temp.add_flags(POST_ANONYMIZED);
|
||||
|
||||
(*handler)(temp);
|
||||
}
|
||||
|
|
@ -894,7 +895,7 @@ void posts_as_equity::report_subtotal()
|
|||
value_t total = 0L;
|
||||
foreach (values_map::value_type& pair, values) {
|
||||
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)
|
||||
handle_value(amount_pair.second, pair.second.account, &xact, temps,
|
||||
handler);
|
||||
|
|
@ -907,7 +908,7 @@ void posts_as_equity::report_subtotal()
|
|||
values.clear();
|
||||
|
||||
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) {
|
||||
post_t& balance_post = temps.create_post(xact, balance_account);
|
||||
balance_post.amount = - pair.second;
|
||||
|
|
@ -1166,8 +1167,10 @@ void forecast_posts::flush()
|
|||
}
|
||||
|
||||
date_t& begin = *(*least).first.start;
|
||||
#if !defined(NO_ASSERTS)
|
||||
if ((*least).first.finish)
|
||||
assert(begin < *(*least).first.finish);
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -226,16 +226,12 @@ class sort_posts : public item_handler<post_t>
|
|||
|
||||
public:
|
||||
sort_posts(post_handler_ptr handler, const expr_t& _sort_order)
|
||||
: item_handler<post_t>(handler),
|
||||
sort_order(_sort_order) {
|
||||
TRACE_CTOR(sort_posts,
|
||||
"post_handler_ptr, const value_expr&");
|
||||
: item_handler<post_t>(handler), sort_order(_sort_order) {
|
||||
TRACE_CTOR(sort_posts, "post_handler_ptr, const value_expr&");
|
||||
}
|
||||
sort_posts(post_handler_ptr handler, const string& _sort_order)
|
||||
: item_handler<post_t>(handler),
|
||||
sort_order(_sort_order) {
|
||||
TRACE_CTOR(sort_posts,
|
||||
"post_handler_ptr, const string&");
|
||||
: item_handler<post_t>(handler), sort_order(_sort_order) {
|
||||
TRACE_CTOR(sort_posts, "post_handler_ptr, const string&");
|
||||
}
|
||||
virtual ~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()
|
||||
{
|
||||
#if defined(LOGGING_ON)
|
||||
INFO("Initialization file is " << HANDLER(init_file_).str());
|
||||
INFO("Price database is " << session().HANDLER(price_db_).str());
|
||||
|
||||
foreach (const path& pathname, session().HANDLER(file_).data_files)
|
||||
INFO("Journal file is " << pathname.string());
|
||||
#endif // defined(LOGGING_ON)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
value_t get_addr(item_t& item) {
|
||||
return long(&item);
|
||||
}
|
||||
|
||||
value_t get_depth(item_t&) {
|
||||
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>);
|
||||
else if (name == "actual_date")
|
||||
return WRAP_FUNCTOR(get_wrapper<&get_actual_date>);
|
||||
else if (name == "addr")
|
||||
return WRAP_FUNCTOR(get_wrapper<&get_addr>);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
|
|
|
|||
|
|
@ -94,9 +94,9 @@ void posts_commodities_iterator::reset(journal_t& journal)
|
|||
comm->varied_history()) {
|
||||
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) {
|
||||
foreach (commodity_t::history_map::value_type hpair,
|
||||
foreach (commodity_t::history_map::value_type& hpair,
|
||||
pair.second.prices) {
|
||||
xact_t * xact;
|
||||
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
|
||||
// definition, and then at the point of every use if they could
|
||||
// not be found there.
|
||||
#if defined(DEBUG_ON)
|
||||
if (SHOW_DEBUG("expr.compile")) {
|
||||
DEBUG("expr.compile", "Found definition:");
|
||||
def->dump(*_log_stream, 0);
|
||||
}
|
||||
#endif // defined(DEBUG_ON)
|
||||
return copy(def);
|
||||
}
|
||||
else if (left()) {
|
||||
|
|
|
|||
|
|
@ -61,10 +61,16 @@ class expr_t::parser_t : public noncopyable
|
|||
return lookahead;
|
||||
}
|
||||
|
||||
#if !defined(NO_ASSERTS)
|
||||
void push_token(const token_t& tok) const {
|
||||
assert(&tok == &lookahead);
|
||||
use_lookahead = true;
|
||||
}
|
||||
#else
|
||||
void push_token(const token_t&) const {
|
||||
use_lookahead = true;
|
||||
}
|
||||
#endif // !defined(NO_ASSERTS)
|
||||
void push_token() const {
|
||||
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);
|
||||
details.print(name, comm.pool().keep_base);
|
||||
|
||||
DEBUG("amounts.commodities", "make_qualified_name for "
|
||||
<< *comm.qualified_symbol << std::endl << details);
|
||||
#if defined(DEBUG_ON)
|
||||
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());
|
||||
|
||||
return name.str();
|
||||
|
|
@ -361,4 +364,76 @@ commodity_pool_t::parse_price_expression(const std::string& str,
|
|||
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
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public:
|
|||
|
||||
virtual ~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);
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +131,12 @@ public:
|
|||
const bool add_prices = true,
|
||||
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)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
|
|
|||
11
src/post.h
11
src/post.h
|
|
@ -52,11 +52,12 @@ class account_t;
|
|||
class post_t : public item_t
|
||||
{
|
||||
public:
|
||||
#define POST_VIRTUAL 0x08 // the account was specified with (parens)
|
||||
#define POST_MUST_BALANCE 0x10 // posting must balance in the transaction
|
||||
#define POST_CALCULATED 0x20 // posting's amount was calculated
|
||||
#define POST_COST_CALCULATED 0x40 // posting's cost was calculated
|
||||
#define POST_COST_IN_FULL 0x80 // cost specified using @@
|
||||
#define POST_VIRTUAL 0x04 // the account was specified with (parens)
|
||||
#define POST_MUST_BALANCE 0x08 // posting must balance in the transaction
|
||||
#define POST_CALCULATED 0x10 // posting's amount was calculated
|
||||
#define POST_COST_CALCULATED 0x20 // posting's cost was calculated
|
||||
#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
|
||||
account_t * account;
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ namespace {
|
|||
|
||||
foreach (post_t * post, xact.posts) {
|
||||
if (post->has_flags(ITEM_TEMP | ITEM_GENERATED) &&
|
||||
! post->has_flags(POST_ANONYMIZED) &&
|
||||
! report.HANDLED(print_virtual))
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -115,8 +115,10 @@ struct string_from_python
|
|||
utf8::unchecked::utf16to8(value, value + size, std::back_inserter(str));
|
||||
else if (sizeof(Py_UNICODE) == 4) // UTF-32
|
||||
utf8::unchecked::utf32to8(value, value + size, std::back_inserter(str));
|
||||
#if !defined(NO_ASSERTS)
|
||||
else
|
||||
assert(! "Py_UNICODE has an unexpected size");
|
||||
#endif
|
||||
|
||||
if (value == 0) throw_error_already_set();
|
||||
void* storage =
|
||||
|
|
|
|||
|
|
@ -842,6 +842,18 @@ value_t report_t::echo_command(call_scope_t& scope)
|
|||
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)
|
||||
{
|
||||
switch (*p) {
|
||||
|
|
@ -1318,9 +1330,10 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
|
|||
case symbol_t::COMMAND:
|
||||
switch (*p) {
|
||||
case 'a':
|
||||
if (is_eq(p, "accounts"))
|
||||
if (is_eq(p, "accounts")) {
|
||||
return WRAP_FUNCTOR(reporter<>(new report_accounts(*this), *this,
|
||||
"#accounts"));
|
||||
}
|
||||
break;
|
||||
|
||||
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"));
|
||||
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);
|
||||
else if (is_eq(p, "emacs"))
|
||||
}
|
||||
else if (is_eq(p, "emacs")) {
|
||||
return WRAP_FUNCTOR
|
||||
(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);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (*(p + 1) == '\0' || is_eq(p, "print"))
|
||||
if (*(p + 1) == '\0' || is_eq(p, "print")) {
|
||||
return WRAP_FUNCTOR
|
||||
(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
|
||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||
(new format_posts(*this, report_format(HANDLER(prices_format_)),
|
||||
maybe_format(HANDLER(prepend_format_)),
|
||||
HANDLER(prepend_width_).value.to_long()),
|
||||
*this, "#prices"));
|
||||
else if (is_eq(p, "pricedb"))
|
||||
}
|
||||
else if (is_eq(p, "pricedb")) {
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||
(new format_posts(*this, report_format(HANDLER(pricedb_format_)),
|
||||
maybe_format(HANDLER(prepend_format_)),
|
||||
HANDLER(prepend_width_).value.to_long()),
|
||||
*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,
|
||||
"#payees"));
|
||||
}
|
||||
break;
|
||||
|
||||
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
|
||||
(reporter<>
|
||||
(new format_posts(*this, report_format(HANDLER(register_format_)),
|
||||
maybe_format(HANDLER(prepend_format_)),
|
||||
HANDLER(prepend_width_).value.to_long()),
|
||||
*this, "#register"));
|
||||
else if (is_eq(p, "reload"))
|
||||
}
|
||||
else if (is_eq(p, "reload")) {
|
||||
return MAKE_FUNCTOR(report_t::reload_command);
|
||||
}
|
||||
break;
|
||||
|
||||
case 's':
|
||||
|
|
@ -1448,6 +1473,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
|
|||
case 'e':
|
||||
if (is_eq(p, "eval"))
|
||||
return WRAP_FUNCTOR(eval_command);
|
||||
else if (is_eq(p, "expr"))
|
||||
return WRAP_FUNCTOR(parse_command);
|
||||
break;
|
||||
case 'f':
|
||||
if (is_eq(p, "format"))
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ public:
|
|||
|
||||
value_t reload_command(call_scope_t&);
|
||||
value_t echo_command(call_scope_t& scope);
|
||||
value_t pricemap_command(call_scope_t& scope);
|
||||
|
||||
keep_details_t what_to_keep() {
|
||||
bool lots = HANDLED(lots) || HANDLED(lots_actual);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
class commodity_pool_t;
|
||||
class xact_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))
|
||||
context.state_stack.push_front(acct);
|
||||
#if !defined(NO_ASSERTS)
|
||||
else
|
||||
assert(! "Failed to create account");
|
||||
#endif
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
while (peek_whitespace_line()) {
|
||||
#if defined(NO_ASSERTS)
|
||||
read_line(line);
|
||||
#else
|
||||
std::streamsize len = read_line(line);
|
||||
assert(len > 0);
|
||||
#endif
|
||||
|
||||
regex = skip_ws(line);
|
||||
if (! *regex)
|
||||
|
|
@ -786,8 +792,12 @@ void instance_t::account_mapping_directive(char * line)
|
|||
context.top_account()->find_account(account_name)));
|
||||
|
||||
while (peek_whitespace_line()) {
|
||||
#if defined(NO_ASSERTS)
|
||||
read_line(line);
|
||||
#else
|
||||
std::streamsize len = read_line(line);
|
||||
assert(len > 0);
|
||||
#endif
|
||||
|
||||
payee_regex = skip_ws(line);
|
||||
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);
|
||||
day_type the_day = day ? *day : date_t::day_type(1);
|
||||
|
||||
#if !defined(NO_ASSERTS)
|
||||
if (day)
|
||||
assert(! wday);
|
||||
else if (wday)
|
||||
assert(! day);
|
||||
#endif
|
||||
|
||||
// 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.
|
||||
|
|
|
|||
14
src/utils.h
14
src/utils.h
|
|
@ -49,17 +49,17 @@
|
|||
*/
|
||||
/*@{*/
|
||||
|
||||
#define TIMERS_ON 1
|
||||
|
||||
#if defined(DEBUG_MODE)
|
||||
#define VERIFY_ON 1
|
||||
#define TRACING_ON 1
|
||||
#define DEBUG_ON 1
|
||||
#define TIMERS_ON 1
|
||||
#elif defined(NDEBUG)
|
||||
#define NO_ASSERTS 1
|
||||
#define NO_LOGGING 1
|
||||
//#define NO_LOGGING 1
|
||||
#else
|
||||
#define TRACING_ON 1 // use --trace X to enable
|
||||
#define TIMERS_ON 1
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
|
|
@ -434,8 +434,8 @@ void finish_timer(const char * name);
|
|||
(SHOW_TRACE(lvl) ? ledger::finish_timer(#name) : ((void)0))
|
||||
#else
|
||||
#define TRACE_START(name, lvl, msg)
|
||||
#define TRACE_STOP(name)
|
||||
#define TRACE_FINISH(name)
|
||||
#define TRACE_STOP(name, lvl)
|
||||
#define TRACE_FINISH(name, lvl)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_ON)
|
||||
|
|
@ -474,8 +474,8 @@ void finish_timer(const char * name);
|
|||
#else // ! (LOGGING_ON && TIMERS_ON)
|
||||
|
||||
#define TRACE_START(lvl, msg, name)
|
||||
#define TRACE_STOP(name)
|
||||
#define TRACE_FINISH(name)
|
||||
#define TRACE_STOP(name, lvl)
|
||||
#define TRACE_FINISH(name, lvl)
|
||||
|
||||
#define DEBUG_START(name, 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;
|
||||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1041,6 +1055,20 @@ bool value_t::is_greater_than(const value_t& val) const
|
|||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -878,7 +878,6 @@ public:
|
|||
sequence_t::iterator begin() {
|
||||
return as_sequence_lval().begin();
|
||||
}
|
||||
|
||||
sequence_t::iterator end() {
|
||||
return as_sequence_lval().end();
|
||||
}
|
||||
|
|
@ -886,7 +885,6 @@ public:
|
|||
sequence_t::const_iterator begin() const {
|
||||
return as_sequence().begin();
|
||||
}
|
||||
|
||||
sequence_t::const_iterator end() const {
|
||||
return as_sequence().end();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,10 +62,12 @@ xact_base_t::~xact_base_t()
|
|||
|
||||
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
|
||||
// temporary transactions.
|
||||
if (! post->has_flags(ITEM_TEMP))
|
||||
assert(! has_flags(ITEM_TEMP));
|
||||
#endif
|
||||
|
||||
posts.push_back(post);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,18 +2,18 @@
|
|||
<<<
|
||||
>>>1
|
||||
>>>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
|
||||
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
|
||||
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_
|
||||
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_
|
||||
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_
|
||||
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&
|
||||
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&
|
||||
=== 7
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ set -e
|
|||
|
||||
# Exit if it's not a branch we're interested in being thorough about
|
||||
if echo $(git rev-parse --symbolic-full-name HEAD) | \
|
||||
egrep -q '^refs/heads/(next|t/)'; then
|
||||
egrep -q '^refs/heads/(t/)'; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
|
@ -41,12 +41,12 @@ cd $TMPDIR
|
|||
if [ ! -f Makefile -o \
|
||||
Makefile.in -nt Makefile -o \
|
||||
configure -nt Makefile -o \
|
||||
Makefile.am -nt Makefile.in -o \
|
||||
configure.ac -nt configure -o \
|
||||
tools/Makefile.am -nt Makefile.in -o \
|
||||
tools/configure.ac -nt configure -o \
|
||||
\( -f acprep -a acprep -nt Makefile \) ]
|
||||
then
|
||||
if [ -f acprep ]; then
|
||||
./acprep default --local
|
||||
echo Will run acprep in a moment
|
||||
elif [ -f autogen.sh ]; then
|
||||
sh autogen.sh && ./configure
|
||||
else
|
||||
|
|
@ -56,6 +56,10 @@ fi
|
|||
|
||||
# Finally, (re)build this proposed source tree and see if it passes
|
||||
# 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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue