Merge branch 'next'

This commit is contained in:
John Wiegley 2009-10-25 21:27:56 -04:00
commit 9dadaebfeb
57 changed files with 839 additions and 607 deletions

View file

@ -136,7 +136,6 @@ pkginclude_HEADERS = \
\
src/pyinterp.h \
\
lib/fdstream.h \
lib/sha1.h \
lib/gettext.h \
\

133
acprep
View file

@ -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:

View file

@ -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

View file

@ -47,4 +47,4 @@ cppunit-debug:
cppunit-build: cppunit-release cppunit-debug
build-all: cppunit-build boost-build
build-all: boost-build cppunit-build

View file

@ -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*/

View file

@ -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;

View file

@ -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) {}

View file

@ -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();

View file

@ -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 << ')';

View file

@ -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'.

View file

@ -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;

View file

@ -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 << "\"";

View file

@ -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");

View file

@ -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 { \

View file

@ -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());

View file

@ -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) {

View file

@ -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 {

View file

@ -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_"

View file

@ -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 << ' ';

View file

@ -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 =

View file

@ -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();
}

View file

@ -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())));

View file

@ -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;

View file

@ -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
{

View file

@ -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) {

View file

@ -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&);

View file

@ -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;
}

View file

@ -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())

View file

@ -165,8 +165,10 @@ void export_times()
register_optional_to_python<datetime_t>();
register_optional_to_python<date_t>();
scope().attr("parse_datetime") = &py_parse_datetime;
scope().attr("parse_date") = &py_parse_date;
scope().attr("parse_datetime") = &py_parse_datetime;
scope().attr("parse_date") = &py_parse_date;
scope().attr("times_initialize") = &times_initialize;
scope().attr("times_shutdown") = &times_shutdown;
#if 0
class_< interval_t > ("Interval")

View file

@ -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;

View file

@ -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];

View file

@ -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;

View file

@ -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;

View file

@ -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_);

View file

@ -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), "

View file

@ -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();
}
}

View file

@ -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_);

View file

@ -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];
}

View file

@ -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>

View file

@ -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

View file

@ -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);

View file

@ -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";
}
}

View file

@ -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
}

View file

@ -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

View file

@ -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:

View file

@ -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);
}

View file

@ -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>);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -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();
}

View file

@ -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()

View file

@ -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();
}

View file

@ -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

View file

@ -15,8 +15,8 @@ public:
DateTimeTestCase() {}
virtual ~DateTimeTestCase() {}
//virtual void setUp();
//virtual void tearDown();
virtual void setUp();
virtual void tearDown();
void testConstructors();