summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-10-25 21:27:56 -0400
committerJohn Wiegley <johnw@newartisans.com>2009-10-25 21:27:56 -0400
commit9dadaebfeb461ba795124281018d0f7eac200cf4 (patch)
tree941243868b1dcacd68cbd52a2f96e40bf70a5d3b
parentf35bc939c96c3a3bf09c5881d638b5ba60449c03 (diff)
parente696bfd913a10edd19f9e35eb1aee2c97b11e7f6 (diff)
downloadfork-ledger-9dadaebfeb461ba795124281018d0f7eac200cf4.tar.gz
fork-ledger-9dadaebfeb461ba795124281018d0f7eac200cf4.tar.bz2
fork-ledger-9dadaebfeb461ba795124281018d0f7eac200cf4.zip
Merge branch 'next'
-rw-r--r--Makefile.am1
-rwxr-xr-xacprep129
-rw-r--r--configure.ac31
-rw-r--r--lib/Makefile2
-rw-r--r--lib/fdstream.h184
-rw-r--r--src/accum.cc2
-rw-r--r--src/accum.h4
-rw-r--r--src/amount.cc10
-rw-r--r--src/annotate.cc2
-rw-r--r--src/chain.cc8
-rw-r--r--src/commodity.cc9
-rw-r--r--src/emacs.cc4
-rw-r--r--src/error.cc29
-rw-r--r--src/error.h16
-rw-r--r--src/filters.cc24
-rw-r--r--src/filters.h3
-rw-r--r--src/format.cc17
-rw-r--r--src/format.h12
-rw-r--r--src/generate.cc4
-rw-r--r--src/global.cc6
-rw-r--r--src/interactive.h4
-rw-r--r--src/item.cc2
-rw-r--r--src/op.cc99
-rw-r--r--src/op.h5
-rw-r--r--src/option.cc4
-rw-r--r--src/option.h10
-rw-r--r--src/parser.cc11
-rw-r--r--src/post.cc3
-rw-r--r--src/py_times.cc6
-rw-r--r--src/pyfstream.h11
-rw-r--r--src/pyinterp.cc2
-rw-r--r--src/pyinterp.h23
-rw-r--r--src/quotes.cc2
-rw-r--r--src/report.cc42
-rw-r--r--src/report.h14
-rw-r--r--src/session.cc2
-rw-r--r--src/session.h6
-rw-r--r--src/stream.cc3
-rw-r--r--src/system.hh.in8
-rw-r--r--src/times.cc354
-rw-r--r--src/times.h41
-rw-r--r--src/unistring.h30
-rw-r--r--src/utils.cc107
-rw-r--r--src/utils.h21
-rw-r--r--src/value.cc28
-rw-r--r--src/value.h12
-rw-r--r--src/xact.cc39
-rw-r--r--test/baseline/opt-csv-format.test4
-rw-r--r--test/baseline/opt-prices-format.test10
-rw-r--r--test/baseline/opt-pricesdb-format.test10
-rw-r--r--test/regress/BBFA1759.test4
-rw-r--r--test/unit/t_amount.cc2
-rw-r--r--test/unit/t_balance.cc2
-rw-r--r--test/unit/t_commodity.cc2
-rw-r--r--test/unit/t_expr.cc2
-rw-r--r--test/unit/t_times.cc10
-rw-r--r--test/unit/t_times.h4
57 files changed, 834 insertions, 602 deletions
diff --git a/Makefile.am b/Makefile.am
index 8ed18fbb..2556e1df 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -136,7 +136,6 @@ pkginclude_HEADERS = \
\
src/pyinterp.h \
\
- lib/fdstream.h \
lib/sha1.h \
lib/gettext.h \
\
diff --git a/acprep b/acprep
index fc82534f..ef264254 100755
--- a/acprep
+++ b/acprep
@@ -192,7 +192,6 @@ class PrepareBuild(CommandLineApp):
self.envvars = {
'PYTHON_HOME': '/usr',
'PYTHON_VERSION': '2.5',
- 'BOOST_VERSION': None,
'BOOST_SUFFIX': None,
'BOOST_HOME': '/usr',
'LEDGER_PRODUCTS': None,
@@ -520,12 +519,17 @@ class PrepareBuild(CommandLineApp):
if exists('/opt/local/bin/port'):
self.log.info('Looks like you are using MacPorts on OS X')
packages = [
- 'sudo', 'port', 'install',
- 'boost', '+python25+debug+st',
- 'gmp', 'mpfr', 'gettext',
- 'libedit', 'cppunit',
- #'texlive', 'doxygen', 'graphviz', 'texinfo',
- 'lcov', 'sloccount'
+ 'sudo', 'port', 'install', '-f',
+ 'automake', 'autoconf', 'libtool',
+ 'python26', 'boost-jam',
+ 'libiconv', '+universal', 'zlib', '+universal',
+ 'gmp' ,'+universal', 'mpfr', '+universal',
+ 'ncurses', '+universal', 'ncursesw', '+universal',
+ 'gettext' ,'+universal', 'libedit' ,'+universal',
+ 'boost', '+universal+st+debug+python26+doc',
+ 'cppunit' ,'+universal',
+ 'texlive', 'doxygen', 'graphviz', 'texinfo',
+ 'lcov', 'sloccount'
]
self.log.info('Executing: ' + string.join(packages, ' '))
self.execute(*packages)
@@ -624,7 +628,6 @@ class PrepareBuild(CommandLineApp):
self.execute('make',
'BOOST_SOURCE=%s' % boost,
- 'BOOST_VERSION=%s' % environ['BOOST_VERSION'],
'CC=%s' % environ['CC'],
'CXX=%s' % environ['CXX'],
'LD=%s' % environ['LD'],
@@ -649,14 +652,6 @@ class PrepareBuild(CommandLineApp):
suffix = match.group(1)
self.log.debug('Found Boost suffix => ' + suffix)
self.envvars['BOOST_HOME'] = dirname(path)
-
- match = re.search('[0-9]+_[0-9]+', suffix)
- if match:
- version = match.group(0)
- self.log.debug('Found Boost version in suffix => ' +
- version)
- if not self.envvars['BOOST_VERSION']:
- self.envvars['BOOST_VERSION'] = version
return suffix
else:
self.log.debug('The directory "%s" is not valid, skipping' %
@@ -678,8 +673,6 @@ class PrepareBuild(CommandLineApp):
self.log.debug('Boost is located here:')
self.log.debug('BOOST_HOME => ' +
self.envvars['BOOST_HOME'])
- self.log.debug('BOOST_VERSION => ' +
- str(self.envvars['BOOST_VERSION']))
self.log.debug('BOOST_SUFFIX => ' + suffix)
break
if suffix is None:
@@ -692,9 +685,8 @@ class PrepareBuild(CommandLineApp):
# Each of these becomes '-isystem <name>'
for path in ['/usr/local/include',
- '%s/include/boost-%s' %
- (self.envvars['BOOST_HOME'],
- self.envvars['BOOST_VERSION']),
+ '%s/include/boost' %
+ self.envvars['BOOST_HOME'],
'%s/include' % self.envvars['BOOST_HOME'],
'%s/include/python%s' %
(self.envvars['PYTHON_HOME'],
@@ -737,7 +729,7 @@ class PrepareBuild(CommandLineApp):
self.log.debug('System type is => ' + system)
# These options are global defaults at the moment
- self.option_warn()
+ #self.option_warn()
if not self.no_pch:
self.option_pch()
@@ -780,8 +772,8 @@ class PrepareBuild(CommandLineApp):
self.option_no_pch()
if '--enable-pch' not in self.configure_args and \
- exists('/opt/local/bin/ccache') or \
- exists('/usr/local/bin/ccache'):
+ (exists('/opt/local/bin/ccache') or \
+ exists('/usr/local/bin/ccache')):
self.envvars['CC'] = 'ccache ' + self.envvars['CC']
self.envvars['CXX'] = 'ccache ' + self.envvars['CXX']
self.envvars['LD'] = 'ccache ' + self.envvars['LD']
@@ -877,6 +869,8 @@ class PrepareBuild(CommandLineApp):
def option_warn(self, option=None, opt_str=None, value=None, parser=None):
self.log.debug('Saw option --warn')
self.CXXFLAGS.append('-ansi')
+ self.CXXFLAGS.append('-pedantic')
+ self.CXXFLAGS.append('-pedantic-errors')
self.CXXFLAGS.append('-Wall')
self.CXXFLAGS.append('-Winvalid-pch')
self.CXXFLAGS.append('-Wextra')
@@ -892,6 +886,7 @@ class PrepareBuild(CommandLineApp):
self.CXXFLAGS.append('-Wwrite-strings')
self.CXXFLAGS.append('-Wno-old-style-cast')
self.CXXFLAGS.append('-Wno-deprecated')
+ self.CXXFLAGS.append('-Werror')
def option_boost(self, option=None, opt_str=None, value=None, parser=None):
self.log.debug('Saw option --boost')
@@ -939,60 +934,73 @@ class PrepareBuild(CommandLineApp):
self.CXXFLAGS.append('-g')
self.LDFLAGS.append('-g')
- if not self.options.use_glibcxx_debug:
- return
+ if self.options.use_glibcxx_debug:
+ self.log.debug('We are using GLIBCXX_DEBUG, so setting up flags')
- self.log.debug('We are using GLIBCXX_DEBUG, so setting up flags')
+ self.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1')
- self.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1')
+ if exists('/usr/local/stow/cppunit-debug/include'):
+ if '/usr/local/stow/cppunit/include' in self.sys_include_dirs:
+ self.sys_include_dirs.remove('/usr/local/stow/cppunit/include')
+ self.sys_library_dirs.remove('/usr/local/stow/cppunit/lib')
- if exists('/usr/local/stow/cppunit-debug/include'):
- if '/usr/local/stow/cppunit/include' in self.sys_include_dirs:
- self.sys_include_dirs.remove('/usr/local/stow/cppunit/include')
- self.sys_library_dirs.remove('/usr/local/stow/cppunit/lib')
+ self.sys_include_dirs.insert(0, '/usr/local/stow/cppunit-debug/include')
+ self.sys_library_dirs.insert(0, '/usr/local/stow/cppunit-debug/lib')
- self.sys_include_dirs.insert(0, '/usr/local/stow/cppunit-debug/include')
- self.sys_library_dirs.insert(0, '/usr/local/stow/cppunit-debug/lib')
+ if exists('/usr/local/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'])
- 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.envvars['BOOST_VERSION'] = '1_40'
+ self.sys_include_dirs.append('/usr/local/include/boost-1_40')
- self.log.debug('Setting BOOST_SUFFIX => %s' %
- self.envvars['BOOST_SUFFIX'])
- self.log.debug('Setting BOOST_VERSION => %s' %
- self.envvars['BOOST_VERSION'])
+ elif exists('/opt/local/lib/libboost_regex-d.a'):
+ self.envvars['BOOST_HOME'] = '/opt/local'
+ self.envvars['BOOST_SUFFIX'] = '-d'
- self.sys_include_dirs.append('/usr/local/include/boost-1_40')
+ self.log.debug('Setting BOOST_SUFFIX => %s' %
+ self.envvars['BOOST_SUFFIX'])
- elif exists('/usr/local/lib/libboost_regex-xgcc43-sd-1_40.a'):
- self.envvars['BOOST_HOME'] = '/usr/local'
- self.envvars['BOOST_SUFFIX'] = '-xgcc43-sd-1_40'
- self.envvars['BOOST_VERSION'] = '1_40'
+ self.sys_include_dirs.append('/opt/local/include/boost')
+ else:
+ 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'):
+ self.envvars['BOOST_HOME'] = '/opt/local'
+ self.envvars['BOOST_SUFFIX'] = ''
+ self.log.debug('Setting BOOST_SUFFIX => %s' %
+ self.envvars['BOOST_SUFFIX'])
+
+ self.sys_include_dirs.append('/opt/local/include/boost')
+
+ 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.log.debug('Setting BOOST_VERSION => %s' %
- self.envvars['BOOST_VERSION'])
self.sys_include_dirs.append('/usr/local/include/boost-1_40')
- elif exists('/usr/local/lib/libboost_regex-xgcc42-sd-1_40.a'):
- self.envvars['BOOST_HOME'] = '/usr/local'
- self.envvars['BOOST_SUFFIX'] = '-xgcc42-sd-1_40'
- self.envvars['BOOST_VERSION'] = '1_40'
+ elif 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.debug('Setting BOOST_VERSION => %s' %
- self.envvars['BOOST_VERSION'])
- 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')
+ self.sys_include_dirs.append('/opt/local/include/boost')
def setup_flavor_gcov(self):
self.CXXFLAGS.append('-g')
@@ -1122,6 +1130,7 @@ class PrepareBuild(CommandLineApp):
def phase_config(self, *args):
self.log.debug('Executing phase: config')
+ self.phase_submodule()
self.phase_autoconf()
self.phase_configure(*args)
if self.should_clean:
diff --git a/configure.ac b/configure.ac
index c45ff636..ad1c4b37 100644
--- a/configure.ac
+++ b/configure.ac
@@ -88,7 +88,7 @@ AC_CACHE_CHECK(
if (status < 0) {
;
} else if (status == 0) {
- char *arg0;
+ char *arg0 = NULL;
status = dup2(pfd[0], STDIN_FILENO);
@@ -160,8 +160,8 @@ AC_CACHE_CHECK(
[[#include <stdlib.h>
#include <stdio.h>
#include <editline/readline.h>]],
- [[rl_readline_name = "foo";
- char * line = readline("foo: ");
+ [[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])
@@ -255,6 +255,31 @@ 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 Python
AM_PATH_PYTHON(2.4,, :)
if [test "$PYTHON" != :]; then
diff --git a/lib/Makefile b/lib/Makefile
index 709358df..6b46b422 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -47,4 +47,4 @@ cppunit-debug:
cppunit-build: cppunit-release cppunit-debug
-build-all: cppunit-build boost-build
+build-all: boost-build cppunit-build
diff --git a/lib/fdstream.h b/lib/fdstream.h
deleted file mode 100644
index 526c9f53..00000000
--- a/lib/fdstream.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/* The following code declares classes to read from and write to
- * file descriptore or file handles.
- *
- * See
- * http://www.josuttis.com/cppcode
- * for details and the latest version.
- *
- * - open:
- * - integrating BUFSIZ on some systems?
- * - optimized reading of multiple characters
- * - stream for reading AND writing
- * - i18n
- *
- * (C) Copyright Nicolai M. Josuttis 2001.
- * Permission to copy, use, modify, sell and distribute this software
- * is granted provided this copyright notice appears in all copies.
- * This software is provided "as is" without express or implied
- * warranty, and with no claim as to its suitability for any purpose.
- *
- * Version: Jul 28, 2002
- * History:
- * Jul 28, 2002: bugfix memcpy() => memmove()
- * fdinbuf::underflow(): cast for return statements
- * Aug 05, 2001: first public version
- */
-#ifndef BOOST_FDSTREAM_HPP
-#define BOOST_FDSTREAM_HPP
-
-#include <istream>
-#include <ostream>
-#include <streambuf>
-// for EOF:
-#include <cstdio>
-// for memmove():
-#include <cstring>
-
-
-// low-level read and write functions
-#ifdef _MSC_VER
-# include <io.h>
-#else
-# include <unistd.h>
-//extern "C" {
-// int write (int fd, const char* buf, int num);
-// int read (int fd, char* buf, int num);
-//}
-#endif
-
-
-// BEGIN namespace BOOST
-namespace boost {
-
-
-/************************************************************
- * fdostream
- * - a stream that writes on a file descriptor
- ************************************************************/
-
-
-class fdoutbuf : public std::streambuf {
- protected:
- int fd; // file descriptor
- public:
- // constructor
- fdoutbuf (int _fd) : fd(_fd) {
- }
- protected:
- // write one character
- virtual int_type overflow (int_type c) {
- if (c != EOF) {
- char z = static_cast<char>(c);
- if (write (fd, &z, 1) != 1) {
- return EOF;
- }
- }
- return c;
- }
- // write multiple characters
- virtual
- std::streamsize xsputn (const char* s,
- std::streamsize num) {
- return write(fd,s,num);
- }
-};
-
-class fdostream : public std::ostream {
- protected:
- fdoutbuf buf;
- public:
- fdostream (int fd) : std::ostream(0), buf(fd) {
- rdbuf(&buf);
- }
-};
-
-
-/************************************************************
- * fdistream
- * - a stream that reads on a file descriptor
- ************************************************************/
-
-class fdinbuf : public std::streambuf {
- protected:
- int fd; // file descriptor
- protected:
- /* data buffer:
- * - at most, pbSize characters in putback area plus
- * - at most, bufSize characters in ordinary read buffer
- */
- static const int pbSize = 4; // size of putback area
- static const int bufSize = 1024; // size of the data buffer
- char buffer[bufSize+pbSize]; // data buffer
-
- public:
- /* constructor
- * - initialize file descriptor
- * - initialize empty data buffer
- * - no putback area
- * => force underflow()
- */
- fdinbuf (int _fd) : fd(_fd) {
- setg (buffer+pbSize, // beginning of putback area
- buffer+pbSize, // read position
- buffer+pbSize); // end position
- }
-
- protected:
- // insert new characters into the buffer
- virtual int_type underflow () {
-#ifndef _MSC_VER
- using std::memmove;
-#endif
-
- // is read position before end of buffer?
- if (gptr() < egptr()) {
- return traits_type::to_int_type(*gptr());
- }
-
- /* process size of putback area
- * - use number of characters read
- * - but at most size of putback area
- */
- std::streamsize numPutback;
- numPutback = gptr() - eback();
- if (numPutback > pbSize) {
- numPutback = pbSize;
- }
-
- /* copy up to pbSize characters previously read into
- * the putback area
- */
- memmove (buffer+(pbSize-numPutback), gptr()-numPutback,
- numPutback);
-
- // read at most bufSize new characters
- ssize_t num;
- num = read (fd, buffer+pbSize, bufSize);
- if (num <= 0) {
- // ERROR or EOF
- return EOF;
- }
-
- // reset buffer pointers
- setg (buffer+(pbSize-numPutback), // beginning of putback area
- buffer+pbSize, // read position
- buffer+pbSize+num); // end of buffer
-
- // return next character
- return traits_type::to_int_type(*gptr());
- }
-};
-
-class fdistream : public std::istream {
- protected:
- fdinbuf buf;
- public:
- fdistream (int fd) : std::istream(0), buf(fd) {
- rdbuf(&buf);
- }
-};
-
-
-} // END namespace boost
-
-#endif /*BOOST_FDSTREAM_HPP*/
diff --git a/src/accum.cc b/src/accum.cc
index d01d0e52..b918c76a 100644
--- a/src/accum.cc
+++ b/src/accum.cc
@@ -53,7 +53,7 @@ std::streamsize straccbuf::xsputn(const char * s, std::streamsize num)
if (*p == '%') {
const char * q = p + 1;
if (*q && *q != '%' && std::isdigit(*q) &&
- std::size_t(*q - '0') == index) {
+ std::string::size_type(*q - '0') == index) {
p++;
buf << std::string(s, num);
matched = true;
diff --git a/src/accum.h b/src/accum.h
index caf87d28..c29926d5 100644
--- a/src/accum.h
+++ b/src/accum.h
@@ -56,8 +56,8 @@ namespace ledger {
class straccbuf : public std::streambuf
{
protected:
- std::string str; // accumulator
- std::size_t index;
+ std::string str; // accumulator
+ std::string::size_type index;
public:
straccbuf() : index(0) {}
diff --git a/src/amount.cc b/src/amount.cc
index 2434f110..5aa985c8 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -623,9 +623,9 @@ namespace {
"mpfr_print = " << buf << " (precision " << prec << ")");
if (zeros_prec >= 0) {
- int index = std::strlen(buf);
- int point = 0;
- for (int i = 0; i < index; i++) {
+ string::size_type index = std::strlen(buf);
+ string::size_type point = 0;
+ for (string::size_type i = 0; i < index; i++) {
if (buf[i] == '.') {
point = i;
break;
@@ -837,7 +837,7 @@ namespace {
READ_INTO(in, buf, 255, c,
std::isdigit(c) || c == '-' || c == '.' || c == ',');
- int len = std::strlen(buf);
+ string::size_type len = std::strlen(buf);
while (len > 0 && ! std::isdigit(buf[len - 1])) {
buf[--len] = '\0';
in.unget();
@@ -989,7 +989,7 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
// necessary.
if (last_comma != string::npos || last_period != string::npos) {
- int len = quant.length();
+ string::size_type len = quant.length();
scoped_array<char> buf(new char[len + 1]);
const char * p = quant.c_str();
char * t = buf.get();
diff --git a/src/annotate.cc b/src/annotate.cc
index 1ea39b5d..c6084f7f 100644
--- a/src/annotate.cc
+++ b/src/annotate.cc
@@ -127,7 +127,7 @@ void annotation_t::print(std::ostream& out, bool keep_base) const
<< '}';
if (date)
- out << " [" << format_date(*date, string("%Y/%m/%d")) << ']';
+ out << " [" << format_date(*date, FMT_WRITTEN) << ']';
if (tag)
out << " (" << *tag << ')';
diff --git a/src/chain.cc b/src/chain.cc
index 7b9083f0..25f4833c 100644
--- a/src/chain.cc
+++ b/src/chain.cc
@@ -65,10 +65,10 @@ post_handler_ptr chain_post_handlers(report_t& report,
if (report.HANDLED(head_) || report.HANDLED(tail_))
handler.reset
(new truncate_xacts(handler,
- report.HANDLED(head_) ?
- report.HANDLER(head_).value.to_long() : 0,
- report.HANDLED(tail_) ?
- report.HANDLER(tail_).value.to_long() : 0));
+ report.HANDLED(head_) ?
+ report.HANDLER(head_).value.to_int() : 0,
+ report.HANDLED(tail_) ?
+ report.HANDLER(tail_).value.to_int() : 0));
// filter_posts will only pass through posts matching the
// `display_predicate'.
diff --git a/src/commodity.cc b/src/commodity.cc
index 37f0b573..4041946b 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -498,10 +498,9 @@ void commodity_t::parse_symbol(std::istream& in, string& symbol)
char * _p = buf;
c = static_cast<char>(in.peek());
while (_p - buf < 255 && in.good() && ! in.eof() && c != '\n') {
- int bytes = 0;
- int size = _p - buf;
-
- unsigned char d = c;
+ std::size_t bytes = 0;
+ std::ptrdiff_t size = _p - buf;
+ unsigned char d = c;
// Check for the start of a UTF-8 multi-byte encoded string
if (d >= 192 && d <= 223 && size < 254)
@@ -518,7 +517,7 @@ void commodity_t::parse_symbol(std::istream& in, string& symbol)
break;
if (bytes > 0) { // we're looking at a UTF-8 encoding
- for (int i = 0; i < bytes; i++) {
+ for (std::size_t i = 0; i < bytes; i++) {
in.get(c);
if (in.bad() || in.eof())
break;
diff --git a/src/emacs.cc b/src/emacs.cc
index 4486b67a..57054690 100644
--- a/src/emacs.cc
+++ b/src/emacs.cc
@@ -41,7 +41,7 @@ namespace ledger {
void format_emacs_posts::write_xact(xact_t& xact)
{
out << "\"" << xact.pathname << "\" "
- << (static_cast<std::size_t>(xact.beg_line) + 1) << " ";
+ << (xact.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 << " (" << (static_cast<std::size_t>(post.beg_line) + 1) << " ";
+ out << " (" << (post.beg_line + 1) << " ";
out << "\"" << post.reported_account()->fullname() << "\" \""
<< post.amount << "\"";
diff --git a/src/error.cc b/src/error.cc
index 54d17ad3..70759b08 100644
--- a/src/error.cc
+++ b/src/error.cc
@@ -47,16 +47,16 @@ string error_context()
return context;
}
-string file_context(const path& file, std::size_t line)
+string file_context(const path& file, const std::size_t line)
{
std::ostringstream buf;
buf << "\"" << file << "\", line " << line << ": ";
return buf.str();
}
-string line_context(const string& line,
- std::size_t pos,
- std::size_t end_pos)
+string line_context(const string& line,
+ const string::size_type pos,
+ const string::size_type end_pos)
{
std::ostringstream buf;
buf << " " << line << "\n";
@@ -64,11 +64,11 @@ string line_context(const string& line,
if (pos != 0) {
buf << " ";
if (end_pos == 0) {
- for (std::size_t i = 0; i < pos; i += 1)
+ for (string::size_type i = 0; i < pos; i += 1)
buf << " ";
buf << "^";
} else {
- for (std::size_t i = 0; i < end_pos; i += 1) {
+ for (string::size_type i = 0; i < end_pos; i += 1) {
if (i >= pos)
buf << "^";
else
@@ -79,12 +79,12 @@ string line_context(const string& line,
return buf.str();
}
-string source_context(const path& file,
- istream_pos_type pos,
- istream_pos_type end_pos,
- const string& prefix)
+string source_context(const path& file,
+ const istream_pos_type pos,
+ const istream_pos_type end_pos,
+ const string& prefix)
{
- std::streamoff len = end_pos - pos;
+ const std::streamoff len = end_pos - pos;
if (! len || file == path("/dev/stdin"))
return _("<no source context>");
@@ -97,10 +97,9 @@ string source_context(const path& file,
in.seekg(pos, std::ios::beg);
scoped_array<char> buf(new char[len + 1]);
- in.read(buf.get(), static_cast<int>(len));
- assert(static_cast<std::size_t>(in.gcount()) ==
- static_cast<std::size_t>(len));
- buf[static_cast<int>(len)] = '\0';
+ in.read(buf.get(), len);
+ assert(in.gcount() == len);
+ buf[len] = '\0';
bool first = true;
for (char * p = std::strtok(buf.get(), "\n");
diff --git a/src/error.h b/src/error.h
index 42eab8d9..21f5bd8f 100644
--- a/src/error.h
+++ b/src/error.h
@@ -87,14 +87,14 @@ extern std::ostringstream _ctxt_buffer;
string error_context();
string file_context(const path& file, std::size_t line);
-string line_context(const string& line,
- std::size_t pos = 0,
- std::size_t end_pos = 0);
-
-string source_context(const path& file,
- istream_pos_type pos,
- istream_pos_type end_pos,
- const string& prefix = "");
+string line_context(const string& line,
+ const string::size_type pos = 0,
+ const string::size_type end_pos = 0);
+
+string source_context(const path& file,
+ const istream_pos_type pos,
+ const istream_pos_type end_pos,
+ const string& prefix = "");
#define DECLARE_EXCEPTION(name, kind) \
class name : public kind { \
diff --git a/src/filters.cc b/src/filters.cc
index 967e0843..08e7a22f 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -133,21 +133,6 @@ void sort_posts::post_accumulated_posts()
posts.clear();
}
-namespace {
- string to_hex(uint_least32_t * message_digest)
- {
- std::ostringstream buf;
-
- for(int i = 0; i < 5 ; i++) {
- buf.width(8);
- buf.fill('0');
- buf << std::hex << message_digest[i];
- break; // only output the first dword
- }
- return buf.str();
- }
-}
-
void anonymize_posts::operator()(post_t& post)
{
SHA1 sha;
@@ -531,15 +516,14 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
std::ostringstream out_date;
if (spec_fmt) {
- out_date << format_date(*range_finish, string(spec_fmt));
+ out_date << format_date(*range_finish, FMT_CUSTOM, spec_fmt);
}
else if (date_format) {
- string fmt = "- ";
- fmt += *date_format;
- out_date << format_date(*range_finish, string(fmt));
+ out_date << "- " << format_date(*range_finish, FMT_CUSTOM,
+ date_format->c_str());
}
else {
- out_date << format_date(*range_finish, std::string("- ") + output_date_format);
+ out_date << "- " << format_date(*range_finish);
}
xact_temps.push_back(xact_t());
diff --git a/src/filters.h b/src/filters.h
index 050e3dcf..a03d3160 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -142,7 +142,8 @@ class truncate_xacts : public item_handler<post_t>
truncate_xacts();
public:
- truncate_xacts(post_handler_ptr handler, int _head_count, int _tail_count)
+ truncate_xacts(post_handler_ptr handler,
+ int _head_count, int _tail_count)
: item_handler<post_t>(handler),
head_count(_head_count), tail_count(_tail_count),
xacts_seen(0), last_xact(NULL) {
diff --git a/src/format.cc b/src/format.cc
index ecac1133..ea38c861 100644
--- a/src/format.cc
+++ b/src/format.cc
@@ -345,7 +345,7 @@ void format_t::format(std::ostream& out_str, scope_t& scope)
}
DEBUG("format.expr", "value = (" << value << ")");
- value.print(out, elem->min_width, -1,
+ value.print(out, static_cast<int>(elem->min_width), -1,
! elem->has_flags(ELEMENT_ALIGN_LEFT));
}
catch (const calc_error&) {
@@ -362,15 +362,15 @@ void format_t::format(std::ostream& out_str, scope_t& scope)
if (elem->max_width > 0 || elem->min_width > 0) {
unistring temp(out.str());
+ string result;
- string result;
if (elem->max_width > 0 && elem->max_width < temp.length()) {
result = truncate(temp, elem->max_width);
} else {
result = temp.extract();
- for (int i = 0; i < (static_cast<int>(elem->min_width) -
- static_cast<int>(temp.length())); i++)
- result += " ";
+ if (elem->min_width > temp.length())
+ for (std::size_t i = 0; i < elem->min_width - temp.length(); i++)
+ result += " ";
}
out_str << result;
} else {
@@ -379,8 +379,9 @@ void format_t::format(std::ostream& out_str, scope_t& scope)
}
}
-string format_t::truncate(const unistring& ustr, std::size_t width,
- const int account_abbrev_length)
+string format_t::truncate(const unistring& ustr,
+ const std::size_t width,
+ const std::size_t account_abbrev_length)
{
assert(width < 4095);
@@ -434,7 +435,7 @@ string format_t::truncate(const unistring& ustr, std::size_t width,
if (newlen > width) {
unistring temp(*i);
- if (temp.length() > static_cast<std::size_t>(account_abbrev_length)) {
+ if (temp.length() > account_abbrev_length) {
result << temp.extract(0, account_abbrev_length) << ":";
newlen -= temp.length() - account_abbrev_length;
} else {
diff --git a/src/format.h b/src/format.h
index 03ed28c7..bc513f71 100644
--- a/src/format.h
+++ b/src/format.h
@@ -65,10 +65,7 @@ class format_t : public noncopyable
{
#define ELEMENT_ALIGN_LEFT 0x01
- enum kind_t {
- STRING,
- EXPR,
- };
+ enum kind_t { STRING, EXPR };
kind_t type;
std::size_t min_width;
@@ -89,7 +86,7 @@ class format_t : public noncopyable
friend inline void mark_red(std::ostream& out, const element_t * elem) {
out.setf(std::ios::left);
out.width(0);
- out << "\e[31m";
+ out << "\033[31m";
if (elem->has_flags(ELEMENT_ALIGN_LEFT))
out << std::left;
@@ -145,8 +142,9 @@ public:
elem->dump(out);
}
- static string truncate(const unistring& str, std::size_t width,
- const int account_abbrev_length = -1);
+ static string truncate(const unistring& str,
+ const std::size_t width,
+ const std::size_t account_abbrev_length = 0);
};
#define FMT_PREFIX "fmt_"
diff --git a/src/generate.cc b/src/generate.cc
index 8796f0bf..ebbc3cd7 100644
--- a/src/generate.cc
+++ b/src/generate.cc
@@ -321,11 +321,11 @@ void generate_posts_iterator::generate_note(std::ostream& out)
void generate_posts_iterator::generate_xact(std::ostream& out)
{
- out << format_date(next_date, string("%Y/%m/%d"));
+ out << format_date(next_date, FMT_WRITTEN);
next_date += gregorian::days(six_gen());
if (truth_gen()) {
out << '=';
- out << format_date(next_eff_date, string("%Y/%m/%d"));
+ out << format_date(next_eff_date, FMT_WRITTEN);
next_eff_date += gregorian::days(six_gen());
}
out << ' ';
diff --git a/src/global.cc b/src/global.cc
index 24716fae..02c9e79a 100644
--- a/src/global.cc
+++ b/src/global.cc
@@ -433,8 +433,10 @@ void global_scope_t::normalize_report_options(const string& verb)
rep.session.commodity_pool->price_db = none;
if (rep.HANDLED(date_format_)) {
- output_datetime_format = rep.HANDLER(date_format_).str() + " %H:%M:%S";
- output_date_format = rep.HANDLER(date_format_).str();
+ set_date_format(rep.HANDLER(date_format_).str().c_str());
+ }
+ if (rep.HANDLED(datetime_format_)) {
+ set_datetime_format(rep.HANDLER(datetime_format_).str().c_str());
}
if (rep.HANDLED(start_of_week_)) {
if (optional<date_time::weekdays> weekday =
diff --git a/src/interactive.h b/src/interactive.h
index a0388726..0396b1c8 100644
--- a/src/interactive.h
+++ b/src/interactive.h
@@ -92,6 +92,10 @@ inline bool interactive_t::get<bool>(std::size_t index) {
return value_at(index).to_boolean();
}
template <>
+inline int interactive_t::get<int>(std::size_t index) {
+ return value_at(index).to_int();
+}
+template <>
inline long interactive_t::get<long>(std::size_t index) {
return value_at(index).to_long();
}
diff --git a/src/item.cc b/src/item.cc
index 54f36e11..c4db7a51 100644
--- a/src/item.cc
+++ b/src/item.cc
@@ -142,7 +142,7 @@ void item_t::parse_tags(const char * p, optional<date_t::year_type> current_year
for (char * q = std::strtok(buf.get(), " \t");
q;
q = std::strtok(NULL, " \t")) {
- const std::size_t len = std::strlen(q);
+ const string::size_type len = std::strlen(q);
if (! tag.empty()) {
if (! has_tag(tag))
set_tag(tag, string(p + (q - buf.get())));
diff --git a/src/op.cc b/src/op.cc
index 559db616..f1ba61e2 100644
--- a/src/op.cc
+++ b/src/op.cc
@@ -38,10 +38,10 @@
namespace ledger {
-expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope)
+expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
{
if (is_ident()) {
- DEBUG("expr.compile", "Looking up identifier '" << as_ident() << "'");
+ DEBUG("expr.compile", "lookup: " << as_ident());
if (ptr_op_t def = scope.lookup(as_ident())) {
// Identifier references are first looked up at the point of
@@ -79,9 +79,10 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope)
return wrap_value(value_t());
}
- ptr_op_t lhs(left()->compile(scope));
+ ptr_op_t lhs(left()->compile(scope, depth));
ptr_op_t rhs(kind > UNARY_OPERATORS && has_right() ?
- (kind == O_LOOKUP ? right() : right()->compile(scope)) : NULL);
+ (kind == O_LOOKUP ? right() :
+ right()->compile(scope, depth)) : NULL);
if (lhs == left() && (! rhs || rhs == right()))
return this;
@@ -90,19 +91,20 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope)
// Reduce constants immediately if possible
if ((! lhs || lhs->is_value()) && (! rhs || rhs->is_value()))
- return wrap_value(intermediate->calc(scope));
+ return wrap_value(intermediate->calc(scope, NULL, depth));
return intermediate;
}
-value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
+value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
{
+#if defined(DEBUG_ON)
+ bool skip_debug = false;
+#endif
try {
value_t result;
- DEBUG("expr.calc", "calculating '" << op_context(this) << "'");
-
switch (kind) {
case VALUE:
result = as_value();
@@ -116,7 +118,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
// directly, so we create an empty call_scope_t to reflect the scope for
// this implicit call.
call_scope_t call_args(scope);
- result = left()->calc(call_args, locus);
+ result = left()->calc(call_args, locus, depth + 1);
break;
}
@@ -126,6 +128,9 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
// resolved.
call_scope_t call_args(scope);
result = as_function()(call_args);
+#if defined(DEBUG_ON)
+ skip_debug = true;
+#endif
break;
}
@@ -157,7 +162,8 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
throw_(calc_error,
_("Too many arguments in function call (saw %1)") << args_count);
- result = right()->compile(local_scope)->calc(local_scope, locus);
+ result = right()->compile(local_scope, depth + 1)
+ ->calc(local_scope, locus, depth + 1);
break;
}
@@ -173,7 +179,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
} else {
scope_t& objscope(obj.as_ref_lval<scope_t>());
if (ptr_op_t member = objscope.lookup(right()->as_ident())) {
- result = member->calc(objscope);
+ result = member->calc(objscope, NULL, depth + 1);
break;
}
}
@@ -192,7 +198,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
call_scope_t call_args(scope);
if (has_right())
- call_args.set_args(right()->calc(scope, locus));
+ call_args.set_args(right()->calc(scope, locus, depth + 1));
ptr_op_t func = left();
const string& name(func->as_ident());
@@ -204,74 +210,83 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
if (func->is_function())
result = func->as_function()(call_args);
else
- result = func->calc(call_args, locus);
+ result = func->calc(call_args, locus, depth + 1);
break;
}
case O_MATCH:
- result = (right()->calc(scope, locus).as_mask()
- .match(left()->calc(scope, locus).to_string()));
+ result = (right()->calc(scope, locus, depth + 1).as_mask()
+ .match(left()->calc(scope, locus, depth + 1).to_string()));
break;
case O_EQ:
- result = left()->calc(scope, locus) == right()->calc(scope, locus);
+ result = (left()->calc(scope, locus, depth + 1) ==
+ right()->calc(scope, locus, depth + 1));
break;
case O_LT:
- result = left()->calc(scope, locus) < right()->calc(scope, locus);
+ result = (left()->calc(scope, locus, depth + 1) <
+ right()->calc(scope, locus, depth + 1));
break;
case O_LTE:
- result = left()->calc(scope, locus) <= right()->calc(scope, locus);
+ result = (left()->calc(scope, locus, depth + 1) <=
+ right()->calc(scope, locus, depth + 1));
break;
case O_GT:
- result = left()->calc(scope, locus) > right()->calc(scope, locus);
+ result = (left()->calc(scope, locus, depth + 1) >
+ right()->calc(scope, locus, depth + 1));
break;
case O_GTE:
- result = left()->calc(scope, locus) >= right()->calc(scope, locus);
+ result = (left()->calc(scope, locus, depth + 1) >=
+ right()->calc(scope, locus, depth + 1));
break;
case O_ADD:
- result = left()->calc(scope, locus) + right()->calc(scope, locus);
+ result = (left()->calc(scope, locus, depth + 1) +
+ right()->calc(scope, locus, depth + 1));
break;
case O_SUB:
- result = left()->calc(scope, locus) - right()->calc(scope, locus);
+ result = (left()->calc(scope, locus, depth + 1) -
+ right()->calc(scope, locus, depth + 1));
break;
case O_MUL:
- result = left()->calc(scope, locus) * right()->calc(scope, locus);
+ result = (left()->calc(scope, locus, depth + 1) *
+ right()->calc(scope, locus, depth + 1));
break;
case O_DIV:
- result = left()->calc(scope, locus) / right()->calc(scope, locus);
+ result = (left()->calc(scope, locus, depth + 1) /
+ right()->calc(scope, locus, depth + 1));
break;
case O_NEG:
- result = left()->calc(scope, locus).negated();
+ result = left()->calc(scope, locus, depth + 1).negated();
break;
case O_NOT:
- result = ! left()->calc(scope, locus);
+ result = ! left()->calc(scope, locus, depth + 1);
break;
case O_AND:
- if (left()->calc(scope, locus))
- result = right()->calc(scope, locus);
+ if (left()->calc(scope, locus, depth + 1))
+ result = right()->calc(scope, locus, depth + 1);
else
result = false;
break;
case O_OR:
- if (value_t temp = left()->calc(scope, locus))
+ if (value_t temp = left()->calc(scope, locus, depth + 1))
result = temp;
else
- result = right()->calc(scope, locus);
+ result = right()->calc(scope, locus, depth + 1);
break;
case O_QUERY:
assert(right());
assert(right()->kind == O_COLON);
- if (value_t temp = left()->calc(scope, locus))
- result = right()->left()->calc(scope, locus);
+ if (value_t temp = left()->calc(scope, locus, depth + 1))
+ result = right()->left()->calc(scope, locus, depth + 1);
else
- result = right()->right()->calc(scope, locus);
+ result = right()->right()->calc(scope, locus, depth + 1);
break;
case O_COLON:
@@ -279,7 +294,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
break;
case O_CONS:
- result = left()->calc(scope, locus);
+ result = left()->calc(scope, locus, depth + 1);
DEBUG("op.cons", "car = " << result);
if (has_right()) {
@@ -296,7 +311,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
value_op = next;
next = NULL;
}
- temp.push_back(value_op->calc(scope, locus));
+ temp.push_back(value_op->calc(scope, locus, depth + 1));
DEBUG("op.cons", "temp now = " << temp);
}
result = temp;
@@ -304,7 +319,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
break;
case O_SEQ: {
- left()->calc(scope, locus);
+ left()->calc(scope, locus, depth + 1);
assert(has_right());
ptr_op_t next = right();
@@ -317,7 +332,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
value_op = next;
next = NULL;
}
- result = value_op->calc(scope, locus);
+ result = value_op->calc(scope, locus, depth + 1);
}
break;
}
@@ -328,7 +343,15 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus)
break;
}
- DEBUG("expr.calc", "result is '" << result << "'");
+#if defined(DEBUG_ON)
+ if (! skip_debug && SHOW_DEBUG("expr.calc")) {
+ for (int i = 0; i < depth; i++)
+ ledger::_log_buffer << '.';
+ ledger::_log_buffer << op_context(this) << " => ";
+ result.dump(ledger::_log_buffer, true);
+ DEBUG("expr.calc", "");
+ }
+#endif
return result;
diff --git a/src/op.h b/src/op.h
index 1f9af185..c79ed3f6 100644
--- a/src/op.h
+++ b/src/op.h
@@ -262,8 +262,9 @@ private:
}
public:
- ptr_op_t compile(scope_t& scope);
- value_t calc(scope_t& scope, ptr_op_t * locus = NULL);
+ ptr_op_t compile(scope_t& scope, const int depth = 0);
+ value_t calc(scope_t& scope, ptr_op_t * locus = NULL,
+ const int depth = 0);
struct context_t
{
diff --git a/src/option.cc b/src/option.cc
index 1275e270..f47410e2 100644
--- a/src/option.cc
+++ b/src/option.cc
@@ -110,8 +110,8 @@ void process_option(const string& whence, const string& name, scope_t& scope,
void process_environment(const char ** envp, const string& tag,
scope_t& scope)
{
- const char * tag_p = tag.c_str();
- std::size_t tag_len = tag.length();
+ const char * tag_p = tag.c_str();
+ string::size_type tag_len = tag.length();
for (const char ** p = envp; *p; p++) {
if (! tag_p || std::strncmp(*p, tag_p, tag_len) == 0) {
diff --git a/src/option.h b/src/option.h
index 6809a27c..89f1ad08 100644
--- a/src/option.h
+++ b/src/option.h
@@ -56,11 +56,11 @@ template <typename T>
class option_t
{
protected:
- const char * name;
- std::size_t name_len;
- const char ch;
- bool handled;
- optional<string> source;
+ const char * name;
+ string::size_type name_len;
+ const char ch;
+ bool handled;
+ optional<string> source;
option_t& operator=(const option_t&);
diff --git a/src/parser.cc b/src/parser.cc
index 39004758..a6053d69 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -491,9 +491,10 @@ expr_t::parser_t::parse(std::istream& in, const parse_flags_t& flags,
if (original_string) {
add_error_context(_("While parsing value expression:"));
- std::size_t end_pos =
- in.good() ? static_cast<std::size_t>(in.tellg()) : 0;
- std::size_t pos = static_cast<std::size_t>(end_pos);
+ std::streamoff end_pos = 0;
+ if (in.good())
+ end_pos = in.tellg();
+ std::streamoff pos = end_pos;
if (pos > 0)
pos -= lookahead.length;
@@ -504,7 +505,9 @@ expr_t::parser_t::parse(std::istream& in, const parse_flags_t& flags,
DEBUG("parser.error", " token kind = " << int(lookahead.kind));
DEBUG("parser.error", " token length = " << lookahead.length);
- add_error_context(line_context(*original_string, pos, end_pos));
+ add_error_context(line_context(*original_string,
+ static_cast<string::size_type>(pos),
+ static_cast<string::size_type>(end_pos)));
}
throw;
}
diff --git a/src/post.cc b/src/post.cc
index 9b416434..90c10a3b 100644
--- a/src/post.cc
+++ b/src/post.cc
@@ -195,7 +195,8 @@ namespace {
string name = env->reported_account()->fullname();
if (env.has(0) && env.get<long>(0) > 2)
- name = format_t::truncate(name, env.get<long>(0) - 2, true);
+ name = format_t::truncate(name, env.get<long>(0) - 2,
+ 2 /* account_abbrev_length */);
if (env->has_flags(POST_VIRTUAL)) {
if (env->must_balance())
diff --git a/src/py_times.cc b/src/py_times.cc
index 4d6519ed..e140a23c 100644
--- a/src/py_times.cc
+++ b/src/py_times.cc
@@ -165,8 +165,10 @@ void export_times()
register_optional_to_python<datetime_t>();
register_optional_to_python<date_t>();
- scope().attr("parse_datetime") = &py_parse_datetime;
- scope().attr("parse_date") = &py_parse_date;
+ scope().attr("parse_datetime") = &py_parse_datetime;
+ scope().attr("parse_date") = &py_parse_date;
+ scope().attr("times_initialize") = &times_initialize;
+ scope().attr("times_shutdown") = &times_shutdown;
#if 0
class_< interval_t > ("Interval")
diff --git a/src/pyfstream.h b/src/pyfstream.h
index 5e39d38d..3da37523 100644
--- a/src/pyfstream.h
+++ b/src/pyfstream.h
@@ -109,9 +109,9 @@ protected:
* - at most, pbSize characters in putback area plus
* - at most, bufSize characters in ordinary read buffer
*/
- static const int pbSize = 4; // size of putback area
- static const int bufSize = 1024; // size of the data buffer
- char buffer[bufSize + pbSize]; // data buffer
+ static const size_t pbSize = 4; // size of putback area
+ static const size_t bufSize = 1024; // size of the data buffer
+ char buffer[bufSize + pbSize]; // data buffer
public:
/* constructor
@@ -147,7 +147,7 @@ protected:
* - use number of characters read
* - but at most size of putback area
*/
- int numPutback;
+ size_t numPutback;
numPutback = gptr() - eback();
if (numPutback > pbSize) {
numPutback = pbSize;
@@ -160,14 +160,13 @@ protected:
numPutback);
// read at most bufSize new characters
- int num;
PyObject *line = PyFile_GetLine(reinterpret_cast<PyObject *>(fo), bufSize);
if (! line || ! PyString_Check(line)) {
// ERROR or EOF
return EOF;
}
- num = PyString_Size(line);
+ Py_ssize_t num = PyString_Size(line);
if (num == 0)
return EOF;
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index a163175f..f5b1a543 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -266,7 +266,7 @@ value_t python_interpreter_t::python_command(call_scope_t& args)
std::strcpy(argv[i + 1], arg.c_str());
}
- int status = Py_Main(args.size() + 1, argv);
+ int status = Py_Main(static_cast<int>(args.size()) + 1, argv);
for (std::size_t i = 0; i < args.size() + 1; i++)
delete[] argv[i];
diff --git a/src/pyinterp.h b/src/pyinterp.h
index dd9ca64c..4943eb2f 100644
--- a/src/pyinterp.h
+++ b/src/pyinterp.h
@@ -105,6 +105,7 @@ public:
virtual expr_t::ptr_op_t lookup(const string& name);
+#if BOOST_VERSION >= 103700
OPTION_(python_interpreter_t, import_, DO_(scope) {
interactive_t args(scope, "s");
@@ -114,23 +115,31 @@ public:
python::object sys_dict = module_sys.attr("__dict__");
python::list paths(sys_dict["path"]);
-#if BOOST_VERSION >= 103700
paths.insert(0, file.parent_path().string());
-#else
- paths.insert(0, file.branch_path().string());
-#endif
sys_dict["path"] = paths;
-#if BOOST_VERSION >= 103700
string name = file.filename();
if (contains(name, ".py"))
parent->import(file.stem());
else
parent->import(name);
-#else
+ });
+#else // BOOST_VERSION >= 103700
+ OPTION_(python_interpreter_t, import_, DO_(scope) {
+ interactive_t args(scope, "s");
+
+ path file(args.get<string>(0));
+
+ python::object module_sys = parent->import("sys");
+ python::object sys_dict = module_sys.attr("__dict__");
+
+ python::list paths(sys_dict["path"]);
+ paths.insert(0, file.branch_path().string());
+ sys_dict["path"] = paths;
+
parent->import(file.leaf());
-#endif
});
+#endif // BOOST_VERSION >= 103700
};
extern shared_ptr<python_interpreter_t> python_session;
diff --git a/src/quotes.cc b/src/quotes.cc
index d4be462e..797e6dd5 100644
--- a/src/quotes.cc
+++ b/src/quotes.cc
@@ -86,7 +86,7 @@ commodity_quote_from_script(commodity_t& commodity,
std::ios_base::out | std::ios_base::app);
#endif
database << "P "
- << format_datetime(point->when, string("%Y/%m/%d %H:%M:%S"))
+ << format_datetime(point->when, FMT_WRITTEN)
<< " " << commodity.symbol()
<< " " << point->price
<< std::endl;
diff --git a/src/report.cc b/src/report.cc
index 4c8a40e6..9c8ad8ba 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -211,8 +211,8 @@ value_t report_t::fn_truncated(call_scope_t& scope)
interactive_t args(scope, "v&ll");
return string_value(format_t::truncate
(args.get<string>(0),
- args.has(1) && args.get<long>(1) > 0 ? args.get<long>(1) : 0,
- args.has(2) ? args.get<long>(2) : -1));
+ args.has(1) && args.get<int>(1) > 0 ? args.get<int>(1) : 0,
+ args.has(2) ? args.get<int>(2) : 0));
}
value_t report_t::fn_justify(call_scope_t& scope)
@@ -220,8 +220,8 @@ value_t report_t::fn_justify(call_scope_t& scope)
interactive_t args(scope, "vl&lbbs");
std::ostringstream out;
args.value_at(0)
- .print(out, args.get<long>(1),
- args.has(2) ? args.get<long>(2) : -1,
+ .print(out, args.get<int>(1),
+ args.has(2) ? args.get<int>(2) : -1,
args.has(3) ? args.get<bool>(3) : false,
args.has(4) ? args.get<bool>(4) : false,
args.has(5) ? args.get<string>(5) :
@@ -263,9 +263,12 @@ value_t report_t::fn_join(call_scope_t& scope)
value_t report_t::fn_format_date(call_scope_t& scope)
{
- interactive_t args(scope, "ds");
- return string_value(format_date(args.get<date_t>(0),
- args.get<string>(1)));
+ interactive_t args(scope, "d&s");
+ if (args.has(1))
+ return string_value(format_date(args.get<date_t>(0), FMT_CUSTOM,
+ args.get<string>(1).c_str()));
+ else
+ return string_value(format_date(args.get<date_t>(0), FMT_PRINTED));
}
value_t report_t::fn_ansify_if(call_scope_t& scope)
@@ -275,19 +278,19 @@ value_t report_t::fn_ansify_if(call_scope_t& scope)
if (args.has(1)) {
string color = args.get<string>(1);
std::ostringstream buf;
- if (color == "black") buf << "\e[30m";
- else if (color == "red") buf << "\e[31m";
- else if (color == "green") buf << "\e[32m";
- else if (color == "yellow") buf << "\e[33m";
- else if (color == "blue") buf << "\e[34m";
- else if (color == "magenta") buf << "\e[35m";
- else if (color == "cyan") buf << "\e[36m";
- else if (color == "white") buf << "\e[37m";
- else if (color == "bold") buf << "\e[1m";
- else if (color == "underline") buf << "\e[4m";
- else if (color == "blink") buf << "\e[5m";
+ if (color == "black") buf << "\033[30m";
+ else if (color == "red") buf << "\033[31m";
+ else if (color == "green") buf << "\033[32m";
+ else if (color == "yellow") buf << "\033[33m";
+ else if (color == "blue") buf << "\033[34m";
+ else if (color == "magenta") buf << "\033[35m";
+ else if (color == "cyan") buf << "\033[36m";
+ else if (color == "white") buf << "\033[37m";
+ else if (color == "bold") buf << "\033[1m";
+ else if (color == "underline") buf << "\033[4m";
+ else if (color == "blink") buf << "\033[5m";
buf << args.value_at(0);
- buf << "\e[0m";
+ buf << "\033[0m";
return string_value(buf.str());
} else {
return args.value_at(0);
@@ -521,6 +524,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
case 'd':
OPT(daily);
else OPT(date_format_);
+ else OPT(datetime_format_);
else OPT(depth_);
else OPT(deviation);
else OPT_(display_);
diff --git a/src/report.h b/src/report.h
index 71dc4ca2..5921a154 100644
--- a/src/report.h
+++ b/src/report.h
@@ -218,6 +218,7 @@ public:
HANDLER(current).report(out);
HANDLER(daily).report(out);
HANDLER(date_format_).report(out);
+ HANDLER(datetime_format_).report(out);
HANDLER(depth_).report(out);
HANDLER(deviation).report(out);
HANDLER(display_).report(out);
@@ -412,10 +413,8 @@ public:
parent->HANDLER(period_).on(string("--daily"), "daily");
});
- OPTION__(report_t, date_format_, // -y
- CTOR(report_t, date_format_) {
- on(none, "%y-%b-%d");
- });
+ OPTION(report_t, date_format_);
+ OPTION(report_t, datetime_format_);
OPTION_(report_t, depth_, DO_(scope) {
interactive_t args(scope, "sl");
@@ -633,9 +632,9 @@ public:
OPTION__(report_t, print_format_, CTOR(report_t, print_format_) {
on(none,
- "%(format_date(xact.date, \"%Y/%m/%d\"))"
+ "%(xact.date)"
"%(!effective & xact.effective_date ?"
- " \"=\" + format_date(xact.effective_date, \"%Y/%m/%d\") : \"\")"
+ " \"=\" + xact.effective_date : \"\")"
"%(xact.cleared ? \" *\" : (xact.pending ? \" !\" : \"\"))"
"%(code ? \" (\" + code + \")\" :"
" \"\") %(payee)%(xact.comment)\n"
@@ -673,7 +672,8 @@ public:
OPTION__(report_t, register_format_, CTOR(report_t, register_format_) {
on(none,
- "%(ansify_if(justify(date, date_width), green if color & date > today))"
+ "%(ansify_if(justify(format_date(date), date_width), green "
+ " if color & date > today))"
" %(ansify_if(justify(truncated(payee, payee_width), payee_width), "
" bold if color & !cleared))"
" %(ansify_if(justify(truncated(account, account_width, abbrev_len), "
diff --git a/src/session.cc b/src/session.cc
index f7a8655b..b46d545e 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -45,6 +45,7 @@ namespace ledger {
void set_session_context(session_t * session)
{
if (session) {
+ times_initialize();
amount_t::initialize(session->commodity_pool);
// jww (2009-02-04): Is amount_t the right place for parse_conversion to
@@ -57,6 +58,7 @@ void set_session_context(session_t * session)
else if (! session) {
value_t::shutdown();
amount_t::shutdown();
+ times_shutdown();
}
}
diff --git a/src/session.h b/src/session.h
index 894c59fa..a51cdba6 100644
--- a/src/session.h
+++ b/src/session.h
@@ -144,9 +144,9 @@ public:
});
OPTION_(session_t, input_date_format_, DO_(args) {
- // This changes the global variable inside times.h, which affects the
- // basic date parser
- input_date_format = args[1].as_string();
+ // This changes static variables inside times.h, which affects the basic
+ // date parser.
+ set_input_date_format(args[1].as_string().c_str());
});
OPTION(session_t, price_db_);
diff --git a/src/stream.cc b/src/stream.cc
index c7fd58fa..e39b74e0 100644
--- a/src/stream.cc
+++ b/src/stream.cc
@@ -100,7 +100,8 @@ namespace {
}
else { // parent
close(pfd[0]);
- *os = new boost::fdostream(pfd[1]);
+ typedef iostreams::stream<iostreams::file_descriptor_sink> fdstream;
+ *os = new fdstream(pfd[1]);
}
return pfd[1];
}
diff --git a/src/system.hh.in b/src/system.hh.in
index 1f4a7d63..07598173 100644
--- a/src/system.hh.in
+++ b/src/system.hh.in
@@ -83,8 +83,8 @@ namespace std {
}
}
-typedef std::size_t istream_pos_type;
-typedef std::size_t ostream_pos_type;
+typedef std::streamoff istream_pos_type;
+typedef std::streamoff ostream_pos_type;
#else // ! (defined(__GNUG__) && __GNUG__ < 3)
@@ -119,7 +119,6 @@ typedef std::ostream::pos_type ostream_pos_type;
#if defined(HAVE_UNIX_PIPES)
#include <sys/types.h>
#include <sys/wait.h>
-#include "fdstream.h"
#endif
#if defined(HAVE_GETTEXT)
#include "gettext.h"
@@ -154,6 +153,9 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/intrusive_ptr.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/write.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/operators.hpp>
#include <boost/optional.hpp>
diff --git a/src/times.cc b/src/times.cc
index 45f7ed10..facdc4f6 100644
--- a/src/times.cc
+++ b/src/times.cc
@@ -35,55 +35,182 @@
namespace ledger {
-date_time::weekdays start_of_week = gregorian::Sunday;
-optional<std::string> input_date_format;
-std::string output_datetime_format = "%Y-%m-%d %H:%M:%S";
-std::string output_date_format = "%Y-%m-%d";
+date_time::weekdays start_of_week = gregorian::Sunday;
+
+//#define USE_BOOST_FACETS 1
namespace {
- struct date_format_t {
- const char * format;
- bool has_year;
- date_format_t(const char * _format, bool _has_year)
- : format(_format), has_year(_has_year) {}
- };
+ template <typename T, typename InputFacetType, typename OutputFacetType>
+ class temporal_io_t : public noncopyable
+ {
+ const char * fmt_str;
+#if defined(USE_BOOST_FACETS)
+ std::istringstream input_stream;
+ std::ostringstream output_stream;
+ InputFacetType * input_facet;
+ OutputFacetType * output_facet;
+ std::string temp_string;
+#endif // USE_BOOST_FACETS
+
+ public:
+ bool has_year;
+ bool input;
+
+ temporal_io_t(const char * _fmt_str, bool _input)
+ : fmt_str(_fmt_str), has_year(icontains(fmt_str, "%y")),
+ input(_input) {
+#if defined(USE_BOOST_FACETS)
+ if (input) {
+ input_facet = new InputFacetType(fmt_str);
+ input_stream.imbue(std::locale(std::locale::classic(), input_facet));
+ } else {
+ output_facet = new OutputFacetType(fmt_str);
+ output_stream.imbue(std::locale(std::locale::classic(), output_facet));
+ }
+#endif // USE_BOOST_FACETS
+ }
+
+ void set_format(const char * fmt) {
+ fmt_str = fmt;
+ has_year = icontains(fmt_str, "%y");
+
+#if defined(USE_BOOST_FACETS)
+ if (input)
+ input_facet->format(fmt_str);
+ else
+ output_facet->format(fmt_str);
+#endif // USE_BOOST_FACETS
+ }
+
+ T parse(const char * str) {
+ }
- const date_format_t formats[] = {
- date_format_t("%m/%d", false),
- date_format_t("%Y/%m/%d", true),
- date_format_t("%Y/%m", true),
- date_format_t("%y/%m/%d", true),
- date_format_t("%m.%d", false),
- date_format_t("%Y.%m.%d", true),
- date_format_t("%Y.%m", true),
- date_format_t("%y.%m.%d", true),
- date_format_t("%m-%d", false),
- date_format_t("%Y-%m-%d", true),
- date_format_t("%Y-%m", true),
- date_format_t("%y-%m-%d", true)
+ std::string format(const T& when) {
+#if defined(USE_BOOST_FACETS)
+ output_stream.str(temp_string);
+ output_stream.seekp(std::ios_base::beg);
+ output_stream.clear();
+ output_stream << when;
+ return output_stream.str();
+#else // USE_BOOST_FACETS
+ std::tm data(to_tm(when));
+ char buf[128];
+ std::strftime(buf, 127, fmt_str, &data);
+ return buf;
+#endif // USE_BOOST_FACETS
+ }
};
- date_t parse_date_mask_routine(const char * date_str, const date_format_t& df,
- optional<date_t::year_type> year, bool& saw_year)
+ template <>
+ datetime_t temporal_io_t<datetime_t, posix_time::time_input_facet,
+ posix_time::time_facet>
+ ::parse(const char * str)
{
- std::string str(date_str);
+#if defined(USE_BOOST_FACETS)
+ input_stream.seekg(std::ios_base::beg);
+ input_stream.clear();
+ input_stream.str(str);
- gregorian::date_input_facet * facet(new gregorian::date_input_facet(df.format));
- std::istringstream sstr(str);
- sstr.imbue(std::locale(sstr.getloc(), facet));
+ datetime_t when;
+ input_stream >> when;
+#if defined(DEBUG_ON)
+ if (when.is_not_a_date_time())
+ DEBUG("times.parse", "Failed to parse date/time '" << str
+ << "' using pattern '" << fmt_str << "'");
+#endif
- date_t when;
- sstr >> when;
+ if (! when.is_not_a_date_time() &&
+ input_stream.good() && ! input_stream.eof() &&
+ input_stream.peek() != EOF) {
+ DEBUG("times.parse", "This string has leftovers: '" << str << "'");
+ return datetime_t();
+ }
+ return when;
+#else // USE_BOOST_FACETS
+ std::tm data;
+ std::memset(&data, 0, sizeof(std::tm));
+ if (strptime(str, fmt_str, &data))
+ return posix_time::ptime_from_tm(data);
+ else
+ return datetime_t();
+#endif // USE_BOOST_FACETS
+ }
- if (! when.is_not_a_date()) {
- if (sstr.good() && ! sstr.eof() && sstr.peek() != EOF)
+ template <>
+ date_t temporal_io_t<date_t, gregorian::date_input_facet,
+ gregorian::date_facet>
+ ::parse(const char * str)
+ {
+#if defined(USE_BOOST_FACETS)
+ input_stream.seekg(std::ios_base::beg);
+ input_stream.clear();
+ input_stream.str(str);
+
+ date_t when;
+ input_stream >> when;
+#if defined(DEBUG_ON)
+ if (when.is_not_a_date())
+ DEBUG("times.parse", "Failed to parse date '" << str
+ << "' using pattern '" << fmt_str << "'");
+#endif
+
+ if (! when.is_not_a_date() &&
+ input_stream.good() && ! input_stream.eof() &&
+ input_stream.peek() != EOF) {
+ DEBUG("times.parse", "This string has leftovers: '" << str << "'");
return date_t();
+ }
+ return when;
+#else // USE_BOOST_FACETS
+ std::tm data;
+ std::memset(&data, 0, sizeof(std::tm));
+ data.tm_mday = 1; // some formats have no day
+ if (strptime(str, fmt_str, &data))
+ return gregorian::date_from_tm(data);
+ else
+ return date_t();
+#endif // USE_BOOST_FACETS
+ }
+
+ typedef temporal_io_t<datetime_t, posix_time::time_input_facet,
+ posix_time::time_facet> datetime_io_t;
+ typedef temporal_io_t<date_t, gregorian::date_input_facet,
+ gregorian::date_facet> date_io_t;
+
+ shared_ptr<datetime_io_t> input_datetime_io;
+ shared_ptr<date_io_t> input_date_io;
+ shared_ptr<datetime_io_t> written_datetime_io;
+ shared_ptr<date_io_t> written_date_io;
+ shared_ptr<datetime_io_t> printed_datetime_io;
+ shared_ptr<date_io_t> printed_date_io;
+
+ std::vector<shared_ptr<date_io_t> > readers;
+
+ date_t parse_date_mask_routine(const char * date_str, date_io_t& io,
+ optional<date_t::year_type> year,
+ bool& saw_year)
+ {
+ date_t when;
+
+ if (std::strchr(date_str, '/')) {
+ when = io.parse(date_str);
+ } else {
+ char buf[128];
+ VERIFY(std::strlen(date_str) < 127);
+ std::strcpy(buf, date_str);
+ for (char * p = buf; *p; p++)
+ if (*p == '.' || *p == '-')
+ *p = '/';
+
+ when = io.parse(buf);
+ }
+
+ if (! when.is_not_a_date()) {
DEBUG("times.parse", "Parsed date string: " << date_str);
- DEBUG("times.parse", "Parsed result is: " << when);
- DEBUG("times.parse", "Format used was: " << df.format);
+ DEBUG("times.parse", "Parsed result is: " << when);
- if (! df.has_year) {
+ if (! io.has_year) {
saw_year = false;
when = date_t(year ? *year : CURRENT_DATE().year(),
@@ -98,25 +225,24 @@ namespace {
return when;
}
- date_t parse_date_mask(const char * date_str, optional<date_t::year_type> year,
- bool& saw_year)
+ date_t parse_date_mask(const char * date_str,
+ optional<date_t::year_type> year, bool& saw_year)
{
- if (input_date_format) {
- date_format_t df(input_date_format->c_str(), true);
- if (! icontains(*input_date_format, "%y"))
- df.has_year = false;
- date_t when = parse_date_mask_routine(date_str, df, year, saw_year);
+ if (input_date_io.get()) {
+ date_t when = parse_date_mask_routine(date_str, *input_date_io.get(),
+ year, saw_year);
if (! when.is_not_a_date())
return when;
}
- for (uint8_t i = 0; i < (sizeof(formats) / sizeof(date_format_t)); i++) {
- date_t when = parse_date_mask_routine(date_str, formats[i], year,
- saw_year);
+ foreach (shared_ptr<date_io_t>& reader, readers) {
+ date_t when = parse_date_mask_routine(date_str, *reader.get(),
+ year, saw_year);
if (! when.is_not_a_date())
return when;
}
+ throw_(date_error, _("Invalid date: %1") << date_str);
return date_t();
}
}
@@ -174,15 +300,9 @@ string_to_month_of_year(const std::string& str)
datetime_t parse_datetime(const char * str, optional<date_t::year_type>)
{
- posix_time::time_input_facet * facet
- (new posix_time::time_input_facet("%Y/%m/%d %H:%M:%S"));
-
- std::string temp(str);
- std::istringstream sstr(temp);
- sstr.imbue(std::locale(sstr.getloc(), facet));
-
- datetime_t when;
- sstr >> when;
+ datetime_t when = input_datetime_io->parse(str);
+ if (when.is_not_a_date_time())
+ throw_(date_error, _("Invalid date/time: %1") << str);
return when;
}
@@ -481,7 +601,7 @@ namespace {
inline void read_lower_word(std::istream& in, string& word) {
in >> word;
- for (int i = 0, l = word.length(); i < l; i++)
+ for (string::size_type i = 0, l = word.length(); i < l; i++)
word[i] = static_cast<char>(std::tolower(word[i]));
}
@@ -662,4 +782,126 @@ void date_interval_t::parse(std::istream& in)
}
}
+namespace {
+ typedef std::map<std::string, datetime_io_t *> datetime_io_map;
+ typedef std::map<std::string, date_io_t *> date_io_map;
+
+ datetime_io_map temp_datetime_io;
+ date_io_map temp_date_io;
+}
+
+std::string format_datetime(const datetime_t& when,
+ const format_type_t format_type,
+ const optional<const char *>& format)
+{
+ if (format_type == FMT_WRITTEN) {
+ return written_datetime_io->format(when);
+ }
+ else if (format_type == FMT_CUSTOM || format) {
+ datetime_io_map::iterator i = temp_datetime_io.find(*format);
+ if (i != temp_datetime_io.end()) {
+ return (*i).second->format(when);
+ } else {
+ datetime_io_t * formatter = new datetime_io_t(*format, false);
+ temp_datetime_io.insert(datetime_io_map::value_type(*format, formatter));
+ return formatter->format(when);
+ }
+ }
+ else if (format_type == FMT_PRINTED) {
+ return printed_datetime_io->format(when);
+ }
+ else {
+ assert(0);
+ return "";
+ }
+}
+
+std::string format_date(const date_t& when,
+ const format_type_t format_type,
+ const optional<const char *>& format)
+{
+ if (format_type == FMT_WRITTEN) {
+ return written_date_io->format(when);
+ }
+ else if (format_type == FMT_CUSTOM || format) {
+ date_io_map::iterator i = temp_date_io.find(*format);
+ if (i != temp_date_io.end()) {
+ return (*i).second->format(when);
+ } else {
+ date_io_t * formatter = new date_io_t(*format, false);
+ temp_date_io.insert(date_io_map::value_type(*format, formatter));
+ return formatter->format(when);
+ }
+ }
+ else if (format_type == FMT_PRINTED) {
+ return printed_date_io->format(when);
+ }
+ else {
+ assert(0);
+ return "";
+ }
+}
+
+namespace {
+ bool is_initialized = false;
+}
+
+void set_datetime_format(const char * format)
+{
+ printed_datetime_io->set_format(format);
+}
+
+void set_date_format(const char * format)
+{
+ printed_date_io->set_format(format);
+}
+
+void set_input_date_format(const char * format)
+{
+ input_date_io.reset(new date_io_t(format, true));
+}
+
+void times_initialize()
+{
+ if (! is_initialized) {
+ input_datetime_io.reset(new datetime_io_t("%Y/%m/%d %H:%M:%S", true));
+
+ written_datetime_io.reset(new datetime_io_t("%Y/%m/%d %H:%M:%S", false));
+ written_date_io.reset(new date_io_t("%Y/%m/%d", false));
+
+ printed_datetime_io.reset(new datetime_io_t("%y-%b-%d %H:%M:%S", false));
+ printed_date_io.reset(new date_io_t("%y-%b-%d", false));
+
+ readers.push_back(shared_ptr<date_io_t>(new date_io_t("%m/%d", true)));
+ readers.push_back(shared_ptr<date_io_t>(new date_io_t("%Y/%m/%d", true)));
+ readers.push_back(shared_ptr<date_io_t>(new date_io_t("%Y/%m", true)));
+ readers.push_back(shared_ptr<date_io_t>(new date_io_t("%y/%m/%d", true)));
+
+ is_initialized = true;
+ }
+}
+
+void times_shutdown()
+{
+ if (is_initialized) {
+ input_datetime_io.reset();
+ input_date_io.reset();
+ written_datetime_io.reset();
+ written_date_io.reset();
+ printed_datetime_io.reset();
+ printed_date_io.reset();
+
+ readers.clear();
+
+ foreach (datetime_io_map::value_type& pair, temp_datetime_io)
+ checked_delete(pair.second);
+ temp_datetime_io.clear();
+
+ foreach (date_io_map::value_type& pair, temp_date_io)
+ checked_delete(pair.second);
+ temp_date_io.clear();
+
+ is_initialized = false;
+ }
+}
} // namespace ledger
diff --git a/src/times.h b/src/times.h
index 247c9393..c77cde1d 100644
--- a/src/times.h
+++ b/src/times.h
@@ -74,7 +74,6 @@ inline bool is_valid(const date_t& moment) {
#define CURRENT_DATE() boost::gregorian::day_clock::universal_day()
extern date_time::weekdays start_of_week;
-extern optional<std::string> input_date_format;
optional<date_time::weekdays>
string_to_day_of_week(const std::string& str);
@@ -97,33 +96,20 @@ inline date_t parse_date(const std::string& str,
return parse_date(str.c_str(), current_year);
}
-extern std::string output_datetime_format;
+enum format_type_t {
+ FMT_WRITTEN, FMT_PRINTED, FMT_CUSTOM
+};
-inline std::string format_datetime(const datetime_t& when,
- const optional<std::string>& format = none)
-{
- posix_time::time_facet * facet
- (new posix_time::time_facet(format ? format->c_str() :
- output_datetime_format.c_str()));
- std::ostringstream buf;
- buf.imbue(std::locale(std::locale::classic(), facet));
- buf << when;
- return buf.str();
-}
+std::string format_datetime(const datetime_t& when,
+ const format_type_t format_type = FMT_PRINTED,
+ const optional<const char *>& format = none);
+void set_datetime_format(const char * format);
-extern std::string output_date_format;
-
-inline std::string format_date(const date_t& when,
- const optional<std::string>& format = none)
-{
- gregorian::date_facet * facet
- (new gregorian::date_facet(format ? format->c_str() :
- output_date_format.c_str()));
- std::ostringstream buf;
- buf.imbue(std::locale(std::locale::classic(), facet));
- buf << when;
- return buf.str();
-}
+std::string format_date(const date_t& when,
+ const format_type_t format_type = FMT_PRINTED,
+ const optional<const char *>& format = none);
+void set_date_format(const char * format);
+void set_input_date_format(const char * format);
class date_interval_t : public equality_comparable<date_interval_t>
{
@@ -207,6 +193,9 @@ public:
date_interval_t& operator++();
};
+void times_initialize();
+void times_shutdown();
+
std::ostream& operator<<(std::ostream& out,
const date_interval_t::duration_t& duration);
diff --git a/src/unistring.h b/src/unistring.h
index 5467a151..268f60e3 100644
--- a/src/unistring.h
+++ b/src/unistring.h
@@ -70,7 +70,7 @@ public:
std::size_t len = input.length();
VERIFY(utf8::is_valid(p, p + len));
- utf8::utf8to32(p, p + len, std::back_inserter(utf32chars));
+ utf8::unchecked::utf8to32(p, p + len, std::back_inserter(utf32chars));
}
~unistring() {
TRACE_DTOR(unistring);
@@ -80,18 +80,22 @@ public:
return utf32chars.size();
}
- std::string extract(const std::size_t begin = 0,
- const std::size_t len = 0) const
+ std::string extract(const std::string::size_type begin = 0,
+ const std::string::size_type len = 0) const
{
- std::string utf8result;
- std::size_t this_len = length();
+ std::string utf8result;
+ std::string::size_type this_len = length();
+
assert(begin <= this_len);
assert(begin + len <= this_len);
+
if (this_len)
- utf8::utf32to8(utf32chars.begin() + begin,
- utf32chars.begin() + begin +
- (len ? (len > this_len ? this_len : len) : this_len),
- std::back_inserter(utf8result));
+ utf8::unchecked::utf32to8
+ (utf32chars.begin() + begin,
+ utf32chars.begin() + begin +
+ (len ? (len > this_len ? this_len : len) : this_len),
+ std::back_inserter(utf8result));
+
return utf8result;
}
};
@@ -103,9 +107,9 @@ inline void justify(std::ostream& out,
bool redden = false)
{
if (! right) {
- if (redden) out << "\e[31m";
+ if (redden) out << "\033[31m";
out << str;
- if (redden) out << "\e[0m";
+ if (redden) out << "\033[0m";
}
unistring temp(str);
@@ -115,9 +119,9 @@ inline void justify(std::ostream& out,
out << ' ';
if (right) {
- if (redden) out << "\e[31m";
+ if (redden) out << "\033[31m";
out << str;
- if (redden) out << "\e[0m";
+ if (redden) out << "\033[0m";
}
}
diff --git a/src/utils.cc b/src/utils.cc
index f2449daf..0afea4c2 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -71,32 +71,34 @@ namespace ledger {
bool verify_enabled = false;
typedef std::pair<std::string, std::size_t> allocation_pair;
-typedef std::map<void *, allocation_pair> live_memory_map;
-typedef std::multimap<void *, allocation_pair> live_objects_map;
+typedef std::map<void *, allocation_pair> memory_map;
+typedef std::multimap<void *, allocation_pair> objects_map;
typedef std::pair<std::size_t, std::size_t> count_size_pair;
typedef std::map<std::string, count_size_pair> object_count_map;
-static live_memory_map * live_memory = NULL;
-static object_count_map * live_memory_count = NULL;
-static object_count_map * total_memory_count = NULL;
+namespace {
+ bool memory_tracing_active = false;
-static bool memory_tracing_active = false;
-
-static live_objects_map * live_objects = NULL;
-static object_count_map * live_object_count = NULL;
-static object_count_map * total_object_count = NULL;
-static object_count_map * total_ctor_count = NULL;
+ memory_map * live_memory = NULL;
+ memory_map * freed_memory = NULL;
+ object_count_map * live_memory_count = NULL;
+ object_count_map * total_memory_count = NULL;
+ objects_map * live_objects = NULL;
+ object_count_map * live_object_count = NULL;
+ object_count_map * total_object_count = NULL;
+ object_count_map * total_ctor_count = NULL;
+}
void initialize_memory_tracing()
{
memory_tracing_active = false;
- live_memory = new live_memory_map;
+ live_memory = new memory_map;
+ freed_memory = new memory_map;
live_memory_count = new object_count_map;
total_memory_count = new object_count_map;
-
- live_objects = new live_objects_map;
+ live_objects = new objects_map;
live_object_count = new object_count_map;
total_object_count = new object_count_map;
total_ctor_count = new object_count_map;
@@ -118,9 +120,9 @@ void shutdown_memory_tracing()
}
checked_delete(live_memory); live_memory = NULL;
+ checked_delete(freed_memory); freed_memory = NULL;
checked_delete(live_memory_count); live_memory_count = NULL;
checked_delete(total_memory_count); total_memory_count = NULL;
-
checked_delete(live_objects); live_objects = NULL;
checked_delete(live_object_count); live_object_count = NULL;
checked_delete(total_object_count); total_object_count = NULL;
@@ -153,12 +155,16 @@ std::size_t current_memory_size()
static void trace_new_func(void * ptr, const char * which, std::size_t size)
{
+ if (! live_memory || ! memory_tracing_active) return;
+
memory_tracing_active = false;
- if (! live_memory) return;
+ memory_map::iterator i = freed_memory->find(ptr);
+ if (i != freed_memory->end())
+ freed_memory->erase(i);
live_memory->insert
- (live_memory_map::value_type(ptr, allocation_pair(which, size)));
+ (memory_map::value_type(ptr, allocation_pair(which, size)));
add_to_count_map(*live_memory_count, which, size);
add_to_count_map(*total_memory_count, which, size);
@@ -169,9 +175,9 @@ static void trace_new_func(void * ptr, const char * which, std::size_t size)
static void trace_delete_func(void * ptr, const char * which)
{
- memory_tracing_active = false;
+ if (! live_memory || ! memory_tracing_active) return;
- if (! live_memory) return;
+ memory_tracing_active = false;
// Ignore deletions of memory not tracked, since it's possible that
// a user (like boost) allocated a block of memory before memory
@@ -179,15 +185,25 @@ static void trace_delete_func(void * ptr, const char * which)
// If it really is a double-delete, the malloc library on OS/X will
// notify me.
- live_memory_map::iterator i = live_memory->find(ptr);
- if (i == live_memory->end())
+ memory_map::iterator i = live_memory->find(ptr);
+ if (i == live_memory->end()) {
+ i = freed_memory->find(ptr);
+ if (i != freed_memory->end())
+ VERIFY(! "Freeing a block of memory twice");
+ else
+ VERIFY(! "Freeing an unknown block of memory");
+ memory_tracing_active = true;
return;
+ }
std::size_t size = (*i).second.second;
VERIFY((*i).second.first == which);
live_memory->erase(i);
+ freed_memory->insert
+ (memory_map::value_type(ptr, allocation_pair(which, size)));
+
object_count_map::iterator j = live_memory_count->find(which);
VERIFY(j != live_memory_count->end());
@@ -269,9 +285,9 @@ std::size_t current_objects_size()
void trace_ctor_func(void * ptr, const char * cls_name, const char * args,
std::size_t cls_size)
{
- memory_tracing_active = false;
+ if (! live_objects || ! memory_tracing_active) return;
- if (! live_objects) return;
+ memory_tracing_active = false;
static char name[1024];
std::strcpy(name, cls_name);
@@ -282,7 +298,7 @@ void trace_ctor_func(void * ptr, const char * cls_name, const char * args,
DEBUG("memory.debug", "TRACE_CTOR " << ptr << " " << name);
live_objects->insert
- (live_objects_map::value_type(ptr, allocation_pair(cls_name, cls_size)));
+ (objects_map::value_type(ptr, allocation_pair(cls_name, cls_size)));
add_to_count_map(*live_object_count, cls_name, cls_size);
add_to_count_map(*total_object_count, cls_name, cls_size);
@@ -294,13 +310,13 @@ void trace_ctor_func(void * ptr, const char * cls_name, const char * args,
void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size)
{
- if (! live_objects) return;
+ if (! live_objects || ! memory_tracing_active) return;
memory_tracing_active = false;
DEBUG("memory.debug", "TRACE_DTOR " << ptr << " " << cls_name);
- live_objects_map::iterator i = live_objects->find(ptr);
+ objects_map::iterator i = live_objects->find(ptr);
if (i == live_objects->end()) {
warning_(_("Attempting to delete %1 a non-living %2") << ptr << cls_name);
memory_tracing_active = true;
@@ -331,7 +347,7 @@ void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size)
void report_memory(std::ostream& out, bool report_all)
{
- if (! live_memory) return;
+ if (! live_memory || ! memory_tracing_active) return;
if (live_memory_count->size() > 0) {
out << "NOTE: There may be memory held by Boost "
@@ -343,7 +359,7 @@ void report_memory(std::ostream& out, bool report_all)
if (live_memory->size() > 0) {
out << "Live memory:" << std::endl;
- foreach (const live_memory_map::value_type& pair, *live_memory)
+ foreach (const memory_map::value_type& pair, *live_memory)
out << " " << std::right << std::setw(12) << pair.first
<< " " << std::right << std::setw(7) << pair.second.second
<< " " << std::left << pair.second.first
@@ -363,7 +379,7 @@ void report_memory(std::ostream& out, bool report_all)
if (live_objects->size() > 0) {
out << "Live objects:" << std::endl;
- foreach (const live_objects_map::value_type& pair, *live_objects)
+ foreach (const objects_map::value_type& pair, *live_objects)
out << " " << std::right << std::setw(12) << pair.first
<< " " << std::right << std::setw(7) << pair.second.second
<< " " << std::left << pair.second.first
@@ -402,17 +418,19 @@ string::string(const char * str) : std::string(str) {
string::string(const char * str, const char * end) : std::string(str, end) {
TRACE_CTOR(string, "const char *, const char *");
}
-string::string(const string& str, int x) : std::string(str, x) {
- TRACE_CTOR(string, "const string&, int");
+string::string(const string& str, size_type x) : std::string(str, x) {
+ TRACE_CTOR(string, "const string&, size_type");
}
-string::string(const string& str, int x, int y) : std::string(str, x, y) {
- TRACE_CTOR(string, "const string&, int, int");
+string::string(const string& str, size_type x, size_type y)
+ : std::string(str, x, y) {
+ TRACE_CTOR(string, "const string&, size_type, size_type");
}
-string::string(const char * str, int x) : std::string(str, x) {
- TRACE_CTOR(string, "const char *, int");
+string::string(const char * str, size_type x) : std::string(str, x) {
+ TRACE_CTOR(string, "const char *, size_type");
}
-string::string(const char * str, int x, int y) : std::string(str, x, y) {
- TRACE_CTOR(string, "const char *, int, int");
+string::string(const char * str, size_type x, size_type y)
+ : std::string(str, x, y) {
+ TRACE_CTOR(string, "const char *, size_type, size_type");
}
string::~string() throw() {
TRACE_DTOR(string);
@@ -557,6 +575,7 @@ static timer_map timers;
void start_timer(const char * name, log_level_t lvl)
{
#if defined(VERIFY_ON)
+ bool tracing_active = memory_tracing_active;
memory_tracing_active = false;
#endif
@@ -571,13 +590,14 @@ void start_timer(const char * name, log_level_t lvl)
_log_buffer.str("");
#if defined(VERIFY_ON)
- memory_tracing_active = true;
+ memory_tracing_active = tracing_active;
#endif
}
void stop_timer(const char * name)
{
#if defined(VERIFY_ON)
+ bool tracing_active = memory_tracing_active;
memory_tracing_active = false;
#endif
@@ -588,19 +608,24 @@ void stop_timer(const char * name)
(*i).second.active = false;
#if defined(VERIFY_ON)
- memory_tracing_active = true;
+ memory_tracing_active = tracing_active;
#endif
}
void finish_timer(const char * name)
{
#if defined(VERIFY_ON)
+ bool tracing_active = memory_tracing_active;
memory_tracing_active = false;
#endif
timer_map::iterator i = timers.find(name);
- if (i == timers.end())
+ if (i == timers.end()) {
+#if defined(VERIFY_ON)
+ memory_tracing_active = tracing_active;
+#endif
return;
+ }
time_duration spent = (*i).second.spent;
if ((*i).second.active) {
@@ -626,7 +651,7 @@ void finish_timer(const char * name)
timers.erase(i);
#if defined(VERIFY_ON)
- memory_tracing_active = true;
+ memory_tracing_active = tracing_active;
#endif
}
diff --git a/src/utils.h b/src/utils.h
index 462cef52..7f5ca017 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -173,10 +173,10 @@ public:
string(size_type len, char x);
string(const char * str);
string(const char * str, const char * end);
- string(const string& str, int x);
- string(const string& str, int x, int y);
- string(const char * str, int x);
- string(const char * str, int x, int y);
+ string(const string& str, size_type x);
+ string(const string& str, size_type x, size_type y);
+ string(const char * str, size_type x);
+ string(const char * str, size_type x, size_type y);
~string() throw();
};
@@ -594,6 +594,19 @@ inline char peek_next_nonws(std::istream& in) {
*_p = '\0'; \
}
+inline string to_hex(uint_least32_t * message_digest)
+{
+ std::ostringstream buf;
+
+ for(int i = 0; i < 5 ; i++) {
+ buf.width(8);
+ buf.fill('0');
+ buf << std::hex << message_digest[i];
+ break; // only output the first dword
+ }
+ return buf.str();
+}
+
extern const string version;
} // namespace ledger
diff --git a/src/value.cc b/src/value.cc
index 702b889e..6ce46f5c 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -173,6 +173,17 @@ date_t value_t::to_date() const
}
}
+int value_t::to_int() const
+{
+ if (is_long()) {
+ return static_cast<int>(as_long());
+ } else {
+ value_t temp(*this);
+ temp.in_place_cast(INTEGER);
+ return static_cast<int>(temp.as_long());
+ }
+}
+
long value_t::to_long() const
{
if (is_long()) {
@@ -973,7 +984,7 @@ void value_t::in_place_cast(type_t cast_type)
set_datetime(datetime_t(as_date(), time_duration(0, 0, 0, 0)));
return;
case STRING:
- set_string(format_date(as_date(), string("%Y-%m-%d")));
+ set_string(format_date(as_date(), FMT_WRITTEN));
return;
default:
break;
@@ -985,7 +996,7 @@ void value_t::in_place_cast(type_t cast_type)
set_date(as_datetime().date());
return;
case STRING:
- set_string(format_datetime(as_datetime(), string("%Y-%m-%d %H:%M:%S")));
+ set_string(format_datetime(as_datetime(), FMT_WRITTEN));
return;
default:
break;
@@ -1484,16 +1495,17 @@ void value_t::print(std::ostream& out,
case DATETIME:
if (date_format)
- out << format_datetime(as_datetime(), *date_format);
+ out << format_datetime(as_datetime(), FMT_CUSTOM,
+ date_format->c_str());
else
- out << format_datetime(as_datetime());
+ out << format_datetime(as_datetime(), FMT_WRITTEN);
break;
case DATE:
if (date_format)
- out << format_date(as_date(), *date_format);
+ out << format_date(as_date(), FMT_CUSTOM, date_format->c_str());
else
- out << format_date(as_date());
+ out << format_date(as_date(), FMT_WRITTEN);
break;
case INTEGER:
@@ -1568,10 +1580,10 @@ void value_t::dump(std::ostream& out, const bool relaxed) const
break;
case DATETIME:
- out << '[' << format_datetime(as_datetime()) << ']';
+ out << '[' << format_datetime(as_datetime(), FMT_WRITTEN) << ']';
break;
case DATE:
- out << '[' << format_date(as_date()) << ']';
+ out << '[' << format_date(as_date(), FMT_WRITTEN) << ']';
break;
case INTEGER:
diff --git a/src/value.h b/src/value.h
index 62943e62..23c8c8d5 100644
--- a/src/value.h
+++ b/src/value.h
@@ -211,6 +211,8 @@ private:
void destroy() {
DEBUG("value.storage.refcount", "Destroying " << this);
switch (type) {
+ case VOID:
+ return;
case BALANCE:
checked_delete(boost::get<balance_t *>(data));
break;
@@ -220,6 +222,7 @@ private:
default:
break;
}
+ data = false;
type = VOID;
}
};
@@ -635,10 +638,12 @@ public:
void set_string(const string& val = "") {
set_type(STRING);
storage->data = val;
+ VERIFY(boost::get<string>(storage->data) == val);
}
void set_string(const char * val = "") {
set_type(STRING);
storage->data = string(val);
+ VERIFY(boost::get<string>(storage->data) == val);
}
bool is_mask() const {
@@ -733,6 +738,7 @@ public:
* exception is thrown.
*/
bool to_boolean() const;
+ int to_int() const;
long to_long() const;
datetime_t to_datetime() const;
date_t to_date() const;
@@ -788,7 +794,7 @@ public:
/**
* Collection-style access methods for SEQUENCE values.
*/
- value_t& operator[](const int index) {
+ value_t& operator[](const std::size_t index) {
VERIFY(! is_null());
if (is_sequence())
return as_sequence_lval()[index];
@@ -799,7 +805,7 @@ public:
static value_t null;
return null;
}
- const value_t& operator[](const int index) const {
+ const value_t& operator[](const std::size_t index) const {
VERIFY(! is_null());
if (is_sequence())
return as_sequence()[index];
@@ -933,7 +939,7 @@ public:
#define NULL_VALUE (value_t())
-inline value_t string_value(const string& str) {
+inline value_t string_value(const string& str = "") {
return value_t(str, true);
}
diff --git a/src/xact.cc b/src/xact.cc
index bd8a5955..175a1467 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -352,6 +352,33 @@ void xact_t::add_post(post_t * post)
}
namespace {
+ value_t get_magnitude(xact_t& xact) {
+ balance_t halfbal;
+ foreach (post_t * post, xact.posts)
+ if (post->amount.sign() > 0)
+ halfbal += post->amount.number();
+ return halfbal;
+ }
+
+ value_t get_idstring(xact_t& xact) {
+ std::ostringstream buf;
+ buf << *xact._date;
+ buf << xact.payee;
+
+ get_magnitude(xact).print(buf);
+
+ return string_value(buf.str());
+ }
+ value_t get_id(xact_t& xact) {
+ SHA1 sha;
+ sha.Reset();
+ sha << get_idstring(xact).as_string().c_str();
+
+ uint_least32_t message_digest[5];
+ sha.Result(message_digest);
+ return string_value(to_hex(message_digest));
+ }
+
value_t get_code(xact_t& xact) {
if (xact.code)
return string_value(*xact.code);
@@ -377,6 +404,18 @@ expr_t::ptr_op_t xact_t::lookup(const string& name)
return WRAP_FUNCTOR(get_wrapper<&get_code>);
break;
+ case 'i':
+ if (name == "id")
+ return WRAP_FUNCTOR(get_wrapper<&get_id>);
+ else if (name == "idstring")
+ return WRAP_FUNCTOR(get_wrapper<&get_idstring>);
+ break;
+
+ case 'm':
+ if (name == "magnitude")
+ return WRAP_FUNCTOR(get_wrapper<&get_magnitude>);
+ break;
+
case 'p':
if (name[1] == '\0' || name == "payee")
return WRAP_FUNCTOR(get_wrapper<&get_payee>);
diff --git a/test/baseline/opt-csv-format.test b/test/baseline/opt-csv-format.test
index 7efefc0d..d4975f93 100644
--- a/test/baseline/opt-csv-format.test
+++ b/test/baseline/opt-csv-format.test
@@ -4,7 +4,7 @@ csv --csv-format='"%(date)"\n'
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
Income:Dividends:Vanguard:VMMXX $-0.35
>>>1
-"07-Feb-02"
-"07-Feb-02"
+"2007/02/02"
+"2007/02/02"
>>>2
=== 0
diff --git a/test/baseline/opt-prices-format.test b/test/baseline/opt-prices-format.test
index ec93d9cd..f8033c59 100644
--- a/test/baseline/opt-prices-format.test
+++ b/test/baseline/opt-prices-format.test
@@ -10,10 +10,10 @@ P 2009/02/01 17:30:00 AAPL $50.00
Assets:Brokerage 100 AAPL
Income
>>>1
-09-Jan-01 13:30:00 $10.00
-09-Jan-01 14:30:00 $20.00
-09-Jan-01 15:30:00 $30.00
-09-Jan-01 16:30:00 $40.00
-09-Feb-01 17:30:00 $50.00
+2009/01/01 13:30:00 $10.00
+2009/01/01 14:30:00 $20.00
+2009/01/01 15:30:00 $30.00
+2009/01/01 16:30:00 $40.00
+2009/02/01 17:30:00 $50.00
>>>2
=== 0
diff --git a/test/baseline/opt-pricesdb-format.test b/test/baseline/opt-pricesdb-format.test
index 28998903..b90371cd 100644
--- a/test/baseline/opt-pricesdb-format.test
+++ b/test/baseline/opt-pricesdb-format.test
@@ -10,10 +10,10 @@ P 2009/02/01 17:30:00 AAPL $50.00
Assets:Brokerage 100 AAPL
Income
>>>1
-P 09-Jan-01 $10.00
-P 09-Jan-01 $20.00
-P 09-Jan-01 $30.00
-P 09-Jan-01 $40.00
-P 09-Feb-01 $50.00
+P 2009/01/01 $10.00
+P 2009/01/01 $20.00
+P 2009/01/01 $30.00
+P 2009/01/01 $40.00
+P 2009/02/01 $50.00
>>>2
=== 0
diff --git a/test/regress/BBFA1759.test b/test/regress/BBFA1759.test
index ca6842dc..26862703 100644
--- a/test/regress/BBFA1759.test
+++ b/test/regress/BBFA1759.test
@@ -3,8 +3,8 @@ period june 2008
>>>1
global details =>
- start: 2008-06-01
- end: 2008-07-01
+ start: 08-Jun-01
+ end: 08-Jul-01
factor: 1
>>>2
=== 0
diff --git a/test/unit/t_amount.cc b/test/unit/t_amount.cc
index ba863ca7..c2a6b8c9 100644
--- a/test/unit/t_amount.cc
+++ b/test/unit/t_amount.cc
@@ -11,6 +11,7 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(AmountTestCase, "math");
void AmountTestCase::setUp()
{
+ times_initialize();
amount_t::initialize();
// Cause the display precision for dollars to be initialized to 2.
@@ -24,6 +25,7 @@ void AmountTestCase::tearDown()
{
amount_t::stream_fullstrings = false;
amount_t::shutdown();
+ times_shutdown();
}
void AmountTestCase::testParser()
diff --git a/test/unit/t_balance.cc b/test/unit/t_balance.cc
index 335d1a52..c7d633b8 100644
--- a/test/unit/t_balance.cc
+++ b/test/unit/t_balance.cc
@@ -11,6 +11,7 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(BalanceTestCase, "math");
void BalanceTestCase::setUp()
{
+ times_initialize();
amount_t::initialize();
// Cause the display precision for dollars to be initialized to 2.
@@ -24,4 +25,5 @@ void BalanceTestCase::tearDown()
{
amount_t::stream_fullstrings = false;
amount_t::shutdown();
+ times_shutdown();
}
diff --git a/test/unit/t_commodity.cc b/test/unit/t_commodity.cc
index de46211c..3d84ead6 100644
--- a/test/unit/t_commodity.cc
+++ b/test/unit/t_commodity.cc
@@ -10,12 +10,14 @@ using namespace ledger;
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CommodityTestCase, "math");
void CommodityTestCase::setUp() {
+ times_initialize();
amount_t::initialize();
amount_t::stream_fullstrings = true;
}
void CommodityTestCase::tearDown() {
amount_t::shutdown();
+ times_shutdown();
}
void CommodityTestCase::testPriceHistory()
diff --git a/test/unit/t_expr.cc b/test/unit/t_expr.cc
index 49d7dd23..6c88a08a 100644
--- a/test/unit/t_expr.cc
+++ b/test/unit/t_expr.cc
@@ -10,10 +10,12 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ValueExprTestCase, "expr");
void ValueExprTestCase::setUp()
{
+ times_initialize();
amount_t::initialize();
}
void ValueExprTestCase::tearDown()
{
amount_t::shutdown();
+ times_shutdown();
}
diff --git a/test/unit/t_times.cc b/test/unit/t_times.cc
index 8485a2c9..d8a67b43 100644
--- a/test/unit/t_times.cc
+++ b/test/unit/t_times.cc
@@ -9,6 +9,16 @@ using namespace ledger;
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DateTimeTestCase, "util");
+void DateTimeTestCase::setUp()
+{
+ times_initialize();
+}
+
+void DateTimeTestCase::tearDown()
+{
+ times_shutdown();
+}
+
void DateTimeTestCase::testConstructors()
{
#ifndef NOT_FOR_PYTHON
diff --git a/test/unit/t_times.h b/test/unit/t_times.h
index 28784113..5bbadf21 100644
--- a/test/unit/t_times.h
+++ b/test/unit/t_times.h
@@ -15,8 +15,8 @@ public:
DateTimeTestCase() {}
virtual ~DateTimeTestCase() {}
- //virtual void setUp();
- //virtual void tearDown();
+ virtual void setUp();
+ virtual void tearDown();
void testConstructors();