summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt18
-rw-r--r--src/amount.cc4
-rw-r--r--src/annotate.cc4
-rw-r--r--src/balance.cc18
-rw-r--r--src/balance.h7
-rw-r--r--src/commodity.cc4
-rw-r--r--src/context.h31
-rw-r--r--src/draft.cc2
-rw-r--r--src/error.cc10
-rw-r--r--src/error.h17
-rw-r--r--src/expr.cc14
-rw-r--r--src/filters.cc25
-rw-r--r--src/filters.h1
-rw-r--r--src/format.cc4
-rw-r--r--src/global.h6
-rw-r--r--src/item.cc2
-rw-r--r--src/item.h14
-rw-r--r--src/main.cc19
-rw-r--r--src/mask.cc3
-rw-r--r--src/op.cc4
-rw-r--r--src/op.h22
-rw-r--r--src/option.cc5
-rw-r--r--src/output.cc7
-rw-r--r--src/print.cc4
-rw-r--r--src/py_post.cc5
-rw-r--r--src/py_value.cc8
-rw-r--r--src/pyinterp.cc16
-rw-r--r--src/query.cc1
-rw-r--r--src/quotes.cc7
-rw-r--r--src/report.cc9
-rw-r--r--src/report.h1
-rw-r--r--src/session.cc4
-rw-r--r--src/session.h4
-rw-r--r--src/stream.cc6
-rw-r--r--src/strptime.cc7
-rw-r--r--src/system.hh.in45
-rw-r--r--src/textual.cc88
-rw-r--r--src/timelog.cc2
-rw-r--r--src/times.cc118
-rw-r--r--src/token.cc4
-rw-r--r--src/utils.h10
-rw-r--r--src/value.cc6
-rw-r--r--src/value.h10
-rw-r--r--src/xact.cc14
-rw-r--r--src/xact.h6
45 files changed, 248 insertions, 368 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 71d9478a..9b39ea94 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -52,7 +52,6 @@ set(LEDGER_SOURCES
times.cc
error.cc
utils.cc
- strptime.cc
wcwidth.cc)
if (HAVE_BOOST_PYTHON)
@@ -134,11 +133,18 @@ set(LEDGER_INCLUDES
value.h
views.h
xact.h
- strptime.h
${PROJECT_BINARY_DIR}/system.hh)
+# Windows provides no strptime(), so supply our own.
+if (WIN32 OR CYGWIN)
+ list(APPEND LEDGER_INCLUDES
+ strptime.h)
+ list(APPEND LEDGER_SOURCES
+ strptime.cc)
+endif()
+
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
- if (CMAKE_CXX_COMPILER MATCHES "clang\\+\\+")
+ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_definitions(
# -Weverything
# -Wno-disabled-macro-expansion
@@ -193,7 +199,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
DEPENDS ${_header_filename})
endmacro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
- elseif (CMAKE_CXX_COMPILER MATCHES "g\\+\\+")
+ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(GXX_WARNING_FLAGS
-pedantic
-Wall
@@ -261,7 +267,9 @@ else()
endmacro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
endif()
-add_pch_rule(${PROJECT_BINARY_DIR}/system.hh LEDGER_SOURCES LEDGER_CLI_SOURCES)
+if(PRECOMPILE_SYSTEM_HH)
+ add_pch_rule(${PROJECT_BINARY_DIR}/system.hh LEDGER_SOURCES LEDGER_CLI_SOURCES)
+endif()
include(GNUInstallDirs)
diff --git a/src/amount.cc b/src/amount.cc
index 05145f87..c6463b2b 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -604,7 +604,9 @@ void amount_t::in_place_invert()
throw_(amount_error, _("Cannot invert an uninitialized amount"));
_dup();
- mpq_inv(MP(quantity), MP(quantity));
+
+ if (sign() != 0)
+ mpq_inv(MP(quantity), MP(quantity));
}
void amount_t::in_place_round()
diff --git a/src/annotate.cc b/src/annotate.cc
index ab81d412..c5ccdf07 100644
--- a/src/annotate.cc
+++ b/src/annotate.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -81,7 +81,7 @@ bool annotation_t::operator<(const annotation_t& rhs) const
void annotation_t::parse(std::istream& in)
{
do {
- istream_pos_type pos = in.tellg();
+ std::istream::pos_type pos = in.tellg();
if (static_cast<int>(pos) < 0)
return;
diff --git a/src/balance.cc b/src/balance.cc
index fa1bc20c..1ae9edb2 100644
--- a/src/balance.cc
+++ b/src/balance.cc
@@ -240,6 +240,14 @@ balance_t::strip_annotations(const keep_details_t& what_to_keep) const
return temp;
}
+void balance_t::sorted_amounts(amounts_array& sorted) const
+{
+ foreach (const amounts_map::value_type& pair, amounts)
+ sorted.push_back(&pair.second);
+ std::stable_sort(sorted.begin(), sorted.end(),
+ commodity_t::compare_by_commodity());
+}
+
void balance_t::map_sorted_amounts(function<void(const amount_t&)> fn) const
{
if (! amounts.empty()) {
@@ -249,16 +257,8 @@ void balance_t::map_sorted_amounts(function<void(const amount_t&)> fn) const
fn(amount);
}
else {
- typedef std::vector<const amount_t *> amounts_array;
amounts_array sorted;
-
- foreach (const amounts_map::value_type& pair, amounts)
- if (pair.second)
- sorted.push_back(&pair.second);
-
- std::stable_sort(sorted.begin(), sorted.end(),
- commodity_t::compare_by_commodity());
-
+ sorted_amounts(sorted);
foreach (const amount_t * amount, sorted)
fn(*amount);
}
diff --git a/src/balance.h b/src/balance.h
index 8e773fc5..b9c9c2c8 100644
--- a/src/balance.h
+++ b/src/balance.h
@@ -81,6 +81,7 @@ class balance_t
{
public:
typedef std::map<commodity_t *, amount_t> amounts_map;
+ typedef std::vector<const amount_t *> amounts_array;
amounts_map amounts;
@@ -529,6 +530,12 @@ public:
balance_t strip_annotations(const keep_details_t& what_to_keep) const;
/**
+ * Given a balance, insert a commodity-wise sort of the amounts into the
+ * given amounts_array.
+ */
+ void sorted_amounts(amounts_array& sorted) const;
+
+ /**
* Iteration primitives. `map_sorted_amounts' allows one to visit
* each amount in balance in the proper order for displaying to the
* user. Mostly used by `print' and other routinse where the sort
diff --git a/src/commodity.cc b/src/commodity.cc
index a8520ca1..d6d5ca98 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -294,7 +294,7 @@ bool commodity_t::symbol_needs_quotes(const string& symbol)
void commodity_t::parse_symbol(std::istream& in, string& symbol)
{
- istream_pos_type pos = in.tellg();
+ std::istream::pos_type pos = in.tellg();
char buf[256];
char c = peek_next_nonws(in);
diff --git a/src/context.h b/src/context.h
index 4a7a5441..ca7af060 100644
--- a/src/context.h
+++ b/src/context.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -58,18 +58,19 @@ public:
shared_ptr<std::istream> stream;
- path pathname;
- path current_directory;
- journal_t * journal;
- account_t * master;
- scope_t * scope;
- char linebuf[MAX_LINE + 1];
- istream_pos_type line_beg_pos;
- istream_pos_type curr_pos;
- std::size_t linenum;
- std::size_t errors;
- std::size_t count;
- std::size_t sequence;
+ path pathname;
+ path current_directory;
+ journal_t * journal;
+ account_t * master;
+ scope_t * scope;
+ char linebuf[MAX_LINE + 1];
+ std::istream::pos_type line_beg_pos;
+ std::istream::pos_type curr_pos;
+ std::size_t linenum;
+ std::size_t errors;
+ std::size_t count;
+ std::size_t sequence;
+ std::string last;
explicit parse_context_t(const path& cwd)
: current_directory(cwd), master(NULL), scope(NULL),
@@ -112,11 +113,7 @@ inline parse_context_t open_for_reading(const path& pathname,
const path& cwd)
{
path filename = resolve_path(pathname);
-#if BOOST_VERSION >= 104600 && BOOST_FILESYSTEM_VERSION >= 3
filename = filesystem::absolute(filename, cwd);
-#else
- filename = filesystem::complete(filename, cwd);
-#endif
if (! exists(filename) || is_directory(filename))
throw_(std::runtime_error,
_f("Cannot read journal file %1%") % filename);
diff --git a/src/draft.cc b/src/draft.cc
index 424b7a9a..12d7faf7 100644
--- a/src/draft.cc
+++ b/src/draft.cc
@@ -68,7 +68,7 @@ void draft_t::xact_template_t::dump(std::ostream& out) const
} else {
foreach (const post_template_t& post, posts) {
out << std::endl
- << _f("[Posting \"%1\"]") % (post.from ? _("from") : _("to"))
+ << _f("[Posting \"%1%\"]") % (post.from ? _("from") : _("to"))
<< std::endl;
if (post.account_mask)
diff --git a/src/error.cc b/src/error.cc
index 7e49645b..1ab92840 100644
--- a/src/error.cc
+++ b/src/error.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -78,10 +78,10 @@ string line_context(const string& line,
return buf.str();
}
-string source_context(const path& file,
- const istream_pos_type pos,
- const istream_pos_type end_pos,
- const string& prefix)
+string source_context(const path& file,
+ const std::istream::pos_type pos,
+ const std::istream::pos_type end_pos,
+ const string& prefix)
{
const std::streamoff len = end_pos - pos;
if (! len || file.empty())
diff --git a/src/error.h b/src/error.h
index 88e09329..3bdcde98 100644
--- a/src/error.h
+++ b/src/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -47,7 +47,7 @@ namespace ledger {
extern std::ostringstream _desc_buffer;
template <typename T>
-inline void throw_func(const string& message) {
+[[ noreturn ]] inline void throw_func(const string& message) {
_desc_buffer.clear();
_desc_buffer.str("");
throw T(message);
@@ -81,10 +81,10 @@ string line_context(const string& line,
const string::size_type pos = 0,
const string::size_type end_pos = 0);
-string source_context(const path& file,
- const istream_pos_type pos,
- const istream_pos_type end_pos,
- const string& prefix = "");
+string source_context(const path& file,
+ const std::istream::pos_type pos,
+ const std::istream::pos_type end_pos,
+ const string& prefix = "");
#define DECLARE_EXCEPTION(name, kind) \
class name : public kind { \
@@ -95,8 +95,9 @@ string source_context(const path& file,
struct error_count {
std::size_t count;
- explicit error_count(std::size_t _count) : count(_count) {}
- const char * what() const { return ""; }
+ std::string message;
+ explicit error_count(std::size_t _count, std::string _msg) : count(_count), message(_msg) {}
+ const char * what() const { return message.c_str(); }
};
} // namespace ledger
diff --git a/src/expr.cc b/src/expr.cc
index 85818e4b..c8945d3d 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -94,9 +94,9 @@ void expr_t::parse(std::istream& in, const parse_flags_t& flags,
const optional<string>& original_string)
{
parser_t parser;
- istream_pos_type start_pos = in.tellg();
+ std::istream::pos_type start_pos = in.tellg();
ptr = parser.parse(in, flags, original_string);
- istream_pos_type end_pos = in.tellg();
+ std::istream::pos_type end_pos = in.tellg();
if (original_string) {
set_text(*original_string);
@@ -290,10 +290,10 @@ value_t source_command(call_scope_t& args)
in = &std::cin;
}
- symbol_scope_t file_locals(args);
- std::size_t linenum = 0;
- char buf[4096];
- istream_pos_type pos;
+ symbol_scope_t file_locals(args);
+ std::size_t linenum = 0;
+ char buf[4096];
+ std::istream::pos_type pos;
while (in->good() && ! in->eof()) {
pos = in->tellg();
diff --git a/src/filters.cc b/src/filters.cc
index 4e9e633a..3dfd2327 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -1245,19 +1245,34 @@ void generate_posts::add_post(const date_interval_t& period, post_t& post)
void budget_posts::report_budget_items(const date_t& date)
{
+ { // Cleanup pending items that finished before date
+ // We have to keep them until the last day they apply because operator() needs them to see if a
+ // posting is budgeted or not
+ std::list<pending_posts_list::iterator> posts_to_erase;
+ for (pending_posts_list::iterator i = pending_posts.begin(); i != pending_posts.end(); i++) {
+ pending_posts_list::value_type& pair(*i);
+ if (pair.first.finish && ! pair.first.start && pair.first.finish < date) {
+ posts_to_erase.push_back(i);
+ }
+ }
+ foreach (pending_posts_list::iterator& i, posts_to_erase)
+ pending_posts.erase(i);
+ }
+
if (pending_posts.size() == 0)
return;
bool reported;
do {
- std::list<pending_posts_list::iterator> posts_to_erase;
-
reported = false;
for (pending_posts_list::iterator i = pending_posts.begin();
i != pending_posts.end();
i++) {
pending_posts_list::value_type& pair(*i);
+ if (pair.first.finish && ! pair.first.start)
+ continue; // skip expired posts
+
optional<date_t> begin = pair.first.start;
if (! begin) {
optional<date_t> range_begin;
@@ -1285,9 +1300,6 @@ void budget_posts::report_budget_items(const date_t& date)
post_t& post = *pair.second;
++pair.first;
- if (! pair.first.start)
- posts_to_erase.push_back(i);
-
DEBUG("budget.generate", "Reporting budget for "
<< post.reported_account()->fullname());
@@ -1312,9 +1324,6 @@ void budget_posts::report_budget_items(const date_t& date)
reported = true;
}
}
-
- foreach (pending_posts_list::iterator& i, posts_to_erase)
- pending_posts.erase(i);
} while (reported);
}
diff --git a/src/filters.h b/src/filters.h
index c1dc2e04..cf053a24 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -604,6 +604,7 @@ public:
virtual ~changed_value_posts() {
TRACE_DTOR(changed_value_posts);
+ temps.clear();
handler.reset();
}
diff --git a/src/format.cc b/src/format.cc
index bb578141..5b9baa21 100644
--- a/src/format.cc
+++ b/src/format.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -103,7 +103,7 @@ namespace {
p += std::strlen(p);
} else {
assert(str.good());
- istream_pos_type pos = str.tellg();
+ std::istream::pos_type pos = str.tellg();
expr.set_text(string(p, p + long(pos)));
p += long(pos) - 1;
diff --git a/src/global.h b/src/global.h
index 01ad60cc..4eb02571 100644
--- a/src/global.h
+++ b/src/global.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -129,7 +129,7 @@ public:
out << '-' << Ledger_VERSION_DATE;
out << _(", the command-line accounting tool");
out <<
- _("\n\nCopyright (c) 2003-2018, John Wiegley. All rights reserved.\n\n\
+ _("\n\nCopyright (c) 2003-2019, John Wiegley. All rights reserved.\n\n\
This program is made available under the terms of the BSD Public License.\n\
See LICENSE file included with the distribution for details and disclaimer.");
out << std::endl;
@@ -166,7 +166,7 @@ See LICENSE file included with the distribution for details and disclaimer.");
OPTION_(global_scope_t, version, DO() { // -v
parent->show_version_info(std::cout);
- throw error_count(0); // exit immediately
+ throw error_count(0, ""); // exit immediately
});
};
diff --git a/src/item.cc b/src/item.cc
index bd025c52..7132103e 100644
--- a/src/item.cc
+++ b/src/item.cc
@@ -152,7 +152,7 @@ void item_t::parse_tags(const char * p,
if (const char * b = std::strchr(p, '[')) {
if (*(b + 1) != '\0' &&
(std::isdigit(*(b + 1)) || *(b + 1) == '=')) {
- if (const char * e = std::strchr(p, ']')) {
+ if (const char * e = std::strchr(b, ']')) {
char buf[256];
std::strncpy(buf, b + 1, static_cast<std::size_t>(e - b - 1));
buf[e - b - 1] = '\0';
diff --git a/src/item.h b/src/item.h
index a28bf59e..51539eff 100644
--- a/src/item.h
+++ b/src/item.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -48,12 +48,12 @@ namespace ledger {
struct position_t
{
- path pathname;
- istream_pos_type beg_pos;
- std::size_t beg_line;
- istream_pos_type end_pos;
- std::size_t end_line;
- std::size_t sequence;
+ path pathname;
+ std::istream::pos_type beg_pos;
+ std::size_t beg_line;
+ std::istream::pos_type end_pos;
+ std::size_t end_line;
+ std::size_t sequence;
position_t()
: beg_pos(0), beg_line(0), end_pos(0), end_line(0), sequence(0) {
diff --git a/src/main.cc b/src/main.cc
index c8b9ec3a..218579cf 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -35,6 +35,10 @@
// was moved there for the sake of clarity here
#include "session.h"
+#ifdef HAVE_EDIT
+#include <editline/readline.h>
+#endif
+
using namespace ledger;
#if HAVE_BOOST_PYTHON
@@ -69,9 +73,6 @@ int main(int argc, char * argv[], char * envp[])
// Initialize global Boost/C++ environment
std::ios::sync_with_stdio(false);
-#if BOOST_VERSION < 104600
- filesystem::path::default_name_check(filesystem::portable_posix_name);
-#endif
std::signal(SIGINT, sigint_handler);
#if !defined(_WIN32) && !defined(__CYGWIN__)
@@ -128,13 +129,9 @@ int main(int argc, char * argv[], char * envp[])
bool exit_loop = false;
-#if HAVE_EDIT
-
+#ifdef HAVE_EDIT
rl_readline_name = const_cast<char *>("Ledger");
-#if 0
- // jww (2009-02-05): NYI
- rl_attempted_completion_function = ledger_completion;
-#endif
+ // TODO: rl_attempted_completion_function = ledger_completion;
while (char * p = readline(global_scope->prompt_string())) {
char * expansion = NULL;
@@ -173,7 +170,7 @@ int main(int argc, char * argv[], char * envp[])
global_scope->execute_command_wrapper(split_arguments(p), true);
}
-#if HAVE_EDIT
+#ifdef HAVE_EDIT
if (expansion)
std::free(expansion);
std::free(p);
diff --git a/src/mask.cc b/src/mask.cc
index 434acad6..35e690de 100644
--- a/src/mask.cc
+++ b/src/mask.cc
@@ -75,9 +75,8 @@ mask_t& mask_t::assign_glob(const string& pat)
if (i + 1 < len) {
re_pat += pat[++i];
break;
- } else {
- // fallthrough...
}
+ // fallthrough...
default:
re_pat += pat[i];
break;
diff --git a/src/op.cc b/src/op.cc
index 00b84459..5801b1dd 100644
--- a/src/op.cc
+++ b/src/op.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -963,7 +963,7 @@ void expr_t::op_t::dump(std::ostream& out, const int depth) const
string op_context(const expr_t::ptr_op_t op,
const expr_t::ptr_op_t locus)
{
- ostream_pos_type start_pos, end_pos;
+ std::ostream::pos_type start_pos, end_pos;
expr_t::op_t::context_t context(op, locus, &start_pos, &end_pos);
std::ostringstream buf;
buf << " ";
diff --git a/src/op.h b/src/op.h
index bbbb5d81..aab362c7 100644
--- a/src/op.h
+++ b/src/op.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -285,19 +285,19 @@ public:
struct context_t
{
- ptr_op_t expr_op;
- ptr_op_t op_to_find;
- ostream_pos_type * start_pos;
- ostream_pos_type * end_pos;
- bool relaxed;
+ ptr_op_t expr_op;
+ ptr_op_t op_to_find;
+ std::ostream::pos_type * start_pos;
+ std::ostream::pos_type * end_pos;
+ bool relaxed;
context_t() : start_pos(NULL), end_pos(NULL), relaxed(false) {}
- context_t(const ptr_op_t& _expr_op,
- const ptr_op_t& _op_to_find,
- ostream_pos_type * const _start_pos = NULL,
- ostream_pos_type * const _end_pos = NULL,
- const bool _relaxed = true)
+ context_t(const ptr_op_t& _expr_op,
+ const ptr_op_t& _op_to_find,
+ std::ostream::pos_type * const _start_pos = NULL,
+ std::ostream::pos_type * const _end_pos = NULL,
+ const bool _relaxed = true)
: expr_op(_expr_op), op_to_find(_op_to_find),
start_pos(_start_pos), end_pos(_end_pos),
relaxed(_relaxed) {}
diff --git a/src/option.cc b/src/option.cc
index ab6c37e0..81f9af5b 100644
--- a/src/option.cc
+++ b/src/option.cc
@@ -42,6 +42,11 @@ namespace {
{
char buf[128];
char * p = buf;
+
+ if (name.length() > 127) {
+ throw_(option_error, _f("Illegal option --%1%") % name);
+ }
+
foreach (char ch, name) {
if (ch == '-')
*p++ = '_';
diff --git a/src/output.cc b/src/output.cc
index c2fa83ac..09d3ad9e 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -284,8 +284,9 @@ void report_accounts::flush()
std::ostream& out(report.output_stream);
format_t prepend_format;
std::size_t prepend_width;
+ bool do_prepend_format;
- if (report.HANDLED(prepend_format_)) {
+ if ((do_prepend_format = report.HANDLED(prepend_format_))) {
prepend_format.parse_format(report.HANDLER(prepend_format_).str());
prepend_width = report.HANDLED(prepend_width_)
? lexical_cast<std::size_t>(report.HANDLER(prepend_width_).str())
@@ -293,7 +294,7 @@ void report_accounts::flush()
}
foreach (accounts_pair& entry, accounts) {
- if (prepend_format) {
+ if (do_prepend_format) {
bind_scope_t bound_scope(report, *entry.first);
out.width(static_cast<std::streamsize>(prepend_width));
out << prepend_format(bound_scope);
diff --git a/src/print.cc b/src/print.cc
index 9fa75eab..92323777 100644
--- a/src/print.cc
+++ b/src/print.cc
@@ -103,11 +103,13 @@ namespace {
void print_xact(report_t& report, std::ostream& out, xact_t& xact)
{
format_type_t format_type = FMT_WRITTEN;
+ string format_str;
optional<const char *> format;
if (report.HANDLED(date_format_)) {
format_type = FMT_CUSTOM;
- format = report.HANDLER(date_format_).str().c_str();
+ format_str = report.HANDLER(date_format_).str();
+ format = format_str.c_str();
}
std::ostringstream buf;
diff --git a/src/py_post.cc b/src/py_post.cc
index 6195570b..525b47c2 100644
--- a/src/py_post.cc
+++ b/src/py_post.cc
@@ -153,6 +153,11 @@ void export_post()
return_value_policy<return_by_value>()),
make_setter(&post_t::cost,
return_value_policy<return_by_value>()))
+ .add_property("given_cost",
+ make_getter(&post_t::given_cost,
+ return_value_policy<return_by_value>()),
+ make_setter(&post_t::given_cost,
+ return_value_policy<return_by_value>()))
.add_property("assigned_amount",
make_getter(&post_t::assigned_amount,
return_value_policy<return_by_value>()),
diff --git a/src/py_value.cc b/src/py_value.cc
index f4f63946..486228c0 100644
--- a/src/py_value.cc
+++ b/src/py_value.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -88,12 +88,6 @@ namespace {
return buf.str();
}
- string py_dump_relaxed(const value_t& value) {
- std::ostringstream buf;
- value.dump(buf, true);
- return buf.str();
- }
-
void py_set_string(value_t& value, const string& str) {
return value.set_string(str);
}
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index 19430bef..fad0b559 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -222,27 +222,13 @@ object python_interpreter_t::import_option(const string& str)
python::list paths(sys_dict["path"]);
if (contains(str, ".py")) {
-#if BOOST_VERSION >= 103700
path& cwd(parsing_context.get_current().current_directory);
-#if BOOST_VERSION >= 104600 && BOOST_FILESYSTEM_VERSION >= 3
path parent(filesystem::absolute(file, cwd).parent_path());
-#else
- path parent(filesystem::complete(file, cwd).parent_path());
-#endif
DEBUG("python.interp", "Adding " << parent << " to PYTHONPATH");
paths.insert(0, parent.string());
sys_dict["path"] = paths;
-#if BOOST_VERSION >= 104600
name = file.stem().string();
-#else
- name = file.stem();
-#endif
-#else // BOOST_VERSION >= 103700
- paths.insert(0, file.branch_path().string());
- sys_dict["path"] = paths;
- name = file.leaf();
-#endif // BOOST_VERSION >= 103700
}
try {
diff --git a/src/query.cc b/src/query.cc
index fc1d4ff0..883bea40 100644
--- a/src/query.cc
+++ b/src/query.cc
@@ -155,6 +155,7 @@ query_t::lexer_t::next_token(query_t::lexer_t::token_t::kind_t tok_context)
case ')':
if (! consume_next && tok_context == token_t::TOK_EXPR)
goto test_ident;
+ // fall through...
case '(':
case '&':
case '|':
diff --git a/src/quotes.cc b/src/quotes.cc
index 50791560..8ae8ca90 100644
--- a/src/quotes.cc
+++ b/src/quotes.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -79,13 +79,8 @@ commodity_quote_from_script(commodity_t& commodity,
if (optional<std::pair<commodity_t *, price_point_t> > point =
commodity_pool_t::current_pool->parse_price_directive(buf)) {
if (commodity_pool_t::current_pool->price_db) {
-#if defined(__GNUG__) && __GNUG__ < 3
- ofstream database(*commodity_pool_t::current_pool->price_db,
- ios::out | ios::app);
-#else
ofstream database(*commodity_pool_t::current_pool->price_db,
std::ios_base::out | std::ios_base::app);
-#endif
database << "P "
<< format_datetime(point->second.when, FMT_WRITTEN)
<< " " << commodity.symbol()
diff --git a/src/report.cc b/src/report.cc
index cb7f09dc..13e6a61f 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -841,6 +841,13 @@ value_t report_t::fn_commodity(call_scope_t& args)
return string_value(args.get<amount_t>(0).commodity().symbol());
}
+value_t report_t::fn_clear_commodity(call_scope_t& args)
+{
+ amount_t amt(args.get<amount_t>(0));
+ amt.clear_commodity();
+ return amt;
+}
+
value_t report_t::fn_nail_down(call_scope_t& args)
{
value_t arg0(args[0]);
@@ -1384,6 +1391,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
return MAKE_FUNCTOR(report_t::fn_commodity);
else if (is_eq(p, "ceiling"))
return MAKE_FUNCTOR(report_t::fn_ceiling);
+ else if (is_eq(p, "clear_commodity"))
+ return MAKE_FUNCTOR(report_t::fn_clear_commodity);
break;
case 'd':
diff --git a/src/report.h b/src/report.h
index 635c3887..1bda0407 100644
--- a/src/report.h
+++ b/src/report.h
@@ -175,6 +175,7 @@ public:
value_t fn_truncated(call_scope_t& scope);
value_t fn_floor(call_scope_t& scope);
value_t fn_ceiling(call_scope_t& scope);
+ value_t fn_clear_commodity(call_scope_t& scope);
value_t fn_round(call_scope_t& scope);
value_t fn_roundto(call_scope_t& scope);
value_t fn_unround(call_scope_t& scope);
diff --git a/src/session.cc b/src/session.cc
index e95123e8..427850d9 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -76,7 +76,7 @@ std::size_t session_t::read_data(const string& master_account)
file = path(home_var) / ".ledger";
if (! file.empty() && exists(file))
- HANDLER(file_).data_files.insert(file);
+ HANDLER(file_).data_files.push_back(file);
else
throw_(parse_error, "No journal file was specified (please use -f)");
@@ -214,7 +214,7 @@ journal_t * session_t::read_journal_files()
journal_t * session_t::read_journal(const path& pathname)
{
HANDLER(file_).data_files.clear();
- HANDLER(file_).data_files.insert(pathname);
+ HANDLER(file_).data_files.push_back(pathname);
return read_journal_files();
}
diff --git a/src/session.h b/src/session.h
index 47732a3d..4dce3816 100644
--- a/src/session.h
+++ b/src/session.h
@@ -153,14 +153,14 @@ public:
OPTION__
(session_t, file_, // -f
- std::set<path COMMA ComparePaths> data_files;
+ std::list<path> data_files;
CTOR(session_t, file_) {}
DO_(str) {
if (parent->flush_on_next_data_file) {
data_files.clear();
parent->flush_on_next_data_file = false;
}
- data_files.insert(str);
+ data_files.push_back(str);
});
OPTION_(session_t, input_date_format_, DO_(str) {
diff --git a/src/stream.cc b/src/stream.cc
index c4bbb42e..91a190d8 100644
--- a/src/stream.cc
+++ b/src/stream.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -89,11 +89,7 @@ namespace {
else { // parent
close(pfd[0]);
typedef iostreams::stream<iostreams::file_descriptor_sink> fdstream;
-#if BOOST_VERSION >= 104400
*os = new fdstream(pfd[1], iostreams::never_close_handle);
-#else // BOOST_VERSION >= 104400
- *os = new fdstream(pfd[1]);
-#endif // BOOST_VERSION >= 104400
}
return pfd[1];
#else
diff --git a/src/strptime.cc b/src/strptime.cc
index 069b9267..ac6885a6 100644
--- a/src/strptime.cc
+++ b/src/strptime.cc
@@ -12,7 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if !(defined(_WIN32) || defined(__CYGWIN__))
+#error This file should only be compiled on Windows.
+#endif
+
// Implement strptime under windows
#include "strptime.h"
@@ -200,5 +203,3 @@ static char* _strptime(const char *s, const char *format, struct tm *tm) {
char* strptime(const char *buf, const char *fmt, struct tm *tm) {
return _strptime(buf, fmt, tm);
}
-
-#endif // _WIN32
diff --git a/src/system.hh.in b/src/system.hh.in
index 38ac1e63..97651e8b 100644
--- a/src/system.hh.in
+++ b/src/system.hh.in
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -57,11 +57,9 @@
#define Ledger_VERSION_PRERELEASE "@Ledger_VERSION_PRERELEASE@"
#define Ledger_VERSION_DATE @Ledger_VERSION_DATE@
-#define HAVE_EDIT @HAVE_EDIT@
#define HAVE_GETTEXT @HAVE_GETTEXT@
-#cmakedefine HAVE_ACCESS
-#cmakedefine HAVE_REALPATH
+#cmakedefine HAVE_EDIT
#cmakedefine HAVE_GETPWUID
#cmakedefine HAVE_GETPWNAM
#cmakedefine HAVE_IOCTL
@@ -83,14 +81,9 @@
/* System includes */
/*------------------------------------------------------------------------*/
-#if defined(__GNUG__) && __GNUG__ < 3
-#define _XOPEN_SOURCE
-#endif
-
#include <algorithm>
#include <exception>
#include <typeinfo>
-#include <locale>
#include <stdexcept>
#include <iostream>
#include <streambuf>
@@ -107,29 +100,6 @@
#include <string>
#include <vector>
-#if defined(__GNUG__) && __GNUG__ < 3
-
-namespace std {
- inline ostream & right (ostream & i) {
- i.setf(i.right, i.adjustfield);
- return i;
- }
- inline ostream & left (ostream & i) {
- i.setf(i.left, i.adjustfield);
- return i;
- }
-}
-
-typedef std::streamoff istream_pos_type;
-typedef std::streamoff ostream_pos_type;
-
-#else // ! (defined(__GNUG__) && __GNUG__ < 3)
-
-typedef std::istream::pos_type istream_pos_type;
-typedef std::ostream::pos_type ostream_pos_type;
-
-#endif
-
#include <cassert>
#include <cctype>
#include <cstdarg>
@@ -138,12 +108,6 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <cstring>
#include <csignal>
-#if defined __FreeBSD__ && __FreeBSD__ <= 4
-// FreeBSD has a broken isspace macro, so don't use it
-#undef isspace(c)
-#endif
-
-#include <sys/stat.h>
#if defined(_WIN32) || defined(__CYGWIN__)
#include <io.h>
#else
@@ -167,10 +131,6 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <mpfr.h>
#include "utf8.h"
-#if HAVE_EDIT
-#include <editline/readline.h>
-#endif
-
#include <boost/algorithm/string.hpp>
#include <boost/any.hpp>
#include <boost/bind.hpp>
@@ -247,7 +207,6 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <boost/python/detail/wrap_python.hpp>
#include <datetime.h>
-#include <unicodeobject.h>
#include <boost/python/module_init.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
diff --git a/src/textual.cc b/src/textual.cc
index 8fbc5c08..04e90e45 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -282,6 +282,10 @@ void instance_t::parse()
std::cerr << _("Error: ") << err.what() << std::endl;
context.errors++;
+ if (! current_context.empty())
+ context.last = current_context + "\n" + err.what();
+ else
+ context.last = err.what();
}
}
@@ -553,7 +557,7 @@ void instance_t::option_directive(char * line)
void instance_t::automated_xact_directive(char * line)
{
- istream_pos_type pos = context.line_beg_pos;
+ std::istream::pos_type pos = context.line_beg_pos;
bool reveal_context = true;
@@ -649,7 +653,7 @@ void instance_t::automated_xact_directive(char * line)
void instance_t::period_xact_directive(char * line)
{
- istream_pos_type pos = context.line_beg_pos;
+ std::istream::pos_type pos = context.line_beg_pos;
bool reveal_context = true;
@@ -739,17 +743,8 @@ void instance_t::include_directive(char * line)
DEBUG("textual.include", "resolved path: " << filename.string());
mask_t glob;
-#if BOOST_VERSION >= 103700
path parent_path = filename.parent_path();
-#if BOOST_VERSION >= 104600
glob.assign_glob('^' + filename.filename().string() + '$');
-#else
- glob.assign_glob('^' + filename.filename() + '$');
-#endif
-#else // BOOST_VERSION >= 103700
- path parent_path = filename.branch_path();
- glob.assign_glob('^' + filename.leaf() + '$');
-#endif // BOOST_VERSION >= 103700
bool files_found = false;
if (exists(parent_path)) {
@@ -757,21 +752,9 @@ void instance_t::include_directive(char * line)
for (filesystem::directory_iterator iter(parent_path);
iter != end;
++iter) {
-#if BOOST_VERSION <= 103500
- if (is_regular(*iter))
-#else
if (is_regular_file(*iter))
-#endif
{
-#if BOOST_VERSION >= 103700
-#if BOOST_VERSION >= 104600
string base = (*iter).path().filename().string();
-#else
- string base = (*iter).filename();
-#endif
-#else // BOOST_VERSION >= 103700
- string base = (*iter).leaf();
-#endif // BOOST_VERSION >= 103700
if (glob.match(base)) {
journal_t * journal = context.journal;
account_t * master = top_account();
@@ -912,8 +895,8 @@ void instance_t::end_apply_directive(char * kind)
void instance_t::account_directive(char * line)
{
- istream_pos_type beg_pos = context.line_beg_pos;
- std::size_t beg_linenum = context.linenum;
+ std::istream::pos_type beg_pos = context.line_beg_pos;
+ std::size_t beg_linenum = context.linenum;
char * p = skip_ws(line);
account_t * account =
@@ -1644,29 +1627,30 @@ post_t * instance_t::parse_post(char * line,
}
DEBUG("textual.parse", "line " << context.linenum << ": "
- << "POST assign: parsed amt = " << *post->assigned_amount);
+ << "POST assign: parsed balance amount = " << *post->assigned_amount);
- amount_t& amt(*post->assigned_amount);
+ const amount_t& amt(*post->assigned_amount);
value_t account_total
(post->account->amount().strip_annotations(keep_details_t()));
DEBUG("post.assign", "line " << context.linenum << ": "
<< "account balance = " << account_total);
- DEBUG("post.assign",
- "line " << context.linenum << ": " << "post amount = " << amt);
+ DEBUG("post.assign", "line " << context.linenum << ": "
+ << "post amount = " << amt << " (is_zero = " << amt.is_zero() << ")");
- amount_t diff = amt;
+ balance_t diff = amt;
switch (account_total.type()) {
case value_t::AMOUNT:
- if (account_total.as_amount().commodity_ptr() == diff.commodity_ptr())
- diff -= account_total.as_amount();
+ diff -= account_total.as_amount();
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Subtracting amount " << account_total.as_amount() << " from diff, yielding " << diff);
break;
case value_t::BALANCE:
- if (optional<amount_t> comm_bal =
- account_total.as_balance().commodity_amount(amt.commodity()))
- diff -= *comm_bal;
+ diff -= account_total.as_balance();
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Subtracting balance " << account_total.as_balance() << " from diff, yielding " << diff);
break;
default:
@@ -1680,18 +1664,34 @@ post_t * instance_t::parse_post(char * line,
// Subtract amounts from previous posts to this account in the xact.
for (post_t* p : xact->posts) {
- if (p->account == post->account &&
- p->amount.commodity_ptr() == diff.commodity_ptr()) {
+ if (p->account == post->account) {
diff -= p->amount;
DEBUG("textual.parse", "line " << context.linenum << ": "
- << "Subtract " << p->amount << ", diff = " << diff);
+ << "Subtracting " << p->amount << ", diff = " << diff);
}
}
+ // If amt has a commodity, restrict balancing to that. Otherwise, it's the blanket '0' and
+ // check that all of them are zero.
+ if (amt.has_commodity()) {
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Finding commodity " << amt.commodity() << " (" << amt << ") in balance " << diff);
+ optional<amount_t> wanted_commodity = diff.commodity_amount(amt.commodity());
+ if (!wanted_commodity) {
+ diff = amt - amt; // this is '0' with the correct commodity.
+ } else {
+ diff = *wanted_commodity;
+ }
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Diff is now " << diff);
+ }
+
if (post->amount.is_null()) {
// balance assignment
if (! diff.is_zero()) {
- post->amount = diff;
+ // This will fail if there are more than 1 commodity in diff, which is wanted,
+ // as amount cannot store more than 1 commodity.
+ post->amount = diff.to_amount();
DEBUG("textual.parse", "line " << context.linenum << ": "
<< "Overwrite null posting");
}
@@ -1699,10 +1699,11 @@ post_t * instance_t::parse_post(char * line,
// balance assertion
diff -= post->amount;
if (! no_assertions && ! diff.is_zero()) {
- amount_t tot = amt - diff;
+ balance_t tot = -diff + amt;
+ DEBUG("textual.parse", "Balance assertion: off by " << diff << " (expected to see " << tot << ")");
throw_(parse_error,
_f("Balance assertion off by %1% (expected to see %2%)")
- % diff % tot);
+ % diff.to_string() % tot.to_string());
}
}
@@ -2012,7 +2013,8 @@ std::size_t journal_t::read_textual(parse_context_stack_t& context_stack)
TRACE_FINISH(parsing_total, 1);
if (context_stack.get_current().errors > 0)
- throw error_count(context_stack.get_current().errors);
+ throw error_count(context_stack.get_current().errors,
+ context_stack.get_current().last);
return context_stack.get_current().count;
}
diff --git a/src/timelog.cc b/src/timelog.cc
index 2a618afd..5b289a34 100644
--- a/src/timelog.cc
+++ b/src/timelog.cc
@@ -170,7 +170,7 @@ void time_log_t::close()
foreach (account_t * account, accounts) {
DEBUG("timelog", "Clocking out from account " << account->fullname());
context.count += clock_out_from_timelog
- (time_xacts, time_xact_t(none, CURRENT_TIME(), account), context);
+ (time_xacts, time_xact_t(none, CURRENT_TIME(), false, account), context);
}
assert(time_xacts.empty());
}
diff --git a/src/times.cc b/src/times.cc
index 8e4df020..74773755 100644
--- a/src/times.cc
+++ b/src/times.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -43,23 +43,11 @@ optional<datetime_t> epoch;
date_time::weekdays start_of_week = gregorian::Sunday;
-//#define USE_BOOST_FACETS 1
-#if defined(USE_BOOST_FACETS)
-#error "Boost facets are not quite working yet"
-#endif
-
namespace {
template <typename T, typename InputFacetType, typename OutputFacetType>
class temporal_io_t : public noncopyable
{
- string 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
+ string fmt_str;
public:
date_traits_t traits;
@@ -71,15 +59,6 @@ namespace {
icontains(fmt_str, "%m") || icontains(fmt_str, "%b"),
icontains(fmt_str, "%d")),
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) {
@@ -88,29 +67,15 @@ namespace {
icontains(fmt_str, "%m") ||
icontains(fmt_str, "%b"),
icontains(fmt_str, "%d"));
-#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 *) {}
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.c_str(), &data);
return buf;
-#endif // USE_BOOST_FACETS
}
};
@@ -119,34 +84,12 @@ namespace {
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 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.c_str(), &data))
return posix_time::ptime_from_tm(data);
else
return datetime_t();
-#endif // USE_BOOST_FACETS
}
template <>
@@ -154,27 +97,6 @@ namespace {
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 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_year = CURRENT_DATE().year() - 1900;
@@ -183,7 +105,6 @@ namespace {
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,
@@ -206,7 +127,9 @@ namespace {
date_t parse_date_mask_routine(const char * date_str, date_io_t& io,
date_traits_t * traits = NULL)
{
- VERIFY(std::strlen(date_str) < 127);
+ if (std::strlen(date_str) > 127) {
+ throw_(date_error, _f("Invalid date: %1%") % date_str);
+ }
char buf[128];
std::strcpy(buf, date_str);
@@ -420,7 +343,6 @@ class date_parser_t
TOK_DASH,
TOK_DOT,
- TOK_A_YEAR,
TOK_A_MONTH,
TOK_A_WDAY,
@@ -512,9 +434,6 @@ class date_parser_t
case TOK_SLASH: return "/";
case TOK_DASH: return "-";
case TOK_DOT: return ".";
- case TOK_A_YEAR:
- out << boost::get<date_specifier_t::year_type>(*value);
- break;
case TOK_A_MONTH:
out << date_specifier_t::month_type
(boost::get<date_time::months_of_year>(*value));
@@ -566,7 +485,6 @@ class date_parser_t
case TOK_SLASH: out << "TOK_SLASH"; break;
case TOK_DASH: out << "TOK_DASH"; break;
case TOK_DOT: out << "TOK_DOT"; break;
- case TOK_A_YEAR: out << "TOK_A_YEAR"; break;
case TOK_A_MONTH: out << "TOK_A_MONTH"; break;
case TOK_A_WDAY: out << "TOK_A_WDAY"; break;
case TOK_AGO: out << "TOK_AGO"; break;
@@ -727,7 +645,11 @@ void date_parser_t::determine_when(date_parser_t::lexer_t::token_t& tok,
when += gregorian::days(amount * adjust);
break;
default:
- specifier.day = date_specifier_t::day_type(amount);
+ if (amount > 31) {
+ specifier.year = date_specifier_t::year_type(amount);
+ } else {
+ specifier.day = date_specifier_t::day_type(amount);
+ }
break;
}
@@ -832,16 +754,13 @@ void date_parser_t::determine_when(date_parser_t::lexer_t::token_t& tok,
break;
}
- case lexer_t::token_t::TOK_A_YEAR:
- specifier.year = boost::get<date_specifier_t::year_type>(*tok.value);
- break;
case lexer_t::token_t::TOK_A_MONTH:
specifier.month =
date_specifier_t::month_type
(boost::get<date_time::months_of_year>(*tok.value));
tok = lexer.peek_token();
switch (tok.kind) {
- case lexer_t::token_t::TOK_A_YEAR:
+ case lexer_t::token_t::TOK_INT:
specifier.year = boost::get<date_specifier_t::year_type>(*tok.value);
break;
case lexer_t::token_t::END_REACHED:
@@ -898,12 +817,6 @@ date_interval_t date_parser_t::parse()
determine_when(tok, *inclusion_specifier);
break;
- case lexer_t::token_t::TOK_A_YEAR:
- if (! inclusion_specifier)
- inclusion_specifier = date_specifier_t();
- determine_when(tok, *inclusion_specifier);
- break;
-
case lexer_t::token_t::TOK_A_MONTH:
if (! inclusion_specifier)
inclusion_specifier = date_specifier_t();
@@ -1612,13 +1525,8 @@ date_parser_t::lexer_t::token_t date_parser_t::lexer_t::next_token()
if (! term.empty()) {
if (std::isdigit(term[0])) {
- if (term.length() == 4)
- return token_t(token_t::TOK_A_YEAR,
- token_t::content_t
- (lexical_cast<date_specifier_t::year_type>(term)));
- else
- return token_t(token_t::TOK_INT,
- token_t::content_t(lexical_cast<unsigned short>(term)));
+ return token_t(token_t::TOK_INT,
+ token_t::content_t(lexical_cast<unsigned short>(term)));
}
else if (std::isalpha(term[0])) {
to_lower(term);
diff --git a/src/token.cc b/src/token.cc
index 1ec052ed..76bf5106 100644
--- a/src/token.cc
+++ b/src/token.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -380,7 +380,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags)
break;
default: {
- istream_pos_type pos = in.tellg();
+ std::istream::pos_type pos = in.tellg();
// First, check to see if it's a reserved word, such as: and or not
int result = parse_reserved_word(in);
diff --git a/src/utils.h b/src/utils.h
index b21dff7a..c9146dd7 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -44,7 +44,11 @@
#ifndef _UTILS_H
#define _UTILS_H
+#if (BOOST_VERSION >= 106600)
+#include <boost/uuid/detail/sha1.hpp>
+#else
#include <boost/uuid/sha1.hpp>
+#endif
/**
* @name Default values
@@ -496,10 +500,6 @@ inline T& downcast(U& object) {
path resolve_path(const path& pathname);
-#ifdef HAVE_REALPATH
-extern "C" char * realpath(const char *, char resolved_path[]);
-#endif
-
inline const string& either_or(const string& first,
const string& second) {
return first.empty() ? second : first;
diff --git a/src/value.cc b/src/value.cc
index 1841505d..5ce30530 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -129,11 +129,7 @@ value_t::operator bool() const
void value_t::set_type(type_t new_type)
{
if (new_type == VOID) {
-#if BOOST_VERSION >= 103700
storage.reset();
-#else
- storage = intrusive_ptr<storage_t>();
-#endif
} else {
if (! storage || storage->refc > 1)
storage = new storage_t;
diff --git a/src/value.h b/src/value.h
index 35581bfb..e44f9354 100644
--- a/src/value.h
+++ b/src/value.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2019, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -878,22 +878,14 @@ public:
VERIFY(! is_null());
if (! is_sequence()) {
-#if BOOST_VERSION >= 103700
storage.reset();
-#else
- storage = intrusive_ptr<storage_t>();
-#endif
} else {
as_sequence_lval().pop_back();
const sequence_t& seq(as_sequence());
std::size_t new_size = seq.size();
if (new_size == 0) {
-#if BOOST_VERSION >= 103700
storage.reset();
-#else
- storage = intrusive_ptr<storage_t>();
-#endif
}
else if (new_size == 1) {
*this = seq.front();
diff --git a/src/xact.cc b/src/xact.cc
index d29072d4..10a7106a 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -395,10 +395,12 @@ bool xact_base_t::finalize()
some_null = true;
}
- if (post->has_flags(POST_DEFERRED))
- post->account->add_deferred_post(id(), post);
- else
- post->account->add_post(post);
+ if (post->has_flags(POST_DEFERRED)) {
+ if (!post->amount.is_null())
+ post->account->add_deferred_post(id(), post);
+ } else {
+ post->account->add_post(post);
+ }
post->xdata().add_flags(POST_EXT_VISITED);
post->account->xdata().add_flags(ACCOUNT_EXT_VISITED);
@@ -806,6 +808,10 @@ void auto_xact_t::extend_xact(xact_base_t& xact, parse_context_t& context)
xact.add_post(new_post);
new_post->account->add_post(new_post);
+ // Add flags so this post updates the account balance
+ new_post->xdata().add_flags(POST_EXT_VISITED);
+ new_post->account->xdata().add_flags(ACCOUNT_EXT_VISITED);
+
if (new_post->must_balance())
needs_further_verification = true;
}
diff --git a/src/xact.h b/src/xact.h
index b0a4417e..26e263fc 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -115,7 +115,7 @@ public:
virtual string description() {
if (pos) {
std::ostringstream buf;
- buf << _f("transaction at line %1") << pos->beg_line;
+ buf << _f("transaction at line %1%") % pos->beg_line;
return buf.str();
} else {
return string(_("generated transaction"));
@@ -177,7 +177,7 @@ public:
virtual string description() {
if (pos) {
std::ostringstream buf;
- buf << _f("automated transaction at line %1") << pos->beg_line;
+ buf << _f("automated transaction at line %1%") % pos->beg_line;
return buf.str();
} else {
return string(_("generated automated transaction"));
@@ -220,7 +220,7 @@ class period_xact_t : public xact_base_t
virtual string description() {
if (pos) {
std::ostringstream buf;
- buf << _f("periodic transaction at line %1") << pos->beg_line;
+ buf << _f("periodic transaction at line %1%") % pos->beg_line;
return buf.str();
} else {
return string(_("generated periodic transaction"));