diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 10 | ||||
-rw-r--r-- | src/amount.cc | 4 | ||||
-rw-r--r-- | src/annotate.cc | 4 | ||||
-rw-r--r-- | src/commodity.cc | 4 | ||||
-rw-r--r-- | src/context.h | 31 | ||||
-rw-r--r-- | src/draft.cc | 2 | ||||
-rw-r--r-- | src/error.cc | 10 | ||||
-rw-r--r-- | src/error.h | 17 | ||||
-rw-r--r-- | src/expr.cc | 14 | ||||
-rw-r--r-- | src/format.cc | 4 | ||||
-rw-r--r-- | src/global.h | 2 | ||||
-rw-r--r-- | src/item.cc | 2 | ||||
-rw-r--r-- | src/item.h | 14 | ||||
-rw-r--r-- | src/main.cc | 19 | ||||
-rw-r--r-- | src/mask.cc | 3 | ||||
-rw-r--r-- | src/op.cc | 4 | ||||
-rw-r--r-- | src/op.h | 22 | ||||
-rw-r--r-- | src/output.cc | 7 | ||||
-rw-r--r-- | src/py_post.cc | 5 | ||||
-rw-r--r-- | src/py_value.cc | 8 | ||||
-rw-r--r-- | src/pyinterp.cc | 16 | ||||
-rw-r--r-- | src/query.cc | 1 | ||||
-rw-r--r-- | src/quotes.cc | 7 | ||||
-rw-r--r-- | src/session.cc | 4 | ||||
-rw-r--r-- | src/session.h | 4 | ||||
-rw-r--r-- | src/stream.cc | 6 | ||||
-rw-r--r-- | src/strptime.cc | 7 | ||||
-rw-r--r-- | src/system.hh.in | 45 | ||||
-rw-r--r-- | src/textual.cc | 88 | ||||
-rw-r--r-- | src/times.cc | 83 | ||||
-rw-r--r-- | src/token.cc | 4 | ||||
-rw-r--r-- | src/utils.h | 10 | ||||
-rw-r--r-- | src/value.cc | 6 | ||||
-rw-r--r-- | src/value.h | 10 | ||||
-rw-r--r-- | src/xact.cc | 8 | ||||
-rw-r--r-- | src/xact.h | 6 |
36 files changed, 172 insertions, 319 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 71d9478a..9cd54dbe 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,9 +133,16 @@ 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\\+\\+") add_definitions( 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/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/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..8f8266ac 100644 --- a/src/global.h +++ b/src/global.h @@ -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/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/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/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/times.cc b/src/times.cc index eda71ae7..db0d74ff 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, 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 5df9ebc5..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 + 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); @@ -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")); |