Merge branch 'next'
This commit is contained in:
commit
a2cb549b1d
53 changed files with 4092 additions and 439 deletions
|
|
@ -59,6 +59,7 @@ libledger_data_la_SOURCES = \
|
|||
src/timelog.cc \
|
||||
src/textual.cc \
|
||||
src/journal.cc \
|
||||
src/archive.cc \
|
||||
src/account.cc \
|
||||
src/xact.cc \
|
||||
src/post.cc \
|
||||
|
|
@ -118,6 +119,7 @@ pkginclude_HEADERS = \
|
|||
src/xact.h \
|
||||
src/account.h \
|
||||
src/journal.h \
|
||||
src/archive.h \
|
||||
src/timelog.h \
|
||||
src/iterators.h \
|
||||
src/compare.h \
|
||||
|
|
|
|||
61
README-1ST
Normal file
61
README-1ST
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
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.
|
||||
|
||||
===============================================================================
|
||||
|
||||
F.A.Q.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
- Q: The build fails saying it can't find utf8.h
|
||||
|
||||
A: You didn't run ./acprep update.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
- Q: Configure fails saying it can't find boost_regex
|
||||
|
||||
A: Look in config.log and search for "boost_regex", then scroll down a bit
|
||||
until you see the exact compile error. Usually it's failing because
|
||||
your include directory is different from anything acprep is expecting to
|
||||
see. It could also be failing because your Boost libraries have a
|
||||
custom "suffix" on them.
|
||||
|
||||
Let's say your Boost was installed in ~/boost, and every library has the
|
||||
suffix '-xgcc42'. This is what you would run:
|
||||
|
||||
CPPFLAGS=-I$HOME/boost acprep --boost=xgcc42 update
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
- Q: Configure fails saying it can't find MPFR
|
||||
|
||||
A: You need MPFR version 2.4.0 or higher. This version does not come with
|
||||
most Debian distributions, so you will need to build it.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
- Q: Something else fails, or Ledger crashes on startup
|
||||
|
||||
A: This, I am most interested in hearing about. Please e-mail me a copy of
|
||||
config.log and your build log to <johnw@newartisans.com>. Also, if
|
||||
Ledger is crashing, try running it under gdb like so:
|
||||
|
||||
$ gdb ledger
|
||||
(gdb) run <ARGS TO LEDGER>
|
||||
... runs till crash ...
|
||||
(gdb) bt
|
||||
|
||||
Send me that backtrace output, and the output from "ledger --version".
|
||||
|
||||
----------------------------------------------------------------------
|
||||
216
acprep
216
acprep
|
|
@ -293,7 +293,7 @@ class PrepareBuild(CommandLineApp):
|
|||
else:
|
||||
cmd = 'config'
|
||||
|
||||
self.log.debug('Invoking primary phase: ' + cmd)
|
||||
self.log.info('Invoking primary phase: ' + cmd)
|
||||
PrepareBuild.__dict__['phase_' + cmd](self, *args)
|
||||
|
||||
#########################################################################
|
||||
|
|
@ -364,7 +364,7 @@ class PrepareBuild(CommandLineApp):
|
|||
|
||||
def ensure(self, dirname):
|
||||
if not exists(dirname):
|
||||
self.log.debug('Making directory: ' + dirname)
|
||||
self.log.info('Making directory: ' + dirname)
|
||||
os.makedirs(dirname)
|
||||
elif not isdir(dirname):
|
||||
self.log.error('Directory is not a directory: ' + dirname)
|
||||
|
|
@ -396,11 +396,11 @@ class PrepareBuild(CommandLineApp):
|
|||
return False
|
||||
|
||||
def phase_products(self, *args):
|
||||
self.log.debug('Executing phase: products')
|
||||
self.log.info('Executing phase: products')
|
||||
print self.products_directory()
|
||||
|
||||
def phase_info(self, *args):
|
||||
self.log.debug('Executing phase: info')
|
||||
self.log.info('Executing phase: info')
|
||||
|
||||
environ, conf_args = self.configure_environment()
|
||||
|
||||
|
|
@ -433,7 +433,7 @@ class PrepareBuild(CommandLineApp):
|
|||
self.log.debug(' %s' % arg)
|
||||
|
||||
def phase_sloc(self, *args):
|
||||
self.log.debug('Executing phase: sloc')
|
||||
self.log.info('Executing phase: sloc')
|
||||
self.execute('sloccount', 'src', 'python', 'lisp', 'test')
|
||||
|
||||
#########################################################################
|
||||
|
|
@ -441,13 +441,13 @@ class PrepareBuild(CommandLineApp):
|
|||
#########################################################################
|
||||
|
||||
def phase_gettext(self, *args):
|
||||
self.log.debug('Executing phase: gettext')
|
||||
self.log.info('Executing phase: gettext')
|
||||
|
||||
# configure the template files
|
||||
assert exists('po') and isdir('po')
|
||||
if not exists(join('po', 'Makevars')):
|
||||
assert exists(join('po', 'Makevars.template'))
|
||||
self.log.debug('Moving po/Makevars.template -> po/Makevars')
|
||||
self.log.info('Moving po/Makevars.template -> po/Makevars')
|
||||
os.rename(join('po', 'Makevars.template'),
|
||||
join('po', 'Makevars'))
|
||||
|
||||
|
|
@ -460,22 +460,36 @@ class PrepareBuild(CommandLineApp):
|
|||
POTFILES_in.close()
|
||||
|
||||
def phase_version(self, *args):
|
||||
self.log.debug('Executing phase: version')
|
||||
self.log.info('Executing phase: version')
|
||||
version_m4 = open('version.m4', 'w')
|
||||
version_m4.write("m4_define([VERSION_NUMBER], [%s])" %
|
||||
self.current_version())
|
||||
version_m4.close()
|
||||
|
||||
def phase_autogen(self, *args):
|
||||
self.log.debug('Executing phase: autogen')
|
||||
self.execute('sh', 'autogen.sh')
|
||||
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.execute('sh', 'tools/autogen.sh')
|
||||
|
||||
def phase_aclocal(self, *args):
|
||||
self.log.debug('Executing phase: aclocal')
|
||||
self.log.info('Executing phase: aclocal')
|
||||
self.execute('aclocal', '-I', 'm4')
|
||||
|
||||
def phase_autoconf(self, *args):
|
||||
self.log.debug('Executing phase: autoconf')
|
||||
self.log.info('Executing phase: autoconf')
|
||||
|
||||
if not exists('configure.ac') or \
|
||||
self.isnewer('tools/configure.ac', 'configure.ac'):
|
||||
shutil.copyfile('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')
|
||||
|
||||
reason = self.need_to_prepare_autotools()
|
||||
if reason:
|
||||
self.log.info('autogen.sh must be run ' + reason)
|
||||
|
|
@ -491,13 +505,13 @@ class PrepareBuild(CommandLineApp):
|
|||
#########################################################################
|
||||
|
||||
def phase_submodule(self, *args):
|
||||
self.log.debug('Executing phase: submodule')
|
||||
self.log.info('Executing phase: submodule')
|
||||
if exists('.git') and isdir('.git'):
|
||||
self.execute('git', 'submodule', 'init')
|
||||
self.execute('git', 'submodule', 'update')
|
||||
|
||||
def phase_pull(self, *args):
|
||||
self.log.debug('Executing phase: pull')
|
||||
self.log.info('Executing phase: pull')
|
||||
if not exists('.git') and not isdir('.git'):
|
||||
self.log.error("This is not a Git clone.")
|
||||
sys.exit(1)
|
||||
|
|
@ -509,7 +523,7 @@ class PrepareBuild(CommandLineApp):
|
|||
#########################################################################
|
||||
|
||||
def phase_dependencies(self, *args):
|
||||
self.log.debug('Executing phase: dependencies')
|
||||
self.log.info('Executing phase: dependencies')
|
||||
|
||||
self.log.info("Installing Ledger's build dependencies ...")
|
||||
|
||||
|
|
@ -581,7 +595,7 @@ class PrepareBuild(CommandLineApp):
|
|||
self.execute(*packages)
|
||||
|
||||
def phase_buildlibs(self, *args):
|
||||
self.log.debug('Executing phase: buildlibs')
|
||||
self.log.info('Executing phase: buildlibs')
|
||||
|
||||
try:
|
||||
os.chdir('lib')
|
||||
|
|
@ -645,12 +659,12 @@ class PrepareBuild(CommandLineApp):
|
|||
entries.sort()
|
||||
for entry in entries:
|
||||
if re.search('boost_regex', entry):
|
||||
self.log.debug('Found a Boost library: ' + entry)
|
||||
self.log.info('Found a Boost library: ' + entry)
|
||||
|
||||
match = re.match('libboost_regex([^.]*)\.(a|so|dylib)', entry)
|
||||
if match:
|
||||
suffix = match.group(1)
|
||||
self.log.debug('Found Boost suffix => ' + suffix)
|
||||
self.log.info('Found Boost suffix => ' + suffix)
|
||||
self.envvars['BOOST_HOME'] = dirname(path)
|
||||
return suffix
|
||||
else:
|
||||
|
|
@ -660,20 +674,20 @@ class PrepareBuild(CommandLineApp):
|
|||
|
||||
def locate_boost(self):
|
||||
if self.envvars['BOOST_SUFFIX']:
|
||||
self.log.debug(("Not looking for Boost, since " +
|
||||
self.log.info(("Not looking for Boost, since " +
|
||||
"a suffix of '%s' was given") %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
else:
|
||||
suffix = None
|
||||
for path in ['/usr/local/lib', '/opt/local/lib',
|
||||
'/sw/lib', '/usr/lib']:
|
||||
self.log.debug('Looking for Boost in %s...' % path)
|
||||
self.log.info('Looking for Boost in %s...' % path)
|
||||
suffix = self.locate_boost_in_dir(path)
|
||||
if suffix is not None:
|
||||
self.log.debug('Boost is located here:')
|
||||
self.log.debug('BOOST_HOME => ' +
|
||||
self.log.info('Boost is located here:')
|
||||
self.log.info('BOOST_HOME => ' +
|
||||
self.envvars['BOOST_HOME'])
|
||||
self.log.debug('BOOST_SUFFIX => ' + suffix)
|
||||
self.log.info('BOOST_SUFFIX => ' + suffix)
|
||||
break
|
||||
if suffix is None:
|
||||
self.log.error("Boost could not be found.")
|
||||
|
|
@ -695,7 +709,7 @@ class PrepareBuild(CommandLineApp):
|
|||
'/sw/include']:
|
||||
if exists(path) and isdir(path) and \
|
||||
path != '/usr/include':
|
||||
self.log.debug('Noticing include directory => ' + path)
|
||||
self.log.info('Noticing include directory => ' + path)
|
||||
self.sys_include_dirs.append(path)
|
||||
|
||||
# Each of these becomes '-L<name>'
|
||||
|
|
@ -707,17 +721,19 @@ class PrepareBuild(CommandLineApp):
|
|||
'/opt/local/lib',
|
||||
'/sw/lib']:
|
||||
if exists(path) and isdir(path):
|
||||
self.log.debug('Noticing library directory => ' + path)
|
||||
self.log.info('Noticing library directory => ' + path)
|
||||
self.sys_library_dirs.append(path)
|
||||
|
||||
def setup_for_johnw(self):
|
||||
# jww (2009-03-09): Some peculiarities specific to my system
|
||||
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('/Users/johnw/Dropbox/Accounts/ledger.dat'):
|
||||
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')
|
||||
|
||||
self.CXXFLAGS.append('-march=nocona')
|
||||
self.CXXFLAGS.append('-msse3')
|
||||
self.CPPFLAGS.append('-D_GLIBCXX_FULLY_DYNAMIC_STRING=1')
|
||||
|
||||
self.options.use_glibcxx_debug = True
|
||||
|
||||
|
|
@ -726,7 +742,7 @@ class PrepareBuild(CommandLineApp):
|
|||
|
||||
system = self.get_stdout('uname', '-s')
|
||||
|
||||
self.log.debug('System type is => ' + system)
|
||||
self.log.info('System type is => ' + system)
|
||||
|
||||
# These options are global defaults at the moment
|
||||
#self.option_warn()
|
||||
|
|
@ -796,7 +812,7 @@ class PrepareBuild(CommandLineApp):
|
|||
self.log.error('Unknown build flavor "%s"' % self.current_flavor)
|
||||
sys.exit(1)
|
||||
|
||||
self.log.debug('Setting up build flavor => ' + self.current_flavor)
|
||||
self.log.info('Setting up build flavor => ' + self.current_flavor)
|
||||
PrepareBuild.__dict__['setup_flavor_' + self.current_flavor](self)
|
||||
|
||||
self.setup_flags()
|
||||
|
|
@ -927,23 +943,23 @@ class PrepareBuild(CommandLineApp):
|
|||
#########################################################################
|
||||
|
||||
def setup_flavor_default(self):
|
||||
if 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.log.debug('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
|
||||
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
|
||||
|
||||
elif exists('/opt/local/lib/libboost_regex.a'):
|
||||
if exists('/opt/local/lib/libboost_regex.a'):
|
||||
self.envvars['BOOST_HOME'] = '/opt/local'
|
||||
self.envvars['BOOST_SUFFIX'] = ''
|
||||
|
||||
self.log.debug('Setting BOOST_SUFFIX => %s' %
|
||||
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-s-1_40.a'):
|
||||
self.envvars['BOOST_HOME'] = '/usr/local'
|
||||
self.envvars['BOOST_SUFFIX'] = '-xgcc44-s-1_40'
|
||||
self.log.info('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
|
||||
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
|
||||
|
||||
def setup_flavor_debug(self):
|
||||
self.configure_args.append('--enable-debug')
|
||||
|
||||
|
|
@ -960,64 +976,65 @@ class PrepareBuild(CommandLineApp):
|
|||
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')
|
||||
if exists('/usr/local/stow/cppunit-debug/include'):
|
||||
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/lib/libboost_regex-xgcc44-sd-1_40.a'):
|
||||
self.envvars['BOOST_HOME'] = '/usr/local'
|
||||
self.envvars['BOOST_SUFFIX'] = '-xgcc44-sd-1_40'
|
||||
self.log.debug('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
|
||||
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
|
||||
|
||||
elif exists('/opt/local/lib/libboost_regex-d.a'):
|
||||
if exists('/opt/local/lib/libboost_regex-d.a'):
|
||||
self.envvars['BOOST_HOME'] = '/opt/local'
|
||||
self.envvars['BOOST_SUFFIX'] = '-d'
|
||||
|
||||
self.log.debug('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
self.log.info('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
|
||||
self.sys_include_dirs.append('/opt/local/include/boost')
|
||||
else:
|
||||
if exists('/usr/local/lib/libboost_regex-xgcc44-s-1_40.a'):
|
||||
|
||||
elif exists('/usr/local/lib/libboost_regex-xgcc44-sd-1_40.a'):
|
||||
self.envvars['BOOST_HOME'] = '/usr/local'
|
||||
self.envvars['BOOST_SUFFIX'] = '-xgcc44-s-1_40'
|
||||
self.log.debug('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
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')
|
||||
|
||||
elif exists('/opt/local/lib/libboost_regex.a'):
|
||||
else:
|
||||
if exists('/opt/local/lib/libboost_regex.a'):
|
||||
self.envvars['BOOST_HOME'] = '/opt/local'
|
||||
self.envvars['BOOST_SUFFIX'] = ''
|
||||
|
||||
self.log.debug('Setting BOOST_SUFFIX => %s' %
|
||||
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-s-1_40.a'):
|
||||
self.envvars['BOOST_HOME'] = '/usr/local'
|
||||
self.envvars['BOOST_SUFFIX'] = '-xgcc44-s-1_40'
|
||||
self.log.info('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
|
||||
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
|
||||
|
||||
def setup_flavor_opt(self):
|
||||
self.CXXFLAGS.append('-O3')
|
||||
self.CXXFLAGS.append('-fomit-frame-pointer')
|
||||
|
||||
if 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.log.debug('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
|
||||
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
|
||||
|
||||
elif exists('/opt/local/lib/libboost_regex.a'):
|
||||
if exists('/opt/local/lib/libboost_regex.a'):
|
||||
self.envvars['BOOST_HOME'] = '/opt/local'
|
||||
self.envvars['BOOST_SUFFIX'] = ''
|
||||
|
||||
self.log.debug('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
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-s-1_40.a'):
|
||||
self.envvars['BOOST_HOME'] = '/usr/local'
|
||||
self.envvars['BOOST_SUFFIX'] = '-xgcc44-s-1_40'
|
||||
self.log.info('Setting BOOST_SUFFIX => %s' %
|
||||
self.envvars['BOOST_SUFFIX'])
|
||||
|
||||
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
|
||||
|
||||
def setup_flavor_gcov(self):
|
||||
self.CXXFLAGS.append('-g')
|
||||
self.CXXFLAGS.append('-fprofile-arcs')
|
||||
|
|
@ -1038,7 +1055,7 @@ class PrepareBuild(CommandLineApp):
|
|||
"""Alter the Makefile so that it's not nearly so verbose.
|
||||
|
||||
This makes errors and warnings much easier to spot."""
|
||||
self.log.debug('Executing phase: patch')
|
||||
self.log.info('Executing phase: patch')
|
||||
|
||||
if exists('Makefile'):
|
||||
self.log.debug('Patching generated Makefile')
|
||||
|
|
@ -1108,7 +1125,7 @@ class PrepareBuild(CommandLineApp):
|
|||
return False
|
||||
|
||||
def phase_configure(self, *args):
|
||||
self.log.debug('Executing phase: configure')
|
||||
self.log.info('Executing phase: configure')
|
||||
|
||||
self.configured = True
|
||||
|
||||
|
|
@ -1130,7 +1147,10 @@ class PrepareBuild(CommandLineApp):
|
|||
self.log.debug('configure args => ' + str(conf_args))
|
||||
|
||||
configure = Popen(conf_args, shell=False, env=environ)
|
||||
configure.wait()
|
||||
retcode = configure.wait()
|
||||
if retcode < 0:
|
||||
self.log.error("Child was terminated by signal", -retcode)
|
||||
sys.exit(1)
|
||||
|
||||
if not self.options.no_patch:
|
||||
self.phase_patch()
|
||||
|
|
@ -1145,7 +1165,7 @@ class PrepareBuild(CommandLineApp):
|
|||
os.chdir(self.source_dir)
|
||||
|
||||
def phase_config(self, *args):
|
||||
self.log.debug('Executing phase: config')
|
||||
self.log.info('Executing phase: config')
|
||||
self.phase_submodule()
|
||||
self.phase_autoconf()
|
||||
self.phase_configure(*args)
|
||||
|
|
@ -1157,7 +1177,7 @@ class PrepareBuild(CommandLineApp):
|
|||
#########################################################################
|
||||
|
||||
def phase_make(self, *args):
|
||||
self.log.debug('Executing phase: make')
|
||||
self.log.info('Executing phase: make')
|
||||
|
||||
config_args = []
|
||||
make_args = []
|
||||
|
|
@ -1182,15 +1202,12 @@ class PrepareBuild(CommandLineApp):
|
|||
self.log.debug('Changing directory to ' + build_dir)
|
||||
os.chdir(build_dir)
|
||||
|
||||
self.log.debug('make args => ' + str(make_args))
|
||||
|
||||
configure = Popen(['make'] + make_args, shell=False)
|
||||
configure.wait()
|
||||
self.execute(*(['make'] + make_args))
|
||||
finally:
|
||||
os.chdir(self.source_dir)
|
||||
|
||||
def phase_update(self, *args):
|
||||
self.log.debug('Executing phase: update')
|
||||
self.log.info('Executing phase: update')
|
||||
self.phase_pull()
|
||||
self.phase_make(*args)
|
||||
|
||||
|
|
@ -1199,15 +1216,15 @@ class PrepareBuild(CommandLineApp):
|
|||
#########################################################################
|
||||
|
||||
def phase_clean(self, *args):
|
||||
self.log.debug('Executing phase: clean')
|
||||
self.log.info('Executing phase: clean')
|
||||
self.phase_make('clean')
|
||||
|
||||
def phase_distclean(self, *args):
|
||||
self.log.debug('Executing phase: distclean')
|
||||
self.log.info('Executing phase: distclean')
|
||||
self.phase_make('distclean')
|
||||
|
||||
def phase_gitclean(self, *args):
|
||||
self.log.debug('Executing phase: gitclean')
|
||||
self.log.info('Executing phase: gitclean')
|
||||
self.execute('git', 'clean', '-dfx')
|
||||
|
||||
#########################################################################
|
||||
|
|
@ -1238,7 +1255,7 @@ class PrepareBuild(CommandLineApp):
|
|||
'@loader_path/' + base, dest_file)
|
||||
|
||||
def phase_bindmg(self, *args):
|
||||
self.log.debug('Executing phase: bindmg')
|
||||
self.log.info('Executing phase: bindmg')
|
||||
|
||||
self.phase_make()
|
||||
|
||||
|
|
@ -1263,7 +1280,7 @@ class PrepareBuild(CommandLineApp):
|
|||
shutil.rmtree(tempdir)
|
||||
|
||||
def phase_upload(self, *args):
|
||||
self.log.debug('Executing phase: upload')
|
||||
self.log.info('Executing phase: upload')
|
||||
|
||||
self.phase_bindmg()
|
||||
|
||||
|
|
@ -1295,7 +1312,7 @@ class PrepareBuild(CommandLineApp):
|
|||
shutil.rmtree(self.build_directory())
|
||||
|
||||
def phase_distcheck(self, *args):
|
||||
self.log.debug('Executing phase: distcheck')
|
||||
self.log.info('Executing phase: distcheck')
|
||||
|
||||
self.configure_flavor('default', False)
|
||||
|
||||
|
|
@ -1320,7 +1337,7 @@ class PrepareBuild(CommandLineApp):
|
|||
self.phase_make(*make_args)
|
||||
|
||||
def phase_rsync(self, *args):
|
||||
self.log.debug('Executing phase: rsync')
|
||||
self.log.info('Executing phase: rsync')
|
||||
|
||||
source_copy_dir = join(self.ensure(self.products_directory()),
|
||||
'ledger-proof')
|
||||
|
|
@ -1332,32 +1349,28 @@ class PrepareBuild(CommandLineApp):
|
|||
self.source_dir = source_copy_dir
|
||||
|
||||
def phase_proof(self, *args):
|
||||
self.log.debug('Executing phase: proof')
|
||||
self.log.info('Executing phase: proof')
|
||||
|
||||
self.phase_makeall(*args)
|
||||
|
||||
self.log.info('=== Copying source tree ===')
|
||||
self.phase_rsync()
|
||||
|
||||
self.phase_makeall(*args)
|
||||
|
||||
self.configure_flavor('opt')
|
||||
self.log.info('=== Building opt ===')
|
||||
self.phase_make(*args)
|
||||
self.log.info('=== Testing opt ===')
|
||||
self.phase_make('fullcheck')
|
||||
|
||||
self.configure_flavor('gcov')
|
||||
self.log.info('=== Building gcov ===')
|
||||
self.phase_make(*args)
|
||||
self.log.info('=== Testing gcov ===')
|
||||
self.phase_make('check')
|
||||
|
||||
self.configure_flavor('debug')
|
||||
self.log.info('=== Building debug ===')
|
||||
self.phase_make(*args)
|
||||
self.log.info('=== Testing debug ===')
|
||||
self.phase_make('fullcheck')
|
||||
|
||||
self.configure_flavor('default')
|
||||
self.log.info('=== Building default ===')
|
||||
self.phase_make(*args)
|
||||
self.log.info('=== Testing default ===')
|
||||
self.phase_make('fullcheck')
|
||||
|
||||
|
|
@ -1365,7 +1378,7 @@ class PrepareBuild(CommandLineApp):
|
|||
self.phase_distcheck()
|
||||
|
||||
def phase_makeall(self, *args):
|
||||
self.log.debug('Executing phase: makeall')
|
||||
self.log.info('Executing phase: makeall')
|
||||
|
||||
self.configure_flavor('opt', False)
|
||||
|
||||
|
|
@ -1403,11 +1416,6 @@ class PrepareBuild(CommandLineApp):
|
|||
|
||||
self.configure_flavor('default', False)
|
||||
|
||||
def phase_do_all(self, *args):
|
||||
self.log.debug('Executing phase: do_all')
|
||||
self.phase_makeall(*args)
|
||||
self.phase_proof(*args)
|
||||
|
||||
#########################################################################
|
||||
# Help #
|
||||
#########################################################################
|
||||
|
|
|
|||
0
autogen.sh
Executable file → Normal file
0
autogen.sh
Executable file → Normal file
32
configure.ac
32
configure.ac
|
|
@ -280,6 +280,38 @@ else
|
|||
AC_MSG_FAILURE("Could not find boost_iostreams library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for boost_serialization
|
||||
AC_CACHE_CHECK(
|
||||
[if boost_serialization is available],
|
||||
[boost_serialization_cpplib_avail_cv_],
|
||||
[boost_serialization_save_libs=$LIBS
|
||||
LIBS="-lboost_serialization$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <boost/archive/binary_oarchive.hpp>
|
||||
#include <iostream>
|
||||
struct foo {
|
||||
int a;
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int) {
|
||||
ar & a;
|
||||
}
|
||||
};]],
|
||||
[[boost::archive::binary_oarchive oa(std::cout);
|
||||
foo x;
|
||||
oa << x;]])],
|
||||
[boost_serialization_cpplib_avail_cv_=true],
|
||||
[boost_serialization_cpplib_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$boost_serialization_save_libs])
|
||||
|
||||
if [test x$boost_serialization_cpplib_avail_cv_ = xtrue ]; then
|
||||
AC_DEFINE([HAVE_BOOST_SERIALIZATION], [1], [Whether Boost.Serialization is available])
|
||||
LIBS="-lboost_serialization$BOOST_SUFFIX $LIBS"
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_BOOST_SERIALIZATION, test x$boost_serialization_cpplib_avail_cv_ = xtrue)
|
||||
|
||||
# check for Python
|
||||
AM_PATH_PYTHON(2.4,, :)
|
||||
if [test "$PYTHON" != :]; then
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
;; Emacs Lisp Archive Entry
|
||||
;; Filename: ledger.el
|
||||
;; Version: 2.7
|
||||
;; Version: 3.0
|
||||
;; Date: Fri 18-Jul-2008
|
||||
;; Keywords: data
|
||||
;; Author: John Wiegley (johnw AT gnu DOT org)
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ void account_t::xdata_t::details_t::update(post_t& post,
|
|||
posts_virtuals_count++;
|
||||
|
||||
if (gather_all)
|
||||
filenames.insert(post.pathname);
|
||||
filenames.insert(post.pos->pathname);
|
||||
|
||||
date_t date = post.date();
|
||||
|
||||
|
|
|
|||
|
|
@ -232,6 +232,26 @@ public:
|
|||
return xdata_ && xdata_->has_flags(flags);
|
||||
}
|
||||
std::size_t children_with_flags(xdata_t::flags_t flags) const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<supports_flags<> >(*this);
|
||||
ar & boost::serialization::base_object<scope_t>(*this);
|
||||
ar & parent;
|
||||
ar & name;
|
||||
ar & note;
|
||||
ar & depth;
|
||||
ar & accounts;
|
||||
ar & posts;
|
||||
ar & _fullname;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const account_t& account);
|
||||
|
|
|
|||
101
src/amount.cc
101
src/amount.cc
|
|
@ -56,25 +56,25 @@ struct amount_t::bigint_t : public supports_flags<>
|
|||
|
||||
mpq_t val;
|
||||
precision_t prec;
|
||||
uint_least16_t ref;
|
||||
uint_least16_t refc;
|
||||
|
||||
#define MP(bigint) ((bigint)->val)
|
||||
|
||||
bigint_t() : prec(0), ref(1) {
|
||||
bigint_t() : prec(0), refc(1) {
|
||||
TRACE_CTOR(bigint_t, "");
|
||||
mpq_init(val);
|
||||
}
|
||||
bigint_t(const bigint_t& other)
|
||||
: supports_flags<>(static_cast<uint_least8_t>
|
||||
(other.flags() & ~BIGINT_BULK_ALLOC)),
|
||||
prec(other.prec), ref(1) {
|
||||
prec(other.prec), refc(1) {
|
||||
TRACE_CTOR(bigint_t, "copy");
|
||||
mpq_init(val);
|
||||
mpq_set(val, other.val);
|
||||
}
|
||||
~bigint_t() {
|
||||
TRACE_DTOR(bigint_t);
|
||||
assert(ref == 0);
|
||||
assert(refc == 0);
|
||||
mpq_clear(val);
|
||||
}
|
||||
|
||||
|
|
@ -83,8 +83,8 @@ struct amount_t::bigint_t : public supports_flags<>
|
|||
DEBUG("ledger.validate", "amount_t::bigint_t: prec > 128");
|
||||
return false;
|
||||
}
|
||||
if (ref > 16535) {
|
||||
DEBUG("ledger.validate", "amount_t::bigint_t: ref > 16535");
|
||||
if (refc > 16535) {
|
||||
DEBUG("ledger.validate", "amount_t::bigint_t: refc > 16535");
|
||||
return false;
|
||||
}
|
||||
if (flags() & ~(BIGINT_BULK_ALLOC | BIGINT_KEEP_PREC)) {
|
||||
|
|
@ -94,6 +94,20 @@ struct amount_t::bigint_t : public supports_flags<>
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& ar, const unsigned int /* version */)
|
||||
{
|
||||
ar & boost::serialization::base_object<supports_flags<> >(*this);
|
||||
ar & val;
|
||||
ar & prec;
|
||||
ar & refc;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
shared_ptr<commodity_pool_t> amount_t::current_pool;
|
||||
|
|
@ -147,8 +161,8 @@ void amount_t::_copy(const amount_t& amt)
|
|||
} else {
|
||||
quantity = amt.quantity;
|
||||
DEBUG("amounts.refs",
|
||||
quantity << " ref++, now " << (quantity->ref + 1));
|
||||
quantity->ref++;
|
||||
quantity << " refc++, now " << (quantity->refc + 1));
|
||||
quantity->refc++;
|
||||
}
|
||||
}
|
||||
commodity_ = amt.commodity_;
|
||||
|
|
@ -160,7 +174,7 @@ void amount_t::_dup()
|
|||
{
|
||||
VERIFY(valid());
|
||||
|
||||
if (quantity->ref > 1) {
|
||||
if (quantity->refc > 1) {
|
||||
bigint_t * q = new bigint_t(*quantity);
|
||||
_release();
|
||||
quantity = q;
|
||||
|
|
@ -184,9 +198,9 @@ void amount_t::_release()
|
|||
{
|
||||
VERIFY(valid());
|
||||
|
||||
DEBUG("amounts.refs", quantity << " ref--, now " << (quantity->ref - 1));
|
||||
DEBUG("amounts.refs", quantity << " refc--, now " << (quantity->refc - 1));
|
||||
|
||||
if (--quantity->ref == 0) {
|
||||
if (--quantity->refc == 0) {
|
||||
if (quantity->has_flags(BIGINT_BULK_ALLOC))
|
||||
quantity->~bigint_t();
|
||||
else
|
||||
|
|
@ -920,7 +934,7 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
|
|||
quantity = new bigint_t;
|
||||
safe_holder.reset(quantity);
|
||||
}
|
||||
else if (quantity->ref > 1) {
|
||||
else if (quantity->refc > 1) {
|
||||
_release();
|
||||
quantity = new bigint_t;
|
||||
safe_holder.reset(quantity);
|
||||
|
|
@ -1095,8 +1109,8 @@ bool amount_t::valid() const
|
|||
return false;
|
||||
}
|
||||
|
||||
if (quantity->ref == 0) {
|
||||
DEBUG("ledger.validate", "amount_t: quantity->ref == 0");
|
||||
if (quantity->refc == 0) {
|
||||
DEBUG("ledger.validate", "amount_t: quantity->refc == 0");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1107,4 +1121,63 @@ bool amount_t::valid() const
|
|||
return true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
|
||||
template<class Archive>
|
||||
void amount_t::serialize(Archive& ar, const unsigned int /* version */)
|
||||
{
|
||||
ar & current_pool;
|
||||
ar & is_initialized;
|
||||
ar & quantity;
|
||||
ar & commodity_;
|
||||
}
|
||||
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, MP_INT& mpz, const unsigned int /* version */)
|
||||
{
|
||||
ar & mpz._mp_alloc;
|
||||
ar & mpz._mp_size;
|
||||
ar & mpz._mp_d;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, MP_RAT& mpq, const unsigned int /* version */)
|
||||
{
|
||||
ar & mpq._mp_num;
|
||||
ar & mpq._mp_den;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, long unsigned int& integer,
|
||||
const unsigned int /* version */)
|
||||
{
|
||||
ar & make_binary_object(&integer, sizeof(long unsigned int));
|
||||
}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
BOOST_CLASS_EXPORT(ledger::annotated_commodity_t)
|
||||
|
||||
template void boost::serialization::serialize(boost::archive::binary_oarchive&,
|
||||
MP_INT&, const unsigned int);
|
||||
template void boost::serialization::serialize(boost::archive::binary_iarchive&,
|
||||
MP_RAT&, const unsigned int);
|
||||
template void boost::serialization::serialize(boost::archive::binary_iarchive&,
|
||||
long unsigned int&,
|
||||
const unsigned int);
|
||||
|
||||
template void ledger::amount_t::serialize(boost::archive::binary_oarchive&,
|
||||
const unsigned int);
|
||||
template void ledger::amount_t::serialize(boost::archive::binary_iarchive&,
|
||||
const unsigned int);
|
||||
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
|
|
|
|||
10
src/amount.h
10
src/amount.h
|
|
@ -691,6 +691,16 @@ public:
|
|||
|
||||
bool valid() const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */);
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
|
||||
/*@}*/
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,21 @@ struct annotation_t : public supports_flags<>,
|
|||
assert(*this);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<supports_flags<> >(*this);
|
||||
ar & price;
|
||||
ar & date;
|
||||
ar & tag;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
struct keep_details_t
|
||||
|
|
@ -136,6 +151,21 @@ struct keep_details_t
|
|||
return keep_price || keep_date || keep_tag;
|
||||
}
|
||||
bool keep_any(const commodity_t& comm) const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & keep_price;
|
||||
ar & keep_date;
|
||||
ar & keep_tag;
|
||||
ar & only_actuals;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out,
|
||||
|
|
@ -183,6 +213,22 @@ public:
|
|||
|
||||
virtual commodity_t& strip_annotations(const keep_details_t& what_to_keep);
|
||||
virtual void write_annotations(std::ostream& out) const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
explicit annotated_commodity_t() : ptr(NULL) {}
|
||||
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<commodity_t>(*this);
|
||||
ar & ptr;
|
||||
ar & details;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
inline annotated_commodity_t&
|
||||
|
|
|
|||
247
src/archive.cc
Normal file
247
src/archive.cc
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <system.hh>
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
|
||||
#include "archive.h"
|
||||
#include "amount.h"
|
||||
#include "commodity.h"
|
||||
#include "pool.h"
|
||||
#include "scope.h"
|
||||
#include "account.h"
|
||||
#include "post.h"
|
||||
#include "xact.h"
|
||||
|
||||
#define ARCHIVE_VERSION 0x03000001
|
||||
|
||||
//BOOST_IS_ABSTRACT(ledger::scope_t)
|
||||
BOOST_CLASS_EXPORT(ledger::scope_t)
|
||||
BOOST_CLASS_EXPORT(ledger::child_scope_t)
|
||||
BOOST_CLASS_EXPORT(ledger::symbol_scope_t)
|
||||
BOOST_CLASS_EXPORT(ledger::call_scope_t)
|
||||
BOOST_CLASS_EXPORT(ledger::account_t)
|
||||
BOOST_CLASS_EXPORT(ledger::item_t)
|
||||
BOOST_CLASS_EXPORT(ledger::post_t)
|
||||
BOOST_CLASS_EXPORT(ledger::xact_base_t)
|
||||
BOOST_CLASS_EXPORT(ledger::xact_t)
|
||||
BOOST_CLASS_EXPORT(ledger::auto_xact_t)
|
||||
BOOST_CLASS_EXPORT(ledger::period_xact_t)
|
||||
|
||||
template void ledger::journal_t::serialize(boost::archive::binary_oarchive&,
|
||||
const unsigned int);
|
||||
template void ledger::journal_t::serialize(boost::archive::binary_iarchive&,
|
||||
const unsigned int);
|
||||
namespace ledger {
|
||||
|
||||
void archive_t::read_header()
|
||||
{
|
||||
if (exists(file)) {
|
||||
// Open the stream, read the version number and the list of sources
|
||||
ifstream stream(file, std::ios::binary);
|
||||
boost::archive::binary_iarchive iarchive(stream);
|
||||
|
||||
DEBUG("archive.journal", "Reading header from archive");
|
||||
iarchive >> *this;
|
||||
|
||||
DEBUG("archive.journal",
|
||||
"Version number: " << std::hex << version << std::dec);
|
||||
DEBUG("archive.journal", "Number of sources: " << sources.size());
|
||||
|
||||
foreach (const journal_t::fileinfo_t& i, sources)
|
||||
DEBUG("archive.journal", "Loaded source: " << *i.filename);
|
||||
}
|
||||
}
|
||||
|
||||
bool archive_t::should_load(const std::list<path>& data_files)
|
||||
{
|
||||
std::size_t found = 0;
|
||||
|
||||
DEBUG("archive.journal", "Should the archive be loaded?");
|
||||
|
||||
if (! exists(file)) {
|
||||
DEBUG("archive.journal", "No, it does not exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version != ARCHIVE_VERSION) {
|
||||
DEBUG("archive.journal", "No, it fails the version check");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data_files.empty()) {
|
||||
DEBUG("archive.journal", "No, there were no data files!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sources.empty()) {
|
||||
DEBUG("archive.journal", "No, there were no sources!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data_files.size() != sources.size()) {
|
||||
DEBUG("archive.journal", "No, number of sources doesn't match: "
|
||||
<< data_files.size() << " != " << sources.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (const path& p, data_files) {
|
||||
DEBUG("archive.journal", "Scanning for data file: " << p);
|
||||
|
||||
if (! exists(p)) {
|
||||
DEBUG("archive.journal", "No, an input source no longer exists: " << p);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (const journal_t::fileinfo_t& i, sources) {
|
||||
assert(! i.from_stream);
|
||||
assert(i.filename);
|
||||
|
||||
DEBUG("archive.journal", "Comparing against source file: " << *i.filename);
|
||||
|
||||
if (*i.filename == p) {
|
||||
if (! exists(*i.filename)) {
|
||||
DEBUG("archive.journal",
|
||||
"No, a referent source no longer exists: " << *i.filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i.modtime != posix_time::from_time_t(last_write_time(p))) {
|
||||
DEBUG("archive.journal", "No, a source's modtime has changed: " << p);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i.size != file_size(p)) {
|
||||
DEBUG("archive.journal", "No, a source's size has changed: " << p);
|
||||
return false;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found != data_files.size()) {
|
||||
DEBUG("archive.journal", "No, not every source's name matched");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG("archive.journal", "Yes, it should be loaded!");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool archive_t::should_save(shared_ptr<journal_t> journal)
|
||||
{
|
||||
std::list<path> data_files;
|
||||
|
||||
DEBUG("archive.journal", "Should the archive be saved?");
|
||||
|
||||
if (journal->was_loaded) {
|
||||
DEBUG("archive.journal", "No, it's one we loaded before");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (journal->sources.empty()) {
|
||||
DEBUG("archive.journal", "No, there were no sources!");
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (const journal_t::fileinfo_t& i, journal->sources) {
|
||||
if (i.from_stream) {
|
||||
DEBUG("archive.journal", "No, one source was from a stream");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! exists(*i.filename)) {
|
||||
DEBUG("archive.journal",
|
||||
"No, a source no longer exists: " << *i.filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
data_files.push_back(*i.filename);
|
||||
}
|
||||
|
||||
if (should_load(data_files)) {
|
||||
DEBUG("archive.journal", "No, because it's still loadable");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG("archive.journal", "Yes, it should be saved!");
|
||||
return true;
|
||||
}
|
||||
|
||||
void archive_t::save(shared_ptr<journal_t> journal)
|
||||
{
|
||||
INFO_START(archive, "Saved journal file cache");
|
||||
|
||||
ofstream archive(file, std::ios::binary);
|
||||
boost::archive::binary_oarchive oa(archive);
|
||||
|
||||
version = ARCHIVE_VERSION;
|
||||
sources = journal->sources;
|
||||
|
||||
foreach (const journal_t::fileinfo_t& i, sources)
|
||||
DEBUG("archive.journal", "Saving source: " << *i.filename);
|
||||
|
||||
DEBUG("archive.journal",
|
||||
"Creating archive with version " << std::hex << version << std::dec);
|
||||
oa << *this;
|
||||
|
||||
DEBUG("archive.journal",
|
||||
"Archiving journal with " << sources.size() << " sources");
|
||||
oa << *journal;
|
||||
|
||||
INFO_FINISH(archive);
|
||||
}
|
||||
|
||||
bool archive_t::load(shared_ptr<journal_t> journal)
|
||||
{
|
||||
INFO_START(archive, "Read cached journal file");
|
||||
|
||||
ifstream stream(file, std::ios::binary);
|
||||
boost::archive::binary_iarchive iarchive(stream);
|
||||
|
||||
// Skip past the archive header, it was already read in before
|
||||
archive_t temp;
|
||||
iarchive >> temp;
|
||||
|
||||
iarchive >> *journal.get();
|
||||
journal->was_loaded = true;
|
||||
|
||||
INFO_FINISH(archive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
105
src/archive.h
Normal file
105
src/archive.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup report Reporting
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file archive.h
|
||||
* @author John Wiegley
|
||||
*
|
||||
* @ingroup report
|
||||
*
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
#ifndef _ARCHIVE_H
|
||||
#define _ARCHIVE_H
|
||||
|
||||
#include "journal.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
class archive_t
|
||||
{
|
||||
path file;
|
||||
uint32_t version;
|
||||
|
||||
std::list<journal_t::fileinfo_t> sources;
|
||||
|
||||
public:
|
||||
archive_t() {
|
||||
TRACE_CTOR(archive_t, "");
|
||||
}
|
||||
archive_t(const path& _file)
|
||||
: file(_file), version(0) {
|
||||
TRACE_CTOR(archive_t, "const path&");
|
||||
}
|
||||
archive_t(const archive_t& ar)
|
||||
: file(ar.file), version(0) {
|
||||
TRACE_CTOR(archive_t, "copy");
|
||||
}
|
||||
~archive_t() {
|
||||
TRACE_DTOR(archive_t);
|
||||
}
|
||||
|
||||
void read_header();
|
||||
|
||||
bool should_load(const std::list<path>& data_files);
|
||||
bool should_save(shared_ptr<journal_t> journal);
|
||||
|
||||
void save(shared_ptr<journal_t> journal);
|
||||
bool load(shared_ptr<journal_t> journal);
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & version;
|
||||
ar & sources;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _ARCHIVE_H
|
||||
|
|
@ -228,12 +228,14 @@ balance_t::commodity_amount(const optional<const commodity_t&>& commodity) const
|
|||
return temp.commodity_amount(commodity);
|
||||
|
||||
throw_(amount_error,
|
||||
_("Requested amount of a balance with multiple commodities: %1") << temp);
|
||||
_("Requested amount of a balance with multiple commodities: %1")
|
||||
<< temp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (amounts.size() > 0) {
|
||||
amounts_map::const_iterator i = amounts.find(&*commodity);
|
||||
amounts_map::const_iterator i =
|
||||
amounts.find(const_cast<commodity_t *>(&*commodity));
|
||||
if (i != amounts.end())
|
||||
return i->second;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class balance_t
|
|||
multiplicative<balance_t, long> > > > > > > > > > > > > >
|
||||
{
|
||||
public:
|
||||
typedef std::map<const commodity_t *, amount_t> amounts_map;
|
||||
typedef std::map<commodity_t *, amount_t> amounts_map;
|
||||
|
||||
amounts_map amounts;
|
||||
|
||||
|
|
@ -523,6 +523,18 @@ public:
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & amounts;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
|
||||
|
|
|
|||
14
src/chain.cc
14
src/chain.cc
|
|
@ -223,33 +223,33 @@ post_handler_ptr chain_post_handlers(report_t& report,
|
|||
|
||||
if (report.HANDLED(set_account_))
|
||||
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
|
||||
report.session.master.get(),
|
||||
report.session.journal->master,
|
||||
report.HANDLER(set_account_).str(),
|
||||
report));
|
||||
else if (report.HANDLED(set_payee_))
|
||||
handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
|
||||
report.session.master.get(),
|
||||
report.session.journal->master,
|
||||
report.HANDLER(set_payee_).str(),
|
||||
report));
|
||||
else if (report.HANDLED(comm_as_payee))
|
||||
handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
|
||||
report.session.master.get(),
|
||||
report.session.journal->master,
|
||||
expr_t("commodity"), report));
|
||||
else if (report.HANDLED(code_as_payee))
|
||||
handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
|
||||
report.session.master.get(),
|
||||
report.session.journal->master,
|
||||
expr_t("code"), report));
|
||||
else if (report.HANDLED(payee_as_account))
|
||||
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
|
||||
report.session.master.get(),
|
||||
report.session.journal->master,
|
||||
expr_t("payee"), report));
|
||||
else if (report.HANDLED(comm_as_account))
|
||||
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
|
||||
report.session.master.get(),
|
||||
report.session.journal->master,
|
||||
expr_t("commodity"), report));
|
||||
else if (report.HANDLED(code_as_account))
|
||||
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
|
||||
report.session.master.get(),
|
||||
report.session.journal->master,
|
||||
expr_t("code"), report));
|
||||
|
||||
return handler;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,19 @@ struct price_point_t
|
|||
{
|
||||
datetime_t when;
|
||||
amount_t price;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & when;
|
||||
ar & price;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -78,7 +91,7 @@ class commodity_t
|
|||
public:
|
||||
class base_t : public noncopyable, public supports_flags<uint_least16_t>
|
||||
{
|
||||
base_t();
|
||||
base_t() {}
|
||||
|
||||
public:
|
||||
typedef std::map<const datetime_t, amount_t> history_map;
|
||||
|
|
@ -100,6 +113,18 @@ public:
|
|||
, const int indent = 0
|
||||
#endif
|
||||
) const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & prices;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
typedef std::map<commodity_t *, history_t> history_by_commodity_map;
|
||||
|
|
@ -126,6 +151,18 @@ public:
|
|||
|
||||
optional<history_t&>
|
||||
history(const optional<commodity_t&>& commodity = none);
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & histories;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
#define COMMODITY_STYLE_DEFAULTS 0x000
|
||||
|
|
@ -158,6 +195,25 @@ public:
|
|||
~base_t() {
|
||||
TRACE_DTOR(base_t);
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<supports_flags<uint_least16_t> >(*this);
|
||||
ar & symbol;
|
||||
ar & precision;
|
||||
ar & name;
|
||||
ar & note;
|
||||
ar & varied_history;
|
||||
ar & smaller;
|
||||
ar & larger;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
@ -330,6 +386,31 @@ public:
|
|||
}
|
||||
|
||||
bool valid() const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
supports_flags<uint_least16_t> temp_flags;
|
||||
|
||||
protected:
|
||||
explicit commodity_t()
|
||||
: delegates_flags<uint_least16_t>(temp_flags), parent_(NULL),
|
||||
annotated(false) {}
|
||||
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<delegates_flags<uint_least16_t> >(*this);
|
||||
ar & base;
|
||||
ar & parent_;
|
||||
ar & qualified_symbol;
|
||||
ar & mapping_key_;
|
||||
ar & annotated;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const commodity_t& comm) {
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ namespace {
|
|||
if (tmpl.payee_mask.match((*j)->payee)) {
|
||||
matching = *j;
|
||||
DEBUG("derive.xact",
|
||||
"Found payee match: transaction on line " << (*j)->beg_line);
|
||||
"Found payee match: transaction on line " << (*j)->pos->beg_line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -332,7 +332,7 @@ namespace {
|
|||
if (post.account_mask->match(x->account->fullname())) {
|
||||
new_post.reset(new post_t(*x));
|
||||
DEBUG("derive.xact",
|
||||
"Founding posting from line " << x->beg_line);
|
||||
"Founding posting from line " << x->pos->beg_line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ namespace ledger {
|
|||
|
||||
void format_emacs_posts::write_xact(xact_t& xact)
|
||||
{
|
||||
out << "\"" << xact.pathname << "\" "
|
||||
<< (xact.beg_line + 1) << " ";
|
||||
out << "\"" << xact.pos->pathname << "\" "
|
||||
<< (xact.pos->beg_line + 1) << " ";
|
||||
|
||||
tm when = gregorian::to_tm(xact.date());
|
||||
std::time_t date = std::mktime(&when); // jww (2008-04-20): Is this GMT or local?
|
||||
|
|
@ -77,7 +77,7 @@ void format_emacs_posts::operator()(post_t& post)
|
|||
out << "\n";
|
||||
}
|
||||
|
||||
out << " (" << (post.beg_line + 1) << " ";
|
||||
out << " (" << (post.pos->beg_line + 1) << " ";
|
||||
out << "\"" << post.reported_account()->fullname() << "\" \""
|
||||
<< post.amount << "\"";
|
||||
|
||||
|
|
|
|||
|
|
@ -96,10 +96,10 @@ string source_context(const path& file,
|
|||
ifstream in(file);
|
||||
in.seekg(pos, std::ios::beg);
|
||||
|
||||
scoped_array<char> buf(new char[len + 1]);
|
||||
in.read(buf.get(), len);
|
||||
assert(in.gcount() == len);
|
||||
buf[len] = '\0';
|
||||
scoped_array<char> buf(new char[static_cast<std::size_t>(len) + 1]);
|
||||
in.read(buf.get(), static_cast<std::streamsize>(len));
|
||||
assert(in.gcount() == static_cast<std::streamsize>(len));
|
||||
buf[static_cast<std::size_t>(len)] = '\0';
|
||||
|
||||
bool first = true;
|
||||
for (char * p = std::strtok(buf.get(), "\n");
|
||||
|
|
|
|||
18
src/expr.h
18
src/expr.h
|
|
@ -103,7 +103,7 @@ public:
|
|||
expr_t(const string& _str, const uint_least8_t flags = 0);
|
||||
expr_t(std::istream& in, const uint_least8_t flags = 0);
|
||||
|
||||
virtual ~expr_t() throw();
|
||||
~expr_t() throw();
|
||||
|
||||
expr_t& operator=(const expr_t& _expr);
|
||||
expr_t& operator=(const string& _expr) {
|
||||
|
|
@ -163,6 +163,22 @@ public:
|
|||
void dump(std::ostream& out) const;
|
||||
|
||||
static value_t eval(const string& _expr, scope_t& scope);
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & ptr;
|
||||
ar & context;
|
||||
ar & str;
|
||||
if (Archive::is_loading::value)
|
||||
compiled = false;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const expr_t& expr);
|
||||
|
|
|
|||
22
src/flags.h
22
src/flags.h
|
|
@ -99,6 +99,17 @@ public:
|
|||
void drop_flags(const flags_t arg) {
|
||||
_flags = static_cast<T>(static_cast<U>(_flags) & static_cast<U>(~arg));
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */)
|
||||
{
|
||||
ar & _flags;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -201,6 +212,17 @@ public:
|
|||
void drop_flags(const flags_t arg) {
|
||||
_flags.drop_flags(arg);
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */)
|
||||
{
|
||||
ar & _flags;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
#endif // _FLAGS_H
|
||||
|
|
|
|||
|
|
@ -435,17 +435,18 @@ void global_scope_t::normalize_report_options(const string& verb)
|
|||
item_t::use_effective_date = (rep.HANDLED(effective) &&
|
||||
! rep.HANDLED(actual_dates));
|
||||
|
||||
rep.session.commodity_pool->keep_base = rep.HANDLED(base);
|
||||
rep.session.commodity_pool->get_quotes = rep.session.HANDLED(download);
|
||||
rep.session.journal->commodity_pool->keep_base = rep.HANDLED(base);
|
||||
rep.session.journal->commodity_pool->get_quotes = rep.session.HANDLED(download);
|
||||
|
||||
if (rep.session.HANDLED(price_exp_))
|
||||
rep.session.commodity_pool->quote_leeway =
|
||||
rep.session.journal->commodity_pool->quote_leeway =
|
||||
rep.session.HANDLER(price_exp_).value.as_long();
|
||||
|
||||
if (rep.session.HANDLED(price_db_))
|
||||
rep.session.commodity_pool->price_db = rep.session.HANDLER(price_db_).str();
|
||||
rep.session.journal->commodity_pool->price_db =
|
||||
rep.session.HANDLER(price_db_).str();
|
||||
else
|
||||
rep.session.commodity_pool->price_db = none;
|
||||
rep.session.journal->commodity_pool->price_db = none;
|
||||
|
||||
if (rep.HANDLED(date_format_))
|
||||
set_date_format(rep.HANDLER(date_format_).str().c_str());
|
||||
|
|
@ -542,7 +543,8 @@ void global_scope_t::normalize_report_options(const string& verb)
|
|||
|
||||
if (! rep.HANDLER(date_width_).specified)
|
||||
rep.HANDLER(date_width_)
|
||||
.on_with(none, format_date(CURRENT_DATE(), FMT_PRINTED).length());
|
||||
.on_with(none, static_cast<long>(format_date(CURRENT_DATE(),
|
||||
FMT_PRINTED).length()));
|
||||
|
||||
long date_width = rep.HANDLER(date_width_).value.to_long();
|
||||
long payee_width = (rep.HANDLER(payee_width_).specified ?
|
||||
|
|
|
|||
|
|
@ -118,9 +118,9 @@ void interactive_t::verify_arguments() const
|
|||
label = _("any value");
|
||||
wrong_arg = false;
|
||||
break;
|
||||
case 'P':
|
||||
label = _("a pointer");
|
||||
wrong_arg = ! next_arg->is_pointer();
|
||||
case '^':
|
||||
label = _("a scope");
|
||||
wrong_arg = ! next_arg->is_scope();
|
||||
break;
|
||||
case 'S':
|
||||
label = _("a sequence");
|
||||
|
|
|
|||
32
src/item.cc
32
src/item.cc
|
|
@ -187,7 +187,7 @@ namespace {
|
|||
}
|
||||
|
||||
value_t get_actual(item_t& item) {
|
||||
return ! item.has_flags(ITEM_GENERATED);
|
||||
return ! item.has_flags(ITEM_GENERATED | ITEM_TEMP);
|
||||
}
|
||||
|
||||
value_t get_date(item_t& item) {
|
||||
|
|
@ -224,23 +224,26 @@ namespace {
|
|||
}
|
||||
|
||||
value_t get_pathname(item_t& item) {
|
||||
return string_value(item.pathname.string());
|
||||
if (item.pos)
|
||||
return string_value(item.pos->pathname.string());
|
||||
else
|
||||
return string_value(empty_string);
|
||||
}
|
||||
|
||||
value_t get_beg_pos(item_t& item) {
|
||||
return long(item.beg_pos);
|
||||
return item.pos ? long(item.pos->beg_pos) : 0L;
|
||||
}
|
||||
|
||||
value_t get_beg_line(item_t& item) {
|
||||
return long(item.beg_line);
|
||||
return item.pos ? long(item.pos->beg_line) : 0L;
|
||||
}
|
||||
|
||||
value_t get_end_pos(item_t& item) {
|
||||
return long(item.end_pos);
|
||||
return item.pos ? long(item.pos->end_pos) : 0L;
|
||||
}
|
||||
|
||||
value_t get_end_line(item_t& item) {
|
||||
return long(item.end_line);
|
||||
return item.pos ? long(item.pos->end_line) : 0L;
|
||||
}
|
||||
|
||||
value_t get_depth(item_t&) {
|
||||
|
|
@ -397,12 +400,13 @@ bool item_t::valid() const
|
|||
|
||||
void print_item(std::ostream& out, const item_t& item, const string& prefix)
|
||||
{
|
||||
out << source_context(item.pathname, item.beg_pos, item.end_pos, prefix);
|
||||
out << source_context(item.pos->pathname, item.pos->beg_pos,
|
||||
item.pos->end_pos, prefix);
|
||||
}
|
||||
|
||||
string item_context(const item_t& item, const string& desc)
|
||||
{
|
||||
std::streamoff len = item.end_pos - item.beg_pos;
|
||||
std::streamoff len = item.pos->end_pos - item.pos->beg_pos;
|
||||
if (! len)
|
||||
return _("<no item context>");
|
||||
|
||||
|
|
@ -411,18 +415,18 @@ string item_context(const item_t& item, const string& desc)
|
|||
|
||||
std::ostringstream out;
|
||||
|
||||
if (item.pathname == path("/dev/stdin")) {
|
||||
if (item.pos->pathname == path("/dev/stdin")) {
|
||||
out << desc << _(" from standard input:");
|
||||
return out.str();
|
||||
}
|
||||
|
||||
out << desc << _(" from \"") << item.pathname.string() << "\"";
|
||||
out << desc << _(" from \"") << item.pos->pathname.string() << "\"";
|
||||
|
||||
if (item.beg_line != item.end_line)
|
||||
out << _(", lines ") << item.beg_line << "-"
|
||||
<< item.end_line << ":\n";
|
||||
if (item.pos->beg_line != item.pos->end_line)
|
||||
out << _(", lines ") << item.pos->beg_line << "-"
|
||||
<< item.pos->end_line << ":\n";
|
||||
else
|
||||
out << _(", line ") << item.beg_line << ":\n";
|
||||
out << _(", line ") << item.pos->beg_line << ":\n";
|
||||
|
||||
print_item(out, item, "> ");
|
||||
|
||||
|
|
|
|||
97
src/item.h
97
src/item.h
|
|
@ -50,6 +50,53 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
struct position_t
|
||||
{
|
||||
path pathname;
|
||||
istream_pos_type beg_pos;
|
||||
std::size_t beg_line;
|
||||
istream_pos_type end_pos;
|
||||
std::size_t end_line;
|
||||
|
||||
position_t() : beg_pos(0), beg_line(0), end_pos(0), end_line(0) {
|
||||
TRACE_CTOR(position_t, "");
|
||||
}
|
||||
position_t(const position_t& pos) {
|
||||
TRACE_CTOR(position_t, "copy");
|
||||
*this = pos;
|
||||
}
|
||||
~position_t() throw() {
|
||||
TRACE_DTOR(position_t);
|
||||
}
|
||||
|
||||
position_t& operator=(const position_t& pos) {
|
||||
if (this != &pos) {
|
||||
pathname = pos.pathname;
|
||||
beg_pos = pos.beg_pos;
|
||||
beg_line = pos.beg_line;
|
||||
end_pos = pos.end_pos;
|
||||
end_line = pos.end_line;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & pathname;
|
||||
ar & beg_pos;
|
||||
ar & beg_line;
|
||||
ar & end_pos;
|
||||
ar & end_line;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
|
|
@ -61,28 +108,21 @@ public:
|
|||
#define ITEM_NORMAL 0x00 // no flags at all, a basic posting
|
||||
// jww (2009-10-27): I'm not consistent on the difference between these two.
|
||||
#define ITEM_GENERATED 0x01 // posting was not found in a journal
|
||||
#define ITEM_TEMP 0x02 // posting is a temporary object
|
||||
#define ITEM_TEMP 0x02 // posting is a managed temporary
|
||||
|
||||
enum state_t { UNCLEARED = 0, CLEARED, PENDING };
|
||||
|
||||
state_t _state;
|
||||
|
||||
optional<date_t> _date;
|
||||
optional<date_t> _date_eff;
|
||||
optional<string> note;
|
||||
|
||||
typedef std::map<string, optional<string> > string_map;
|
||||
|
||||
state_t _state;
|
||||
optional<date_t> _date;
|
||||
optional<date_t> _date_eff;
|
||||
optional<string> note;
|
||||
optional<position_t> pos;
|
||||
optional<string_map> metadata;
|
||||
|
||||
path pathname;
|
||||
istream_pos_type beg_pos;
|
||||
std::size_t beg_line;
|
||||
istream_pos_type end_pos;
|
||||
std::size_t end_line;
|
||||
|
||||
item_t(flags_t _flags = ITEM_NORMAL, const optional<string>& _note = none)
|
||||
: supports_flags<>(_flags), _state(UNCLEARED), note(_note),
|
||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
||||
: supports_flags<>(_flags), _state(UNCLEARED), note(_note)
|
||||
{
|
||||
TRACE_CTOR(item_t, "flags_t, const string&");
|
||||
}
|
||||
|
|
@ -102,14 +142,8 @@ public:
|
|||
|
||||
_date = item._date;
|
||||
_date_eff = item._date_eff;
|
||||
|
||||
note = item.note;
|
||||
|
||||
pathname = item.pathname;
|
||||
beg_pos = item.beg_pos;
|
||||
beg_line = item.beg_line;
|
||||
end_pos = item.end_pos;
|
||||
end_line = item.end_line;
|
||||
pos = item.pos;
|
||||
}
|
||||
|
||||
virtual bool operator==(const item_t& xact) {
|
||||
|
|
@ -158,6 +192,25 @@ public:
|
|||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
|
||||
bool valid() const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<supports_flags<> >(*this);
|
||||
ar & boost::serialization::base_object<scope_t>(*this);
|
||||
ar & _state;
|
||||
ar & _date;
|
||||
ar & _date_eff;
|
||||
ar & note;
|
||||
ar & metadata;
|
||||
ar & pos;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
value_t get_comment(item_t& item);
|
||||
|
|
|
|||
|
|
@ -32,11 +32,34 @@
|
|||
#include <system.hh>
|
||||
|
||||
#include "journal.h"
|
||||
#include "amount.h"
|
||||
#include "commodity.h"
|
||||
#include "pool.h"
|
||||
#include "xact.h"
|
||||
#include "account.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
journal_t::journal_t()
|
||||
: master(new account_t), was_loaded(false),
|
||||
commodity_pool(new commodity_pool_t)
|
||||
{
|
||||
TRACE_CTOR(journal_t, "");
|
||||
|
||||
// Add time commodity conversions, so that timelog's may be parsed
|
||||
// in terms of seconds, but reported as minutes or hours.
|
||||
if (commodity_t * commodity = commodity_pool->create("s"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
else
|
||||
assert(false);
|
||||
|
||||
// Add a "percentile" commodity
|
||||
if (commodity_t * commodity = commodity_pool->create("%"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
|
||||
journal_t::~journal_t()
|
||||
{
|
||||
TRACE_DTOR(journal_t);
|
||||
|
|
@ -52,6 +75,9 @@ journal_t::~journal_t()
|
|||
|
||||
foreach (period_xact_t * xact, period_xacts)
|
||||
checked_delete(xact);
|
||||
|
||||
checked_delete(master);
|
||||
commodity_pool.reset();
|
||||
}
|
||||
|
||||
void journal_t::add_account(account_t * acct)
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@
|
|||
|
||||
#include "utils.h"
|
||||
#include "hooks.h"
|
||||
#include "times.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
typedef std::list<path> paths_list;
|
||||
|
||||
class commodity_pool_t;
|
||||
class xact_t;
|
||||
class auto_xact_t;
|
||||
class xact_finalizer_t;
|
||||
|
|
@ -72,18 +72,60 @@ typedef std::list<period_xact_t *> period_xacts_list;
|
|||
class journal_t : public noncopyable
|
||||
{
|
||||
public:
|
||||
account_t * master;
|
||||
account_t * basket;
|
||||
xacts_list xacts;
|
||||
struct fileinfo_t
|
||||
{
|
||||
optional<path> filename;
|
||||
uintmax_t size;
|
||||
datetime_t modtime;
|
||||
bool from_stream;
|
||||
|
||||
auto_xacts_list auto_xacts;
|
||||
period_xacts_list period_xacts;
|
||||
fileinfo_t() : size(0), from_stream(true) {
|
||||
TRACE_CTOR(journal_t::fileinfo_t, "");
|
||||
}
|
||||
fileinfo_t(const path& _filename)
|
||||
: filename(_filename), from_stream(false) {
|
||||
TRACE_CTOR(journal_t::fileinfo_t, "const path&");
|
||||
size = file_size(*filename);
|
||||
modtime = posix_time::from_time_t(last_write_time(*filename));
|
||||
}
|
||||
fileinfo_t(const fileinfo_t& info)
|
||||
: filename(info.filename), size(info.size),
|
||||
modtime(info.modtime), from_stream(info.from_stream)
|
||||
{
|
||||
TRACE_CTOR(journal_t::fileinfo_t, "copy");
|
||||
}
|
||||
~fileinfo_t() throw() {
|
||||
TRACE_DTOR(journal_t::fileinfo_t);
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & filename;
|
||||
ar & size;
|
||||
ar & modtime;
|
||||
ar & from_stream;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
account_t * master;
|
||||
account_t * basket;
|
||||
xacts_list xacts;
|
||||
auto_xacts_list auto_xacts;
|
||||
period_xacts_list period_xacts;
|
||||
std::list<fileinfo_t> sources;
|
||||
bool was_loaded;
|
||||
|
||||
shared_ptr<commodity_pool_t> commodity_pool;
|
||||
hooks_t<xact_finalizer_t, xact_t> xact_finalize_hooks;
|
||||
|
||||
journal_t(account_t * _master = NULL) : master(_master) {
|
||||
TRACE_CTOR(journal_t, "");
|
||||
}
|
||||
journal_t();
|
||||
~journal_t();
|
||||
|
||||
// These four methods are delegated to the current session, since all
|
||||
|
|
@ -110,6 +152,23 @@ public:
|
|||
bool strict = false);
|
||||
|
||||
bool valid() const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & master;
|
||||
ar & basket;
|
||||
ar & xacts;
|
||||
ar & auto_xacts;
|
||||
ar & period_xacts;
|
||||
ar & sources;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
19
src/mask.h
19
src/mask.h
|
|
@ -94,6 +94,25 @@ public:
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
string temp;
|
||||
if (Archive::is_loading::value) {
|
||||
ar & temp;
|
||||
*this = temp;
|
||||
} else {
|
||||
temp = expr.str();
|
||||
ar & temp;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const mask_t& mask) {
|
||||
|
|
|
|||
|
|
@ -172,12 +172,12 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
|
|||
left()->left() && left()->left()->is_function()) {
|
||||
call_scope_t call_args(scope);
|
||||
if (value_t obj = left()->left()->as_function()(call_args)) {
|
||||
if (obj.is_pointer()) {
|
||||
if (obj.as_pointer_lval<scope_t>() == NULL) {
|
||||
if (obj.is_scope()) {
|
||||
if (obj.as_scope() == NULL) {
|
||||
throw_(calc_error,
|
||||
_("Left operand of . operator is NULL"));
|
||||
} else {
|
||||
scope_t& objscope(obj.as_ref_lval<scope_t>());
|
||||
scope_t& objscope(*obj.as_scope());
|
||||
if (ptr_op_t member = objscope.lookup(right()->as_ident())) {
|
||||
result = member->calc(objscope, NULL, depth + 1);
|
||||
break;
|
||||
|
|
|
|||
28
src/op.h
28
src/op.h
|
|
@ -192,6 +192,7 @@ public:
|
|||
}
|
||||
|
||||
ptr_op_t& left() {
|
||||
assert(kind > TERMINALS || kind == IDENT);
|
||||
return left_;
|
||||
}
|
||||
const ptr_op_t& left() const {
|
||||
|
|
@ -289,6 +290,33 @@ public:
|
|||
|
||||
static ptr_op_t wrap_value(const value_t& val);
|
||||
static ptr_op_t wrap_functor(const function_t& fobj);
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & refc;
|
||||
ar & kind;
|
||||
if (Archive::is_loading::value || ! left_ || left_->kind != FUNCTION) {
|
||||
ar & left_;
|
||||
} else {
|
||||
ptr_op_t temp_op;
|
||||
ar & temp_op;
|
||||
}
|
||||
if (Archive::is_loading::value || kind == VALUE || kind == IDENT ||
|
||||
(kind > UNARY_OPERATORS &&
|
||||
(! has_right() || ! right()->is_function()))) {
|
||||
ar & data;
|
||||
} else {
|
||||
variant<ptr_op_t, value_t, string, function_t> temp_data;
|
||||
ar & temp_data;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
inline expr_t::ptr_op_t
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ void format_accounts::flush()
|
|||
disp_pred.predicate.parse(report.HANDLER(display_).str());
|
||||
}
|
||||
|
||||
mark_accounts(*report.session.master, report.HANDLED(flat));
|
||||
mark_accounts(*report.session.journal->master, report.HANDLED(flat));
|
||||
|
||||
std::size_t displayed = 0;
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ void format_accounts::flush()
|
|||
|
||||
if (displayed > 1 &&
|
||||
! report.HANDLED(no_total) && ! report.HANDLED(percent)) {
|
||||
bind_scope_t bound_scope(report, *report.session.master);
|
||||
bind_scope_t bound_scope(report, *report.session.journal->master);
|
||||
separator_format.format(out, bound_scope);
|
||||
total_line_format.format(out, bound_scope);
|
||||
}
|
||||
|
|
|
|||
18
src/pool.h
18
src/pool.h
|
|
@ -134,6 +134,24 @@ public:
|
|||
parse_price_expression(const std::string& str,
|
||||
const bool add_prices = true,
|
||||
const optional<datetime_t>& moment = none);
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & commodities;
|
||||
ar & null_commodity;
|
||||
ar & default_commodity;
|
||||
ar & keep_base;
|
||||
ar & price_db;
|
||||
ar & quote_leeway;
|
||||
ar & get_quotes;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
17
src/post.h
17
src/post.h
|
|
@ -205,6 +205,23 @@ public:
|
|||
}
|
||||
|
||||
friend class xact_t;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<item_t>(*this);
|
||||
ar & xact;
|
||||
ar & account;
|
||||
ar & amount;
|
||||
ar & cost;
|
||||
ar & assigned_amount;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -94,6 +94,19 @@ public:
|
|||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & predicate;
|
||||
ar & what_to_keep;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
class query_lexer_t
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(value_overloads, value, 0, 2)
|
|||
namespace {
|
||||
expr_t py_value_getattr(const value_t& value, const string& name)
|
||||
{
|
||||
if (value.is_pointer()) {
|
||||
if (scope_t * scope = value.as_pointer<scope_t>())
|
||||
if (value.is_scope()) {
|
||||
if (scope_t * scope = value.as_scope())
|
||||
return expr_t(scope->lookup(name), scope);
|
||||
}
|
||||
throw_(value_error, _("Cannot lookup attributes in %1") << value.label());
|
||||
|
|
@ -283,7 +283,7 @@ void export_value()
|
|||
.value("BALANCE", value_t::BALANCE)
|
||||
.value("STRING", value_t::STRING)
|
||||
.value("SEQUENCE", value_t::SEQUENCE)
|
||||
.value("POINTER", value_t::POINTER)
|
||||
.value("SCOPE", value_t::SCOPE)
|
||||
;
|
||||
|
||||
scope().attr("NULL_VALUE") = NULL_VALUE;
|
||||
|
|
|
|||
|
|
@ -87,11 +87,11 @@ void report_t::accounts_report(acct_handler_ptr handler)
|
|||
|
||||
scoped_ptr<accounts_iterator> iter;
|
||||
if (! HANDLED(sort_)) {
|
||||
iter.reset(new basic_accounts_iterator(*session.master));
|
||||
iter.reset(new basic_accounts_iterator(*session.journal->master));
|
||||
} else {
|
||||
expr_t sort_expr(HANDLER(sort_).str());
|
||||
sort_expr.set_context(this);
|
||||
iter.reset(new sorted_accounts_iterator(*session.master.get(),
|
||||
iter.reset(new sorted_accounts_iterator(*session.journal->master,
|
||||
sort_expr, HANDLED(flat)));
|
||||
}
|
||||
|
||||
|
|
|
|||
66
src/scope.h
66
src/scope.h
|
|
@ -67,6 +67,16 @@ public:
|
|||
|
||||
virtual void define(const string&, expr_t::ptr_op_t) {}
|
||||
virtual expr_t::ptr_op_t lookup(const string& name) = 0;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive &, const unsigned int /* version */) {}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -100,6 +110,19 @@ public:
|
|||
return parent->lookup(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<scope_t>(*this);
|
||||
ar & parent;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -127,6 +150,19 @@ public:
|
|||
virtual void define(const string& name, expr_t::ptr_op_t def);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<child_scope_t>(*this);
|
||||
ar & symbols;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -138,8 +174,6 @@ class call_scope_t : public child_scope_t
|
|||
{
|
||||
value_t args;
|
||||
|
||||
call_scope_t();
|
||||
|
||||
public:
|
||||
explicit call_scope_t(scope_t& _parent) : child_scope_t(_parent) {
|
||||
TRACE_CTOR(call_scope_t, "scope_t&");
|
||||
|
|
@ -182,6 +216,21 @@ public:
|
|||
bool empty() const {
|
||||
return args.size() == 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
explicit call_scope_t() {}
|
||||
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<child_scope_t>(*this);
|
||||
ar & args;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -215,6 +264,19 @@ public:
|
|||
return def;
|
||||
return child_scope_t::lookup(name);
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<child_scope_t>(*this);
|
||||
ar & grandchild;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
130
src/session.cc
130
src/session.cc
|
|
@ -32,13 +32,12 @@
|
|||
#include <system.hh>
|
||||
|
||||
#include "session.h"
|
||||
#include "commodity.h"
|
||||
#include "pool.h"
|
||||
#include "xact.h"
|
||||
#include "account.h"
|
||||
#include "journal.h"
|
||||
#include "iterators.h"
|
||||
#include "filters.h"
|
||||
#include "archive.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ void set_session_context(session_t * session)
|
|||
{
|
||||
if (session) {
|
||||
times_initialize();
|
||||
amount_t::initialize(session->commodity_pool);
|
||||
amount_t::initialize(session->journal->commodity_pool);
|
||||
|
||||
// jww (2009-02-04): Is amount_t the right place for parse_conversion to
|
||||
// happen?
|
||||
|
|
@ -64,12 +63,8 @@ void set_session_context(session_t * session)
|
|||
|
||||
session_t::session_t()
|
||||
: flush_on_next_data_file(false),
|
||||
|
||||
current_year(CURRENT_DATE().year()),
|
||||
|
||||
commodity_pool(new commodity_pool_t),
|
||||
master(new account_t),
|
||||
journal(new journal_t(master.get()))
|
||||
journal(new journal_t)
|
||||
{
|
||||
TRACE_CTOR(session_t, "");
|
||||
|
||||
|
|
@ -77,19 +72,6 @@ session_t::session_t()
|
|||
HANDLER(price_db_).on(none, (path(home_var) / ".pricedb").string());
|
||||
else
|
||||
HANDLER(price_db_).on(none, path("./.pricedb").string());
|
||||
|
||||
// Add time commodity conversions, so that timelog's may be parsed
|
||||
// in terms of seconds, but reported as minutes or hours.
|
||||
if (commodity_t * commodity = commodity_pool->create("s"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
else
|
||||
assert(false);
|
||||
|
||||
// Add a "percentile" commodity
|
||||
if (commodity_t * commodity = commodity_pool->create("%"))
|
||||
commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
|
||||
std::size_t session_t::read_journal(std::istream& in,
|
||||
|
|
@ -123,6 +105,9 @@ std::size_t session_t::read_journal(const path& pathname,
|
|||
|
||||
std::size_t session_t::read_data(const string& master_account)
|
||||
{
|
||||
bool populated_data_files = false;
|
||||
bool populated_price_db = false;
|
||||
|
||||
if (HANDLER(file_).data_files.empty()) {
|
||||
path file;
|
||||
if (const char * home_var = std::getenv("HOME"))
|
||||
|
|
@ -132,6 +117,8 @@ std::size_t session_t::read_data(const string& master_account)
|
|||
HANDLER(file_).data_files.push_back(file);
|
||||
else
|
||||
throw_(parse_error, "No journal file was specified (please use -f)");
|
||||
|
||||
populated_data_files = true;
|
||||
}
|
||||
|
||||
std::size_t xact_count = 0;
|
||||
|
|
@ -140,43 +127,75 @@ std::size_t session_t::read_data(const string& master_account)
|
|||
if (! master_account.empty())
|
||||
acct = journal->find_account(master_account);
|
||||
|
||||
if (HANDLED(price_db_)) {
|
||||
path price_db_path = resolve_path(HANDLER(price_db_).str());
|
||||
if (exists(price_db_path) && read_journal(price_db_path) > 0)
|
||||
optional<path> price_db_path;
|
||||
if (HANDLED(price_db_))
|
||||
price_db_path = resolve_path(HANDLER(price_db_).str());
|
||||
|
||||
optional<archive_t> cache;
|
||||
if (HANDLED(cache_) && master_account.empty()) {
|
||||
cache = archive_t(HANDLED(cache_).str());
|
||||
cache->read_header();
|
||||
|
||||
if (price_db_path) {
|
||||
HANDLER(file_).data_files.push_back(*price_db_path);
|
||||
populated_price_db = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! (cache &&
|
||||
cache->should_load(HANDLER(file_).data_files) &&
|
||||
cache->load(journal))) {
|
||||
if (price_db_path) {
|
||||
if (exists(*price_db_path) && read_journal(*price_db_path) > 0)
|
||||
throw_(parse_error, _("Transactions not allowed in price history file"));
|
||||
}
|
||||
journal->sources.push_back(journal_t::fileinfo_t(*price_db_path));
|
||||
HANDLER(file_).data_files.remove(*price_db_path);
|
||||
}
|
||||
|
||||
foreach (const path& pathname, HANDLER(file_).data_files) {
|
||||
path filename = resolve_path(pathname);
|
||||
if (filename == "-") {
|
||||
// To avoid problems with stdin and pipes, etc., we read the entire
|
||||
// file in beforehand into a memory buffer, and then parcel it out
|
||||
// from there.
|
||||
std::ostringstream buffer;
|
||||
foreach (const path& pathname, HANDLER(file_).data_files) {
|
||||
path filename = resolve_path(pathname);
|
||||
if (filename == "-") {
|
||||
// To avoid problems with stdin and pipes, etc., we read the entire
|
||||
// file in beforehand into a memory buffer, and then parcel it out
|
||||
// from there.
|
||||
std::ostringstream buffer;
|
||||
|
||||
while (std::cin.good() && ! std::cin.eof()) {
|
||||
char line[8192];
|
||||
std::cin.read(line, 8192);
|
||||
std::streamsize count = std::cin.gcount();
|
||||
buffer.write(line, count);
|
||||
while (std::cin.good() && ! std::cin.eof()) {
|
||||
char line[8192];
|
||||
std::cin.read(line, 8192);
|
||||
std::streamsize count = std::cin.gcount();
|
||||
buffer.write(line, count);
|
||||
}
|
||||
buffer.flush();
|
||||
|
||||
std::istringstream buf_in(buffer.str());
|
||||
|
||||
xact_count += read_journal(buf_in, "/dev/stdin", acct);
|
||||
journal->sources.push_back(journal_t::fileinfo_t());
|
||||
}
|
||||
buffer.flush();
|
||||
else if (exists(filename)) {
|
||||
xact_count += read_journal(filename, acct);
|
||||
journal->sources.push_back(journal_t::fileinfo_t(filename));
|
||||
}
|
||||
else {
|
||||
throw_(parse_error, _("Could not read journal file '%1'") << filename);
|
||||
}
|
||||
}
|
||||
|
||||
std::istringstream buf_in(buffer.str());
|
||||
assert(xact_count == journal->xacts.size());
|
||||
|
||||
xact_count += read_journal(buf_in, "/dev/stdin", acct);
|
||||
}
|
||||
else if (exists(filename)) {
|
||||
xact_count += read_journal(filename, acct);
|
||||
}
|
||||
else {
|
||||
throw_(parse_error, _("Could not read journal file '%1'") << filename);
|
||||
}
|
||||
if (cache && cache->should_save(journal))
|
||||
cache->save(journal);
|
||||
}
|
||||
|
||||
if (populated_data_files)
|
||||
HANDLER(file_).data_files.clear();
|
||||
else if (populated_price_db)
|
||||
HANDLER(file_).data_files.remove(*price_db_path);
|
||||
|
||||
VERIFY(journal->valid());
|
||||
|
||||
return xact_count;
|
||||
return journal->xacts.size();
|
||||
}
|
||||
|
||||
void session_t::read_journal_files()
|
||||
|
|
@ -200,14 +219,10 @@ void session_t::read_journal_files()
|
|||
void session_t::close_journal_files()
|
||||
{
|
||||
journal.reset();
|
||||
master.reset();
|
||||
commodity_pool.reset();
|
||||
amount_t::shutdown();
|
||||
|
||||
commodity_pool.reset(new commodity_pool_t);
|
||||
amount_t::initialize(commodity_pool);
|
||||
master.reset(new account_t);
|
||||
journal.reset(new journal_t(master.get()));
|
||||
journal.reset(new journal_t);
|
||||
amount_t::initialize(journal->commodity_pool);
|
||||
}
|
||||
|
||||
void session_t::clean_posts()
|
||||
|
|
@ -224,9 +239,9 @@ void session_t::clean_posts(xact_t& xact)
|
|||
|
||||
void session_t::clean_accounts()
|
||||
{
|
||||
basic_accounts_iterator acct_walker(*master);
|
||||
basic_accounts_iterator acct_walker(*journal->master);
|
||||
pass_down_accounts(acct_handler_ptr(new clear_account_xdata), acct_walker);
|
||||
master->clear_xdata();
|
||||
journal->master->clear_xdata();
|
||||
}
|
||||
|
||||
option_t<session_t> * session_t::lookup_option(const char * p)
|
||||
|
|
@ -241,6 +256,9 @@ option_t<session_t> * session_t::lookup_option(const char * p)
|
|||
case 'a':
|
||||
OPT_(account_); // -a
|
||||
break;
|
||||
case 'c':
|
||||
OPT(cache_);
|
||||
break;
|
||||
case 'd':
|
||||
OPT(download); // -Q
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -66,12 +66,9 @@ class session_t : public symbol_scope_t
|
|||
friend void set_session_context(session_t * session);
|
||||
|
||||
public:
|
||||
bool flush_on_next_data_file;
|
||||
date_t::year_type current_year;
|
||||
|
||||
shared_ptr<commodity_pool_t> commodity_pool;
|
||||
scoped_ptr<account_t> master;
|
||||
scoped_ptr<journal_t> journal;
|
||||
bool flush_on_next_data_file;
|
||||
date_t::year_type current_year;
|
||||
shared_ptr<journal_t> journal;
|
||||
|
||||
explicit session_t();
|
||||
virtual ~session_t() {
|
||||
|
|
@ -106,6 +103,7 @@ public:
|
|||
void report_options(std::ostream& out)
|
||||
{
|
||||
HANDLER(account_).report(out);
|
||||
HANDLER(cache_).report(out);
|
||||
HANDLER(download).report(out);
|
||||
HANDLER(file_).report(out);
|
||||
HANDLER(input_date_format_).report(out);
|
||||
|
|
@ -123,6 +121,7 @@ public:
|
|||
*/
|
||||
|
||||
OPTION(session_t, account_); // -a
|
||||
OPTION(session_t, cache_);
|
||||
OPTION(session_t, download); // -Q
|
||||
|
||||
OPTION__
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ value_t report_statistics(call_scope_t& args)
|
|||
std::ostream& out(report.output_stream);
|
||||
|
||||
const account_t::xdata_t::details_t&
|
||||
statistics(report.session.master->family_details(true));
|
||||
statistics(report.session.journal->master->family_details(true));
|
||||
|
||||
if (! is_valid(statistics.earliest_post) &&
|
||||
! is_valid(statistics.latest_post))
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ typedef std::ostream::pos_type ostream_pos_type;
|
|||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/cast.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
|
|
@ -168,6 +167,74 @@ typedef std::ostream::pos_type ostream_pos_type;
|
|||
#include <boost/variant.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
|
||||
#include <boost/archive/binary_iarchive.hpp>
|
||||
#include <boost/archive/binary_oarchive.hpp>
|
||||
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/binary_object.hpp>
|
||||
#include <boost/serialization/optional.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/variant.hpp>
|
||||
#include <boost/serialization/utility.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/level.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/deque.hpp>
|
||||
#include <boost/serialization/list.hpp>
|
||||
#include <boost/serialization/map.hpp>
|
||||
|
||||
#include <boost/date_time/posix_time/time_serialize.hpp>
|
||||
#include <boost/date_time/gregorian/greg_serialize.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, boost::filesystem::path& p, const unsigned int)
|
||||
{
|
||||
std::string s;
|
||||
if (Archive::is_saving::value)
|
||||
s = p.string();
|
||||
|
||||
ar & s;
|
||||
|
||||
if (Archive::is_loading::value)
|
||||
p = s;
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, boost::intrusive_ptr<T>& ptr, const unsigned int)
|
||||
{
|
||||
if (Archive::is_saving::value) {
|
||||
T * p = ptr.get();
|
||||
ar & p;
|
||||
}
|
||||
else if (Archive::is_loading::value) {
|
||||
T * p;
|
||||
ar & p;
|
||||
ptr.reset(p);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive&, boost::function<T>&, const unsigned int)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, istream_pos_type& pos, const unsigned int)
|
||||
{
|
||||
ar & make_binary_object(&pos, sizeof(istream_pos_type));
|
||||
}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
|
||||
#if defined(HAVE_BOOST_PYTHON)
|
||||
|
||||
#include <boost/python.hpp>
|
||||
|
|
|
|||
|
|
@ -525,11 +525,12 @@ void instance_t::automated_xact_directive(char * line)
|
|||
|
||||
journal.auto_xacts.push_back(ae.get());
|
||||
|
||||
ae->pathname = pathname;
|
||||
ae->beg_pos = pos;
|
||||
ae->beg_line = lnum;
|
||||
ae->end_pos = curr_pos;
|
||||
ae->end_line = linenum;
|
||||
ae->pos = position_t();
|
||||
ae->pos->pathname = pathname;
|
||||
ae->pos->beg_pos = pos;
|
||||
ae->pos->beg_line = lnum;
|
||||
ae->pos->end_pos = curr_pos;
|
||||
ae->pos->end_line = linenum;
|
||||
|
||||
ae.release();
|
||||
}
|
||||
|
|
@ -565,11 +566,12 @@ void instance_t::period_xact_directive(char * line)
|
|||
|
||||
journal.period_xacts.push_back(pe.get());
|
||||
|
||||
pe->pathname = pathname;
|
||||
pe->beg_pos = pos;
|
||||
pe->beg_line = lnum;
|
||||
pe->end_pos = curr_pos;
|
||||
pe->end_line = linenum;
|
||||
pe->pos = position_t();
|
||||
pe->pos->pathname = pathname;
|
||||
pe->pos->beg_pos = pos;
|
||||
pe->pos->beg_line = lnum;
|
||||
pe->pos->end_pos = curr_pos;
|
||||
pe->pos->end_line = linenum;
|
||||
|
||||
pe.release();
|
||||
} else {
|
||||
|
|
@ -778,10 +780,11 @@ post_t * instance_t::parse_post(char * line,
|
|||
|
||||
std::auto_ptr<post_t> post(new post_t);
|
||||
|
||||
post->xact = xact; // this could be NULL
|
||||
post->pathname = pathname;
|
||||
post->beg_pos = line_beg_pos;
|
||||
post->beg_line = linenum;
|
||||
post->xact = xact; // this could be NULL
|
||||
post->pos = position_t();
|
||||
post->pos->pathname = pathname;
|
||||
post->pos->beg_pos = line_beg_pos;
|
||||
post->pos->beg_line = linenum;
|
||||
|
||||
char buf[MAX_LINE + 1];
|
||||
std::strcpy(buf, line);
|
||||
|
|
@ -1056,8 +1059,8 @@ post_t * instance_t::parse_post(char * line,
|
|||
_("Unexpected char '%1' (Note: inline math requires parentheses)")
|
||||
<< *next);
|
||||
|
||||
post->end_pos = curr_pos;
|
||||
post->end_line = linenum;
|
||||
post->pos->end_pos = curr_pos;
|
||||
post->pos->end_line = linenum;
|
||||
|
||||
if (! tag_stack.empty()) {
|
||||
foreach (const string& tag, tag_stack)
|
||||
|
|
@ -1107,9 +1110,10 @@ xact_t * instance_t::parse_xact(char * line,
|
|||
|
||||
std::auto_ptr<xact_t> xact(new xact_t);
|
||||
|
||||
xact->pathname = pathname;
|
||||
xact->beg_pos = line_beg_pos;
|
||||
xact->beg_line = linenum;
|
||||
xact->pos = position_t();
|
||||
xact->pos->pathname = pathname;
|
||||
xact->pos->beg_pos = line_beg_pos;
|
||||
xact->pos->beg_line = linenum;
|
||||
|
||||
bool reveal_context = true;
|
||||
|
||||
|
|
@ -1189,8 +1193,8 @@ xact_t * instance_t::parse_xact(char * line,
|
|||
|
||||
// This is a trailing note, and possibly a metadata info tag
|
||||
item->append_note(p + 1, current_year);
|
||||
item->end_pos = curr_pos;
|
||||
item->end_line++;
|
||||
item->pos->end_pos = curr_pos;
|
||||
item->pos->end_line++;
|
||||
} else {
|
||||
reveal_context = false;
|
||||
|
||||
|
|
@ -1216,8 +1220,8 @@ xact_t * instance_t::parse_xact(char * line,
|
|||
}
|
||||
}
|
||||
|
||||
xact->end_pos = curr_pos;
|
||||
xact->end_line = linenum;
|
||||
xact->pos->end_pos = curr_pos;
|
||||
xact->pos->end_line = linenum;
|
||||
|
||||
if (! tag_stack.empty()) {
|
||||
foreach (const string& tag, tag_stack)
|
||||
|
|
@ -1232,8 +1236,8 @@ xact_t * instance_t::parse_xact(char * line,
|
|||
catch (const std::exception& err) {
|
||||
if (reveal_context) {
|
||||
add_error_context(_("While parsing transaction:"));
|
||||
add_error_context(source_context(xact->pathname,
|
||||
xact->beg_pos, curr_pos, "> "));
|
||||
add_error_context(source_context(xact->pos->pathname,
|
||||
xact->pos->beg_pos, curr_pos, "> "));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
|
|
|||
122
src/times.cc
122
src/times.cc
|
|
@ -314,50 +314,18 @@ date_t parse_date(const char * str, optional<date_t::year_type> current_year)
|
|||
return parse_date_mask(str, current_year, saw_year);
|
||||
}
|
||||
|
||||
date_t date_interval_t::add_duration(const date_t& date,
|
||||
const duration_t& duration)
|
||||
{
|
||||
if (duration.type() == typeid(gregorian::days))
|
||||
return date + boost::get<gregorian::days>(duration);
|
||||
else if (duration.type() == typeid(gregorian::weeks))
|
||||
return date + boost::get<gregorian::weeks>(duration);
|
||||
else if (duration.type() == typeid(gregorian::months))
|
||||
return date + boost::get<gregorian::months>(duration);
|
||||
else
|
||||
assert(duration.type() == typeid(gregorian::years));
|
||||
return date + boost::get<gregorian::years>(duration);
|
||||
}
|
||||
|
||||
date_t date_interval_t::subtract_duration(const date_t& date,
|
||||
const duration_t& duration)
|
||||
{
|
||||
if (duration.type() == typeid(gregorian::days))
|
||||
return date - boost::get<gregorian::days>(duration);
|
||||
else if (duration.type() == typeid(gregorian::weeks))
|
||||
return date - boost::get<gregorian::weeks>(duration);
|
||||
else if (duration.type() == typeid(gregorian::months))
|
||||
return date - boost::get<gregorian::months>(duration);
|
||||
else
|
||||
assert(duration.type() == typeid(gregorian::years));
|
||||
return date - boost::get<gregorian::years>(duration);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out,
|
||||
const date_interval_t::duration_t& duration)
|
||||
{
|
||||
if (duration.type() == typeid(gregorian::days))
|
||||
out << boost::get<gregorian::days>(duration).days()
|
||||
<< " day(s)";
|
||||
else if (duration.type() == typeid(gregorian::weeks))
|
||||
out << (boost::get<gregorian::weeks>(duration).days() / 7)
|
||||
<< " week(s)";
|
||||
else if (duration.type() == typeid(gregorian::months))
|
||||
out << boost::get<gregorian::months>(duration).number_of_months()
|
||||
<< " month(s)";
|
||||
if (duration.quantum == date_interval_t::duration_t::DAYS)
|
||||
out << duration.length << " day(s)";
|
||||
else if (duration.quantum == date_interval_t::duration_t::WEEKS)
|
||||
out << duration.length << " week(s)";
|
||||
else if (duration.quantum == date_interval_t::duration_t::MONTHS)
|
||||
out << duration.length << " month(s)";
|
||||
else {
|
||||
assert(duration.type() == typeid(gregorian::years));
|
||||
out << boost::get<gregorian::years>(duration).number_of_years()
|
||||
<< " year(s)";
|
||||
assert(duration.quantum == date_interval_t::duration_t::YEARS);
|
||||
out << duration.length << " year(s)";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
@ -365,7 +333,7 @@ std::ostream& operator<<(std::ostream& out,
|
|||
void date_interval_t::resolve_end()
|
||||
{
|
||||
if (start && ! end_of_duration) {
|
||||
end_of_duration = add_duration(*start, *duration);
|
||||
end_of_duration = duration->add(*start);
|
||||
DEBUG("times.interval",
|
||||
"stabilize: end_of_duration = " << *end_of_duration);
|
||||
}
|
||||
|
|
@ -383,7 +351,7 @@ void date_interval_t::resolve_end()
|
|||
}
|
||||
|
||||
if (start && ! next) {
|
||||
next = add_duration(*start, *skip_duration);
|
||||
next = skip_duration->add(*start);
|
||||
DEBUG("times.interval",
|
||||
"stabilize: next set to: " << *next);
|
||||
}
|
||||
|
|
@ -423,8 +391,8 @@ void date_interval_t::stabilize(const optional<date_t>& date)
|
|||
|
||||
date_t when = start ? *start : *date;
|
||||
|
||||
if (duration->type() == typeid(gregorian::months) ||
|
||||
duration->type() == typeid(gregorian::years)) {
|
||||
if (duration->quantum == duration_t::MONTHS ||
|
||||
duration->quantum == duration_t::YEARS) {
|
||||
DEBUG("times.interval", "stabilize: monthly or yearly duration");
|
||||
|
||||
start = date_t(when.year(), gregorian::Jan, 1);
|
||||
|
|
@ -433,7 +401,7 @@ void date_interval_t::stabilize(const optional<date_t>& date)
|
|||
|
||||
start = date_t(when - gregorian::days(400));
|
||||
|
||||
if (duration->type() == typeid(gregorian::weeks)) {
|
||||
if (duration->quantum == duration_t::WEEKS) {
|
||||
// Move it to a Sunday
|
||||
while (start->day_of_week() != start_of_week)
|
||||
*start += gregorian::days(1);
|
||||
|
|
@ -540,8 +508,8 @@ bool date_interval_t::find_period(const date_t& date)
|
|||
return true;
|
||||
}
|
||||
|
||||
scan = add_duration(scan, *skip_duration);
|
||||
end_of_scan = add_duration(scan, *duration);
|
||||
scan = skip_duration->add(scan);
|
||||
end_of_scan = duration->add(scan);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -565,7 +533,7 @@ date_interval_t& date_interval_t::operator++()
|
|||
} else {
|
||||
start = *next;
|
||||
|
||||
end_of_duration = add_duration(*start, *duration);
|
||||
end_of_duration = duration->add(*start);
|
||||
}
|
||||
|
||||
next = none;
|
||||
|
|
@ -634,15 +602,15 @@ namespace {
|
|||
assert(look_for_start || look_for_end);
|
||||
|
||||
if (word == _("year")) {
|
||||
duration = gregorian::years(1);
|
||||
duration = date_interval_t::duration_t(date_interval_t::duration_t::YEARS, 1);
|
||||
start = gregorian::date(start.year(), 1, 1);
|
||||
}
|
||||
else if (word == _("month")) {
|
||||
duration = gregorian::months(1);
|
||||
duration = date_interval_t::duration_t(date_interval_t::duration_t::MONTHS, 1);
|
||||
start = gregorian::date(start.year(), start.month(), 1);
|
||||
}
|
||||
else if (word == _("today") || word == _("day")) {
|
||||
duration = gregorian::days(1);
|
||||
duration = date_interval_t::duration_t(date_interval_t::duration_t::DAYS, 1);
|
||||
}
|
||||
else {
|
||||
parse_specifier = true;
|
||||
|
|
@ -651,15 +619,15 @@ namespace {
|
|||
if (parse_specifier)
|
||||
parse_inclusion_specifier(word, &start, &end);
|
||||
else
|
||||
end = date_interval_t::add_duration(start, *duration);
|
||||
end = duration->add(start);
|
||||
|
||||
if (type == _("last") && duration) {
|
||||
start = date_interval_t::subtract_duration(start, *duration);
|
||||
end = date_interval_t::subtract_duration(end, *duration);
|
||||
start = duration->subtract(start);
|
||||
end = duration->subtract(end);
|
||||
}
|
||||
else if (type == _("next") && duration) {
|
||||
start = date_interval_t::add_duration(start, *duration);
|
||||
end = date_interval_t::add_duration(end, *duration);
|
||||
start = duration->add(start);
|
||||
end = duration->add(end);
|
||||
}
|
||||
|
||||
if (look_for_start && is_valid(start)) interval.start = start;
|
||||
|
|
@ -683,41 +651,41 @@ void date_interval_t::parse(std::istream& in)
|
|||
int quantity = lexical_cast<int>(word);
|
||||
read_lower_word(in, word);
|
||||
if (word == _("days"))
|
||||
duration = gregorian::days(quantity);
|
||||
duration = duration_t(duration_t::DAYS, quantity);
|
||||
else if (word == _("weeks"))
|
||||
duration = gregorian::weeks(quantity);
|
||||
duration = duration_t(duration_t::WEEKS, quantity);
|
||||
else if (word == _("months"))
|
||||
duration = gregorian::months(quantity);
|
||||
duration = duration_t(duration_t::MONTHS, quantity);
|
||||
else if (word == _("quarters"))
|
||||
duration = gregorian::months(3 * quantity);
|
||||
duration = duration_t(duration_t::MONTHS, 3 * quantity);
|
||||
else if (word == _("years"))
|
||||
duration = gregorian::years(quantity);
|
||||
duration = duration_t(duration_t::YEARS, quantity);
|
||||
}
|
||||
else if (word == _("day"))
|
||||
duration = gregorian::days(1);
|
||||
duration = duration_t(duration_t::DAYS, 1);
|
||||
else if (word == _("week"))
|
||||
duration = gregorian::weeks(1);
|
||||
duration = duration_t(duration_t::WEEKS, 1);
|
||||
else if (word == _("month"))
|
||||
duration = gregorian::months(1);
|
||||
duration = duration_t(duration_t::MONTHS, 1);
|
||||
else if (word == _("quarter"))
|
||||
duration = gregorian::months(3);
|
||||
duration = duration_t(duration_t::MONTHS, 3);
|
||||
else if (word == _("year"))
|
||||
duration = gregorian::years(1);
|
||||
duration = duration_t(duration_t::YEARS, 1);
|
||||
}
|
||||
else if (word == _("daily"))
|
||||
duration = gregorian::days(1);
|
||||
duration = duration_t(duration_t::DAYS, 1);
|
||||
else if (word == _("weekly"))
|
||||
duration = gregorian::weeks(1);
|
||||
duration = duration_t(duration_t::WEEKS, 1);
|
||||
else if (word == _("biweekly"))
|
||||
duration = gregorian::weeks(2);
|
||||
duration = duration_t(duration_t::WEEKS, 2);
|
||||
else if (word == _("monthly"))
|
||||
duration = gregorian::months(1);
|
||||
duration = duration_t(duration_t::MONTHS, 1);
|
||||
else if (word == _("bimonthly"))
|
||||
duration = gregorian::months(2);
|
||||
duration = duration_t(duration_t::MONTHS, 2);
|
||||
else if (word == _("quarterly"))
|
||||
duration = gregorian::months(3);
|
||||
duration = duration_t(duration_t::MONTHS, 3);
|
||||
else if (word == _("yearly"))
|
||||
duration = gregorian::years(1);
|
||||
duration = duration_t(duration_t::YEARS, 1);
|
||||
else if (word == _("this") || word == _("last") || word == _("next") ||
|
||||
word == _("today")) {
|
||||
parse_date_words(in, word, *this);
|
||||
|
|
@ -760,17 +728,17 @@ void date_interval_t::parse(std::istream& in)
|
|||
|
||||
if (wday) {
|
||||
while (start->day_of_week() != *wday)
|
||||
*start -= gregorian::days(1);
|
||||
*start = duration_t(duration_t::DAYS, 1).subtract(*start);
|
||||
|
||||
if (! end)
|
||||
end = *start + gregorian::days(1);
|
||||
end = duration_t(duration_t::DAYS, 1).add(*start);
|
||||
} else {
|
||||
bool overwrite_end = false;
|
||||
|
||||
if (year) {
|
||||
start = date_t(*year, 1, 1);
|
||||
if (! end) {
|
||||
end = *start + gregorian::years(1);
|
||||
end = duration_t(duration_t::YEARS, 1).add(*start);
|
||||
overwrite_end = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -778,7 +746,7 @@ void date_interval_t::parse(std::istream& in)
|
|||
if (mon) {
|
||||
start = date_t(start->year(), *mon, 1);
|
||||
if (! end || overwrite_end)
|
||||
end = *start + gregorian::months(1);
|
||||
end = duration_t(duration_t::MONTHS, 1).add(*start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
88
src/times.h
88
src/times.h
|
|
@ -119,10 +119,71 @@ void set_input_date_format(const char * format);
|
|||
class date_interval_t : public equality_comparable<date_interval_t>
|
||||
{
|
||||
public:
|
||||
typedef variant<gregorian::days,
|
||||
gregorian::weeks,
|
||||
gregorian::months,
|
||||
gregorian::years> duration_t;
|
||||
struct duration_t
|
||||
{
|
||||
enum skip_quantum_t {
|
||||
DAYS, WEEKS, MONTHS, YEARS
|
||||
} quantum;
|
||||
int length;
|
||||
|
||||
duration_t() : quantum(DAYS), length(0) {
|
||||
TRACE_CTOR(date_interval_t::duration_t, "");
|
||||
}
|
||||
duration_t(skip_quantum_t _quantum, int _length)
|
||||
: quantum(_quantum), length(_length) {
|
||||
TRACE_CTOR(date_interval_t::duration_t, "skip_quantum_t, int");
|
||||
}
|
||||
duration_t(const duration_t& dur)
|
||||
: quantum(dur.quantum), length(dur.length) {
|
||||
TRACE_CTOR(date_interval_t::duration_t, "copy");
|
||||
}
|
||||
~duration_t() throw() {
|
||||
TRACE_DTOR(date_interval_t::duration_t);
|
||||
}
|
||||
|
||||
date_t add(const date_t& date) const {
|
||||
switch (quantum) {
|
||||
case DAYS:
|
||||
return date + gregorian::days(length);
|
||||
case WEEKS:
|
||||
return date + gregorian::weeks(length);
|
||||
case MONTHS:
|
||||
return date + gregorian::months(length);
|
||||
case YEARS:
|
||||
return date + gregorian::years(length);
|
||||
default:
|
||||
assert(0); return date_t();
|
||||
}
|
||||
}
|
||||
|
||||
date_t subtract(const date_t& date) const {
|
||||
switch (quantum) {
|
||||
case DAYS:
|
||||
return date - gregorian::days(length);
|
||||
case WEEKS:
|
||||
return date - gregorian::weeks(length);
|
||||
case MONTHS:
|
||||
return date - gregorian::months(length);
|
||||
case YEARS:
|
||||
return date - gregorian::years(length);
|
||||
default:
|
||||
assert(0); return date_t();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & quantum;
|
||||
ar & length;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
static date_t add_duration(const date_t& date,
|
||||
const duration_t& duration);
|
||||
|
|
@ -196,6 +257,25 @@ public:
|
|||
}
|
||||
|
||||
date_interval_t& operator++();
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & start;
|
||||
ar & aligned;
|
||||
ar & skip_duration;
|
||||
ar & factor;
|
||||
ar & next;
|
||||
ar & duration;
|
||||
ar & end_of_duration;
|
||||
ar & end;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
void times_initialize();
|
||||
|
|
|
|||
12
src/utils.h
12
src/utils.h
|
|
@ -178,6 +178,18 @@ public:
|
|||
string(const char * str, size_type x);
|
||||
string(const char * str, size_type x, size_type y);
|
||||
~string() throw();
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<std::string>(*this);
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
inline string operator+(const string& __lhs, const string& __rhs)
|
||||
|
|
|
|||
22
src/value.cc
22
src/value.cc
|
|
@ -113,8 +113,8 @@ value_t::operator bool() const
|
|||
}
|
||||
}
|
||||
return false;
|
||||
case POINTER:
|
||||
return ! as_any_pointer().empty();
|
||||
case SCOPE:
|
||||
return as_scope() != NULL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1206,8 +1206,8 @@ bool value_t::is_realzero() const
|
|||
case SEQUENCE:
|
||||
return as_sequence().empty();
|
||||
|
||||
case POINTER:
|
||||
return as_any_pointer().empty();
|
||||
case SCOPE:
|
||||
return as_scope() == NULL;
|
||||
|
||||
default:
|
||||
throw_(value_error, _("Cannot determine if %1 is really zero") << label());
|
||||
|
|
@ -1235,8 +1235,8 @@ bool value_t::is_zero() const
|
|||
case SEQUENCE:
|
||||
return as_sequence().empty();
|
||||
|
||||
case POINTER:
|
||||
return as_any_pointer().empty();
|
||||
case SCOPE:
|
||||
return as_scope() == NULL;
|
||||
|
||||
default:
|
||||
throw_(value_error, _("Cannot determine if %1 is zero") << label());
|
||||
|
|
@ -1474,7 +1474,7 @@ value_t value_t::strip_annotations(const keep_details_t& what_to_keep) const
|
|||
case DATE:
|
||||
case STRING:
|
||||
case MASK:
|
||||
case POINTER:
|
||||
case SCOPE:
|
||||
return *this;
|
||||
|
||||
case SEQUENCE: {
|
||||
|
|
@ -1579,8 +1579,8 @@ void value_t::print(std::ostream& out,
|
|||
break;
|
||||
}
|
||||
|
||||
case POINTER:
|
||||
out << "<POINTER>";
|
||||
case SCOPE:
|
||||
out << "<SCOPE>";
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -1647,8 +1647,8 @@ void value_t::dump(std::ostream& out, const bool relaxed) const
|
|||
out << '/' << as_mask() << '/';
|
||||
break;
|
||||
|
||||
case POINTER:
|
||||
out << boost::unsafe_any_cast<const void *>(&as_any_pointer());
|
||||
case SCOPE:
|
||||
out << as_scope();
|
||||
break;
|
||||
|
||||
case SEQUENCE: {
|
||||
|
|
|
|||
92
src/value.h
92
src/value.h
|
|
@ -56,6 +56,8 @@ namespace ledger {
|
|||
|
||||
DECLARE_EXCEPTION(value_error, std::runtime_error);
|
||||
|
||||
class scope_t;
|
||||
|
||||
/**
|
||||
* @class value_t
|
||||
*
|
||||
|
|
@ -107,7 +109,7 @@ public:
|
|||
STRING, // a string object
|
||||
MASK, // a regular expression mask
|
||||
SEQUENCE, // a vector of value_t objects
|
||||
POINTER // an opaque pointer of any type
|
||||
SCOPE // a pointer to a scope
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -134,7 +136,7 @@ private:
|
|||
string, // STRING
|
||||
mask_t, // MASK
|
||||
sequence_t *, // SEQUENCE
|
||||
boost::any // POINTER
|
||||
scope_t * // SCOPE
|
||||
> data;
|
||||
|
||||
type_t type;
|
||||
|
|
@ -225,6 +227,20 @@ private:
|
|||
data = false;
|
||||
type = VOID;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & data;
|
||||
ar & type;
|
||||
ar & refc;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -332,10 +348,9 @@ public:
|
|||
set_sequence(val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
explicit value_t(T * item) {
|
||||
TRACE_CTOR(value_t, "T *");
|
||||
set_pointer(item);
|
||||
explicit value_t(scope_t * item) {
|
||||
TRACE_CTOR(value_t, "scope_t *");
|
||||
set_scope(item);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -687,50 +702,19 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Dealing with pointers is bit involved because we actually deal
|
||||
* with typed pointers. For example, if you call as_pointer it
|
||||
* returns a boost::any object, but if you use as_pointer<void>,
|
||||
* then it returns a void *. The latter form only succeeds if the
|
||||
* stored pointers was assigned to the value as a void*, otherwise
|
||||
* it throws an exception.
|
||||
* Dealing with scope pointers.
|
||||
*/
|
||||
bool is_pointer() const {
|
||||
return is_type(POINTER);
|
||||
bool is_scope() const {
|
||||
return is_type(SCOPE);
|
||||
}
|
||||
boost::any& as_any_pointer_lval() {
|
||||
VERIFY(is_pointer());
|
||||
_dup();
|
||||
return boost::get<boost::any>(storage->data);
|
||||
scope_t * as_scope() const {
|
||||
VERIFY(is_scope());
|
||||
return boost::get<scope_t *>(storage->data);
|
||||
}
|
||||
template <typename T>
|
||||
T * as_pointer_lval() {
|
||||
return any_cast<T *>(as_any_pointer_lval());
|
||||
}
|
||||
template <typename T>
|
||||
T& as_ref_lval() {
|
||||
return *as_pointer_lval<T>();
|
||||
}
|
||||
const boost::any& as_any_pointer() const {
|
||||
VERIFY(is_pointer());
|
||||
return boost::get<boost::any>(storage->data);
|
||||
}
|
||||
template <typename T>
|
||||
T * as_pointer() const {
|
||||
return any_cast<T *>(as_any_pointer());
|
||||
}
|
||||
template <typename T>
|
||||
T& as_ref() const {
|
||||
return *as_pointer<T>();
|
||||
}
|
||||
void set_any_pointer(const boost::any& val) {
|
||||
set_type(POINTER);
|
||||
void set_scope(scope_t * val) {
|
||||
set_type(SCOPE);
|
||||
storage->data = val;
|
||||
}
|
||||
template <typename T>
|
||||
void set_pointer(T * val) {
|
||||
set_type(POINTER);
|
||||
storage->data = boost::any(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data conversion methods. These methods convert a value object to
|
||||
|
|
@ -902,8 +886,8 @@ public:
|
|||
return _("a regexp");
|
||||
case SEQUENCE:
|
||||
return _("a sequence");
|
||||
case POINTER:
|
||||
return _("a pointer");
|
||||
case SCOPE:
|
||||
return _("a scope");
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
|
|
@ -926,6 +910,20 @@ public:
|
|||
* Debugging methods.
|
||||
*/
|
||||
bool valid() const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & true_value;
|
||||
ar & false_value;
|
||||
ar & storage;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
#define NULL_VALUE (value_t())
|
||||
|
|
|
|||
|
|
@ -499,7 +499,7 @@ void auto_xact_t::extend_xact(xact_base_t& xact, bool post_handler)
|
|||
|
||||
IF_DEBUG("xact.extend") {
|
||||
DEBUG("xact.extend",
|
||||
"Initial post on line " << initial_post->beg_line << ": "
|
||||
"Initial post on line " << initial_post->pos->beg_line << ": "
|
||||
<< "amount " << initial_post->amount << " (precision "
|
||||
<< initial_post->amount.precision() << ")");
|
||||
|
||||
|
|
@ -509,7 +509,7 @@ void auto_xact_t::extend_xact(xact_base_t& xact, bool post_handler)
|
|||
#endif
|
||||
|
||||
DEBUG("xact.extend",
|
||||
"Posting on line " << post->beg_line << ": "
|
||||
"Posting on line " << post->pos->beg_line << ": "
|
||||
<< "amount " << post->amount << ", amt " << amt
|
||||
<< " (precision " << post->amount.precision()
|
||||
<< " != " << amt.precision() << ")");
|
||||
|
|
|
|||
69
src/xact.h
69
src/xact.h
|
|
@ -80,6 +80,20 @@ public:
|
|||
|
||||
virtual bool finalize();
|
||||
virtual bool valid() const = 0;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<item_t>(*this);
|
||||
ar & journal;
|
||||
ar & posts;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -111,6 +125,20 @@ public:
|
|||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
|
||||
virtual bool valid() const;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<xact_base_t>(*this);
|
||||
ar & code;
|
||||
ar & payee;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -154,6 +182,19 @@ public:
|
|||
virtual bool valid() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<xact_base_t>(*this);
|
||||
ar & predicate;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -180,6 +221,18 @@ struct auto_xact_finalizer_t : public xact_finalizer_t
|
|||
}
|
||||
|
||||
virtual bool operator()(xact_t& xact, bool post);
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & journal;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -205,7 +258,7 @@ class period_xact_t : public xact_base_t
|
|||
TRACE_CTOR(period_xact_t, "const string&");
|
||||
}
|
||||
|
||||
virtual ~period_xact_t() throw() {
|
||||
virtual ~period_xact_t() {
|
||||
TRACE_DTOR(period_xact_t);
|
||||
}
|
||||
|
||||
|
|
@ -218,6 +271,20 @@ class period_xact_t : public xact_base_t
|
|||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /* version */) {
|
||||
ar & boost::serialization::base_object<xact_base_t>(*this);
|
||||
ar & period;
|
||||
ar & period_string;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
520
tools/Makefile.am
Normal file
520
tools/Makefile.am
Normal file
|
|
@ -0,0 +1,520 @@
|
|||
VERSION = 3.0
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
dist_man_MANS = doc/ledger.1
|
||||
SUBDIRS = po intl
|
||||
EXTRA_DIST = autogen.sh config.rpath contrib src/system.hh.in
|
||||
DISTCLEANFILES = .timestamp
|
||||
|
||||
lib_LTLIBRARIES = \
|
||||
libledger_report.la \
|
||||
libledger_data.la \
|
||||
libledger_expr.la \
|
||||
libledger_math.la \
|
||||
libledger_util.la
|
||||
|
||||
lib_cppflags = -I$(srcdir)/src -I$(srcdir)/lib \
|
||||
-I$(srcdir)/lib/utfcpp/source
|
||||
|
||||
libledger_util_la_SOURCES = \
|
||||
src/stream.cc \
|
||||
src/mask.cc \
|
||||
src/times.cc \
|
||||
src/error.cc \
|
||||
src/utils.cc \
|
||||
src/accum.cc \
|
||||
lib/sha1.cpp
|
||||
|
||||
libledger_util_la_CPPFLAGS = $(lib_cppflags)
|
||||
libledger_util_la_LDFLAGS = -release $(VERSION).0
|
||||
|
||||
libledger_math_la_SOURCES = \
|
||||
src/value.cc \
|
||||
src/balance.cc \
|
||||
src/quotes.cc \
|
||||
src/pool.cc \
|
||||
src/annotate.cc \
|
||||
src/commodity.cc \
|
||||
src/amount.cc
|
||||
|
||||
libledger_math_la_CPPFLAGS = $(lib_cppflags)
|
||||
libledger_math_la_LDFLAGS = -release $(VERSION).0
|
||||
|
||||
libledger_expr_la_SOURCES = \
|
||||
src/option.cc \
|
||||
src/format.cc \
|
||||
src/predicate.cc \
|
||||
src/scope.cc \
|
||||
src/interactive.cc \
|
||||
src/expr.cc \
|
||||
src/op.cc \
|
||||
src/parser.cc \
|
||||
src/token.cc
|
||||
|
||||
libledger_expr_la_CPPFLAGS = $(lib_cppflags)
|
||||
libledger_expr_la_LDFLAGS = -release $(VERSION).0
|
||||
|
||||
libledger_data_la_SOURCES = \
|
||||
src/compare.cc \
|
||||
src/iterators.cc \
|
||||
src/timelog.cc \
|
||||
src/textual.cc \
|
||||
src/journal.cc \
|
||||
src/archive.cc \
|
||||
src/account.cc \
|
||||
src/xact.cc \
|
||||
src/post.cc \
|
||||
src/item.cc
|
||||
|
||||
libledger_data_la_CPPFLAGS = $(lib_cppflags)
|
||||
libledger_data_la_LDFLAGS = -release $(VERSION).0
|
||||
|
||||
libledger_report_la_SOURCES = \
|
||||
src/stats.cc \
|
||||
src/generate.cc \
|
||||
src/derive.cc \
|
||||
src/emacs.cc \
|
||||
src/output.cc \
|
||||
src/precmd.cc \
|
||||
src/chain.cc \
|
||||
src/filters.cc \
|
||||
src/temps.cc \
|
||||
src/report.cc \
|
||||
src/session.cc
|
||||
|
||||
libledger_report_la_CPPFLAGS = $(lib_cppflags)
|
||||
libledger_report_la_LDFLAGS = -release $(VERSION).0
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
src/utils.h \
|
||||
src/flags.h \
|
||||
src/hooks.h \
|
||||
src/error.h \
|
||||
src/times.h \
|
||||
src/mask.h \
|
||||
src/stream.h \
|
||||
src/pstream.h \
|
||||
src/unistring.h \
|
||||
src/accum.h \
|
||||
\
|
||||
src/amount.h \
|
||||
src/commodity.h \
|
||||
src/annotate.h \
|
||||
src/pool.h \
|
||||
src/quotes.h \
|
||||
src/balance.h \
|
||||
src/value.h \
|
||||
\
|
||||
src/token.h \
|
||||
src/parser.h \
|
||||
src/op.h \
|
||||
src/expr.h \
|
||||
src/scope.h \
|
||||
src/interactive.h \
|
||||
src/predicate.h \
|
||||
src/format.h \
|
||||
src/option.h \
|
||||
\
|
||||
src/item.h \
|
||||
src/post.h \
|
||||
src/xact.h \
|
||||
src/account.h \
|
||||
src/journal.h \
|
||||
src/archive.h \
|
||||
src/timelog.h \
|
||||
src/iterators.h \
|
||||
src/compare.h \
|
||||
\
|
||||
src/session.h \
|
||||
src/report.h \
|
||||
src/filters.h \
|
||||
src/temps.h \
|
||||
src/chain.h \
|
||||
src/precmd.h \
|
||||
src/derive.h \
|
||||
src/generate.h \
|
||||
src/stats.h \
|
||||
src/output.h \
|
||||
src/emacs.h \
|
||||
\
|
||||
src/global.h \
|
||||
\
|
||||
src/pyinterp.h \
|
||||
\
|
||||
lib/sha1.h \
|
||||
lib/gettext.h \
|
||||
\
|
||||
lib/utfcpp/source/utf8.h \
|
||||
lib/utfcpp/source/utf8/checked.h \
|
||||
lib/utfcpp/source/utf8/core.h \
|
||||
lib/utfcpp/source/utf8/unchecked.h
|
||||
|
||||
nodist_libledger_util_la_SOURCES = system.hh
|
||||
|
||||
BUILT_SOURCES = system.hh
|
||||
CLEANFILES = system.hh
|
||||
|
||||
system.hh: src/system.hh.in
|
||||
cp -p $< $@
|
||||
|
||||
if USE_PCH
|
||||
nodist_libledger_util_la_SOURCES += system.hh.gch
|
||||
|
||||
BUILT_SOURCES += system.hh.gch
|
||||
CLEANFILES += system.hh.gch
|
||||
|
||||
system.hh.gch: system.hh
|
||||
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(lib_cppflags) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
|
||||
-o $@ $<
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
|
||||
bin_PROGRAMS = ledger
|
||||
|
||||
ledger_CPPFLAGS = $(lib_cppflags)
|
||||
if HAVE_BOOST_PYTHON
|
||||
ledger_CPPFLAGS += -I$(srcdir)/python
|
||||
endif
|
||||
ledger_SOURCES = src/main.cc src/global.cc
|
||||
ledger_LDADD = $(LIBOBJS) $(lib_LTLIBRARIES) $(INTLLIBS)
|
||||
ledger_LDFLAGS = -static
|
||||
|
||||
info_TEXINFOS = doc/ledger.texi
|
||||
|
||||
dist_lisp_LISP = lisp/ledger.el lisp/timeclock.el
|
||||
ELCFILES =
|
||||
DISTCLEANFILES += ledger.elc timeclock.elc
|
||||
|
||||
all_sources = $(libledger_util_la_SOURCES) \
|
||||
$(libledger_math_la_SOURCES) \
|
||||
$(libledger_expr_la_SOURCES) \
|
||||
$(libledger_data_la_SOURCES) \
|
||||
$(libledger_report_la_SOURCES) \
|
||||
$(libledger_python_la_SOURCES) \
|
||||
src/pyledger.cc
|
||||
|
||||
all_files = $(all_sources) $(pkginclude_HEADERS)
|
||||
|
||||
######################################################################
|
||||
|
||||
if HAVE_BOOST_PYTHON
|
||||
|
||||
lib_LTLIBRARIES += libledger_python.la
|
||||
|
||||
libledger_python_la_SOURCES = \
|
||||
src/pyutils.h \
|
||||
src/pyfstream.h \
|
||||
src/py_amount.cc \
|
||||
src/py_balance.cc \
|
||||
src/py_chain.cc \
|
||||
src/py_commodity.cc \
|
||||
src/py_expr.cc \
|
||||
src/py_flags.cc \
|
||||
src/py_format.cc \
|
||||
src/py_global.cc \
|
||||
src/py_item.cc \
|
||||
src/py_journal.cc \
|
||||
src/py_post.cc \
|
||||
src/py_report.cc \
|
||||
src/py_scope.cc \
|
||||
src/py_session.cc \
|
||||
src/py_timelog.cc \
|
||||
src/py_times.cc \
|
||||
src/py_utils.cc \
|
||||
src/py_value.cc \
|
||||
src/py_xact.cc \
|
||||
src/pyinterp.cc
|
||||
|
||||
libledger_python_la_CPPFLAGS = $(lib_cppflags) -I$(srcdir)/python
|
||||
|
||||
pyexec_LTLIBRARIES = ledger.la
|
||||
|
||||
ledger_la_CPPFLAGS = $(libledger_python_la_CPPFLAGS)
|
||||
ledger_la_SOURCES = src/pyledger.cc
|
||||
ledger_la_DEPENDENCIES = $(lib_LTLIBRARIES)
|
||||
ledger_la_LDFLAGS = -avoid-version -module
|
||||
ledger_la_LIBADD = $(LIBOBJS) $(lib_LTLIBRARIES) $(INTLLIBS)
|
||||
|
||||
pkgpython_PYTHON = python/__init__.py \
|
||||
python/hello.py \
|
||||
python/server.py
|
||||
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
|
||||
TESTS =
|
||||
|
||||
if HAVE_PYTHON
|
||||
TESTS += RegressTests BaselineTests ConfirmTests GenerateTests
|
||||
endif
|
||||
|
||||
if HAVE_CPPUNIT
|
||||
TESTS += \
|
||||
UtilTests \
|
||||
MathTests \
|
||||
ExprTests \
|
||||
DataTests \
|
||||
ReportTests
|
||||
endif
|
||||
|
||||
if HAVE_BOOST_PYTHON
|
||||
TESTS += PyUnitTests
|
||||
endif
|
||||
|
||||
check_PROGRAMS = $(TESTS)
|
||||
|
||||
UtilTests_SOURCES = \
|
||||
test/UnitTests.cc \
|
||||
test/UnitTests.h \
|
||||
test/UtilTests.cc \
|
||||
test/unit/t_utils.cc \
|
||||
test/unit/t_utils.h \
|
||||
test/unit/t_times.cc \
|
||||
test/unit/t_times.h
|
||||
|
||||
UtilTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
|
||||
UtilTests_LDADD = libledger_util.la -lcppunit
|
||||
|
||||
MathTests_SOURCES = \
|
||||
test/UnitTests.cc \
|
||||
test/UnitTests.h \
|
||||
test/MathTests.cc \
|
||||
test/unit/t_commodity.cc \
|
||||
test/unit/t_commodity.h \
|
||||
test/unit/t_amount.cc \
|
||||
test/unit/t_amount.h \
|
||||
test/unit/t_balance.cc \
|
||||
test/unit/t_balance.h
|
||||
|
||||
MathTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
|
||||
MathTests_LDADD = libledger_math.la $(UtilTests_LDADD)
|
||||
|
||||
ExprTests_SOURCES = \
|
||||
test/UnitTests.cc \
|
||||
test/UnitTests.h \
|
||||
test/ExprTests.cc \
|
||||
test/unit/t_expr.cc \
|
||||
test/unit/t_expr.h
|
||||
|
||||
ExprTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
|
||||
ExprTests_LDADD = libledger_expr.la $(MathTests_LDADD)
|
||||
|
||||
DataTests_SOURCES = \
|
||||
test/UnitTests.cc \
|
||||
test/UnitTests.h \
|
||||
test/DataTests.cc
|
||||
|
||||
DataTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
|
||||
DataTests_LDADD = libledger_data.la $(ExprTests_LDADD)
|
||||
|
||||
ReportTests_SOURCES = \
|
||||
test/UnitTests.cc \
|
||||
test/UnitTests.h \
|
||||
test/ReportTests.cc
|
||||
|
||||
ReportTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
|
||||
ReportTests_LDADD = libledger_report.la $(DataTests_LDADD)
|
||||
|
||||
all_tests_sources = \
|
||||
$(UtilTests_SOURCES) \
|
||||
$(MathTests_SOURCES) \
|
||||
$(ExprTests_SOURCES) \
|
||||
$(DataTests_SOURCES) \
|
||||
$(ReportTests_SOURCES)
|
||||
|
||||
PyUnitTests_SOURCES = test/PyUnitTests.py
|
||||
|
||||
all_py_tests_sources = \
|
||||
$(patsubst test/unit/%.cc,$(top_builddir)/test/python/%.py, \
|
||||
$(filter test/unit/t_%.cc,$(all_tests_sources)))
|
||||
|
||||
test/python/%.py: test/unit/%.cc test/convert.py
|
||||
$(PYTHON) $(srcdir)/test/convert.py $< $@
|
||||
|
||||
test/python/UnitTests.py: $(all_py_tests_sources)
|
||||
@echo "from unittest import TextTestRunner, TestSuite" > $@
|
||||
@for file in $$(ls $(srcdir)/test/unit/*.cc); do \
|
||||
base=$$(basename $$file); \
|
||||
base=$$(echo $$base | sed 's/\.cc//'); \
|
||||
echo "import $$base" >> $@; \
|
||||
done
|
||||
@echo "suites = [" >> $@
|
||||
@for file in $$(ls $(srcdir)/test/unit/*.cc); do \
|
||||
base=$$(basename $$file); \
|
||||
base=$$(echo $$base | sed 's/\.cc//'); \
|
||||
echo " $$base.suite()," >> $@; \
|
||||
done
|
||||
@echo "]" >> $@
|
||||
@echo "TextTestRunner().run(TestSuite(suites))" >> $@
|
||||
|
||||
ledger_python = $(top_builddir)/ledger$(EXEEXT) python
|
||||
|
||||
ESC_python=`echo "$(ledger_python)" | sed 's/\//\\\\\//g'`
|
||||
ESC_srcdir=`echo "$(srcdir)" | sed 's/\//\\\\\//g'`
|
||||
ESC_builddir=`echo "$(top_builddir)" | sed 's/\//\\\\\//g'`
|
||||
ESC_distdir=`echo "$(distdir)" | sed 's/\//\\\\\//g'`
|
||||
|
||||
# jww (2007-05-10): This rule will not be triggered on systems that
|
||||
# define an EXEEXT.
|
||||
PyUnitTests: test/PyUnitTests.py test/python/UnitTests.py
|
||||
@cat $(srcdir)/test/PyUnitTests.py \
|
||||
| sed "s/%python%/$(ESC_python)/" \
|
||||
| sed "s/%srcdir%/$(ESC_srcdir)/g" \
|
||||
| sed "s/%builddir%/$(ESC_builddir)/g" > $@
|
||||
chmod 755 $@
|
||||
|
||||
RegressTests_SOURCES = test/RegressTests.py
|
||||
|
||||
EXTRA_DIST += test/regress test/convert.py test/LedgerHarness.py
|
||||
|
||||
RegressTests: $(srcdir)/test/RegressTests.py
|
||||
echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir)/test/regress \"\$$@\"" > $@
|
||||
chmod 755 $@
|
||||
|
||||
BaselineTests_SOURCES = test/RegressTests.py
|
||||
|
||||
EXTRA_DIST += test/baseline
|
||||
|
||||
BaselineTests: $(srcdir)/test/RegressTests.py
|
||||
echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir)/test/baseline \"\$$@\"" > $@
|
||||
chmod 755 $@
|
||||
|
||||
ConfirmTests_SOURCES = test/ConfirmTests.py
|
||||
|
||||
EXTRA_DIST += test/input
|
||||
|
||||
test/input/mondo.dat: test/input/standard.dat
|
||||
@for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do \
|
||||
for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do \
|
||||
cat $< >> $@; \
|
||||
done; \
|
||||
done
|
||||
|
||||
ConfirmTests: $(srcdir)/test/ConfirmTests.py
|
||||
echo "$(PYTHON) $(srcdir)/test/ConfirmTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir)/test/input \"\$$@\"" > $@
|
||||
chmod 755 $@
|
||||
|
||||
GenerateTests_SOURCES = test/GenerateTests.py
|
||||
|
||||
GenerateTests: $(srcdir)/test/GenerateTests.py
|
||||
echo "$(PYTHON) $(srcdir)/test/GenerateTests.py $(top_builddir)/ledger$(EXEEXT) 1 20 \"\$$@\"" > $@
|
||||
chmod 755 $@
|
||||
|
||||
FULLCHECK=$(srcdir)/test/fullcheck.sh
|
||||
|
||||
if HAVE_CPPUNIT
|
||||
cppunittests: check
|
||||
@sh $(FULLCHECK) $(top_builddir)/UtilTests$(EXEEXT) --verify \
|
||||
2>&1 | grep -v '^GuardMalloc:'
|
||||
@sh $(FULLCHECK) $(top_builddir)/MathTests$(EXEEXT) --verify \
|
||||
2>&1 | grep -v '^GuardMalloc:'
|
||||
@sh $(FULLCHECK) $(top_builddir)/ExprTests$(EXEEXT) --verify \
|
||||
2>&1 | grep -v '^GuardMalloc:'
|
||||
@sh $(FULLCHECK) $(top_builddir)/DataTests$(EXEEXT) --verify \
|
||||
2>&1 | grep -v '^GuardMalloc:'
|
||||
@sh $(FULLCHECK) $(top_builddir)/ReportTests$(EXEEXT) --verify \
|
||||
2>&1 | grep -v '^GuardMalloc:'
|
||||
else
|
||||
cppunittests: check
|
||||
@test 1 -eq 1
|
||||
endif
|
||||
|
||||
fullcheck: cppunittests
|
||||
@$(top_builddir)/RegressTests --verify
|
||||
@$(top_builddir)/BaselineTests --verify
|
||||
@$(top_builddir)/ConfirmTests --verify
|
||||
@$(top_builddir)/GenerateTests --verify
|
||||
@$(top_builddir)/RegressTests --gmalloc
|
||||
@$(top_builddir)/BaselineTests --gmalloc
|
||||
# @$(top_builddir)/ConfirmTests --gmalloc
|
||||
# @$(top_builddir)/GenerateTests --gmalloc
|
||||
|
||||
######################################################################
|
||||
|
||||
EXTRA_DIST += doc/README doc/LICENSE doc/NEWS doc/ledger.pdf
|
||||
if USE_DOXYGEN
|
||||
EXTRA_DIST += doc/Doxyfile doc/refman.pdf
|
||||
endif
|
||||
|
||||
DISTCLEANFILES += doc/ledger.info doc/ledger.pdf
|
||||
if USE_DOXYGEN
|
||||
DISTCLEANFILES += Doxyfile.gen doc/Doxyfile.bak doc/refman.pdf
|
||||
endif
|
||||
|
||||
if USE_DOXYGEN
|
||||
dist-hook-doxygen:
|
||||
find $(distdir)/doc -name .dirstamp -delete
|
||||
rm -fr $(distdir)/doc/latex \
|
||||
$(distdir)/doc/Doxyfile.bak \
|
||||
$(distdir)/doc/Doxyfile.gen
|
||||
cp -pR doc/html $(distdir)/doc
|
||||
else
|
||||
dist-hook-doxygen:
|
||||
@test 1 -eq 1
|
||||
endif
|
||||
|
||||
dist-hook: dist-hook-doxygen
|
||||
find $(distdir) -name .DS_Store -delete
|
||||
find $(distdir) -name .localized -delete
|
||||
rm -f $(distdir)/README.textile
|
||||
cp -p $(srcdir)/doc/README $(distdir)/README
|
||||
|
||||
if USE_DOXYGEN
|
||||
distclean-local-doxygen:
|
||||
rm -fr doc/html doc/latex
|
||||
rm -f doc/refman.pdf
|
||||
else
|
||||
distclean-local-doxygen:
|
||||
@test 1 -eq 1
|
||||
endif
|
||||
|
||||
distclean-local: distclean-local-doxygen
|
||||
rm -fr test/python
|
||||
|
||||
if USE_DOXYGEN
|
||||
ESC_top_builddir=`cd $(top_builddir); pwd | sed 's/\//\\\\\//g'`
|
||||
|
||||
Doxyfile.gen: doc/Doxyfile
|
||||
cat $< | sed "s/%srcdir%/$(ESC_srcdir)/g" \
|
||||
| sed "s/%builddir%/$(ESC_top_builddir)/g" > $@
|
||||
|
||||
doc/html/index.html: Doxyfile.gen $(all_files)
|
||||
BUILD_DIR=`cd $(top_builddir); pwd`; \
|
||||
(cd $(srcdir); doxygen $$BUILD_DIR/Doxyfile.gen)
|
||||
|
||||
# The intention with the following rules is that all of the Doxygen
|
||||
# documentation (both HTML and PDF) is built locally before distcheck is
|
||||
# run, since it's quite possible that the user will not have a complete
|
||||
# TeX + Doxygen + dot environment on their own system.
|
||||
|
||||
doc/refman.pdf: doc/html/index.html
|
||||
(cd doc/latex && make)
|
||||
cp doc/latex/refman.pdf $@
|
||||
|
||||
docs: pdf doc/refman.pdf
|
||||
else
|
||||
docs: pdf
|
||||
endif
|
||||
|
||||
libs:
|
||||
@echo Building dependency libs and installing in /usr/local/stow ...
|
||||
git submodule update --init
|
||||
(cd lib; make)
|
||||
|
||||
report: all
|
||||
-rm -fr build
|
||||
lcov -d $(shell pwd) --zerocounters
|
||||
-mkdir doc/report
|
||||
lcov -c -i -d $(shell pwd) -o doc/report/ledger_base.info
|
||||
make fullcheck
|
||||
lcov -c -d $(shell pwd) --checksum -o doc/report/ledger_test.info
|
||||
lcov -a doc/report/ledger_base.info \
|
||||
-a doc/report/ledger_test.info -o doc/report/ledger_total.info
|
||||
lcov --extract doc/report/ledger_total.info '*src/ledger/*' \
|
||||
-o doc/report/ledger_cov.info
|
||||
genhtml -o doc/report doc/report/ledger_cov.info
|
||||
@echo Coverage reported generated\; now open doc/report/index.html
|
||||
|
||||
# Makefile.am ends here
|
||||
1491
tools/autogen.sh
Executable file
1491
tools/autogen.sh
Executable file
File diff suppressed because it is too large
Load diff
391
tools/configure.ac
Normal file
391
tools/configure.ac
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
|
||||
m4_include([version.m4])
|
||||
|
||||
AC_INIT([ledger],[VERSION_NUMBER],[johnw@newartisans.com])
|
||||
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AM_INIT_AUTOMAKE([dist-bzip2 foreign])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AC_CONFIG_SRCDIR([src/main.cc])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
|
||||
# Checks for programs.
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_CXX
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_LIBTOOL
|
||||
AM_GNU_GETTEXT
|
||||
AM_GNU_GETTEXT_VERSION([0.17])
|
||||
|
||||
# Checks for emacs lisp path
|
||||
AM_PATH_LISPDIR
|
||||
|
||||
# Check for options
|
||||
AC_ARG_ENABLE(debug,
|
||||
[ --enable-debug Turn on debugging],
|
||||
[case "${enableval}" in
|
||||
yes) debug=true ;;
|
||||
no) debug=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
|
||||
esac],[debug=false])
|
||||
|
||||
if [ test x$debug = xtrue ]; then
|
||||
AC_DEFINE([DEBUG_MODE], [1], [Whether debugging is enabled])
|
||||
fi
|
||||
AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
|
||||
|
||||
AC_ARG_ENABLE(pch,
|
||||
[ --enable-pch Use GCC 4.x pre-compiled headers],
|
||||
[case "${enableval}" in
|
||||
yes) pch=true ;;
|
||||
no) pch=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-pch) ;;
|
||||
esac],[pch=false])
|
||||
|
||||
if [ test x$pch = xtrue ]; then
|
||||
AC_DEFINE([USE_PCH], [1], [Whether pre-compiled headers are being used])
|
||||
fi
|
||||
AM_CONDITIONAL(USE_PCH, test x$pch = xtrue)
|
||||
|
||||
AC_ARG_ENABLE(doxygen,
|
||||
[ --enable-doxygen Turns on generation of code documentation],
|
||||
[case "${enableval}" in
|
||||
yes) doxygen=true ;;
|
||||
no) doxygen=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-doxygen) ;;
|
||||
esac],[doxygen=false])
|
||||
|
||||
AM_CONDITIONAL(USE_DOXYGEN, test x$doxygen = xtrue)
|
||||
|
||||
AC_ARG_WITH(boost-suffix,
|
||||
[ --with-boost-suffix=X Append X to the Boost library names],
|
||||
[BOOST_SUFFIX="${withval}"],
|
||||
[BOOST_SUFFIX=""])
|
||||
|
||||
AC_SUBST([BOOST_SUFFIX], $BOOST_SUFFIX)
|
||||
|
||||
# check if UNIX pipes are available
|
||||
AC_CACHE_CHECK(
|
||||
[if pipes can be used],
|
||||
[pipes_avail_cv_],
|
||||
[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;
|
||||
|
||||
status = dup2(pfd[0], STDIN_FILENO);
|
||||
|
||||
close(pfd[1]);
|
||||
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])
|
||||
|
||||
if [test x$pipes_avail_cv_ = xtrue ]; then
|
||||
AC_DEFINE([HAVE_UNIX_PIPES], [1], [Whether UNIX pipes are available])
|
||||
fi
|
||||
|
||||
# check for gmp
|
||||
AC_CACHE_CHECK(
|
||||
[if GMP is available],
|
||||
[libgmp_avail_cv_],
|
||||
[libgmp_save_libs=$LIBS
|
||||
LIBS="-lgmp $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <gmp.h>]], [[mpz_t bar;
|
||||
mpz_init(bar);
|
||||
mpz_clear(bar);]])],[libgmp_avail_cv_=true],[libgmp_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$libgmp_save_libs])
|
||||
|
||||
if [test x$libgmp_avail_cv_ = xtrue ]; then
|
||||
LIBS="-lgmp $LIBS"
|
||||
else
|
||||
AC_MSG_FAILURE("Could not find gmp library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for mpfr
|
||||
AC_CACHE_CHECK(
|
||||
[if MPFR is available],
|
||||
[libmpfr_avail_cv_],
|
||||
[libmpfr_save_libs=$LIBS
|
||||
LIBS="-lmpfr $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <mpfr.h>]], [[mpfr_t bar;
|
||||
mpfr_init(bar);
|
||||
char * buf = NULL;
|
||||
mpfr_asprintf(&buf, "%Rf", bar);
|
||||
mpfr_clear(bar);]])],[libmpfr_avail_cv_=true],[libmpfr_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$libmpfr_save_libs])
|
||||
|
||||
if [test x$libmpfr_avail_cv_ = xtrue ]; then
|
||||
LIBS="-lmpfr $LIBS"
|
||||
else
|
||||
AC_MSG_FAILURE("Could not find mpfr library 2.4.0 or higher (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for edit
|
||||
AC_CACHE_CHECK(
|
||||
[if libedit is available],
|
||||
[libedit_avail_cv_],
|
||||
[libedit_save_libs=$LIBS
|
||||
LIBS="-ledit $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <editline/readline.h>]],
|
||||
[[rl_readline_name = const_cast<char *>("foo");
|
||||
char * line = readline(const_cast<char *>("foo: "));
|
||||
free(line);]])],[libedit_avail_cv_=true],[libedit_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$libedit_save_libs])
|
||||
|
||||
if [test x$libedit_avail_cv_ = xtrue ]; then
|
||||
LIBS="-ledit $LIBS"
|
||||
AC_DEFINE([HAVE_LIBEDIT], [1], [If the libedit library is available])
|
||||
fi
|
||||
|
||||
# check for boost_regex
|
||||
AC_CACHE_CHECK(
|
||||
[if boost_regex is available],
|
||||
[boost_regex_avail_cv_],
|
||||
[boost_regex_save_libs=$LIBS
|
||||
LIBS="-lboost_regex$BOOST_SUFFIX $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <boost/regex.hpp>]],
|
||||
[[boost::regex foo_regexp("Hello, world!");]])],
|
||||
[boost_regex_avail_cv_=true],
|
||||
[boost_regex_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$boost_regex_save_libs])
|
||||
|
||||
if [test x$boost_regex_avail_cv_ = xtrue ]; then
|
||||
LIBS="-lboost_regex$BOOST_SUFFIX $LIBS"
|
||||
else
|
||||
AC_MSG_FAILURE("Could not find boost_regex library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for boost_date_time
|
||||
AC_CACHE_CHECK(
|
||||
[if boost_date_time is available],
|
||||
[boost_date_time_cpplib_avail_cv_],
|
||||
[boost_date_time_save_libs=$LIBS
|
||||
LIBS="-lboost_date_time$BOOST_SUFFIX $LIBS"
|
||||
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>
|
||||
|
||||
using namespace boost::posix_time;
|
||||
using namespace boost::date_time;
|
||||
|
||||
#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());
|
||||
|
||||
ptime t12 = time_to_system_local(t10);
|
||||
|
||||
return t10 != t12;]])],
|
||||
[boost_date_time_cpplib_avail_cv_=true],
|
||||
[boost_date_time_cpplib_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$boost_date_time_save_libs])
|
||||
|
||||
if [test x$boost_date_time_cpplib_avail_cv_ = xtrue ]; then
|
||||
LIBS="-lboost_date_time$BOOST_SUFFIX $LIBS"
|
||||
else
|
||||
AC_MSG_FAILURE("Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for boost_filesystem
|
||||
AC_CACHE_CHECK(
|
||||
[if boost_filesystem is available],
|
||||
[boost_filesystem_cpplib_avail_cv_],
|
||||
[boost_filesystem_save_libs=$LIBS
|
||||
LIBS="-lboost_filesystem$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#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
|
||||
LIBS=$boost_filesystem_save_libs])
|
||||
|
||||
if [test x$boost_filesystem_cpplib_avail_cv_ = xtrue ]; then
|
||||
LIBS="-lboost_filesystem$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
|
||||
else
|
||||
AC_MSG_FAILURE("Could not find boost_filesystem library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for boost_iostreams
|
||||
AC_CACHE_CHECK(
|
||||
[if boost_iostreams is available],
|
||||
[boost_iostreams_cpplib_avail_cv_],
|
||||
[boost_iostreams_save_libs=$LIBS
|
||||
LIBS="-lboost_iostreams$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
|
||||
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);]])],
|
||||
[boost_iostreams_cpplib_avail_cv_=true],
|
||||
[boost_iostreams_cpplib_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$boost_iostreams_save_libs])
|
||||
|
||||
if [test x$boost_iostreams_cpplib_avail_cv_ = xtrue ]; then
|
||||
LIBS="-lboost_iostreams$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
|
||||
else
|
||||
AC_MSG_FAILURE("Could not find boost_iostreams library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for boost_serialization
|
||||
AC_CACHE_CHECK(
|
||||
[if boost_serialization is available],
|
||||
[boost_serialization_cpplib_avail_cv_],
|
||||
[boost_serialization_save_libs=$LIBS
|
||||
LIBS="-lboost_serialization$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <boost/archive/binary_oarchive.hpp>
|
||||
#include <iostream>
|
||||
struct foo {
|
||||
int a;
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int) {
|
||||
ar & a;
|
||||
}
|
||||
};]],
|
||||
[[boost::archive::binary_oarchive oa(std::cout);
|
||||
foo x;
|
||||
oa << x;]])],
|
||||
[boost_serialization_cpplib_avail_cv_=true],
|
||||
[boost_serialization_cpplib_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$boost_serialization_save_libs])
|
||||
|
||||
if [test x$boost_serialization_cpplib_avail_cv_ = xtrue ]; then
|
||||
AC_DEFINE([HAVE_BOOST_SERIALIZATION], [1], [Whether Boost.Serialization is available])
|
||||
LIBS="-lboost_serialization$BOOST_SUFFIX $LIBS"
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_BOOST_SERIALIZATION, test x$boost_serialization_cpplib_avail_cv_ = xtrue)
|
||||
|
||||
# check for Python
|
||||
AM_PATH_PYTHON(2.4,, :)
|
||||
if [test "$PYTHON" != :]; then
|
||||
AM_CONDITIONAL(HAVE_PYTHON, true)
|
||||
AC_CACHE_CHECK(
|
||||
[if boost_python is available],
|
||||
[boost_python_cpplib_avail_cv_],
|
||||
[boost_python_save_libs=$LIBS
|
||||
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_POP
|
||||
LIBS=$boost_python_save_libs])
|
||||
|
||||
if [ test x$boost_python_cpplib_avail_cv_ = xtrue ]; then
|
||||
AC_DEFINE([HAVE_BOOST_PYTHON], [1], [Whether Boost.Python is available])
|
||||
LIBS="-lboost_python$BOOST_SUFFIX -lpython$PYTHON_VERSION $LIBS"
|
||||
fi
|
||||
else
|
||||
AM_CONDITIONAL(HAVE_PYTHON, false)
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_BOOST_PYTHON, test x$boost_python_cpplib_avail_cv_ = xtrue)
|
||||
|
||||
# check for CppUnit
|
||||
AC_CACHE_CHECK(
|
||||
[if cppunit is available],
|
||||
[cppunit_avail_cv_],
|
||||
[cppunit_save_libs=$LIBS
|
||||
LIBS="-lcppunit $LIBS"
|
||||
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;]])],
|
||||
[cppunit_avail_cv_=true],
|
||||
[cppunit_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$cppunit_save_libs])
|
||||
|
||||
AM_CONDITIONAL(HAVE_CPPUNIT, test x$cppunit_avail_cv_ = xtrue)
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_STAT
|
||||
AC_CHECK_HEADERS([langinfo.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_SIZE_T
|
||||
AC_STRUCT_TM
|
||||
|
||||
# Checks for library functions.
|
||||
#AC_FUNC_MKTIME
|
||||
#AC_FUNC_STAT
|
||||
#AC_FUNC_STRFTIME
|
||||
AC_CHECK_FUNCS([access realpath getpwuid getpwnam isatty])
|
||||
|
||||
# Pepare the Makefiles
|
||||
AC_CONFIG_FILES([Makefile po/Makefile.in intl/Makefile])
|
||||
AC_OUTPUT
|
||||
Loading…
Add table
Reference in a new issue