Merge branch 'next'
This commit is contained in:
commit
9dadaebfeb
57 changed files with 839 additions and 607 deletions
|
|
@ -136,7 +136,6 @@ pkginclude_HEADERS = \
|
|||
\
|
||||
src/pyinterp.h \
|
||||
\
|
||||
lib/fdstream.h \
|
||||
lib/sha1.h \
|
||||
lib/gettext.h \
|
||||
\
|
||||
|
|
|
|||
133
acprep
133
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,61 +934,74 @@ 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.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')
|
||||
|
||||
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'] = ''
|
||||
|
||||
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'
|
||||
self.log.debug('Setting BOOST_SUFFIX => %s' %
|
||||
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')
|
||||
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.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_gcov(self):
|
||||
self.CXXFLAGS.append('-g')
|
||||
self.CXXFLAGS.append('-fprofile-arcs')
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
31
configure.ac
31
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
|
||||
|
|
|
|||
|
|
@ -47,4 +47,4 @@ cppunit-debug:
|
|||
|
||||
cppunit-build: cppunit-release cppunit-debug
|
||||
|
||||
build-all: cppunit-build boost-build
|
||||
build-all: boost-build cppunit-build
|
||||
|
|
|
|||
184
lib/fdstream.h
184
lib/fdstream.h
|
|
@ -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*/
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 << ')';
|
||||
|
|
|
|||
|
|
@ -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'.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 << "\"";
|
||||
|
||||
|
|
|
|||
29
src/error.cc
29
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");
|
||||
|
|
|
|||
14
src/error.h
14
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 line_context(const string& line,
|
||||
const string::size_type pos = 0,
|
||||
const string::size_type end_pos = 0);
|
||||
|
||||
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 = "");
|
||||
|
||||
#define DECLARE_EXCEPTION(name, kind) \
|
||||
class name : public kind { \
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
12
src/format.h
12
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_"
|
||||
|
|
|
|||
|
|
@ -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 << ' ';
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())));
|
||||
|
|
|
|||
99
src/op.cc
99
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;
|
||||
|
||||
|
|
|
|||
5
src/op.h
5
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
10
src/option.h
10
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&);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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") = ×_initialize;
|
||||
scope().attr("times_shutdown") = ×_shutdown;
|
||||
|
||||
#if 0
|
||||
class_< interval_t > ("Interval")
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
parent->import(file.leaf());
|
||||
#endif
|
||||
});
|
||||
#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 // BOOST_VERSION >= 103700
|
||||
};
|
||||
|
||||
extern shared_ptr<python_interpreter_t> python_session;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
|
|
|
|||
14
src/report.h
14
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), "
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
360
src/times.cc
360
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) {}
|
||||
};
|
||||
|
||||
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)
|
||||
};
|
||||
|
||||
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 <typename T, typename InputFacetType, typename OutputFacetType>
|
||||
class temporal_io_t : public noncopyable
|
||||
{
|
||||
std::string str(date_str);
|
||||
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
|
||||
|
||||
gregorian::date_input_facet * facet(new gregorian::date_input_facet(df.format));
|
||||
std::istringstream sstr(str);
|
||||
sstr.imbue(std::locale(sstr.getloc(), facet));
|
||||
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) {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
datetime_t temporal_io_t<datetime_t, posix_time::time_input_facet,
|
||||
posix_time::time_facet>
|
||||
::parse(const char * str)
|
||||
{
|
||||
#if defined(USE_BOOST_FACETS)
|
||||
input_stream.seekg(std::ios_base::beg);
|
||||
input_stream.clear();
|
||||
input_stream.str(str);
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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;
|
||||
sstr >> 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()) {
|
||||
if (sstr.good() && ! sstr.eof() && sstr.peek() != EOF)
|
||||
return date_t();
|
||||
|
||||
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
|
||||
|
|
|
|||
41
src/times.h
41
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
107
src/utils.cc
107
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
|
||||
}
|
||||
|
||||
|
|
|
|||
21
src/utils.h
21
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
|
||||
|
|
|
|||
28
src/value.cc
28
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:
|
||||
|
|
|
|||
12
src/value.h
12
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
39
src/xact.cc
39
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>);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ public:
|
|||
DateTimeTestCase() {}
|
||||
virtual ~DateTimeTestCase() {}
|
||||
|
||||
//virtual void setUp();
|
||||
//virtual void tearDown();
|
||||
virtual void setUp();
|
||||
virtual void tearDown();
|
||||
|
||||
void testConstructors();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue