diff options
Diffstat (limited to 'src')
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'; @@ -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; @@ -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 << " "; @@ -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; } @@ -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")); |