Merge branch 'next'

This commit is contained in:
John Wiegley 2009-11-14 20:43:28 -05:00
commit badbeb545b
23 changed files with 474 additions and 210 deletions

View file

@ -1,15 +1,35 @@
README FIRST!!!
===============================================================================
README FIRST!!!
To build this code after doing a Git clone, run:
$ ./acprep update
If you try to configure/build on your own, you are almost certainly going to
run into problems. In future, you can run this command again and it will keep
you updated with the very latest version.
If you try to configure and build on your own, you are almost certainly going
to run into problems. In future, you can run this command again and again,
and it will keep you updated to the very latest version.
===============================================================================
NOTE FOR MAC OS X USERS
To build and install Ledger on the Mac requires several dependencies. If you
are a MacPorts user, you can install these dependencies very simply using:
$ ./acprep dependencies
Once this is done, I recommend building both debug and optimized versions of
Ledger, in a subdirectory of your source tree named 'build' (which acprep will
manage for you, you simply need to make it):
$ mkdir build
$ ./acprep opt make
$ ./acprep debug make
Now install the optimized version, but know that you have 'build/debug/ledger'
available for testing and more useful bug reports.
===============================================================================

179
acprep
View file

@ -42,6 +42,7 @@ class CommandLineApp(object):
force_exit = True # If true, always ends run() with sys.exit()
log_handler = None
darwin_gcc = False
options = {
'debug': False,
@ -188,10 +189,8 @@ class PrepareBuild(CommandLineApp):
self.CPPFLAGS = []
self.CCFLAGS = []
self.ARCHFLAGS = []
self.CXXFLAGS = []
self.LDFLAGS = []
self.LDARCHFLAGS = []
self.envvars = {
'PYTHON_HOME': '/usr',
@ -204,10 +203,8 @@ class PrepareBuild(CommandLineApp):
'CCFLAGS': '',
'CXX': 'g++',
'CXXFLAGS': '',
'ARCHFLAGS': '',
'LD': 'g++',
'LDFLAGS': '',
'LDARCHFLAGS': '',
'LDFLAGS': ''
}
for varname in self.envvars.keys():
@ -554,14 +551,12 @@ class PrepareBuild(CommandLineApp):
self.log.info('Looks like you are using MacPorts on OS X')
packages = [
'sudo', 'port', 'install', '-f',
'automake', 'autoconf', 'libtool',
'python26', 'boost-jam',
'automake', 'autoconf', 'libtool', 'python26',
'libiconv', '+universal', 'zlib', '+universal',
'gmp' ,'+universal', 'mpfr', '+universal',
'ncurses', '+universal', 'ncursesw', '+universal',
'gettext' ,'+universal', 'libedit' ,'+universal',
'boost', '+universal+st+debug+python26+doc',
'cppunit' ,'+universal',
'boost-jam', 'boost', '+st+python26+icu', 'cppunit',
'texlive', 'doxygen', 'graphviz', 'texinfo',
'lcov', 'sloccount'
]
@ -606,8 +601,7 @@ class PrepareBuild(CommandLineApp):
'python-devel', 'bboost-devel',
'gmp-devel', 'gettext-devel',
#'mpfr-devel'
'libedit-devel',
'cppunit-devel',
'libedit-devel', 'cppunit-devel',
#'texlive-full',
#'doxygen', 'graphviz', 'texinfo',
#'lcov', 'sloccount'
@ -696,6 +690,11 @@ class PrepareBuild(CommandLineApp):
path)
return None
def inform_boost_location(self, text, suffix):
self.log.info('Boost %s here:' % text)
self.log.info('BOOST_HOME => ' + self.envvars['BOOST_HOME'])
self.log.info('BOOST_SUFFIX => ' + suffix)
def locate_boost(self):
if self.envvars['BOOST_SUFFIX']:
self.log.info(("Not looking for Boost, since " +
@ -708,10 +707,7 @@ class PrepareBuild(CommandLineApp):
self.log.info('Looking for Boost in %s...' % path)
suffix = self.locate_boost_in_dir(path)
if suffix is not None:
self.log.info('Boost is located here:')
self.log.info('BOOST_HOME => ' +
self.envvars['BOOST_HOME'])
self.log.info('BOOST_SUFFIX => ' + suffix)
self.inform_boost_location('was found', suffix)
break
if suffix is None:
self.log.error("Boost could not be found.")
@ -749,29 +745,25 @@ class PrepareBuild(CommandLineApp):
self.sys_library_dirs.append(path)
def setup_for_johnw(self):
# jww (2009-03-09): Some peculiarities specific to my system
if exists('/Users/johnw/Dropbox/Accounts/ledger.dat'):
if self.current_flavor == 'debug':
if exists('/usr/local/stow/cppunit/include'):
self.sys_include_dirs.insert(0, '/usr/local/stow/cppunit/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/cppunit/lib')
if self.current_flavor != 'opt':
if exists('/usr/local/stow/cppunit/include'):
self.sys_include_dirs.insert(0, '/usr/local/stow/cppunit/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/cppunit/lib')
if exists('/usr/local/stow/icu/include'):
self.sys_include_dirs.insert(0, '/usr/local/stow/icu/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/icu/lib')
if exists('/usr/local/stow/icu/include'):
self.sys_include_dirs.insert(0, '/usr/local/stow/icu/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/icu/lib')
self.CPPFLAGS.append('-D_GLIBCXX_FULLY_DYNAMIC_STRING=1')
self.CPPFLAGS.append('-D_GLIBCXX_FULLY_DYNAMIC_STRING=1')
self.options.use_glibcxx_debug = True
self.options.use_glibcxx_debug = True
self.CXXFLAGS.append('-march=nocona')
self.CXXFLAGS.append('-msse3')
self.CXXFLAGS.append('-march=nocona')
self.CXXFLAGS.append('-msse3')
self.configure_args.append('--disable-shared')
self.configure_args.append('--enable-doxygen')
self.configure_args.append('--enable-python')
self.locate_my_libraries()
self.configure_args.append('--disable-shared')
self.configure_args.append('--enable-doxygen')
self.configure_args.append('--enable-python')
def setup_for_system(self):
self.setup_system_directories()
@ -797,17 +789,18 @@ class PrepareBuild(CommandLineApp):
self.CXXFLAGS.append('-pthread')
elif system == 'Darwin':
#self.ARCHFLAGS += ['-arch', 'i386', '-arch', 'ppc',
# '-isysroot', '/Developer/SDKs/MacOSX10.5.sdk']
#self.LDARCHFLAGS += self.ARCHFLAGS
#ldflag = '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk'
#self.LDARCHFLAGS.append(ldflag)
if exists('/Users/johnw/Dropbox/Accounts/ledger.dat'):
self.setup_for_johnw()
self.setup_for_johnw()
self.locate_darwin_libraries()
# g++ 4.0.1 cannot use PCH headers on OS X 10.5, so we must use a
# newer version.
if exists('/opt/local/bin/g++-mp-4.4'):
if self.current_flavor == 'opt' and \
exists('/usr/bin/g++-4.2'):
self.envvars['CC'] = '/usr/bin/gcc-4.2'
self.envvars['CXX'] = '/usr/bin/g++-4.2'
self.envvars['LD'] = '/usr/bin/g++-4.2'
self.darwin_gcc = True
elif exists('/opt/local/bin/g++-mp-4.4'):
self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.4'
self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.4'
self.envvars['LD'] = '/opt/local/bin/g++-mp-4.4'
@ -815,12 +808,13 @@ class PrepareBuild(CommandLineApp):
self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.3'
self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.3'
self.envvars['LD'] = '/opt/local/bin/g++-mp-4.3'
elif not self.options.use_glibcxx_debug and \
exists('/usr/bin/g++-4.2'):
elif exists('/usr/bin/g++-4.2'):
self.envvars['CC'] = '/usr/bin/gcc-4.2'
self.envvars['CXX'] = '/usr/bin/g++-4.2'
self.envvars['LD'] = '/usr/bin/g++-4.2'
self.darwin_gcc = True
else:
# g++ 4.0.1 cannot use PCH headers on OS X 10.5
self.option_no_pch()
if '--enable-pch' not in self.configure_args and \
@ -859,8 +853,7 @@ class PrepareBuild(CommandLineApp):
def finalize_config(self):
self.setup_flavor()
for var in ('CPPFLAGS', 'CCFLAGS', 'ARCHFLAGS',
'CXXFLAGS', 'LDFLAGS', 'LDARCHFLAGS'):
for var in ('CPPFLAGS', 'CCFLAGS', 'CXXFLAGS', 'LDFLAGS'):
value = self.__dict__[var]
if value:
first = not self.envvars[var]
@ -978,69 +971,71 @@ class PrepareBuild(CommandLineApp):
# The various build flavors #
#########################################################################
def locate_my_libraries(self):
if self.options.use_glibcxx_debug:
def locate_darwin_libraries(self):
if self.current_flavor != 'opt':
self.log.debug('We are using GLIBCXX_DEBUG, so setting up flags')
self.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1')
if self.options.use_glibcxx_debug:
self.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1')
if exists('/usr/local/stow/cppunit-debug/include'):
if '/usr/local/stow/cppunit/include' in self.sys_include_dirs:
self.sys_include_dirs.remove('/usr/local/stow/cppunit/include')
self.sys_library_dirs.remove('/usr/local/stow/cppunit/lib')
if exists('/usr/local/stow/cppunit-debug/include'):
if '/usr/local/stow/cppunit/include' in self.sys_include_dirs:
self.sys_include_dirs.remove('/usr/local/stow/cppunit/include')
self.sys_library_dirs.remove('/usr/local/stow/cppunit/lib')
self.sys_include_dirs.insert(0, '/usr/local/stow/cppunit-debug/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/cppunit-debug/lib')
self.sys_include_dirs.insert(0, '/usr/local/stow/cppunit-debug/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/cppunit-debug/lib')
if exists('/usr/local/stow/icu-debug/include'):
if '/usr/local/stow/icu/include' in self.sys_include_dirs:
self.sys_include_dirs.remove('/usr/local/stow/icu/include')
self.sys_library_dirs.remove('/usr/local/stow/icu/lib')
if exists('/usr/local/stow/icu-debug/include'):
if '/usr/local/stow/icu/include' in self.sys_include_dirs:
self.sys_include_dirs.remove('/usr/local/stow/icu/include')
self.sys_library_dirs.remove('/usr/local/stow/icu/lib')
self.sys_include_dirs.insert(0, '/usr/local/stow/icu-debug/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/icu-debug/lib')
self.sys_include_dirs.insert(0, '/usr/local/stow/icu-debug/include')
self.sys_library_dirs.insert(0, '/usr/local/stow/icu-debug/lib')
if exists('/opt/local/lib/libboost_regex-d.a'):
self.envvars['BOOST_HOME'] = '/opt/local'
self.envvars['BOOST_SUFFIX'] = '-d'
self.log.info('Setting BOOST_SUFFIX => %s' %
self.envvars['BOOST_SUFFIX'])
self.sys_include_dirs.append('/opt/local/include/boost')
elif exists('/usr/local/lib/libboost_regex-xgcc44-sd-1_40.a'):
if exists('/usr/local/lib/libboost_regex-xgcc44-sd-1_40.a'):
self.envvars['BOOST_HOME'] = '/usr/local'
self.envvars['BOOST_SUFFIX'] = '-xgcc44-sd-1_40'
self.log.info('Setting BOOST_SUFFIX => %s' %
self.envvars['BOOST_SUFFIX'])
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
self.inform_boost_location('is really located',
self.envvars['BOOST_SUFFIX'])
elif exists('/usr/local/lib/libboost_regex-xgcc44-d-1_40.a'):
self.envvars['BOOST_HOME'] = '/usr/local'
self.envvars['BOOST_SUFFIX'] = '-xgcc44-d-1_40'
self.log.info('Setting BOOST_SUFFIX => %s' %
self.envvars['BOOST_SUFFIX'])
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
self.inform_boost_location('is really located',
self.envvars['BOOST_SUFFIX'])
elif exists('/opt/local/lib/libboost_regex-d.a'):
self.envvars['BOOST_HOME'] = '/opt/local'
self.envvars['BOOST_SUFFIX'] = '-d'
self.sys_include_dirs.append('/opt/local/include/boost')
self.inform_boost_location('is really located',
self.envvars['BOOST_SUFFIX'])
else:
if exists('/opt/local/lib/libboost_regex.a'):
self.envvars['BOOST_HOME'] = '/opt/local'
self.envvars['BOOST_SUFFIX'] = ''
self.log.info('Setting BOOST_SUFFIX => %s' %
self.envvars['BOOST_SUFFIX'])
self.sys_include_dirs.append('/opt/local/include/boost')
self.inform_boost_location('is really located',
self.envvars['BOOST_SUFFIX'])
elif exists('/usr/local/lib/libboost_regex-xgcc44-s-1_40.a'):
self.envvars['BOOST_HOME'] = '/usr/local'
self.envvars['BOOST_SUFFIX'] = '-xgcc44-s-1_40'
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
self.inform_boost_location('is really located',
self.envvars['BOOST_SUFFIX'])
elif exists('/usr/local/lib/libboost_regex-xgcc44-1_40.a'):
self.envvars['BOOST_HOME'] = '/usr/local'
self.envvars['BOOST_SUFFIX'] = '-xgcc44-1_40'
self.log.info('Setting BOOST_SUFFIX => %s' %
self.envvars['BOOST_SUFFIX'])
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
self.inform_boost_location('is really located',
self.envvars['BOOST_SUFFIX'])
def setup_flavor_default(self):
pass
@ -1052,10 +1047,14 @@ class PrepareBuild(CommandLineApp):
self.LDFLAGS.append('-g')
def setup_flavor_opt(self):
self.CXXFLAGS.append('-O3')
self.LDFLAGS.append('-O3')
self.CXXFLAGS.append('-fomit-frame-pointer')
self.LDFLAGS.append('-fomit-frame-pointer')
if self.darwin_gcc:
self.CXXFLAGS.append('-fast')
self.LDFLAGS.append('-fast')
else:
self.CXXFLAGS.append('-O3')
self.LDFLAGS.append('-O3')
self.CXXFLAGS.append('-fomit-frame-pointer')
self.LDFLAGS.append('-fomit-frame-pointer')
def setup_flavor_gcov(self):
self.CXXFLAGS.append('-g')
@ -1122,8 +1121,8 @@ class PrepareBuild(CommandLineApp):
conf_args = ['sh', join(self.source_dir, 'configure'),
'--srcdir', self.source_dir]
for var in ('CC', 'CPPFLAGS', 'CCFLAGS', 'ARCHFLAGS',
'CXX', 'CXXFLAGS', 'LD', 'LDFLAGS', 'LDARCHFLAGS'):
for var in ('CC', 'CPPFLAGS', 'CCFLAGS', 'CXX', 'CXXFLAGS',
'LD', 'LDFLAGS'):
if self.envvars.has_key(var) and self.envvars[var] and \
(var.endswith('FLAGS') or exists(self.envvars[var])):
conf_args.append('%s=%s' % (var, self.envvars[var]))

View file

@ -1,4 +1,4 @@
.Dd November 12, 2009
.Dd November 13, 2009
.Dt ledger 1
.Sh NAME
.Nm ledger
@ -577,6 +577,7 @@ and displays information about how it was parsed. See the section on
.Xr beancount 1,
.Xr hledger 1
.Sh AUTHORS
.An "John Wiegley" Aq johnw@newartisans.com
.An "John Wiegley"
.Aq johnw@newartisans.com
.\" .Sh BUGS \" Document known, unremedied bugs
.\" .Sh HISTORY \" Document history if command behaves in a unique manner

View file

@ -77,7 +77,8 @@ cppunit-release:
CFLAGS="$(EXTRA_DEFINES) $(ARCH_CFLAGS)" \
LDFLAGS="$(ARCH_LDFLAGS)" \
CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \
--prefix=$(STOW_ROOT)/cppunit && \
--prefix=$(STOW_ROOT)/cppunit \
--disable-doxygen --disable-dot && \
make install)
cppunit-debug:
@ -87,7 +88,8 @@ cppunit-debug:
CFLAGS="-g $(EXTRA_DEFINES) $(ARCH_CFLAGS)" \
LDFLAGS="-g $(ARCH_LDFLAGS)" \
CC="$(CC)" CXX="$(CXX)" LD="$(LD)" \
--prefix=$(STOW_ROOT)/cppunit-debug && \
--prefix=$(STOW_ROOT)/cppunit-debug \
--disable-doxygen --disable-dot && \
make install)
cppunit-build: cppunit-release cppunit-debug

View file

@ -249,7 +249,7 @@ expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
switch (name[0]) {
case 'a':
if (name == "amount")
if (name[1] == '\0' || name == "amount")
return WRAP_FUNCTOR(get_wrapper<&get_amount>);
else if (name == "account")
return WRAP_FUNCTOR(get_wrapper<&get_account>);
@ -272,11 +272,20 @@ expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
case 'i':
if (name == "is_account")
return WRAP_FUNCTOR(get_wrapper<&get_true>);
else if (name == "is_index")
return WRAP_FUNCTOR(get_wrapper<&get_subcount>);
break;
case 'l':
if (name == "latest_cleared")
return WRAP_FUNCTOR(get_wrapper<&get_latest_cleared>);
else if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_depth>);
break;
case 'n':
if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_subcount>);
break;
case 'p':
@ -300,6 +309,16 @@ expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
if (name == "use_direct_amount")
return WRAP_FUNCTOR(get_wrapper<&ignore>);
break;
case 'N':
if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_count>);
break;
case 'O':
if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_total>);
break;
}
return NULL;

View file

@ -56,7 +56,7 @@ struct amount_t::bigint_t : public supports_flags<>
mpq_t val;
precision_t prec;
uint_least16_t refc;
uint_least32_t refc;
#define MP(bigint) ((bigint)->val)
@ -80,11 +80,7 @@ struct amount_t::bigint_t : public supports_flags<>
bool valid() const {
if (prec > 1024) {
DEBUG("ledger.validate", "amount_t::bigint_t: prec > 128");
return false;
}
if (refc > 16535) {
DEBUG("ledger.validate", "amount_t::bigint_t: refc > 16535");
DEBUG("ledger.validate", "amount_t::bigint_t: prec > 1024");
return false;
}
if (flags() & ~(BIGINT_BULK_ALLOC | BIGINT_KEEP_PREC)) {

View file

@ -350,9 +350,9 @@ void collapse_posts::report_subtotal()
component_posts.clear();
last_xact = NULL;
last_post = NULL;
subtotal = 0L;
count = 0;
last_post = NULL;
subtotal = 0L;
count = 0;
}
void collapse_posts::operator()(post_t& post)
@ -364,12 +364,12 @@ void collapse_posts::operator()(post_t& post)
report_subtotal();
post.add_to_value(subtotal, amount_expr);
count++;
component_posts.push_back(&post);
last_xact = post.xact;
last_post = &post;
last_post = &post;
count++;
}
void related_posts::flush()
@ -648,8 +648,15 @@ void posts_as_equity::report_subtotal()
value_t total = 0L;
foreach (values_map::value_type& pair, values) {
handle_value(pair.second.value, pair.second.account, &xact, temps,
*handler);
if (pair.second.value.is_balance()) {
foreach (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);
} else {
handle_value(pair.second.value, pair.second.account, &xact, temps,
*handler);
}
total += pair.second.value;
}
values.clear();

View file

@ -466,7 +466,7 @@ public:
TRACE_DTOR(subtotal_posts);
}
void report_subtotal(const char * spec_fmt = NULL,
void report_subtotal(const char * spec_fmt = NULL,
const optional<date_interval_t>& interval = none);
virtual void flush() {

View file

@ -355,8 +355,11 @@ string format_t::real_calc(scope_t& scope)
}
DEBUG("format.expr", "value = (" << value << ")");
value.print(out, static_cast<int>(elem->min_width), -1,
! elem->has_flags(ELEMENT_ALIGN_LEFT));
if (elem->min_width > 0)
value.print(out, static_cast<int>(elem->min_width), -1,
! elem->has_flags(ELEMENT_ALIGN_LEFT));
else
out << value.to_string();
}
catch (const calc_error&) {
add_error_context(_("While calculating format expression:"));

View file

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

View file

@ -297,6 +297,11 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
return WRAP_FUNCTOR(get_wrapper<&get_account_base>);
break;
case 'b':
if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_cost>);
break;
case 'c':
if (name == "code")
return WRAP_FUNCTOR(get_wrapper<&get_code>);
@ -325,7 +330,9 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
break;
case 'i':
if (name == "id")
if (name == "index")
return WRAP_FUNCTOR(get_wrapper<&get_count>);
else if (name == "id")
return WRAP_FUNCTOR(get_wrapper<&get_id>);
else if (name == "idstring")
return WRAP_FUNCTOR(get_wrapper<&get_idstring>);
@ -339,6 +346,8 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
case 'n':
if (name == "note")
return WRAP_FUNCTOR(get_wrapper<&get_note>);
else if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_count>);
break;
case 'p':
@ -358,7 +367,7 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
break;
case 't':
if (name[1] == '\0' || name == "total")
if (name == "total")
return WRAP_FUNCTOR(get_wrapper<&get_total>);
break;
@ -376,6 +385,21 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
if (name == "xact")
return WRAP_FUNCTOR(get_wrapper<&get_xact>);
break;
case 'N':
if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_count>);
break;
case 'O':
if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_total>);
break;
case 'R':
if (name[1] == '\0')
return WRAP_FUNCTOR(get_wrapper<&get_real>);
break;
}
return item_t::lookup(kind, name);

View file

@ -135,13 +135,11 @@ public:
date_t date;
datetime_t datetime;
account_t * account;
void * ptr;
std::list<sort_value_t> sort_values;
xdata_t()
: supports_flags<uint_least16_t>(), count(0),
account(NULL), ptr(NULL) {
: supports_flags<uint_least16_t>(), count(0), account(NULL) {
TRACE_CTOR(post_t::xdata_t, "");
}
xdata_t(const xdata_t& other)
@ -152,7 +150,6 @@ public:
count(other.count),
date(other.date),
account(other.account),
ptr(NULL),
sort_values(other.sort_values)
{
TRACE_CTOR(post_t::xdata_t, "copy");

View file

@ -230,15 +230,18 @@ void export_journal()
class_< collect_posts, bases<item_handler<post_t> >,
shared_ptr<collect_posts>, boost::noncopyable >("PostCollector")
.def("__len__", &collect_posts::length)
.def("__iter__", range<return_internal_reference<> >
.def("__iter__", range<return_internal_reference<1,
with_custodian_and_ward_postcall<1, 0> > >
(&collect_posts::begin, &collect_posts::end))
;
class_< collector_wrapper, shared_ptr<collector_wrapper>,
boost::noncopyable >("PostCollectorWrapper", no_init)
.def("__len__", &collector_wrapper::length)
.def("__getitem__", posts_getitem, return_internal_reference<>())
.def("__iter__", range<return_internal_reference<> >
.def("__getitem__", posts_getitem, return_internal_reference<1,
with_custodian_and_ward_postcall<0, 1> >())
.def("__iter__", range<return_value_policy<reference_existing_object,
with_custodian_and_ward_postcall<0, 1> > >
(&collector_wrapper::begin, &collector_wrapper::end))
;
@ -263,30 +266,43 @@ void export_journal()
.def(init<path>())
.def(init<string>())
.add_property("master", make_getter(&journal_t::master,
return_internal_reference<>()))
.add_property("master",
make_getter(&journal_t::master,
return_internal_reference<1,
with_custodian_and_ward_postcall<1, 0> >()))
.add_property("bucket",
make_getter(&journal_t::bucket,
return_internal_reference<>()),
return_internal_reference<1,
with_custodian_and_ward_postcall<1, 0> >()),
make_setter(&journal_t::bucket))
.add_property("was_loaded", make_getter(&journal_t::was_loaded))
.add_property("commodity_pool",
make_getter(&journal_t::commodity_pool,
return_internal_reference<>()))
return_internal_reference<1,
with_custodian_and_ward_postcall<1, 0> >()))
.def("add_account", &journal_t::add_account)
.def("remove_account", &journal_t::remove_account)
.def("find_account", py_find_account_1, return_internal_reference<>())
.def("find_account", py_find_account_2, return_internal_reference<>())
.def("find_account", py_find_account_1,
return_internal_reference<1,
with_custodian_and_ward_postcall<0, 1> >())
.def("find_account", py_find_account_2,
return_internal_reference<1,
with_custodian_and_ward_postcall<0, 1> >())
.def("find_account_re", &journal_t::find_account_re,
return_internal_reference<>())
return_internal_reference<1,
with_custodian_and_ward_postcall<0, 1> >())
.def("add_xact", &journal_t::add_xact)
.def("remove_xact", &journal_t::remove_xact)
.def("__len__", xacts_len)
.def("__getitem__", xacts_getitem, return_internal_reference<>())
#if 0
.def("__getitem__", xacts_getitem,
return_internal_reference<1,
with_custodian_and_ward_postcall<0, 1> >())
#endif
.def("__iter__", range<return_internal_reference<> >
(&journal_t::xacts_begin, &journal_t::xacts_end))
@ -304,7 +320,7 @@ void export_journal()
.def("has_xdata", &journal_t::has_xdata)
.def("clear_xdata", &journal_t::clear_xdata)
.def("collect", py_collect)
.def("collect", py_collect, with_custodian_and_ward_postcall<0, 1>())
.def("valid", &journal_t::valid)
;

View file

@ -116,7 +116,7 @@ void export_post()
make_setter(&post_t::xdata_t::datetime))
.add_property("account",
make_getter(&post_t::xdata_t::account,
return_internal_reference<>()),
return_value_policy<reference_existing_object>()),
make_setter(&post_t::xdata_t::account,
with_custodian_and_ward<1, 2>()))
.add_property("sort_values",

View file

@ -296,6 +296,10 @@ value_t python_interpreter_t::python_command(call_scope_t& args)
try {
status = Py_Main(static_cast<int>(args.size()) + 1, argv);
}
catch (const error_already_set&) {
PyErr_Print();
throw_(std::runtime_error, _("Failed to execute Python module"));
}
catch (...) {
for (std::size_t i = 0; i < args.size() + 1; i++)
delete[] argv[i];

View file

@ -915,6 +915,45 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
switch (kind) {
case symbol_t::FUNCTION:
// Support 2.x's single-letter value expression names.
if (*(p + 1) == '\0') {
switch (*p) {
case 'd':
case 'm':
return MAKE_FUNCTOR(report_t::fn_now);
case 'P':
return MAKE_FUNCTOR(report_t::fn_market);
case 't':
return MAKE_FUNCTOR(report_t::fn_display_amount);
case 'T':
return MAKE_FUNCTOR(report_t::fn_display_total);
case 'U':
return MAKE_FUNCTOR(report_t::fn_abs);
case 'S':
return MAKE_FUNCTOR(report_t::fn_strip);
case 'i':
throw_(std::runtime_error,
_("The i value expression variable is no longer supported"));
case 'A':
throw_(std::runtime_error,
_("The A value expression variable is no longer supported"));
case 'v':
case 'V':
throw_(std::runtime_error,
_("The V and v value expression variables are no longer supported"));
case 'I':
case 'B':
throw_(std::runtime_error,
_("The I and B value expression variables are no longer supported"));
case 'g':
case 'G':
throw_(std::runtime_error,
_("The G and g value expression variables are no longer supported"));
default:
return NULL;
}
}
switch (*p) {
case 'a':
if (is_eq(p, "amount_expr"))

View file

@ -775,7 +775,7 @@ public:
"%(ansify_if(justify(format_date(date), date_width), green "
" if color & date > today))"
" %(ansify_if(justify(truncated(payee, payee_width), payee_width), "
" bold if color & !cleared))"
" bold if color & !cleared & actual))"
" %(ansify_if(justify(truncated(account, account_width, abbrev_len), "
" account_width), blue if color))"
" %(justify(scrub(display_amount), amount_width, "

View file

@ -1618,7 +1618,10 @@ void value_t::print(std::ostream& out,
break;
case STRING:
justify(out, as_string(), first_width, right_justify);
if (first_width > 0)
justify(out, as_string(), first_width, right_justify);
else
out << as_string();
break;
case MASK:

View file

@ -412,7 +412,7 @@ bool xact_base_t::verify()
continue;
if (post->amount.commodity() == post->cost->commodity())
throw_(balance_error,
throw_(amount_error,
_("A posting's cost must be of a different commodity than its amount"));
}
@ -538,6 +538,50 @@ bool xact_t::valid() const
return true;
}
namespace {
bool post_pred(expr_t::ptr_op_t op, post_t& post)
{
switch (op->kind) {
case expr_t::op_t::VALUE:
return op->as_value().to_boolean();
break;
case expr_t::op_t::O_MATCH:
if (op->left()->kind == expr_t::op_t::IDENT &&
op->left()->as_ident() == "account" &&
op->right()->kind == expr_t::op_t::VALUE &&
op->right()->as_value().is_mask())
return op->right()->as_value().as_mask()
.match(post.reported_account()->fullname());
else
break;
case expr_t::op_t::O_NOT:
return ! post_pred(op->left(), post);
case expr_t::op_t::O_AND:
return post_pred(op->left(), post) && post_pred(op->right(), post);
case expr_t::op_t::O_OR:
return post_pred(op->left(), post) || post_pred(op->right(), post);
case expr_t::op_t::O_QUERY:
if (post_pred(op->left(), post))
return post_pred(op->right()->left(), post);
else
return post_pred(op->right()->right(), post);
default:
break;
}
throw_(calc_error, _("Unhandled operator"));
return false;
}
} // unnamed namespace
void auto_xact_t::extend_xact(xact_base_t& xact)
{
posts_list initial_posts(xact.posts.begin(), xact.posts.end());
@ -547,8 +591,42 @@ void auto_xact_t::extend_xact(xact_base_t& xact)
bool needs_further_verification = false;
foreach (post_t * initial_post, initial_posts) {
if (! initial_post->has_flags(ITEM_GENERATED) &&
predicate(*initial_post)) {
if (initial_post->has_flags(ITEM_GENERATED))
continue;
bool matches_predicate = false;
if (try_quick_match) {
try {
bool found_memoized_result = false;
if (! memoized_results.empty()) {
std::map<string, bool>::iterator i =
memoized_results.find(initial_post->account->fullname());
if (i != memoized_results.end()) {
found_memoized_result = true;
matches_predicate = (*i).second;
}
}
// Since the majority of people who use automated transactions simply
// match against account names, try using a *much* faster version of
// the predicate evaluator.
if (! found_memoized_result) {
matches_predicate = post_pred(predicate.get_op(), *initial_post);
memoized_results.insert
(std::pair<string, bool>(initial_post->account->fullname(),
matches_predicate));
}
}
catch (...) {
DEBUG("xact.extend.fail",
"The quick matcher failed, going back to regular eval");
try_quick_match = false;
matches_predicate = predicate(*initial_post);
}
} else {
matches_predicate = predicate(*initial_post);
}
if (matches_predicate) {
foreach (post_t * post, posts) {
amount_t post_amount;
if (post->amount.is_null()) {

View file

@ -146,16 +146,20 @@ class auto_xact_t : public xact_base_t
{
public:
predicate_t predicate;
bool try_quick_match;
auto_xact_t() {
std::map<string, bool> memoized_results;
auto_xact_t() : try_quick_match(true) {
TRACE_CTOR(auto_xact_t, "");
}
auto_xact_t(const auto_xact_t& other)
: xact_base_t(), predicate(other.predicate) {
: xact_base_t(), predicate(other.predicate),
try_quick_match(other.try_quick_match) {
TRACE_CTOR(auto_xact_t, "copy");
}
auto_xact_t(const predicate_t& _predicate)
: predicate(_predicate)
: predicate(_predicate), try_quick_match(true)
{
TRACE_CTOR(auto_xact_t, "const predicate_t&");
}

View file

@ -0,0 +1,46 @@
reg --collapse food
<<<
2009/10/01 Test
Expenses:Food:Dining $10
Expenses:Food:Tips $1
Assets:Cash
2009/10/02 Test
Expenses:Food:Dining $10
Expenses:Food:Tips $1
Assets:Cash
2009/10/03 Test
Expenses:Food:Dining $10
Expenses:Food:Tips $1
Assets:Cash
2009/10/04 Test
Expenses:Food:Dining $10
Expenses:Food:Tips $1
Assets:Cash
2009/10/05 Test
Expenses:Food:Dining $10
Expenses:Food:Tips $1
Assets:Cash
2009/10/06 Test
Expenses:Food:Dining $10
Expenses:Food:Tips $1
Assets:Cash
2009/10/07 Test
Expenses:Food:Dining $10
Expenses:Food:Tips $1
Assets:Cash
>>>1
09-Oct-01 Test <Total> $11 $11
09-Oct-02 Test <Total> $11 $22
09-Oct-03 Test <Total> $11 $33
09-Oct-04 Test <Total> $11 $44
09-Oct-05 Test <Total> $11 $55
09-Oct-06 Test <Total> $11 $66
09-Oct-07 Test <Total> $11 $77
>>>2
=== 0

View file

@ -84,31 +84,31 @@ AC_CACHE_CHECK(
[AC_LANG_PUSH(C++)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>]],
[[int status, pfd[2];
status = pipe(pfd);
status = fork();
if (status < 0) {
;
} else if (status == 0) {
char *arg0 = NULL;
[[#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>]],
[[int status, pfd[2];
status = pipe(pfd);
status = fork();
if (status < 0) {
;
} else if (status == 0) {
char *arg0 = NULL;
status = dup2(pfd[0], STDIN_FILENO);
status = dup2(pfd[0], STDIN_FILENO);
close(pfd[1]);
close(pfd[0]);
close(pfd[1]);
close(pfd[0]);
execlp("", arg0, (char *)0);
perror("execl");
exit(1);
} else {
close(pfd[0]);
}]])],
execlp("", arg0, (char *)0);
perror("execl");
exit(1);
} else {
close(pfd[0]);
}]])],
[pipes_avail_cv_=true],
[pipes_avail_cv_=false])
AC_LANG_POP])
@ -213,7 +213,7 @@ AC_CACHE_CHECK(
using namespace boost;]],
[[std::string text = "Активы";
u32regex r = make_u32regex("активы", regex::perl | regex::icase);
return u32regex_search(text, r) ? 0 : 1;]])],
return u32regex_search(text, r) ? 0 : 1;]])],
[boost_regex_icu_avail_cv_=true],
[boost_regex_icu_avail_cv_=false])
AC_LANG_POP
@ -233,26 +233,26 @@ AC_CACHE_CHECK(
AC_LANG_PUSH(C++)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/local_time_adjustor.hpp>
#include <boost/date_time/time_duration.hpp>
[[#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/local_time_adjustor.hpp>
#include <boost/date_time/time_duration.hpp>
using namespace boost::posix_time;
using namespace boost::date_time;
using namespace boost::posix_time;
using namespace boost::date_time;
#include <ctime>
#include <ctime>
inline ptime time_to_system_local(const ptime& when) {
struct std::tm tm_gmt = to_tm(when);
return from_time_t(mktime(&tm_gmt));
}]],
[[ptime t10 = ptime(boost::gregorian::from_string("2007-01-15"),
ptime::time_duration_type());
inline ptime time_to_system_local(const ptime& when) {
struct std::tm tm_gmt = to_tm(when);
return from_time_t(mktime(&tm_gmt));
}]],
[[ptime t10 = ptime(boost::gregorian::from_string("2007-01-15"),
ptime::time_duration_type());
ptime t12 = time_to_system_local(t10);
ptime t12 = time_to_system_local(t10);
return t10 != t12;]])],
return t10 != t12;]])],
[boost_date_time_cpplib_avail_cv_=true],
[boost_date_time_cpplib_avail_cv_=false])
AC_LANG_POP
@ -273,8 +273,8 @@ AC_CACHE_CHECK(
AC_LANG_PUSH(C++)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <boost/filesystem/path.hpp>]],
[[boost::filesystem::path this_path("Hello");]])],
[[#include <boost/filesystem/path.hpp>]],
[[boost::filesystem::path this_path("Hello");]])],
[boost_filesystem_cpplib_avail_cv_=true],
[boost_filesystem_cpplib_avail_cv_=false])
AC_LANG_POP
@ -295,11 +295,11 @@ AC_CACHE_CHECK(
AC_LANG_PUSH(C++)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>]],
[[namespace io = boost::iostreams;
typedef io::stream<io::file_descriptor_sink> ofdstream;
ofdstream outstream(1);]])],
[[#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>]],
[[namespace io = boost::iostreams;
typedef io::stream<io::file_descriptor_sink> ofdstream;
ofdstream outstream(1);]])],
[boost_iostreams_cpplib_avail_cv_=true],
[boost_iostreams_cpplib_avail_cv_=false])
AC_LANG_POP
@ -320,7 +320,7 @@ AC_CACHE_CHECK(
AC_LANG_PUSH(C++)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <boost/archive/binary_oarchive.hpp>
[[#include <boost/archive/binary_oarchive.hpp>
#include <iostream>
struct foo {
int a;
@ -329,7 +329,7 @@ AC_CACHE_CHECK(
ar & a;
}
};]],
[[boost::archive::binary_oarchive oa(std::cout);
[[boost::archive::binary_oarchive oa(std::cout);
foo x;
oa << x;]])],
[boost_serialization_cpplib_avail_cv_=true],
@ -355,16 +355,16 @@ if [ test x$python = xtrue ]; then
LIBS="-lboost_python$BOOST_SUFFIX -lpython$PYTHON_VERSION $LIBS"
AC_LANG_PUSH(C++)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <boost/python.hpp>
using namespace boost::python;
class foo {};
BOOST_PYTHON_MODULE(samp) {
class_< foo > ("foo") ;
}]],
[[return 0]])],
[boost_python_cpplib_avail_cv_=true],
[boost_python_cpplib_avail_cv_=false])
[AC_LANG_PROGRAM(
[[#include <boost/python.hpp>
using namespace boost::python;
class foo {};
BOOST_PYTHON_MODULE(samp) {
class_< foo > ("foo") ;
}]],
[[return 0]])],
[boost_python_cpplib_avail_cv_=true],
[boost_python_cpplib_avail_cv_=false])
AC_LANG_POP
LIBS=$boost_python_save_libs])
@ -390,16 +390,16 @@ AC_CACHE_CHECK(
AC_LANG_PUSH(C++)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <cppunit/CompilerOutputter.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/TextTestProgressListener.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/XmlOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>]],
[[CPPUNIT_NS::TestResult controller;
CPPUNIT_NS::TestResultCollector result;]])],
[[#include <cppunit/CompilerOutputter.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/TextTestProgressListener.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/XmlOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>]],
[[CPPUNIT_NS::TestResult controller;
CPPUNIT_NS::TestResultCollector result;]])],
[cppunit_avail_cv_=true],
[cppunit_avail_cv_=false])
AC_LANG_POP

View file

@ -11,4 +11,5 @@ git rebase master
git push
git checkout master
./acprep upload
mv *.dmg* build
git checkout next