summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt88
-rw-r--r--src/account.cc32
-rw-r--r--src/account.h24
-rw-r--r--src/amount.cc10
-rw-r--r--src/amount.h6
-rw-r--r--src/annotate.cc8
-rw-r--r--src/annotate.h2
-rw-r--r--src/archive.cc2
-rw-r--r--src/archive.h2
-rw-r--r--src/balance.cc2
-rw-r--r--src/balance.h2
-rw-r--r--src/chain.cc2
-rw-r--r--src/chain.h2
-rw-r--r--src/commodity.cc2
-rw-r--r--src/commodity.h2
-rw-r--r--src/compare.cc2
-rw-r--r--src/compare.h2
-rw-r--r--src/context.h6
-rw-r--r--src/convert.cc4
-rw-r--r--src/convert.h2
-rw-r--r--src/csv.cc4
-rw-r--r--src/csv.h2
-rw-r--r--src/draft.cc2
-rw-r--r--src/draft.h2
-rw-r--r--src/emacs.cc156
-rw-r--r--src/emacs.h3
-rw-r--r--src/error.cc4
-rw-r--r--src/error.h2
-rw-r--r--src/expr.cc2
-rw-r--r--src/expr.h2
-rw-r--r--src/exprbase.h2
-rw-r--r--src/filters.cc18
-rw-r--r--src/filters.h2
-rw-r--r--src/flags.h2
-rw-r--r--src/format.cc15
-rw-r--r--src/format.h2
-rw-r--r--src/generate.cc2
-rw-r--r--src/generate.h2
-rw-r--r--src/global.cc10
-rw-r--r--src/global.h8
-rw-r--r--src/history.cc2
-rw-r--r--src/history.h2
-rw-r--r--src/item.cc2
-rw-r--r--src/item.h6
-rw-r--r--src/iterators.cc10
-rw-r--r--src/iterators.h2
-rw-r--r--src/journal.cc150
-rw-r--r--src/journal.h76
-rw-r--r--src/lookup.cc2
-rw-r--r--src/lookup.h2
-rw-r--r--src/main.cc2
-rw-r--r--src/mask.cc2
-rw-r--r--src/mask.h2
-rw-r--r--src/op.cc2
-rw-r--r--src/op.h2
-rw-r--r--src/option.cc2
-rw-r--r--src/option.h4
-rw-r--r--src/org.cc5
-rw-r--r--src/org.h2
-rw-r--r--src/output.cc8
-rw-r--r--src/output.h2
-rw-r--r--src/parser.cc2
-rw-r--r--src/parser.h2
-rw-r--r--src/pool.cc5
-rw-r--r--src/pool.h2
-rw-r--r--src/post.cc2
-rw-r--r--src/post.h8
-rw-r--r--src/precmd.cc2
-rw-r--r--src/precmd.h2
-rw-r--r--src/predicate.h2
-rw-r--r--src/print.cc18
-rw-r--r--src/print.h2
-rw-r--r--src/pstream.h11
-rw-r--r--src/ptree.cc7
-rw-r--r--src/ptree.h2
-rw-r--r--src/py_account.cc29
-rw-r--r--src/py_amount.cc2
-rw-r--r--src/py_balance.cc10
-rw-r--r--src/py_commodity.cc3
-rw-r--r--src/py_expr.cc2
-rw-r--r--src/py_format.cc2
-rw-r--r--src/py_item.cc2
-rw-r--r--src/py_journal.cc2
-rw-r--r--src/py_post.cc2
-rw-r--r--src/py_session.cc4
-rw-r--r--src/py_times.cc4
-rw-r--r--src/py_utils.cc2
-rw-r--r--src/py_value.cc2
-rw-r--r--src/py_xact.cc2
-rw-r--r--src/pyfstream.h2
-rw-r--r--src/pyinterp.cc9
-rw-r--r--src/pyinterp.h2
-rw-r--r--src/pyledger.cc2
-rw-r--r--src/pyutils.h2
-rw-r--r--src/query.cc2
-rw-r--r--src/query.h2
-rw-r--r--src/quotes.cc2
-rw-r--r--src/quotes.h2
-rw-r--r--src/report.cc11
-rw-r--r--src/report.h9
-rw-r--r--src/scope.cc2
-rw-r--r--src/scope.h2
-rw-r--r--src/select.cc20
-rw-r--r--src/select.h2
-rw-r--r--src/session.cc34
-rw-r--r--src/session.h8
-rw-r--r--src/stats.cc2
-rw-r--r--src/stats.h2
-rw-r--r--src/stream.cc14
-rw-r--r--src/stream.h2
-rw-r--r--src/system.hh.in11
-rw-r--r--src/temps.cc2
-rw-r--r--src/temps.h2
-rw-r--r--src/textual.cc132
-rw-r--r--src/timelog.cc2
-rw-r--r--src/timelog.h2
-rw-r--r--src/times.cc13
-rw-r--r--src/times.h6
-rw-r--r--src/token.cc5
-rw-r--r--src/token.h2
-rw-r--r--src/unistring.h14
-rw-r--r--src/utils.cc12
-rw-r--r--src/utils.h19
-rw-r--r--src/value.cc18
-rw-r--r--src/value.h2
-rw-r--r--src/views.cc2
-rw-r--r--src/views.h2
-rw-r--r--src/wcwidth.c.patch74
-rw-r--r--src/wcwidth.cc319
-rw-r--r--src/xact.cc21
-rw-r--r--src/xact.h2
131 files changed, 1248 insertions, 413 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9fd7d295..7b10061f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -49,9 +49,10 @@ set(LEDGER_SOURCES
times.cc
error.cc
utils.cc
- strptime.cc)
+ strptime.cc
+ wcwidth.cc)
-if(HAVE_BOOST_PYTHON)
+if (HAVE_BOOST_PYTHON)
list(APPEND LEDGER_SOURCES
py_account.cc
py_amount.cc
@@ -134,8 +135,8 @@ set(LEDGER_INCLUDES
strptime.h
${PROJECT_BINARY_DIR}/system.hh)
-if(CMAKE_BUILD_TYPE STREQUAL "Debug")
- if((CMAKE_CXX_COMPILER MATCHES "clang") OR (CMAKE_CXX_COMPILER MATCHES "cxx"))
+if (CMAKE_BUILD_TYPE STREQUAL "Debug")
+ if ((CMAKE_CXX_COMPILER MATCHES "clang") OR (CMAKE_CXX_COMPILER MATCHES "cxx"))
add_definitions(
-Weverything
-Wno-disabled-macro-expansion
@@ -155,7 +156,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set_source_files_properties(
${${_src_list}} PROPERTIES COMPILE_FLAGS "-include ${_header_filename}")
- if(_other_srcs)
+ if (_other_srcs)
set_source_files_properties(
${_other_srcs} PROPERTIES COMPILE_FLAGS "-include ${_header_filename}")
endif()
@@ -163,6 +164,13 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(_args ${CMAKE_CXX_FLAGS})
list(APPEND _args ${CMAKE_CXX_FLAGS_DEBUG})
+ if (BUILD_LIBRARY)
+ list(APPEND _args ${CMAKE_SHARED_LIBRARY_CXX_FLAGS})
+ endif()
+ list(APPEND _args "-std=c++11 ")
+ if (CYGWIN)
+ list(APPEND _args "-U__STRICT_ANSI__")
+ endif()
list(APPEND _args "-x c++-header " ${_inc})
list(APPEND _args -c ${_header_filename} -o ${_pch_filename})
@@ -181,7 +189,6 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
elseif(CMAKE_CXX_COMPILER MATCHES "g\\+\\+")
set(GXX_WARNING_FLAGS
- -ansi
-pedantic
-Wall
-Winvalid-pch
@@ -207,7 +214,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set_source_files_properties(
${${_src_list}} PROPERTIES COMPILE_FLAGS "-Winvalid-pch")
- if(_other_srcs)
+ if (_other_srcs)
set_source_files_properties(
${_other_srcs} PROPERTIES COMPILE_FLAGS "-Winvalid-pch")
endif()
@@ -215,7 +222,14 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(_args ${CMAKE_CXX_FLAGS})
list(APPEND _args ${CMAKE_CXX_FLAGS_DEBUG})
+ if (BUILD_LIBRARY)
+ list(APPEND _args ${CMAKE_SHARED_LIBRARY_CXX_FLAGS})
+ endif()
list(APPEND _args ${GXX_WARNING_FLAGS})
+ list(APPEND _args "-std=c++11 ")
+ if (CYGWIN)
+ list(APPEND _args "-U__STRICT_ANSI__")
+ endif()
list(APPEND _args "-x c++-header " ${_inc})
list(APPEND _args -c ${_header_filename} -o ${_gch_filename})
@@ -243,21 +257,63 @@ endif()
add_pch_rule(${PROJECT_BINARY_DIR}/system.hh LEDGER_SOURCES main.cc global.cc)
-if(BUILD_LIBRARY)
- add_library(libledger ${LEDGER_SOURCES} ${PROJECT_SOURCE_DIR}/lib/sha1.cpp)
- set_target_properties(libledger PROPERTIES OUTPUT_NAME ledger)
+include(GNUInstallDirs)
+
+if (BUILD_LIBRARY)
+ set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
+ add_library(libledger SHARED ${LEDGER_SOURCES})
+ add_ledger_library_dependencies(libledger)
+ set_target_properties(libledger PROPERTIES
+ PREFIX ""
+ INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
+ VERSION ${Ledger_VERSION_MAJOR}
+ SOVERSION ${Ledger_VERSION_MAJOR})
add_executable(ledger main.cc global.cc)
+ target_link_libraries(ledger libledger)
- install(TARGETS libledger DESTINATION lib)
- install(FILES ${LEDGER_INCLUDES} DESTINATION include/ledger)
+ install(TARGETS libledger DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ install(FILES ${LEDGER_INCLUDES}
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ledger)
else()
- add_executable(ledger
- ${LEDGER_SOURCES} ${PROJECT_SOURCE_DIR}/lib/sha1.cpp main.cc global.cc)
+ add_executable(ledger ${LEDGER_SOURCES} main.cc global.cc)
+ add_ledger_library_dependencies(ledger)
endif()
-add_ledger_library_dependencies(ledger)
+if (USE_PYTHON)
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c
+ "from __future__ import print_function
+import distutils.sysconfig as s
+print(s.get_python_lib(True, prefix=''))"
+ OUTPUT_VARIABLE _TMP_PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
+ set(PYTHON_SITE_PACKAGES ${_TMP_PYTHON_SITE_PACKAGES}
+ CACHE PATH "python module directory (${_TMP_PYTHON_SITE_PACKAGES})")
+
+ if (PYTHON_SITE_PACKAGES)
+ if (WIN32 AND NOT CYGWIN)
+ set(_ledger_python_module_name "ledger.pyd")
+ elseif(CMAKE_HOST_APPLE)
+ set(_ledger_python_module_name "ledger.so")
+ else()
+ set(_ledger_python_module_name "ledger${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ endif()
+
+ # FIXME: symlink would be sufficient:
+ # maybe using install(CODE "...") and
+ # execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink ...).
+ # Windows will need a special case due to not supporting symlinks.
+ add_custom_command(
+ TARGET libledger POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ $<TARGET_FILE:libledger> "${CMAKE_BINARY_DIR}/${_ledger_python_module_name}")
+ install(
+ FILES "${CMAKE_BINARY_DIR}/${_ledger_python_module_name}"
+ DESTINATION ${PYTHON_SITE_PACKAGES})
+ else()
+ message(WARNING "PYTHON_SITE_PACKAGES not set. Will not install python module.")
+ endif()
+endif()
-install(TARGETS ledger DESTINATION bin)
+install(TARGETS ledger DESTINATION ${CMAKE_INSTALL_BINDIR})
### CMakeLists.txt ends here
diff --git a/src/account.cc b/src/account.cc
index 58812db9..358aa09a 100644
--- a/src/account.cc
+++ b/src/account.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -139,6 +139,36 @@ void account_t::add_post(post_t * post)
}
}
+void account_t::add_deferred_post(const string& uuid, post_t * post)
+{
+ if (! deferred_posts)
+ deferred_posts = deferred_posts_map_t();
+
+ deferred_posts_map_t::iterator i = deferred_posts->find(uuid);
+ if (i == deferred_posts->end()) {
+ posts_list lst;
+ lst.push_back(post);
+ deferred_posts->insert(deferred_posts_map_t::value_type(uuid, lst));
+ } else {
+ (*i).second.push_back(post);
+ }
+}
+
+void account_t::apply_deferred_posts()
+{
+ if (deferred_posts) {
+ foreach (deferred_posts_map_t::value_type& pair, *deferred_posts) {
+ foreach (post_t * post, pair.second)
+ post->account->add_post(post);
+ }
+ deferred_posts = none;
+ }
+
+ // Also apply in child accounts
+ foreach (const accounts_map::value_type& pair, accounts)
+ pair.second->apply_deferred_posts();
+}
+
bool account_t::remove_post(post_t * post)
{
// It's possible that 'post' wasn't yet in this account, but try to
diff --git a/src/account.h b/src/account.h
index b726facf..76e839eb 100644
--- a/src/account.h
+++ b/src/account.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -52,6 +52,7 @@ class post_t;
typedef std::list<post_t *> posts_list;
typedef std::map<string, account_t *> accounts_map;
+typedef std::map<string, posts_list> deferred_posts_map_t;
class account_t : public supports_flags<>, public scope_t
{
@@ -61,13 +62,14 @@ class account_t : public supports_flags<>, public scope_t
#define ACCOUNT_GENERATED 0x04 // account never actually existed
public:
- account_t * parent;
- string name;
- optional<string> note;
- unsigned short depth;
- accounts_map accounts;
- posts_list posts;
- optional<expr_t> value_expr;
+ account_t * parent;
+ string name;
+ optional<string> note;
+ unsigned short depth;
+ accounts_map accounts;
+ posts_list posts;
+ optional<deferred_posts_map_t> deferred_posts;
+ optional<expr_t> value_expr;
mutable string _fullname;
#if DOCUMENT_MODEL
@@ -136,6 +138,8 @@ public:
}
void add_post(post_t * post);
+ void add_deferred_post(const string& uuid, post_t * post);
+ void apply_deferred_posts();
bool remove_post(post_t * post);
posts_list::iterator posts_begin() {
@@ -257,7 +261,11 @@ public:
mutable optional<xdata_t> xdata_;
bool has_xdata() const {
+#if BOOST_VERSION >= 105600
+ return xdata_ != NULL;
+#else
return xdata_;
+#endif
}
void clear_xdata();
xdata_t& xdata() {
diff --git a/src/amount.cc b/src/amount.cc
index 6ff2f4dd..6ddcdb4f 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -301,7 +301,7 @@ void amount_t::_copy(const amount_t& amt)
quantity = new bigint_t(*amt.quantity);
} else {
quantity = amt.quantity;
- DEBUG("amounts.refs",
+ DEBUG("amount.refs",
quantity << " refc++, now " << (quantity->refc + 1));
quantity->refc++;
}
@@ -339,7 +339,7 @@ void amount_t::_release()
{
VERIFY(valid());
- DEBUG("amounts.refs", quantity << " refc--, now " << (quantity->refc - 1));
+ DEBUG("amount.refs", quantity << " refc--, now " << (quantity->refc - 1));
if (--quantity->refc == 0) {
if (quantity->has_flags(BIGINT_BULK_ALLOC))
@@ -928,7 +928,7 @@ void amount_t::annotate(const annotation_t& details)
}
assert(this_base);
- DEBUG("amounts.commodities", "Annotating commodity for amount "
+ DEBUG("amount.commodities", "Annotating commodity for amount "
<< *this << std::endl << details);
if (commodity_t * ann_comm =
@@ -939,7 +939,7 @@ void amount_t::annotate(const annotation_t& details)
assert(false);
#endif
- DEBUG("amounts.commodities", "Annotated amount is " << *this);
+ DEBUG("amount.commodities", "Annotated amount is " << *this);
}
bool amount_t::has_annotation() const
diff --git a/src/amount.h b/src/amount.h
index 938d4b7b..ea5cadd6 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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 met:
+ * modification, are permitted provided that the following conditions are
+ * met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
diff --git a/src/annotate.cc b/src/annotate.cc
index 8816a89c..7c54edef 100644
--- a/src/annotate.cc
+++ b/src/annotate.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -187,8 +187,8 @@ void annotation_t::parse(std::istream& in)
} while (true);
#if DEBUG_ON
- if (SHOW_DEBUG("amounts.commodities") && *this) {
- DEBUG("amounts.commodities",
+ if (SHOW_DEBUG("amount.commodities") && *this) {
+ DEBUG("amount.commodities",
"Parsed commodity annotations: " << std::endl << *this);
}
#endif
@@ -206,7 +206,7 @@ void annotation_t::print(std::ostream& out, bool keep_base,
if (date &&
(! no_computed_annotations || ! has_flags(ANNOTATION_DATE_CALCULATED)))
- out << " [" << format_date(*date, FMT_WRITTEN) << ']';
+ out << " [" << format_date(*date, FMT_PRINTED) << ']';
if (tag &&
(! no_computed_annotations || ! has_flags(ANNOTATION_TAG_CALCULATED)))
diff --git a/src/annotate.h b/src/annotate.h
index 998f7c83..c0fbcd3d 100644
--- a/src/annotate.h
+++ b/src/annotate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/archive.cc b/src/archive.cc
index 6ac1c580..9ae04e85 100644
--- a/src/archive.cc
+++ b/src/archive.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/archive.h b/src/archive.h
index 5c15a9fb..485f9606 100644
--- a/src/archive.h
+++ b/src/archive.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/balance.cc b/src/balance.cc
index b702cb7b..36eab7d4 100644
--- a/src/balance.cc
+++ b/src/balance.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/balance.h b/src/balance.h
index a1ae51ef..752bb4d6 100644
--- a/src/balance.h
+++ b/src/balance.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/chain.cc b/src/chain.cc
index b2f6f203..42f474c4 100644
--- a/src/chain.cc
+++ b/src/chain.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/chain.h b/src/chain.h
index de7f68c7..224bed21 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/commodity.cc b/src/commodity.cc
index 535b31c9..398245fb 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/commodity.h b/src/commodity.h
index d521d80e..3d1ddf04 100644
--- a/src/commodity.h
+++ b/src/commodity.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/compare.cc b/src/compare.cc
index 946cd835..db169cfc 100644
--- a/src/compare.cc
+++ b/src/compare.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/compare.h b/src/compare.h
index 4a91f49f..554e84aa 100644
--- a/src/compare.h
+++ b/src/compare.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/context.h b/src/context.h
index e5457641..e787f335 100644
--- a/src/context.h
+++ b/src/context.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -101,10 +101,10 @@ public:
}
void warning(const string& what) const {
- warning_func(location() + what);
+ warning_func(location() + " " + what);
}
void warning(const boost::format& what) const {
- warning_func(location() + string(what.str()));
+ warning_func(location() + " " + string(what.str()));
}
};
diff --git a/src/convert.cc b/src/convert.cc
index 38ef2c22..a4454c14 100644
--- a/src/convert.cc
+++ b/src/convert.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -86,7 +86,7 @@ value_t convert_command(call_scope_t& args)
if (entry != journal.checksum_map.end()) {
INFO(file_context(reader.get_pathname(),
reader.get_linenum())
- << "Ignoring known UUID " << ref);
+ << " " << "Ignoring known UUID " << ref);
checked_delete(xact); // ignore it
continue;
}
diff --git a/src/convert.h b/src/convert.h
index 17fb4505..020dfea2 100644
--- a/src/convert.h
+++ b/src/convert.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/csv.cc b/src/csv.cc
index 2a3eb080..b0a54f4e 100644
--- a/src/csv.cc
+++ b/src/csv.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -186,7 +186,7 @@ xact_t * csv_reader::read_xact(bool rich_data)
case FIELD_PAYEE: {
bool found = false;
- foreach (payee_mapping_t& value, context.journal->payee_mappings) {
+ foreach (payee_alias_mapping_t& value, context.journal->payee_alias_mappings) {
DEBUG("csv.mappings", "Looking for payee mapping: " << value.first);
if (value.first.match(field)) {
xact->payee = value.second;
diff --git a/src/csv.h b/src/csv.h
index 94f7a328..cda15ea3 100644
--- a/src/csv.h
+++ b/src/csv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/draft.cc b/src/draft.cc
index 6aef2f12..78e53ccd 100644
--- a/src/draft.cc
+++ b/src/draft.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/draft.h b/src/draft.h
index 1cc362ba..7ba40640 100644
--- a/src/draft.h
+++ b/src/draft.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/emacs.cc b/src/emacs.cc
index 9bfd1e4b..dc16c002 100644
--- a/src/emacs.cc
+++ b/src/emacs.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -30,7 +30,7 @@
*/
#include <system.hh>
-
+#include <boost/algorithm/string.hpp>
#include "emacs.h"
#include "xact.h"
#include "post.h"
@@ -38,78 +38,84 @@
namespace ledger {
-void format_emacs_posts::write_xact(xact_t& xact)
-{
- if (xact.pos)
- out << "\"" << xact.pos->pathname.string() << "\" "
- << xact.pos->beg_line << " ";
- else
- out << "\"\" " << -1 << " ";
-
- tm when = gregorian::to_tm(xact.date());
- std::time_t date = std::mktime(&when);
-
- out << "(" << (date / 65536) << " " << (date % 65536) << " 0) ";
-
- if (xact.code)
- out << "\"" << *xact.code << "\" ";
- else
- out << "nil ";
-
- if (xact.payee.empty())
- out << "nil";
- else
- out << "\"" << xact.payee << "\"";
-
- out << "\n";
-}
-
-void format_emacs_posts::operator()(post_t& post)
-{
- if (! post.has_xdata() ||
- ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
- if (! last_xact) {
- out << "((";
- write_xact(*post.xact);
- }
- else if (post.xact != last_xact) {
- out << ")\n (";
- write_xact(*post.xact);
- }
- else {
- out << "\n";
- }
-
- if (post.pos)
- out << " (" << post.pos->beg_line << " ";
- else
- out << " (" << -1 << " ";
-
- out << "\"" << post.reported_account()->fullname() << "\" \""
- << post.amount << "\"";
-
- switch (post.state()) {
- case item_t::UNCLEARED:
- out << " nil";
- break;
- case item_t::CLEARED:
- out << " t";
- break;
- case item_t::PENDING:
- out << " pending";
- break;
- }
-
- if (post.cost)
- out << " \"" << *post.cost << "\"";
- if (post.note)
- out << " \"" << *post.note << "\"";
- out << ")";
-
- last_xact = post.xact;
-
- post.xdata().add_flags(POST_EXT_DISPLAYED);
- }
-}
+ void format_emacs_posts::write_xact(xact_t& xact)
+ {
+ if (xact.pos)
+ out << "\"" << xact.pos->pathname.string() << "\" "
+ << xact.pos->beg_line << " ";
+ else
+ out << "\"\" " << -1 << " ";
+
+ tm when = gregorian::to_tm(xact.date());
+ std::time_t date = std::mktime(&when);
+
+ out << "(" << (date / 65536) << " " << (date % 65536) << " 0) ";
+
+ if (xact.code)
+ out << "\"" << *xact.code << "\" ";
+ else
+ out << "nil ";
+
+ if (xact.payee.empty())
+ out << "nil";
+ else
+ out << "\"" << xact.payee << "\"";
+
+ out << "\n";
+ }
+
+ void format_emacs_posts::operator()(post_t& post)
+ {
+ if (! post.has_xdata() ||
+ ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
+ if (! last_xact) {
+ out << "((";
+ write_xact(*post.xact);
+ }
+ else if (post.xact != last_xact) {
+ out << ")\n (";
+ write_xact(*post.xact);
+ }
+ else {
+ out << "\n";
+ }
+
+ if (post.pos)
+ out << " (" << post.pos->beg_line << " ";
+ else
+ out << " (" << -1 << " ";
+
+ out << "\"" << post.reported_account()->fullname() << "\" \""
+ << post.amount << "\"";
+
+ switch (post.state()) {
+ case item_t::UNCLEARED:
+ out << " nil";
+ break;
+ case item_t::CLEARED:
+ out << " t";
+ break;
+ case item_t::PENDING:
+ out << " pending";
+ break;
+ }
+
+ if (post.cost)
+ out << " \"" << *post.cost << "\"";
+ if (post.note)
+ out << " \"" << escape_string(*post.note) << "\"";
+ out << ")";
+
+ last_xact = post.xact;
+
+ post.xdata().add_flags(POST_EXT_DISPLAYED);
+ }
+ }
+
+ string format_emacs_posts::escape_string(string raw){
+ replace_all(raw, "\\", "\\\\");
+ replace_all(raw, "\"", "\\\"");
+ return raw;
+ }
} // namespace ledger
diff --git a/src/emacs.h b/src/emacs.h
index 368c4c4d..fef7a882 100644
--- a/src/emacs.h
+++ b/src/emacs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -72,6 +72,7 @@ public:
out.flush();
}
virtual void operator()(post_t& post);
+ virtual string escape_string(string raw);
};
} // namespace ledger
diff --git a/src/error.cc b/src/error.cc
index acee85c9..90697c5f 100644
--- a/src/error.cc
+++ b/src/error.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -49,7 +49,7 @@ string error_context()
string file_context(const path& file, const std::size_t line)
{
std::ostringstream buf;
- buf << '"' << file.string() << "\", line " << line << ": ";
+ buf << '"' << file.string() << "\", line " << line << ":";
return buf.str();
}
diff --git a/src/error.h b/src/error.h
index 93d92109..31fa76a3 100644
--- a/src/error.h
+++ b/src/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/expr.cc b/src/expr.cc
index aa1e07d2..e38d794f 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/expr.h b/src/expr.h
index a5119c0b..384cc661 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/exprbase.h b/src/exprbase.h
index 88d6f118..b88fcd7d 100644
--- a/src/exprbase.h
+++ b/src/exprbase.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/filters.cc b/src/filters.cc
index 2b4fe1bf..fd30c966 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -237,7 +237,7 @@ void anonymize_posts::render_commodity(amount_t& amt)
void anonymize_posts::operator()(post_t& post)
{
- SHA1 sha;
+ boost::uuids::detail::sha1 sha;
unsigned int message_digest[5];
bool copy_xact_details = false;
@@ -256,9 +256,9 @@ void anonymize_posts::operator()(post_t& post)
buf << reinterpret_cast<uintmax_t>(post.xact->payee.c_str())
<< integer_gen() << post.xact->payee.c_str();
- sha.Reset();
- sha << buf.str().c_str();
- sha.Result(message_digest);
+ sha.reset();
+ sha.process_bytes(buf.str().c_str(), buf.str().length());
+ sha.get_digest(message_digest);
xact.payee = to_hex(message_digest);
xact.note = none;
@@ -274,9 +274,9 @@ void anonymize_posts::operator()(post_t& post)
std::ostringstream buf;
buf << integer_gen() << acct << acct->fullname();
- sha.Reset();
- sha << buf.str().c_str();
- sha.Result(message_digest);
+ sha.reset();
+ sha.process_bytes(buf.str().c_str(), buf.str().length());
+ sha.get_digest(message_digest);
account_names.push_front(to_hex(message_digest));
}
@@ -1002,7 +1002,7 @@ void interval_posts::flush()
sort_posts_by_date());
// Determine the beginning interval by using the earliest post
- if (all_posts.front() &&
+ if (all_posts.size() > 0 && all_posts.front() &&
! interval.find_period(all_posts.front()->date()))
throw_(std::logic_error, _("Failed to find period for interval report"));
diff --git a/src/filters.h b/src/filters.h
index d6e1b6fc..9b745235 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/flags.h b/src/flags.h
index d584e2d0..f3593517 100644
--- a/src/flags.h
+++ b/src/flags.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/format.cc b/src/format.cc
index e0f74616..2887a387 100644
--- a/src/format.cc
+++ b/src/format.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -74,17 +74,18 @@ namespace {
char letter;
const char * expr;
} single_letter_mappings[] = {
- { 'd', "date" },
+ { 'd', "aux_date ? format_date(date) + \"=\" + format_date(aux_date) : format_date(date)" },
+ { 'D', "date" },
{ 'S', "filename" },
{ 'B', "beg_pos" },
{ 'b', "beg_line" },
{ 'E', "end_pos" },
{ 'e', "end_line" },
- { 'X', "cleared" },
- { 'Y', "xact.cleared" },
- { 'C', "code" },
+ { 'X', "\"* \" if cleared" },
+ { 'Y', "\"* \" if xact.cleared" },
+ { 'C', "\"(\" + code + \") \" if code" },
{ 'P', "payee" },
- { 'a', "account.name" },
+ { 'a', "account" },
{ 'A', "account" },
{ 't', "justify(scrub(display_amount), $min, $max, $left, color)" },
{ 'T', "justify(scrub(display_total), $min, $max, $left, color)" },
@@ -206,7 +207,7 @@ format_t::element_t * format_t::parse_elements(const string& fmt,
sizeof(format_mapping_t)); i++) {
if (*p == single_letter_mappings[i].letter) {
std::ostringstream expr;
- for (const char * ptr = single_letter_mappings[i].expr; *ptr; ){
+ for (const char * ptr = single_letter_mappings[i].expr; *ptr;) {
if (*ptr == '$') {
const char * beg = ++ptr;
while (*ptr && std::isalpha(*ptr))
diff --git a/src/format.h b/src/format.h
index 38f567bd..6ac4075e 100644
--- a/src/format.h
+++ b/src/format.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/generate.cc b/src/generate.cc
index 5bf424bb..6503f414 100644
--- a/src/generate.cc
+++ b/src/generate.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/generate.h b/src/generate.h
index 697feb64..b17116fa 100644
--- a/src/generate.h
+++ b/src/generate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/global.cc b/src/global.cc
index 0061ad76..602e216c 100644
--- a/src/global.cc
+++ b/src/global.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -142,13 +142,13 @@ void global_scope_t::read_init()
throw_(parse_error, _f("Could not find specified init file %1%") % init_file);
}
} else {
- if (const char * home_var = std::getenv("HOME")){
+ if (const char * home_var = std::getenv("HOME")) {
init_file = (path(home_var) / ".ledgerrc");
} else {
init_file = ("./.ledgerrc");
}
}
- if(exists(init_file)){
+ if (exists(init_file)) {
parse_init(init_file);
}
}
@@ -388,7 +388,7 @@ void global_scope_t::read_environment_settings(char * envp[])
process_environment(const_cast<const char **>(envp), "LEDGER_", report());
#if 1
- // These are here for backwards compatability, but are deprecated.
+ // These are here for backwards compatibility, but are deprecated.
if (const char * p = std::getenv("LEDGER")) {
if (! std::getenv("LEDGER_FILE"))
@@ -514,7 +514,7 @@ void handle_debug_options(int argc, char * argv[])
#if TRACING_ON
_log_level = LOG_TRACE;
try {
- _trace_level = boost::lexical_cast<uint8_t>(argv[i + 1]);
+ _trace_level = boost::lexical_cast<uint16_t>(argv[i + 1]);
}
catch (const boost::bad_lexical_cast&) {
throw std::logic_error(_("Argument to --trace must be an integer"));
diff --git a/src/global.h b/src/global.h
index 5fa67d2c..f36dbe3d 100644
--- a/src/global.h
+++ b/src/global.h
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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 met:
+ * modification, are permitted provided that the following conditions are
+ * met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
@@ -127,7 +127,7 @@ public:
out << '-' << Ledger_VERSION_DATE;
out << _(", the command-line accounting tool");
out <<
- _("\n\nCopyright (c) 2003-2013, John Wiegley. All rights reserved.\n\n\
+ _("\n\nCopyright (c) 2003-2015, 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;
diff --git a/src/history.cc b/src/history.cc
index 93883ae0..e3c459f3 100644
--- a/src/history.cc
+++ b/src/history.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/history.h b/src/history.h
index fa69d8da..dd776383 100644
--- a/src/history.h
+++ b/src/history.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/item.cc b/src/item.cc
index a29a3fd3..9effcd23 100644
--- a/src/item.cc
+++ b/src/item.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/item.h b/src/item.h
index b0670ac5..458cb378 100644
--- a/src/item.h
+++ b/src/item.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -191,7 +191,11 @@ public:
static bool use_aux_date;
virtual bool has_date() const {
+#if BOOST_VERSION >= 105600
+ return _date != NULL;
+#else
return _date;
+#endif
}
virtual date_t date() const {
diff --git a/src/iterators.cc b/src/iterators.cc
index 738f33be..21bec5d9 100644
--- a/src/iterators.cc
+++ b/src/iterators.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -204,9 +204,9 @@ void sorted_accounts_iterator::push_back(account_t& account)
compare_items<account_t>(sort_cmp));
#if DEBUG_ON
- if (SHOW_DEBUG("accounts.sorted")) {
+ if (SHOW_DEBUG("account.sorted")) {
foreach (account_t * acct, accounts_list.back())
- DEBUG("accounts.sorted",
+ DEBUG("account.sorted",
"Account (flat): " << acct->fullname());
}
#endif
@@ -237,9 +237,9 @@ void sorted_accounts_iterator::sort_accounts(account_t& account,
compare_items<account_t>(sort_cmp));
#if DEBUG_ON
- if (SHOW_DEBUG("accounts.sorted")) {
+ if (SHOW_DEBUG("account.sorted")) {
foreach (account_t * acct, deque)
- DEBUG("accounts.sorted", "Account: " << acct->fullname());
+ DEBUG("account.sorted", "Account: " << acct->fullname());
}
#endif
}
diff --git a/src/iterators.h b/src/iterators.h
index 3ece313c..86eb86ca 100644
--- a/src/iterators.h
+++ b/src/iterators.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/journal.cc b/src/journal.cc
index 7eeaabe8..ae545477 100644
--- a/src/journal.cc
+++ b/src/journal.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -95,7 +95,9 @@ void journal_t::initialize()
force_checking = false;
check_payees = false;
day_break = false;
- checking_style = CHECK_PERMISSIVE;
+ checking_style = CHECK_NORMAL;
+ recursive_aliases = false;
+ no_aliases = false;
}
void journal_t::add_account(account_t * acct)
@@ -121,26 +123,9 @@ account_t * journal_t::find_account_re(const string& regexp)
account_t * journal_t::register_account(const string& name, post_t * post,
account_t * master_account)
{
- account_t * result = NULL;
-
- // If there any account aliases, substitute before creating an account
+ // If there are any account aliases, substitute before creating an account
// object.
- if (account_aliases.size() > 0) {
- accounts_map::const_iterator i = account_aliases.find(name);
- if (i != account_aliases.end()) {
- result = (*i).second;
- } else {
- // only check the very first account for alias expansion, in case
- // that can be expanded successfully
- size_t colon = name.find(':');
- if(colon != string::npos) {
- accounts_map::const_iterator j = account_aliases.find(name.substr(0, colon));
- if (j != account_aliases.end()) {
- result = find_account((*j).second->fullname() + name.substr(colon));
- }
- }
- }
- }
+ account_t * result = expand_aliases(name);
// Create the account object and associate it with the journal; this
// is registering the account.
@@ -178,7 +163,63 @@ account_t * journal_t::register_account(const string& name, post_t * post,
}
}
}
+ return result;
+}
+
+account_t * journal_t::expand_aliases(string name) {
+ // Aliases are expanded recursively, so if both alias Foo=Bar:Foo and
+ // alias Bar=Baaz:Bar are in effect, first Foo will be expanded to Bar:Foo,
+ // then Bar:Foo will be expanded to Baaz:Bar:Foo.
+ // The expansion loop keeps a list of already expanded names in order to
+ // prevent infinite excursion. Each alias may only be expanded at most once.
+ account_t * result = NULL;
+ if (no_aliases)
+ return result;
+
+ bool keep_expanding = true;
+ std::list<string> already_seen;
+ // loop until no expansion can be found
+ do {
+ if (account_aliases.size() > 0) {
+ accounts_map::const_iterator i = account_aliases.find(name);
+ if (i != account_aliases.end()) {
+ if (std::find(already_seen.begin(), already_seen.end(), name) != already_seen.end()) {
+ throw_(std::runtime_error,
+ _f("Infinite recursion on alias expansion for %1%")
+ % name);
+ }
+ // there is an alias for the full account name, including colons
+ already_seen.push_back(name);
+ result = (*i).second;
+ name = result->fullname();
+ } else {
+ // only check the very first account for alias expansion, in case
+ // that can be expanded successfully
+ size_t colon = name.find(':');
+ if (colon != string::npos) {
+ string first_account_name = name.substr(0, colon);
+ accounts_map::const_iterator j = account_aliases.find(first_account_name);
+ if (j != account_aliases.end()) {
+ if (std::find(already_seen.begin(), already_seen.end(), first_account_name) != already_seen.end()) {
+ throw_(std::runtime_error,
+ _f("Infinite recursion on alias expansion for %1%")
+ % first_account_name);
+ }
+ already_seen.push_back(first_account_name);
+ result = find_account((*j).second->fullname() + name.substr(colon));
+ name = result->fullname();
+ } else {
+ keep_expanding = false;
+ }
+ } else {
+ keep_expanding = false;
+ }
+ }
+ } else {
+ keep_expanding = false;
+ }
+ } while(keep_expanding && recursive_aliases);
return result;
}
@@ -208,7 +249,7 @@ string journal_t::register_payee(const string& name, xact_t * xact)
}
}
- foreach (payee_mapping_t& value, payee_mappings) {
+ foreach (payee_alias_mapping_t& value, payee_alias_mappings) {
if (value.first.match(name)) {
payee = value.second;
break;
@@ -323,6 +364,21 @@ namespace {
}
}
+bool lt_posting_account(post_t * left, post_t * right) {
+ return left->account < right->account;
+}
+
+bool is_equivalent_posting(post_t * left, post_t * right)
+{
+ if (left->account != right->account)
+ return false;
+
+ if (left->amount != right->amount)
+ return false;
+
+ return true;
+}
+
bool journal_t::add_xact(xact_t * xact)
{
xact->journal = this;
@@ -345,12 +401,54 @@ bool journal_t::add_xact(xact_t * xact)
// will have been performed by extend_xact, so asserts can still be
// applied to it.
if (optional<value_t> ref = xact->get_tag(_("UUID"))) {
+ std::string uuid = ref->to_string();
std::pair<checksum_map_t::iterator, bool> result
- = checksum_map.insert(checksum_map_t::value_type(ref->to_string(), xact));
+ = checksum_map.insert(checksum_map_t::value_type(uuid, xact));
if (! result.second) {
- // jww (2012-02-27): Confirm that the xact in
- // (*result.first).second is exact match in its significant
- // details to xact.
+ // This UUID has been seen before; apply any postings which the
+ // earlier version may have deferred.
+ foreach (post_t * post, xact->posts) {
+ account_t * acct = post->account;
+ if (acct->deferred_posts) {
+ auto i = acct->deferred_posts->find(uuid);
+ if (i != acct->deferred_posts->end()) {
+ for (post_t * rpost : (*i).second)
+ if (acct == rpost->account)
+ acct->add_post(rpost);
+ acct->deferred_posts->erase(i);
+ }
+ }
+ }
+
+ xact_t * other = (*result.first).second;
+
+ // Copy the two lists of postings (which should be relatively
+ // short), and make sure that the intersection is the empty set
+ // (i.e., that they are the same list).
+ std::vector<post_t *> this_posts(xact->posts.begin(),
+ xact->posts.end());
+ std::sort(this_posts.begin(), this_posts.end(),
+ lt_posting_account);
+ std::vector<post_t *> other_posts(other->posts.begin(),
+ other->posts.end());
+ std::sort(other_posts.begin(), other_posts.end(),
+ lt_posting_account);
+ bool match = std::equal(this_posts.begin(), this_posts.end(),
+ other_posts.begin(), is_equivalent_posting);
+
+ if (! match || this_posts.size() != other_posts.size()) {
+ add_error_context(_("While comparing this previously seen transaction:"));
+ add_error_context(source_context(other->pos->pathname,
+ other->pos->beg_pos,
+ other->pos->end_pos, "> "));
+ add_error_context(_("to this later transaction:"));
+ add_error_context(source_context(xact->pos->pathname,
+ xact->pos->beg_pos,
+ xact->pos->end_pos, "> "));
+ throw_(std::runtime_error,
+ _f("Transactions with the same UUID must have equivalent postings"));
+ }
+
xact->journal = NULL;
return false;
}
diff --git a/src/journal.h b/src/journal.h
index 716e2910..613b2b96 100644
--- a/src/journal.h
+++ b/src/journal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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,15 +58,17 @@ class account_t;
class parse_context_t;
class parse_context_stack_t;
-typedef std::list<xact_t *> xacts_list;
-typedef std::list<auto_xact_t *> auto_xacts_list;
-typedef std::list<period_xact_t *> period_xacts_list;
-typedef std::pair<mask_t, string> payee_mapping_t;
-typedef std::list<payee_mapping_t> payee_mappings_t;
-typedef std::pair<mask_t, account_t *> account_mapping_t;
-typedef std::list<account_mapping_t> account_mappings_t;
-typedef std::map<string, account_t *> accounts_map;
-typedef std::map<string, xact_t *> checksum_map_t;
+typedef std::list<xact_t *> xacts_list;
+typedef std::list<auto_xact_t *> auto_xacts_list;
+typedef std::list<period_xact_t *> period_xacts_list;
+typedef std::pair<mask_t, string> payee_alias_mapping_t;
+typedef std::list<payee_alias_mapping_t> payee_alias_mappings_t;
+typedef std::pair<string, string> payee_uuid_mapping_t;
+typedef std::list<payee_uuid_mapping_t> payee_uuid_mappings_t;
+typedef std::pair<mask_t, account_t *> account_mapping_t;
+typedef std::list<account_mapping_t> account_mappings_t;
+typedef std::map<string, account_t *> accounts_map;
+typedef std::map<string, xact_t *> checksum_map_t;
typedef std::multimap<string, expr_t::check_expr_pair> tag_check_exprs_map;
@@ -115,33 +117,37 @@ public:
#endif // HAVE_BOOST_SERIALIZATION
};
- account_t * master;
- account_t * bucket;
- xacts_list xacts;
- auto_xacts_list auto_xacts;
- period_xacts_list period_xacts;
- std::list<fileinfo_t> sources;
- std::set<string> known_payees;
- std::set<string> known_tags;
- bool fixed_accounts;
- bool fixed_payees;
- bool fixed_commodities;
- bool fixed_metadata;
- bool was_loaded;
- bool force_checking;
- bool check_payees;
- bool day_break;
- payee_mappings_t payee_mappings;
- account_mappings_t account_mappings;
- accounts_map account_aliases;
- account_mappings_t payees_for_unknown_accounts;
- checksum_map_t checksum_map;
- tag_check_exprs_map tag_check_exprs;
- optional<expr_t> value_expr;
- parse_context_t * current_context;
+ account_t * master;
+ account_t * bucket;
+ xacts_list xacts;
+ auto_xacts_list auto_xacts;
+ period_xacts_list period_xacts;
+ std::list<fileinfo_t> sources;
+ std::set<string> known_payees;
+ std::set<string> known_tags;
+ bool fixed_accounts;
+ bool fixed_payees;
+ bool fixed_commodities;
+ bool fixed_metadata;
+ bool was_loaded;
+ bool force_checking;
+ bool check_payees;
+ bool day_break;
+ bool recursive_aliases;
+ bool no_aliases;
+ payee_alias_mappings_t payee_alias_mappings;
+ payee_uuid_mappings_t payee_uuid_mappings;
+ account_mappings_t account_mappings;
+ accounts_map account_aliases;
+ account_mappings_t payees_for_unknown_accounts;
+ checksum_map_t checksum_map;
+ tag_check_exprs_map tag_check_exprs;
+ optional<expr_t> value_expr;
+ parse_context_t * current_context;
enum checking_style_t {
CHECK_PERMISSIVE,
+ CHECK_NORMAL,
CHECK_WARNING,
CHECK_ERROR
} checking_style;
@@ -167,6 +173,8 @@ public:
account_t * find_account(const string& name, bool auto_create = true);
account_t * find_account_re(const string& regexp);
+ account_t * expand_aliases(string name);
+
account_t * register_account(const string& name, post_t * post,
account_t * master = NULL);
string register_payee(const string& name, xact_t * xact);
diff --git a/src/lookup.cc b/src/lookup.cc
index 2a602569..6dbeb502 100644
--- a/src/lookup.cc
+++ b/src/lookup.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/lookup.h b/src/lookup.h
index ee80faac..fc7063ec 100644
--- a/src/lookup.h
+++ b/src/lookup.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/main.cc b/src/main.cc
index accae197..c26a280a 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/mask.cc b/src/mask.cc
index 56ef02d1..29b53781 100644
--- a/src/mask.cc
+++ b/src/mask.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/mask.h b/src/mask.h
index 877a0011..2b579768 100644
--- a/src/mask.h
+++ b/src/mask.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/op.cc b/src/op.cc
index 15306f02..ff707a14 100644
--- a/src/op.cc
+++ b/src/op.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/op.h b/src/op.h
index bebfcbbd..c45ffb08 100644
--- a/src/op.h
+++ b/src/op.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/option.cc b/src/option.cc
index 256ee45b..8c003e08 100644
--- a/src/option.cc
+++ b/src/option.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/option.h b/src/option.h
index fe3e257b..4646121d 100644
--- a/src/option.h
+++ b/src/option.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -229,7 +229,7 @@ public:
inline bool is_eq(const char * p, const char * n) {
// Test whether p matches n, substituting - in p for _ in n.
for (; *p && *n; p++, n++) {
- if (! (*p == '-' && *n == '_' ) && *p != *n)
+ if (! (*p == '-' && *n == '_') && *p != *n)
return false;
}
// Ignore any trailing underscore
diff --git a/src/org.cc b/src/org.cc
index 736260e6..7d11c36a 100644
--- a/src/org.cc
+++ b/src/org.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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,7 +43,8 @@ namespace ledger {
posts_to_org_table::posts_to_org_table(report_t& _report,
const optional<string>& _prepend_format)
- : report(_report), last_xact(NULL), last_post(NULL)
+ : report(_report), last_xact(NULL), last_post(NULL),
+ header_printed(false), first_report_title(true)
{
first_line_format.parse_format
("|%(format_date(date))"
diff --git a/src/org.h b/src/org.h
index 8f9dcf81..40b7685d 100644
--- a/src/org.h
+++ b/src/org.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/output.cc b/src/output.cc
index 77d28eed..ffd144e1 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -331,10 +331,10 @@ void report_tags::flush()
void report_tags::operator()(post_t& post)
{
- if(post.metadata){
- foreach (const item_t::string_map::value_type& data, *post.metadata){
+ if (post.metadata) {
+ foreach (const item_t::string_map::value_type& data, *post.metadata) {
string tag=data.first;
- if(report.HANDLED(values) && (data.second).first){
+ if (report.HANDLED(values) && (data.second).first) {
tag+=": "+ (data.second).first.get().to_string();
}
std::map<string, std::size_t>::iterator i = tags.find(tag);
diff --git a/src/output.h b/src/output.h
index 31afbd13..ec7ec6c2 100644
--- a/src/output.h
+++ b/src/output.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/parser.cc b/src/parser.cc
index bcb23f48..8044338f 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/parser.h b/src/parser.h
index 8cc8027f..e46fc719 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/pool.cc b/src/pool.cc
index 2627c816..95c0f49d 100644
--- a/src/pool.cc
+++ b/src/pool.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -267,7 +267,8 @@ commodity_pool_t::exchange(const amount_t& amount,
// Do not record commodity exchanges where amount's commodity has a
// fixated price, since this does not establish a market value for the
// base commodity.
- if (! per_unit_cost.is_realzero() &&
+ if (add_price &&
+ ! per_unit_cost.is_realzero() &&
(current_annotation == NULL ||
! (current_annotation->price &&
current_annotation->has_flags(ANNOTATION_PRICE_FIXATED))) &&
diff --git a/src/pool.h b/src/pool.h
index e6b31a29..d24df78c 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/post.cc b/src/post.cc
index 1a24429b..269e2e6c 100644
--- a/src/post.cc
+++ b/src/post.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/post.h b/src/post.h
index 55ca08e4..1e5fc569 100644
--- a/src/post.h
+++ b/src/post.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -60,6 +60,7 @@ public:
#define POST_COST_FIXATED 0x0200 // cost is fixed using = indicator
#define POST_COST_VIRTUAL 0x0400 // cost is virtualized: (@)
#define POST_ANONYMIZED 0x0800 // a temporary, anonymous posting
+#define POST_DEFERRED 0x1000 // the account was specified with <angles>
xact_t * xact; // only set for posts of regular xacts
account_t * account;
@@ -67,6 +68,7 @@ public:
amount_t amount; // can be null until finalization
optional<expr_t> amount_expr;
optional<amount_t> cost;
+ optional<amount_t> given_cost;
optional<amount_t> assigned_amount;
optional<datetime_t> checkin;
optional<datetime_t> checkout;
@@ -203,7 +205,11 @@ public:
mutable optional<xdata_t> xdata_;
bool has_xdata() const {
+#if BOOST_VERSION >= 105600
+ return xdata_ != NULL;
+#else
return xdata_;
+#endif
}
void clear_xdata() {
xdata_ = none;
diff --git a/src/precmd.cc b/src/precmd.cc
index e9c966e9..2da6ba8e 100644
--- a/src/precmd.cc
+++ b/src/precmd.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/precmd.h b/src/precmd.h
index 27925f42..bf2732d7 100644
--- a/src/precmd.h
+++ b/src/precmd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/predicate.h b/src/predicate.h
index 6a1cc01c..30d07223 100644
--- a/src/predicate.h
+++ b/src/predicate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/print.cc b/src/print.cc
index 0683f2e3..02e518f7 100644
--- a/src/print.cc
+++ b/src/print.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -243,13 +243,21 @@ namespace {
amtbuf << string(2 - (slip + amt_slip), ' ');
amtbuf << amt;
- if (post->cost &&
+ if (post->given_cost &&
! post->has_flags(POST_CALCULATED | POST_COST_CALCULATED)) {
+ std::string cost_op;
if (post->has_flags(POST_COST_IN_FULL))
- amtbuf << " @@ " << post->cost->abs();
+ cost_op = "@@";
else
- amtbuf << " @ "
- << (*post->cost / post->amount).abs();
+ cost_op = "@";
+ if (post->has_flags(POST_COST_VIRTUAL))
+ cost_op = "(" + cost_op + ")";
+
+ if (post->has_flags(POST_COST_IN_FULL))
+ amtbuf << " " << cost_op << " " << post->given_cost->abs();
+ else
+ amtbuf << " " << cost_op << " "
+ << (*post->given_cost / post->amount).abs();
}
if (post->assigned_amount)
diff --git a/src/print.h b/src/print.h
index 8d78e8cc..c587b499 100644
--- a/src/print.h
+++ b/src/print.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/pstream.h b/src/pstream.h
index 4886dc0b..3b669aca 100644
--- a/src/pstream.h
+++ b/src/pstream.h
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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 met:
+ * modification, are permitted provided that the following conditions are
+ * met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
@@ -83,7 +83,10 @@ class ptristream : public std::istream
virtual pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode)
{
- switch (way) {
+ // cast to avoid gcc '-Wswitch' warning
+ // as ios_base::beg/cur/end are not necesssarily values of 'way' enum type ios_base::seekdir
+ // based on https://svn.boost.org/trac/boost/ticket/7644
+ switch (static_cast<int>(way)) {
case std::ios::cur:
setg(ptr, gptr()+off, ptr+len);
break;
diff --git a/src/ptree.cc b/src/ptree.cc
index e7afdcd1..3efe4451 100644
--- a/src/ptree.cc
+++ b/src/ptree.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -80,7 +80,12 @@ void format_ptree::flush()
switch (format) {
case FORMAT_XML:
+#if BOOST_VERSION >= 105600
+ auto indented = property_tree::xml_writer_make_settings<std::string> (' ', 2);
+#else
property_tree::xml_writer_settings<char> indented(' ', 2);
+#endif
+
property_tree::write_xml(out, pt, indented);
out << std::endl;
break;
diff --git a/src/ptree.h b/src/ptree.h
index 154c8837..36708dcf 100644
--- a/src/ptree.h
+++ b/src/ptree.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/py_account.cc b/src/py_account.cc
index fbd68140..1cc28b92 100644
--- a/src/py_account.cc
+++ b/src/py_account.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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,7 @@
#include "pyutils.h"
#include "account.h"
#include "post.h"
+#include "expr.h"
namespace ledger {
@@ -97,6 +98,26 @@ namespace {
return str_to_py_unicode(account.fullname());
}
+ value_t py_amount_0(const account_t& account)
+ {
+ return account.amount();
+ }
+
+ value_t py_amount_1(const account_t& account, const boost::optional<expr_t&>& expr)
+ {
+ return account.amount(expr);
+ }
+
+ value_t py_total_0(const account_t& account)
+ {
+ return account.total();
+ }
+
+ value_t py_total_1(const account_t& account, const boost::optional<expr_t&>& expr)
+ {
+ return account.total(expr);
+ }
+
} // unnamed namespace
void export_account()
@@ -221,8 +242,10 @@ void export_account()
.def("xdata", py_xdata,
return_internal_reference<>())
- .def("amount", &account_t::amount)
- .def("total", &account_t::total)
+ .def("amount", py_amount_0)
+ .def("amount", py_amount_1, args("expr"))
+ .def("total", py_total_0)
+ .def("total", py_total_1, args("expr"))
.def("self_details", &account_t::self_details,
return_internal_reference<>())
diff --git a/src/py_amount.cc b/src/py_amount.cc
index 50e16a70..84558a29 100644
--- a/src/py_amount.cc
+++ b/src/py_amount.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/py_balance.cc b/src/py_balance.cc
index 65e3c401..98ed8c60 100644
--- a/src/py_balance.cc
+++ b/src/py_balance.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -56,6 +56,11 @@ namespace {
const datetime_t& moment) {
return balance.value(moment, in_terms_of);
}
+ boost::optional<balance_t> py_value_2d(const balance_t& balance,
+ const commodity_t * in_terms_of,
+ const date_t& moment) {
+ return balance.value(datetime_t(moment), in_terms_of);
+ }
boost::optional<amount_t>
py_commodity_amount_0(const balance_t& balance) {
@@ -64,7 +69,7 @@ namespace {
boost::optional<amount_t>
py_commodity_amount_1(const balance_t& balance,
- const boost::optional<const commodity_t&>& commodity) {
+ const commodity_t& commodity) {
return balance.commodity_amount(commodity);
}
@@ -200,6 +205,7 @@ void export_balance()
.def("value", py_value_0)
.def("value", py_value_1, args("in_terms_of"))
.def("value", py_value_2, args("in_terms_of", "moment"))
+ .def("value", py_value_2d, args("in_terms_of", "moment"))
.def("__nonzero__", &balance_t::is_nonzero)
.def("is_nonzero", &balance_t::is_nonzero)
diff --git a/src/py_commodity.cc b/src/py_commodity.cc
index fd932fc7..27a0e105 100644
--- a/src/py_commodity.cc
+++ b/src/py_commodity.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -315,6 +315,7 @@ void export_commodity()
scope().attr("COMMODITY_STYLE_SUFFIXED") = COMMODITY_STYLE_SUFFIXED;
scope().attr("COMMODITY_STYLE_SEPARATED") = COMMODITY_STYLE_SEPARATED;
scope().attr("COMMODITY_STYLE_DECIMAL_COMMA") = COMMODITY_STYLE_DECIMAL_COMMA;
+ scope().attr("COMMODITY_STYLE_TIME_COLON") = COMMODITY_STYLE_TIME_COLON;
scope().attr("COMMODITY_STYLE_THOUSANDS") = COMMODITY_STYLE_THOUSANDS;
scope().attr("COMMODITY_NOMARKET") = COMMODITY_NOMARKET;
scope().attr("COMMODITY_BUILTIN") = COMMODITY_BUILTIN;
diff --git a/src/py_expr.cc b/src/py_expr.cc
index c680bab4..803388f2 100644
--- a/src/py_expr.cc
+++ b/src/py_expr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/py_format.cc b/src/py_format.cc
index 43266b29..6086d6cb 100644
--- a/src/py_format.cc
+++ b/src/py_format.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/py_item.cc b/src/py_item.cc
index 02b978c5..473bbef8 100644
--- a/src/py_item.cc
+++ b/src/py_item.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/py_journal.cc b/src/py_journal.cc
index 7cce6b11..abbcd866 100644
--- a/src/py_journal.cc
+++ b/src/py_journal.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/py_post.cc b/src/py_post.cc
index 6061d6ee..851828c7 100644
--- a/src/py_post.cc
+++ b/src/py_post.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/py_session.cc b/src/py_session.cc
index 7e2f9e8a..f6053180 100644
--- a/src/py_session.cc
+++ b/src/py_session.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -61,6 +61,8 @@ void export_session()
.def("read_journal_files", &session_t::read_journal_files,
return_internal_reference<>())
.def("close_journal_files", &session_t::close_journal_files)
+ .def("journal", &session_t::get_journal,
+ return_internal_reference<>())
;
scope().attr("session") =
diff --git a/src/py_times.cc b/src/py_times.cc
index 599aa60c..906dcfaa 100644
--- a/src/py_times.cc
+++ b/src/py_times.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -108,7 +108,7 @@ struct datetime_from_python
static void* convertible(PyObject* obj_ptr)
{
MY_PyDateTime_IMPORT;
- if(PyDateTime_Check(obj_ptr)) return obj_ptr;
+ if (PyDateTime_Check(obj_ptr)) return obj_ptr;
return 0;
}
diff --git a/src/py_utils.cc b/src/py_utils.cc
index dc572621..df87bded 100644
--- a/src/py_utils.cc
+++ b/src/py_utils.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/py_value.cc b/src/py_value.cc
index 8b565661..2828e3b8 100644
--- a/src/py_value.cc
+++ b/src/py_value.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/py_xact.cc b/src/py_xact.cc
index 0b07f582..5b4c14d4 100644
--- a/src/py_xact.cc
+++ b/src/py_xact.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/pyfstream.h b/src/pyfstream.h
index 12bbecfd..11f514a2 100644
--- a/src/pyfstream.h
+++ b/src/pyfstream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index e15ff503..54e62946 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -34,6 +34,7 @@
#include "pyinterp.h"
#include "pyutils.h"
#include "account.h"
+#include "report.h"
#include "xact.h"
#include "post.h"
@@ -76,6 +77,12 @@ void initialize_for_python()
export_xact();
export_session();
export_journal();
+
+ if (! scope_t::default_scope) {
+ python_session.reset(new ledger::python_interpreter_t);
+ shared_ptr<session_t> session_ptr = python_session;
+ scope_t::default_scope = new report_t(*session_ptr);
+ }
}
struct python_run
diff --git a/src/pyinterp.h b/src/pyinterp.h
index e961f4c0..32becbf6 100644
--- a/src/pyinterp.h
+++ b/src/pyinterp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/pyledger.cc b/src/pyledger.cc
index ee7b99c9..1f478dec 100644
--- a/src/pyledger.cc
+++ b/src/pyledger.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/pyutils.h b/src/pyutils.h
index 6bb9d0bd..039b2605 100644
--- a/src/pyutils.h
+++ b/src/pyutils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/query.cc b/src/query.cc
index 209205ae..04b18581 100644
--- a/src/query.cc
+++ b/src/query.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/query.h b/src/query.h
index 10820a59..b7608bc7 100644
--- a/src/query.h
+++ b/src/query.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/quotes.cc b/src/quotes.cc
index 2df51ec1..6d179287 100644
--- a/src/quotes.cc
+++ b/src/quotes.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/quotes.h b/src/quotes.h
index 813bdfa3..c14bc495 100644
--- a/src/quotes.h
+++ b/src/quotes.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/report.cc b/src/report.cc
index 29077f10..4b240611 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -181,10 +181,17 @@ void report_t::normalize_options(const string& verb)
}
long cols = 0;
+#if HAVE_IOCTL
+ struct winsize ws;
+#endif
if (HANDLED(columns_))
cols = lexical_cast<long>(HANDLER(columns_).value);
else if (const char * columns = std::getenv("COLUMNS"))
cols = lexical_cast<long>(columns);
+#if HAVE_IOCTL
+ else if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != -1)
+ cols = ws.ws_col;
+#endif
else
cols = 80L;
@@ -1113,6 +1120,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
OPT(csv_format_);
else OPT_ALT(gain, change);
else OPT(cleared);
+ else OPT(cleared_format_);
else OPT(collapse);
else OPT(collapse_if_zero);
else OPT(color);
@@ -1189,6 +1197,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
case 'n':
OPT_CH(collapse);
else OPT(no_color);
+ else OPT(no_pager);
else OPT(no_rounding);
else OPT(no_titles);
else OPT(no_total);
diff --git a/src/report.h b/src/report.h
index 5897e8f6..67e95884 100644
--- a/src/report.h
+++ b/src/report.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -302,6 +302,7 @@ public:
HANDLER(market).report(out);
HANDLER(meta_).report(out);
HANDLER(monthly).report(out);
+ HANDLER(no_pager).report(out);
HANDLER(no_rounding).report(out);
HANDLER(no_titles).report(out);
HANDLER(no_total).report(out);
@@ -464,8 +465,8 @@ public:
" 12 + 1 + 12 + 1 + 12, true, color))"
" %(ansify_if("
" justify((get_at(display_total, 1) ? "
- " (100% * scrub(get_at(display_total, 0))) / "
- " -scrub(get_at(display_total, 1)) : 0), "
+ " (100% * quantity(scrub(get_at(display_total, 0)))) / "
+ " -quantity(scrub(get_at(display_total, 1))) : 0), "
" 5, -1, true, false),"
" magenta if (color and get_at(display_total, 1) and "
" (abs(quantity(scrub(get_at(display_total, 0))) / "
@@ -521,7 +522,7 @@ public:
"%(quoted(code)),"
"%(quoted(payee)),"
"%(quoted(display_account)),"
- "%(quoted(commodity)),"
+ "%(quoted(commodity(scrub(display_amount)))),"
"%(quoted(quantity(scrub(display_amount)))),"
"%(quoted(cleared ? \"*\" : (pending ? \"!\" : \"\"))),"
"%(quoted(join(note | xact.note)))\n");
diff --git a/src/scope.cc b/src/scope.cc
index 10ae45a9..3ca9e0c0 100644
--- a/src/scope.cc
+++ b/src/scope.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/scope.h b/src/scope.h
index d6291439..8ad3afac 100644
--- a/src/scope.h
+++ b/src/scope.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/select.cc b/src/select.cc
index b7e4c920..81800f16 100644
--- a/src/select.cc
+++ b/src/select.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -145,10 +145,17 @@ value_t select_command(call_scope_t& args)
string thus_far = "";
std::size_t cols = 0;
+#if HAVE_IOCTL
+ struct winsize ws;
+#endif
if (report.HANDLED(columns_))
cols = lexical_cast<std::size_t>(report.HANDLER(columns_).value);
else if (const char * columns_env = std::getenv("COLUMNS"))
cols = lexical_cast<std::size_t>(columns_env);
+#if HAVE_IOCTL
+ else if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != -1)
+ cols = ws.ws_col;
+#endif
else
cols = 80;
@@ -291,17 +298,17 @@ value_t select_command(call_scope_t& args)
thus_far += "int(payee_width) + 1";
}
else if (ident == "account") {
- formatter << "ansify_if("
- << "ansify_if(";
+ formatter << "ansify_if(";
if (accounts_report) {
+ formatter << "ansify_if(";
formatter << "partial_account(options.flat), blue if color),";
} else {
formatter << "justify(truncated(";
as_expr(column)->print(formatter);
formatter << ", int(account_width), int(abbrev_len)),"
- << "int(account_width)),";
- formatter << "true, color),";
+ << "int(account_width), -1, ";
+ formatter << "false, color),";
if (! thus_far.empty())
thus_far += " + ";
@@ -358,10 +365,9 @@ value_t select_command(call_scope_t& args)
formatter << ")";
}
formatter << "\\n";
+ DEBUG("select.parse", "formatter: " << formatter.str());
}
else if (keyword == "from") {
- DEBUG("select.parse", "formatter: " << formatter.str());
-
if (arg == "xacts" || arg == "txns" || arg == "transactions") {
report_functor = expr_t::op_t::wrap_functor
(reporter<>(post_handler_ptr(new print_xacts(report,
diff --git a/src/select.h b/src/select.h
index 346067a2..c95e15f7 100644
--- a/src/select.h
+++ b/src/select.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/session.cc b/src/session.cc
index e5425a50..b0d31be9 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -93,25 +93,31 @@ std::size_t session_t::read_data(const string& master_account)
acct = journal->find_account(master_account);
optional<path> price_db_path;
- if (HANDLED(price_db_)){
+ if (HANDLED(price_db_)) {
price_db_path = resolve_path(HANDLER(price_db_).str());
- if (!exists(price_db_path.get())){
+ if (!exists(price_db_path.get())) {
throw_(parse_error, _f("Could not find specified price-db file %1%") % price_db_path);
}
} else {
- if (const char * home_var = std::getenv("HOME")){
+ if (const char * home_var = std::getenv("HOME")) {
price_db_path = (path(home_var) / ".pricedb");
} else {
price_db_path = ("./.ledgerrc");
}
}
+ if (HANDLED(day_break))
+ journal->day_break = true;
+
+ if (HANDLED(recursive_aliases))
+ journal->recursive_aliases = true;
+ if (HANDLED(no_aliases))
+ journal->no_aliases = true;
+
if (HANDLED(explicit))
journal->force_checking = true;
if (HANDLED(check_payees))
journal->check_payees = true;
- if (HANDLED(day_break))
- journal->day_break = true;
if (HANDLED(permissive))
journal->checking_style = journal_t::CHECK_PERMISSIVE;
@@ -119,8 +125,9 @@ std::size_t session_t::read_data(const string& master_account)
journal->checking_style = journal_t::CHECK_ERROR;
else if (HANDLED(strict))
journal->checking_style = journal_t::CHECK_WARNING;
- else if (HANDLED(value_expr_))
- journal->value_expr = HANDLER(value_expr_).str();
+
+ if (HANDLED(value_expr_))
+ journal->value_expr = HANDLER(value_expr_).str();
#if HAVE_BOOST_SERIALIZATION
optional<archive_t> cache;
@@ -258,6 +265,11 @@ void session_t::close_journal_files()
amount_t::initialize();
}
+journal_t * session_t::get_journal()
+{
+ return journal.get();
+}
+
value_t session_t::fn_account(call_scope_t& args)
{
if (args[0].is_string())
@@ -344,12 +356,18 @@ option_t<session_t> * session_t::lookup_option(const char * p)
case 'm':
OPT(master_account_);
break;
+ case 'n':
+ OPT(no_aliases);
+ break;
case 'p':
OPT(price_db_);
else OPT(price_exp_);
else OPT(pedantic);
else OPT(permissive);
break;
+ case 'r':
+ OPT(recursive_aliases);
+ break;
case 's':
OPT(strict);
break;
diff --git a/src/session.h b/src/session.h
index 21be3cc7..b287b19e 100644
--- a/src/session.h
+++ b/src/session.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -84,6 +84,8 @@ public:
journal_t * read_journal_files();
void close_journal_files();
+ journal_t * get_journal();
+
value_t fn_account(call_scope_t& scope);
value_t fn_min(call_scope_t& scope);
value_t fn_max(call_scope_t& scope);
@@ -109,6 +111,8 @@ public:
HANDLER(permissive).report(out);
HANDLER(price_db_).report(out);
HANDLER(price_exp_).report(out);
+ HANDLER(recursive_aliases).report(out);
+ HANDLER(no_aliases).report(out);
HANDLER(strict).report(out);
HANDLER(value_expr_).report(out);
}
@@ -164,6 +168,8 @@ public:
OPTION(session_t, price_db_);
OPTION(session_t, strict);
OPTION(session_t, value_expr_);
+ OPTION(session_t, recursive_aliases);
+ OPTION(session_t, no_aliases);
};
/**
diff --git a/src/stats.cc b/src/stats.cc
index 81d71a46..406ecd3b 100644
--- a/src/stats.cc
+++ b/src/stats.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/stats.h b/src/stats.h
index 5583e704..f0408591 100644
--- a/src/stats.h
+++ b/src/stats.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/stream.cc b/src/stream.cc
index c00c4cc5..c5a40e87 100644
--- a/src/stream.cc
+++ b/src/stream.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -80,18 +80,10 @@ namespace {
close(pfd[1]);
close(pfd[0]);
- // Find command name: its the substring starting right of the
- // rightmost '/' character in the pager pathname. See manpage for
- // strrchr.
-#if BOOST_VERSION >= 103700
- path basename(pager_path.filename());
-#else
- path basename(pager_path.leaf());
-#endif
- execlp(pager_path.string().c_str(), basename.string().c_str(), NULL);
+ execlp("/bin/sh", "/bin/sh", "-c", pager_path.string().c_str(), NULL);
// We should never, ever reach here
- perror((std::string("execlp: ") + pager_path.string()).c_str());
+ perror("execlp: /bin/sh");
exit(1);
}
else { // parent
diff --git a/src/stream.h b/src/stream.h
index bb63873a..05572cb4 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/system.hh.in b/src/system.hh.in
index ff7ea75b..21417e09 100644
--- a/src/system.hh.in
+++ b/src/system.hh.in
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -56,8 +56,6 @@
#define Ledger_VERSION_PATCH @Ledger_VERSION_PATCH@
#define Ledger_VERSION_DATE @Ledger_VERSION_DATE@
-#define HAVE_CXX11 @HAVE_CXX11@
-
#define HAVE_EDIT @HAVE_EDIT@
#define HAVE_GETTEXT @HAVE_GETTEXT@
@@ -65,6 +63,7 @@
#define HAVE_REALPATH @HAVE_REALPATH@
#define HAVE_GETPWUID @HAVE_GETPWUID@
#define HAVE_GETPWNAM @HAVE_GETPWNAM@
+#define HAVE_IOCTL @HAVE_IOCTL@
#define HAVE_ISATTY @HAVE_ISATTY@
#define HAVE_UNIX_PIPES @HAVE_UNIX_PIPES@
@@ -153,14 +152,18 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <pwd.h>
#endif
+#if HAVE_IOCTL
+#include <sys/ioctl.h>
+#endif
+
#if HAVE_UNIX_PIPES
#include <sys/types.h>
#include <sys/wait.h>
#endif
+#include <cstddef> /* needed for gcc 4.9 */
#include <gmp.h>
#include <mpfr.h>
-#include "sha1.h"
#include "utf8.h"
#if HAVE_EDIT
diff --git a/src/temps.cc b/src/temps.cc
index b4778b49..15ccbc3a 100644
--- a/src/temps.cc
+++ b/src/temps.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/temps.h b/src/temps.h
index 99110496..77a7824e 100644
--- a/src/temps.h
+++ b/src/temps.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/textual.cc b/src/textual.cc
index 9e19ee37..8007ca0d 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -77,16 +77,18 @@ namespace {
std::istream& in;
instance_t * parent;
std::list<application_t> apply_stack;
+ bool no_assertions;
#if defined(TIMELOG_SUPPORT)
time_log_t timelog;
#endif
instance_t(parse_context_stack_t& _context_stack,
parse_context_t& _context,
- instance_t * _parent = NULL)
+ instance_t * _parent = NULL,
+ const bool _no_assertions = false)
: context_stack(_context_stack), context(_context),
in(*context.stream.get()), parent(_parent),
- timelog(context) {}
+ no_assertions(_no_assertions), timelog(context) {}
virtual string description() {
return _("textual parser");
@@ -153,6 +155,7 @@ namespace {
void payee_directive(char * line);
void payee_alias_directive(const string& payee, string alias);
+ void payee_uuid_directive(const string& payee, string uuid);
void commodity_directive(char * line);
void commodity_alias_directive(commodity_t& comm, string alias);
@@ -282,6 +285,11 @@ void instance_t::parse()
}
}
+ if (apply_stack.front().value.type() == typeid(optional<datetime_t>))
+ epoch = boost::get<optional<datetime_t> >(apply_stack.front().value);
+
+ apply_stack.pop_front();
+
#if defined(TIMELOG_SUPPORT)
timelog.close();
#endif // TIMELOG_SUPPORT
@@ -416,7 +424,9 @@ void instance_t::read_next_directive(bool& error_flag)
price_xact_directive(line);
break;
case 'Y': // set the current year
- apply_year_directive(line);
+ if (std::strlen(line+1) == 0)
+ throw_(parse_error, _f("Directive '%1%' requires an argument") % line[0]);
+ apply_year_directive(line+1);
break;
}
}
@@ -779,8 +789,8 @@ void instance_t::include_directive(char * line)
context_stack.get_current().master = master;
context_stack.get_current().scope = scope;
try {
- instance_t instance(context_stack,
- context_stack.get_current(), this);
+ instance_t instance(context_stack, context_stack.get_current(),
+ this, no_assertions);
instance.apply_stack.push_front(application_t("account", master));
instance.parse();
}
@@ -860,14 +870,17 @@ void instance_t::apply_rate_directive(char * line)
void instance_t::apply_year_directive(char * line)
{
- apply_stack.push_front(application_t("year", epoch));
-
- // This must be set to the last day of the year, otherwise partial
- // dates like "11/01" will refer to last year's november, not the
- // current year.
- unsigned short year(lexical_cast<unsigned short>(skip_ws(line + 1)));
- DEBUG("times.epoch", "Setting current year to " << year);
- epoch = datetime_t(date_t(year, 12, 31));
+ try {
+ unsigned short year(lexical_cast<unsigned short>(skip_ws(line)));
+ apply_stack.push_front(application_t("year", epoch));
+ DEBUG("times.epoch", "Setting current year to " << year);
+ // This must be set to the last day of the year, otherwise partial
+ // dates like "11/01" will refer to last year's november, not the
+ // current year.
+ epoch = datetime_t(date_t(year, 12, 31));
+ } catch(bad_lexical_cast &) {
+ throw_(parse_error, _f("Argument '%1%' not a valid year") % skip_ws(line));
+ }
}
void instance_t::end_apply_directive(char * kind)
@@ -915,6 +928,10 @@ void instance_t::account_directive(char * line)
char * b = next_element(q);
string keyword(q);
+ // Ensure there's an argument for the directives that need one.
+ if (! b && keyword != "default")
+ throw_(parse_error, _f("Account directive '%1%' requires an argument") % keyword);
+
if (keyword == "alias") {
account_alias_directive(account, b);
}
@@ -977,6 +994,11 @@ void instance_t::account_alias_directive(account_t * account, string alias)
// (account), add a reference to the account in the `account_aliases'
// map, which is used by the post parser to resolve alias references.
trim(alias);
+ // Ensure that no alias like "alias Foo=Foo" is registered.
+ if ( alias == account->fullname()) {
+ throw_(parse_error, _f("Illegal alias %1%=%2%")
+ % alias % account->fullname());
+ }
std::pair<accounts_map::iterator, bool> result =
context.journal->account_aliases.insert
(accounts_map::value_type(alias, account));
@@ -1026,16 +1048,28 @@ void instance_t::payee_directive(char * line)
char * b = next_element(p);
string keyword(p);
+ if (! b)
+ throw_(parse_error, _f("Payee directive '%1%' requires an argument") % keyword);
+
if (keyword == "alias")
payee_alias_directive(payee, b);
+ if (keyword == "uuid")
+ payee_uuid_directive(payee, b);
}
}
void instance_t::payee_alias_directive(const string& payee, string alias)
{
trim(alias);
- context.journal->payee_mappings
- .push_back(payee_mapping_t(mask_t(alias), payee));
+ context.journal->payee_alias_mappings
+ .push_back(payee_alias_mapping_t(mask_t(alias), payee));
+}
+
+void instance_t::payee_uuid_directive(const string& payee, string uuid)
+{
+ trim(uuid);
+ context.journal->payee_uuid_mappings
+ .push_back(payee_uuid_mapping_t(uuid, payee));
}
void instance_t::commodity_directive(char * line)
@@ -1056,6 +1090,10 @@ void instance_t::commodity_directive(char * line)
char * b = next_element(q);
string keyword(q);
+ // Ensure there's an argument for the directives that need one.
+ if (! b && keyword != "nomarket" && keyword != "default")
+ throw_(parse_error, _f("Commodity directive '%1%' requires an argument") % keyword);
+
if (keyword == "alias")
commodity_alias_directive(*commodity, b);
else if (keyword == "value")
@@ -1217,13 +1255,13 @@ void instance_t::python_directive(char * line)
void instance_t::import_directive(char *)
{
throw_(parse_error,
- _("'python' directive seen, but Python support is missing"));
+ _("'import' directive seen, but Python support is missing"));
}
void instance_t::python_directive(char *)
{
throw_(parse_error,
- _("'import' directive seen, but Python support is missing"));
+ _("'python' directive seen, but Python support is missing"));
}
#endif // HAVE_BOOST_PYTHON
@@ -1240,6 +1278,14 @@ bool instance_t::general_directive(char * line)
if (*p == '@' || *p == '!')
p++;
+ // Ensure there's an argument for all directives that need one.
+ if (! arg &&
+ std::strcmp(p, "comment") != 0 && std::strcmp(p, "end") != 0
+ && std::strcmp(p, "python") != 0 && std::strcmp(p, "test") != 0 &&
+ *p != 'Y') {
+ throw_(parse_error, _f("Directive '%1%' requires an argument") % p);
+ }
+
switch (*p) {
case 'a':
if (std::strcmp(p, "account") == 0) {
@@ -1339,6 +1385,13 @@ bool instance_t::general_directive(char * line)
return true;
}
break;
+
+ case 'y':
+ if (std::strcmp(p, "year") == 0) {
+ apply_year_directive(arg);
+ return true;
+ }
+ break;
}
if (expr_t::ptr_op_t op = lookup(symbol_t::DIRECTIVE, p)) {
@@ -1398,8 +1451,7 @@ post_t * instance_t::parse_post(char * line,
}
if (xact &&
- ((xact->_state == item_t::CLEARED && post->_state != item_t::CLEARED) ||
- (xact->_state == item_t::PENDING && post->_state == item_t::UNCLEARED)))
+ (xact->_state != item_t::UNCLEARED && post->_state == item_t::UNCLEARED))
post->set_state(xact->_state);
// Parse the account name
@@ -1425,6 +1477,12 @@ post_t * instance_t::parse_post(char * line,
}
p++; e--;
}
+ else if (*p == '<' && *(e - 1) == '>') {
+ post->add_flags(POST_DEFERRED);
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Parsed a deferred account name");
+ p++; e--;
+ }
string name(p, static_cast<string::size_type>(e - p));
DEBUG("textual.parse", "line " << context.linenum << ": "
@@ -1490,13 +1548,12 @@ post_t * instance_t::parse_post(char * line,
post->add_flags(POST_COST_IN_FULL);
DEBUG("textual.parse", "line " << context.linenum << ": "
<< "And it's for a total price");
+ next++;
}
- if (post->has_flags(POST_COST_VIRTUAL) && *(next + 1) == ')')
+ if (post->has_flags(POST_COST_VIRTUAL) && *next == ')')
++next;
- beg = static_cast<std::streamsize>(++next - line);
-
p = skip_ws(next);
if (*p) {
post->cost = amount_t();
@@ -1538,6 +1595,8 @@ post_t * instance_t::parse_post(char * line,
if (fixed_cost)
post->add_flags(POST_COST_FIXATED);
+ post->given_cost = post->cost;
+
DEBUG("textual.parse", "line " << context.linenum << ": "
<< "Total cost is " << *post->cost);
DEBUG("textual.parse", "line " << context.linenum << ": "
@@ -1612,6 +1671,8 @@ post_t * instance_t::parse_post(char * line,
break;
}
+ amount_t tot = amt - diff;
+
DEBUG("post.assign",
"line " << context.linenum << ": " << "diff = " << diff);
DEBUG("textual.parse", "line " << context.linenum << ": "
@@ -1620,8 +1681,10 @@ post_t * instance_t::parse_post(char * line,
if (! diff.is_zero()) {
if (! post->amount.is_null()) {
diff -= post->amount;
- if (! diff.is_zero())
- throw_(parse_error, _f("Balance assertion off by %1%") % diff);
+ if (! no_assertions && ! diff.is_zero())
+ throw_(parse_error,
+ _f("Balance assertion off by %1% (expected to see %2%)")
+ % diff % tot);
} else {
post->amount = diff;
DEBUG("textual.parse", "line " << context.linenum << ": "
@@ -1770,7 +1833,7 @@ xact_t * instance_t::parse_xact(char * line,
char *q = p - 1;
while (q > next && std::isspace(*q))
--q;
- if (q > next)
+ if (q >= next)
*(q + 1) = '\0';
break;
}
@@ -1844,6 +1907,17 @@ xact_t * instance_t::parse_xact(char * line,
else {
reveal_context = false;
+ if (!last_post) {
+ if (xact->has_tag(_("UUID"))) {
+ string uuid = xact->get_tag(_("UUID"))->to_string();
+ foreach (payee_uuid_mapping_t value, context.journal->payee_uuid_mappings) {
+ if (value.first.compare(uuid) == 0) {
+ xact->payee = value.second;
+ }
+ }
+ }
+ }
+
if (post_t * post =
parse_post(p, len - (p - line), account, xact.get())) {
reveal_context = true;
@@ -1904,13 +1978,17 @@ std::size_t journal_t::read_textual(parse_context_stack_t& context_stack)
{
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
{
- instance_t instance(context_stack, context_stack.get_current());
+ instance_t instance(context_stack, context_stack.get_current(), NULL,
+ checking_style == journal_t::CHECK_PERMISSIVE);
instance.apply_stack.push_front
(application_t("account", context_stack.get_current().master));
instance.parse();
}
TRACE_STOP(parsing_total, 1);
+ // Apply any deferred postings at this time
+ master->apply_deferred_posts();
+
// These tracers were started in textual.cc
TRACE_FINISH(xact_text, 1);
TRACE_FINISH(xact_details, 1);
diff --git a/src/timelog.cc b/src/timelog.cc
index 64017d50..91ee2697 100644
--- a/src/timelog.cc
+++ b/src/timelog.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/timelog.h b/src/timelog.h
index 1ce0be28..af621ee6 100644
--- a/src/timelog.h
+++ b/src/timelog.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/times.cc b/src/times.cc
index b1cb3494..b6c15dc3 100644
--- a/src/times.cc
+++ b/src/times.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -839,6 +839,16 @@ void date_parser_t::determine_when(date_parser_t::lexer_t::token_t& tok,
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:
+ specifier.year = boost::get<date_specifier_t::year_type>(*tok.value);
+ break;
+ case lexer_t::token_t::END_REACHED:
+ break;
+ default:
+ break;
+ }
break;
case lexer_t::token_t::TOK_A_WDAY:
specifier.wday =
@@ -1802,6 +1812,7 @@ void times_initialize()
readers.push_back(shared_ptr<date_io_t>(new date_io_t("%Y/%m/%d", true)));
readers.push_back(shared_ptr<date_io_t>(new date_io_t("%Y/%m", true)));
readers.push_back(shared_ptr<date_io_t>(new date_io_t("%y/%m/%d", true)));
+ readers.push_back(shared_ptr<date_io_t>(new date_io_t("%Y-%m-%d", true)));
is_initialized = true;
}
diff --git a/src/times.h b/src/times.h
index 4b89cc0c..c1bfb1cc 100644
--- a/src/times.h
+++ b/src/times.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -568,7 +568,11 @@ public:
void stabilize(const optional<date_t>& date = none);
bool is_valid() const {
+#if BOOST_VERSION >= 105600
+ return start != NULL;
+#else
return start;
+#endif
}
/** Find the current or next period containing date. Returns false if
diff --git a/src/token.cc b/src/token.cc
index d0ec185b..9fe7873f 100644
--- a/src/token.cc
+++ b/src/token.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -522,7 +522,8 @@ void expr_t::token_t::expected(const char wanted, char c)
void expr_t::token_t::expected(const kind_t wanted)
{
try {
- if (wanted == '\0' || wanted == -1)
+ if (wanted == expr_t::token_t::ERROR ||
+ wanted == expr_t::token_t::UNKNOWN)
throw_(parse_error, _f("Invalid token '%1%'") % *this);
else
throw_(parse_error,
diff --git a/src/token.h b/src/token.h
index 51fa1d78..3fe249aa 100644
--- a/src/token.h
+++ b/src/token.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/unistring.h b/src/unistring.h
index eb38f8b1..3f459d83 100644
--- a/src/unistring.h
+++ b/src/unistring.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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,6 +44,8 @@
namespace ledger {
+int mk_wcwidth(boost::uint32_t ucs);
+
/**
* @class unistring
*
@@ -81,6 +83,14 @@ public:
return utf32chars.size();
}
+ std::size_t width() const {
+ std::size_t width = 0;
+ foreach (const boost::uint32_t& ch, utf32chars) {
+ width += mk_wcwidth(ch);
+ }
+ return width;
+ }
+
std::string extract(const std::string::size_type begin = 0,
const std::string::size_type len = 0) const
{
@@ -133,7 +143,7 @@ inline void justify(std::ostream& out,
unistring temp(str);
- int spacing = width - int(temp.length());
+ int spacing = width - int(temp.width());
while (spacing-- > 0)
out << ' ';
diff --git a/src/utils.cc b/src/utils.cc
index 4f810f93..9b528f54 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -229,7 +229,11 @@ static void trace_delete_func(void * ptr, const char * which)
//#if !defined(__has_feature) || !__has_feature(address_sanitizer)
+#ifdef _GLIBCXX_THROW
+void * operator new(std::size_t size) _GLIBCXX_THROW(std::bad_alloc) {
+#else
void * operator new(std::size_t size) throw (std::bad_alloc) {
+#endif
void * ptr = std::malloc(size);
if (DO_VERIFY() && ledger::memory_tracing_active)
ledger::trace_new_func(ptr, "new", size);
@@ -241,7 +245,11 @@ void * operator new(std::size_t size, const std::nothrow_t&) throw() {
ledger::trace_new_func(ptr, "new", size);
return ptr;
}
+#ifdef _GLIBCXX_THROW
+void * operator new[](std::size_t size) _GLIBCXX_THROW(std::bad_alloc) {
+#else
void * operator new[](std::size_t size) throw (std::bad_alloc) {
+#endif
void * ptr = std::malloc(size);
if (DO_VERIFY() && ledger::memory_tracing_active)
ledger::trace_new_func(ptr, "new[]", size);
@@ -566,7 +574,7 @@ std::ostream * _log_stream = &std::cerr;
std::ostringstream _log_buffer;
#if TRACING_ON
-uint8_t _trace_level;
+uint16_t _trace_level;
#endif
static bool logger_has_run = false;
diff --git a/src/utils.h b/src/utils.h
index c4d11636..b92a6f49 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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,6 +44,8 @@
#ifndef _UTILS_H
#define _UTILS_H
+#include <boost/uuid/sha1.hpp>
+
/**
* @name Default values
*/
@@ -249,7 +251,7 @@ void logger_func(log_level_t level);
#if TRACING_ON
-extern uint8_t _trace_level;
+extern uint16_t _trace_level;
#define SHOW_TRACE(lvl) \
(ledger::_log_level >= ledger::LOG_TRACE && lvl <= ledger::_trace_level)
@@ -483,11 +485,7 @@ inline void check_for_signal() {
/*@{*/
#define foreach BOOST_FOREACH
-#if HAVE_CXX11
using std::unique_ptr;
-#else
-#define unique_ptr std::auto_ptr
-#endif
namespace ledger {
@@ -625,11 +623,12 @@ inline string to_hex(unsigned int * message_digest, const int len = 1)
inline string sha1sum(const string& str)
{
- SHA1 sha;
- sha.Reset();
- sha << str.c_str();
+ boost::uuids::detail::sha1 sha;
+
+ sha.process_bytes(str.c_str(), str.length());
+
unsigned int message_digest[5];
- sha.Result(message_digest);
+ sha.get_digest(message_digest);
return to_hex(message_digest, 5);
}
diff --git a/src/value.cc b/src/value.cc
index 98e48c2f..4ea7c7a8 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -341,6 +341,10 @@ value_t& value_t::operator+=(const value_t& val)
}
switch (type()) {
+ case VOID:
+ *this = value_t(val);
+ return *this;
+
case DATETIME:
switch (val.type()) {
case INTEGER:
@@ -870,6 +874,8 @@ bool value_t::is_less_than(const value_t& val) const
return as_long() < val.as_long();
case AMOUNT:
return val.as_amount() > as_long();
+ case BALANCE:
+ return val.to_amount() > as_long();
default:
break;
}
@@ -886,6 +892,8 @@ bool value_t::is_less_than(const value_t& val) const
return as_amount() < val.as_amount();
else
return commodity_t::compare_by_commodity()(&as_amount(), &val.as_amount());
+ case BALANCE:
+ return val.to_amount() > as_amount();
default:
break;
}
@@ -904,6 +912,8 @@ bool value_t::is_less_than(const value_t& val) const
}
return ! no_amounts;
}
+ case BALANCE:
+ return val.to_amount() > to_amount();
default:
break;
}
@@ -990,6 +1000,8 @@ bool value_t::is_greater_than(const value_t& val) const
return as_long() > val.as_long();
case AMOUNT:
return val.as_amount() < as_long();
+ case BALANCE:
+ return val.to_amount() < as_long();
default:
break;
}
@@ -1001,6 +1013,8 @@ bool value_t::is_greater_than(const value_t& val) const
return as_amount() > val.as_long();
case AMOUNT:
return as_amount() > val.as_amount();
+ case BALANCE:
+ return val.to_amount() < as_amount();
default:
break;
}
@@ -1019,6 +1033,8 @@ bool value_t::is_greater_than(const value_t& val) const
}
return ! no_amounts;
}
+ case BALANCE:
+ return val.to_amount() < to_amount();
default:
break;
}
diff --git a/src/value.h b/src/value.h
index 93760234..c224ce04 100644
--- a/src/value.h
+++ b/src/value.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/views.cc b/src/views.cc
index 2646e84b..61b824cd 100644
--- a/src/views.cc
+++ b/src/views.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/views.h b/src/views.h
index 94bedda5..2be3d978 100644
--- a/src/views.h
+++ b/src/views.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
diff --git a/src/wcwidth.c.patch b/src/wcwidth.c.patch
new file mode 100644
index 00000000..5864a056
--- /dev/null
+++ b/src/wcwidth.c.patch
@@ -0,0 +1,74 @@
+--- wcwidth.c 2007-05-26 18:06:24.000000000 +0800
++++ wcwidth.cc 2014-02-13 18:36:18.668331252 +0800
+@@ -59,15 +59,23 @@
+ * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
+ */
+
+-#include <wchar.h>
++/* This file is modified to work with C++ and present Unicode
++ * characters in uint32_t type.
++ */
++
++#include <system.hh>
++
++namespace ledger {
+
+-struct interval {
+- int first;
+- int last;
+-};
++namespace {
++ struct interval {
++ int first;
++ int last;
++ };
++}
+
+ /* auxiliary function for binary search in interval table */
+-static int bisearch(wchar_t ucs, const struct interval *table, int max) {
++static int bisearch(boost::uint32_t ucs, const struct interval *table, int max) {
+ int min = 0;
+ int mid;
+
+@@ -119,7 +127,7 @@
+ * in ISO 10646.
+ */
+
+-int mk_wcwidth(wchar_t ucs)
++int mk_wcwidth(boost::uint32_t ucs)
+ {
+ /* sorted list of non-overlapping intervals of non-spacing characters */
+ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
+@@ -204,7 +212,7 @@
+ }
+
+
+-int mk_wcswidth(const wchar_t *pwcs, size_t n)
++int mk_wcswidth(const boost::uint32_t *pwcs, size_t n)
+ {
+ int w, width = 0;
+
+@@ -227,7 +235,7 @@
+ * the traditional terminal character-width behaviour. It is not
+ * otherwise recommended for general use.
+ */
+-int mk_wcwidth_cjk(wchar_t ucs)
++int mk_wcwidth_cjk(boost::uint32_t ucs)
+ {
+ /* sorted list of non-overlapping intervals of East Asian Ambiguous
+ * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
+@@ -295,7 +303,7 @@
+ }
+
+
+-int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
++int mk_wcswidth_cjk(const boost::uint32_t *pwcs, size_t n)
+ {
+ int w, width = 0;
+
+@@ -307,3 +315,5 @@
+
+ return width;
+ }
++
++} // namespace ledger
diff --git a/src/wcwidth.cc b/src/wcwidth.cc
new file mode 100644
index 00000000..c23f83d7
--- /dev/null
+++ b/src/wcwidth.cc
@@ -0,0 +1,319 @@
+/*
+ * This is an implementation of wcwidth() and wcswidth() (defined in
+ * IEEE Std 1002.1-2001) for Unicode.
+ *
+ * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
+ * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
+ *
+ * In fixed-width output devices, Latin characters all occupy a single
+ * "cell" position of equal width, whereas ideographic CJK characters
+ * occupy two such cells. Interoperability between terminal-line
+ * applications and (teletype-style) character terminals using the
+ * UTF-8 encoding requires agreement on which character should advance
+ * the cursor by how many cell positions. No established formal
+ * standards exist at present on which Unicode character shall occupy
+ * how many cell positions on character terminals. These routines are
+ * a first attempt of defining such behavior based on simple rules
+ * applied to data provided by the Unicode Consortium.
+ *
+ * For some graphical characters, the Unicode standard explicitly
+ * defines a character-cell width via the definition of the East Asian
+ * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
+ * In all these cases, there is no ambiguity about which width a
+ * terminal shall use. For characters in the East Asian Ambiguous (A)
+ * class, the width choice depends purely on a preference of backward
+ * compatibility with either historic CJK or Western practice.
+ * Choosing single-width for these characters is easy to justify as
+ * the appropriate long-term solution, as the CJK practice of
+ * displaying these characters as double-width comes from historic
+ * implementation simplicity (8-bit encoded characters were displayed
+ * single-width and 16-bit ones double-width, even for Greek,
+ * Cyrillic, etc.) and not any typographic considerations.
+ *
+ * Much less clear is the choice of width for the Not East Asian
+ * (Neutral) class. Existing practice does not dictate a width for any
+ * of these characters. It would nevertheless make sense
+ * typographically to allocate two character cells to characters such
+ * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
+ * represented adequately with a single-width glyph. The following
+ * routines at present merely assign a single-cell width to all
+ * neutral characters, in the interest of simplicity. This is not
+ * entirely satisfactory and should be reconsidered before
+ * establishing a formal standard in this area. At the moment, the
+ * decision which Not East Asian (Neutral) characters should be
+ * represented by double-width glyphs cannot yet be answered by
+ * applying a simple rule from the Unicode database content. Setting
+ * up a proper standard for the behavior of UTF-8 character terminals
+ * will require a careful analysis not only of each Unicode character,
+ * but also of each presentation form, something the author of these
+ * routines has avoided to do so far.
+ *
+ * http://www.unicode.org/unicode/reports/tr11/
+ *
+ * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted. The author
+ * disclaims all warranties with regard to this software.
+ *
+ * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
+ */
+
+/* This file is modified to work with C++ and present Unicode
+ * characters in uint32_t type.
+ */
+
+#include <system.hh>
+
+namespace ledger {
+
+namespace {
+ struct interval {
+ boost::uint32_t first;
+ boost::uint32_t last;
+ };
+}
+
+/* auxiliary function for binary search in interval table */
+static int bisearch(boost::uint32_t ucs, const struct interval *table, int max) {
+ int min = 0;
+ int mid;
+
+ if (ucs < table[0].first || ucs > table[max].last)
+ return 0;
+ while (max >= min) {
+ mid = (min + max) / 2;
+ if (ucs > table[mid].last)
+ min = mid + 1;
+ else if (ucs < table[mid].first)
+ max = mid - 1;
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* The following two functions define the column width of an ISO 10646
+ * character as follows:
+ *
+ * - The null character (U+0000) has a column width of 0.
+ *
+ * - Other C0/C1 control characters and DEL will lead to a return
+ * value of -1.
+ *
+ * - Non-spacing and enclosing combining characters (general
+ * category code Mn or Me in the Unicode database) have a
+ * column width of 0.
+ *
+ * - SOFT HYPHEN (U+00AD) has a column width of 1.
+ *
+ * - Other format characters (general category code Cf in the Unicode
+ * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
+ *
+ * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
+ * have a column width of 0.
+ *
+ * - Spacing characters in the East Asian Wide (W) or East Asian
+ * Full-width (F) category as defined in Unicode Technical
+ * Report #11 have a column width of 2.
+ *
+ * - All remaining characters (including all printable
+ * ISO 8859-1 and WGL4 characters, Unicode control characters,
+ * etc.) have a column width of 1.
+ *
+ * This implementation assumes that wchar_t characters are encoded
+ * in ISO 10646.
+ */
+
+int mk_wcwidth(boost::uint32_t ucs)
+{
+ /* sorted list of non-overlapping intervals of non-spacing characters */
+ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
+ static const struct interval combining[] = {
+ { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
+ { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
+ { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
+ { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
+ { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
+ { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
+ { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
+ { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
+ { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
+ { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
+ { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
+ { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
+ { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
+ { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
+ { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
+ { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
+ { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
+ { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
+ { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
+ { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
+ { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
+ { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
+ { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
+ { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
+ { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
+ { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
+ { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
+ { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
+ { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
+ { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
+ { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
+ { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
+ { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
+ { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
+ { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
+ { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
+ { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
+ { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
+ { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
+ { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
+ { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
+ { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
+ { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
+ { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
+ { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
+ { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
+ { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
+ { 0xE0100, 0xE01EF }
+ };
+
+ /* test for 8-bit control characters */
+ if (ucs == 0)
+ return 0;
+ if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
+ return -1;
+
+ /* binary search in table of non-spacing characters */
+ if (bisearch(ucs, combining,
+ sizeof(combining) / sizeof(struct interval) - 1))
+ return 0;
+
+ /* if we arrive here, ucs is not a combining or C0/C1 control character */
+
+ return 1 +
+ (ucs >= 0x1100 &&
+ (ucs <= 0x115f || /* Hangul Jamo init. consonants */
+ ucs == 0x2329 || ucs == 0x232a ||
+ (ucs >= 0x2e80 && ucs <= 0xa4cf &&
+ ucs != 0x303f) || /* CJK ... Yi */
+ (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
+ (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
+ (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
+ (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
+ (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
+ (ucs >= 0xffe0 && ucs <= 0xffe6) ||
+ (ucs >= 0x20000 && ucs <= 0x2fffd) ||
+ (ucs >= 0x30000 && ucs <= 0x3fffd)));
+}
+
+
+int mk_wcswidth(const boost::uint32_t *pwcs, size_t n)
+{
+ int w, width = 0;
+
+ for (;*pwcs && n-- > 0; pwcs++)
+ if ((w = mk_wcwidth(*pwcs)) < 0)
+ return -1;
+ else
+ width += w;
+
+ return width;
+}
+
+
+/*
+ * The following functions are the same as mk_wcwidth() and
+ * mk_wcswidth(), except that spacing characters in the East Asian
+ * Ambiguous (A) category as defined in Unicode Technical Report #11
+ * have a column width of 2. This variant might be useful for users of
+ * CJK legacy encodings who want to migrate to UCS without changing
+ * the traditional terminal character-width behaviour. It is not
+ * otherwise recommended for general use.
+ */
+int mk_wcwidth_cjk(boost::uint32_t ucs)
+{
+ /* sorted list of non-overlapping intervals of East Asian Ambiguous
+ * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
+ static const struct interval ambiguous[] = {
+ { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
+ { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
+ { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
+ { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
+ { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
+ { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
+ { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
+ { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
+ { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
+ { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
+ { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
+ { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
+ { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
+ { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
+ { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
+ { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
+ { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
+ { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
+ { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
+ { 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
+ { 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
+ { 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
+ { 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
+ { 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
+ { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
+ { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
+ { 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
+ { 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
+ { 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
+ { 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
+ { 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
+ { 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
+ { 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
+ { 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
+ { 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
+ { 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
+ { 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
+ { 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
+ { 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
+ { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
+ { 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
+ { 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
+ { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
+ { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
+ { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
+ { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
+ { 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
+ { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
+ { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
+ { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
+ { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
+ { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
+ };
+
+ /* binary search in table of non-spacing characters */
+ if (bisearch(ucs, ambiguous,
+ sizeof(ambiguous) / sizeof(struct interval) - 1))
+ return 2;
+
+ return mk_wcwidth(ucs);
+}
+
+
+int mk_wcswidth_cjk(const boost::uint32_t *pwcs, size_t n)
+{
+ int w, width = 0;
+
+ for (;*pwcs && n-- > 0; pwcs++)
+ if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
+ return -1;
+ else
+ width += w;
+
+ return width;
+}
+
+} // namespace ledger
diff --git a/src/xact.cc b/src/xact.cc
index 7ea15322..5369c138 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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
@@ -185,7 +185,7 @@ bool xact_base_t::finalize()
if (post_account_bad || null_post_account_bad)
throw_(std::logic_error,
- _f("Posting with null amount's account may be mispelled:\n \"%1%\"")
+ _f("Posting with null amount's account may be misspelled:\n \"%1%\"")
% (post_account_bad ? post->account->fullname() :
null_post->account->fullname()));
else
@@ -292,9 +292,9 @@ bool xact_base_t::finalize()
_("A posting's cost must be of a different commodity than its amount"));
cost_breakdown_t breakdown =
- commodity_pool_t::current_pool->exchange
- (post->amount, *post->cost, false, ! post->has_flags(POST_COST_VIRTUAL),
- datetime_t(date(), time_duration(0, 0, 0, 0)));
+ commodity_pool_t::current_pool->exchange(
+ post->amount, *post->cost, false, ! post->has_flags(POST_COST_VIRTUAL),
+ datetime_t(date(), time_duration(0, 0, 0, 0)));
if (post->amount.has_annotation() && post->amount.annotation().price) {
if (breakdown.basis_cost.commodity() == breakdown.final_cost.commodity()) {
@@ -304,10 +304,9 @@ bool xact_base_t::finalize()
DEBUG("xact.finalize", "gain_loss = " << gain_loss);
gain_loss.in_place_round();
DEBUG("xact.finalize", "gain_loss rounds to = " << gain_loss);
-
if (post->must_balance())
add_or_set_value(balance, gain_loss.reduced());
-
+#if 0
account_t * account;
if (gain_loss.sign() > 0)
account = journal->find_account(_("Equity:Capital Gains"));
@@ -321,6 +320,9 @@ bool xact_base_t::finalize()
p->add_flags(post->flags() & (POST_VIRTUAL | POST_MUST_BALANCE));
}
add_post(p);
+#else
+ *post->cost += gain_loss;
+#endif
DEBUG("xact.finalize", "added gain_loss, balance = " << balance);
} else {
DEBUG("xact.finalize", "gain_loss would have displayed as zero");
@@ -393,7 +395,10 @@ bool xact_base_t::finalize()
some_null = true;
}
- post->account->add_post(post);
+ if (post->has_flags(POST_DEFERRED))
+ 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);
diff --git a/src/xact.h b/src/xact.h
index e59ead75..3ca57953 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2013, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, 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