lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master d1f11ea 1/3: Replace boost::filesystem with s


From: Greg Chicares
Subject: [lmi-commits] [lmi] master d1f11ea 1/3: Replace boost::filesystem with std::filesystem
Date: Thu, 29 Apr 2021 12:32:39 -0400 (EDT)

branch: master
commit d1f11ea63ee32b10c88c61bfac2f30b686302c7d
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Replace boost::filesystem with std::filesystem
    
    Squashed commit of the following:
    
    commit afc9c0e1ab33b704f738f0ef01efd9e352592aa4
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Sat Apr 24 17:40:57 2021 +0200
    
        Remove all remaining mentions of Boost.Filesystem
    
        The files containing these mentions were obsolete in any case and still
        need to be more generally revised, but for now just don't mention the
        library which is not used any longer in them.
    
    commit 71660ded81dbbf0cbb345b6d2a3359ba41779f72
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Sat Apr 24 17:40:07 2021 +0200
    
        Don't build Boost.Filesystem objects in makefiles any longer
    
        This library is not used any more, so stop using it and remove all
        occurrences of boost_filesystem_objects make variable.
    
    commit fe19fd3fd25387f3eeb4f8f6c775435f594c96f6
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Sat Apr 24 17:31:40 2021 +0200
    
        Remove unused platform_boost_libraries make variable
    
        This allows to also get rid of the comments mentioning Boost.Filesystem,
        which is useful as this library is not supposed to be used anywhere any
        longer.
    
    commit f6639a5a2cfbfa32ff881949d4d27d24b53f0ab6
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Mon Dec 28 12:08:35 2020 +0700
    
        Allow path unit tests to pass when using any root name part
    
        Previously, the check in test_oddities() only passed when the current
        root name was "Z:" (which is its default value when using Wine) because
        one of the tests compared the result of calling fs::absolute(), which
        used the actual root name to complete a non-absolute MSW path, with the
        hard-coded string always using "Z:" as the root name.
    
        Fix this by using the actual root name value if available and only
        falling back on "Z:" if it isn't, in which case the exact value used
        doesn't matter anyhow.
    
        Also update the comment which still mentioned boost::filesystem.
    
    commit fcb817ca243dd8b040212092b5efc08d8c9939ad
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Sat Apr 24 15:46:10 2021 +0200
    
        Don't refer to Boost.Filesystems in comments
    
        This library is not used any longer, so don't mention it, even in the
        comments.
    
        Change references to it to the references to std::filesystem where
        applicable or just remove them otherwise.
    
    commit 577a718743ecb6c288861dc18561eb61f9fec7e4
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Fri Nov 27 01:25:47 2020 +0100
    
        Remove the check for Boost.Filesystem library from configure
    
        This is not needed any more, as this library is no longer used.
    
    commit dab074e388422f328933752ae6965560e2c9a62e
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Fri Nov 27 01:16:15 2020 +0100
    
        Revert "Trap exceptions from filesystem library"
    
        This reverts commit 14d582d499d7487ba10e81d9f2213d876b102d78 as it is
        not needed any longer with std::filesystem which doesn't throw
        exceptions if the path contains "invalid" characters.
    
        This commit is best viewed ignoring whitespace-only changes.
    
    commit b521eb148dc51bf6dd99a6d6f7502e17754f85ba
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 24 03:21:45 2020 +0700
    
        Improve remove_nothrow() using non-throwing fs::remove() overload
    
        It is better to avoid throwing any exceptions in the first place, rather
        than throwing and ignoring them.
    
    commit b24248a73b7f99d09b430507589f1a3c03d5d0d5
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Wed Sep 23 19:22:00 2020 +0700
    
        Fix modify_directory() unit test
    
        The expected exception is thrown now.
    
    commit 5c0806ff7bdac97bc14cfd88f99da190337d06b5
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Wed Sep 23 22:13:04 2020 +0700
    
        Fix validate_path() test
    
        std::filesystem::path() ctor from string doesn't throw even if the
        path is invalid.
    
    commit 6bfe84328ddddf27938afb35c776b9b602bef58a
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Sat Apr 24 15:42:48 2021 +0200
    
        Revert "Work around a boost issue"
    
        This reverts commit 9a631cddf896eeda5c4fc2d8f2817cbcda612918 as the
        unexpected exception is not thrown when using std::filesystem.
    
        Notice that the test may still fail in the situation described in the
        comment being removed by this commit, i.e. if a path exists but is
        inaccessible, because chdir() fails in this scenario. However
        is_directory() still returns true, without throwing any exceptions, even
        when using an unformatted disk in a drive.
    
    commit e390d8937770edf8e4cd8f03cbc082e31a397064
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Wed Sep 23 21:47:16 2020 +0700
    
        Fix test of unique_filepath()
    
        fs::replace_extension() doesn't throw an exception, even under MSW, when
        replacing ".." with "..".
    
    commit c9ee04b8f09c48e2f20b8ec5abe2b566ff8ff500
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Mon Sep 21 00:34:22 2020 +0700
    
        Remove path::default_name_check() unavailable in std::filesystem
    
        There is simply no support for name-checking policies in the standard
        filesystem library.
    
    commit 178f347247420b384382da7b7f578de2feda6376
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Mon Sep 21 00:32:22 2020 +0700
    
        Fix fs::path ctor the authenticity test
    
        Don't use fs::native, it was renamed and is not necessary anyhow.
    
    commit efea55c19ba27fc5dfb25069627fb8031f6f4b5e
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Sat Oct 3 12:07:38 2020 +0700
    
        Get rid of fs::path::native_file_string()
    
    commit 85331ef1be9524ac591470dedd78b49dd554bd06
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Fri Sep 18 02:22:05 2020 +0700
    
        Replace boost::filesystem::filesystem_error with the std one
    
    commit a50fc2f5ea6738181a0abb4e81cdf86282739322
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 05:45:57 2020 +0700
    
        Update output_file_existence_checker::path() return value
    
        Return string() by value, not reference, as our wrapper class string()
        returns a temporary string.
    
    commit 5d5cdc836e0087945adb7040a50cb1b87192c12e
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 05:28:34 2020 +0700
    
        Replace fs::path::branch_path() with fs::path::parent_path()
    
    commit 80374a36317c6ccba25e640060f5dc58f347253a
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 05:22:48 2020 +0700
    
        Replace fs::path::leaf() with fs::path::filename()
    
    commit c15a7896a270019357b12a9b4215822d10b6dcbc
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 05:15:44 2020 +0700
    
        Replace fs::path::has_leaf() with fs::path::has_filename()
    
    commit c5025e865d728f875c99f5d12f8595ced907c8f1
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 04:37:38 2020 +0700
    
        Fix return type of fs::last_write_time()
    
        It is not std::time_t any longer, but fs::file_time_type.
    
    commit c5381bf1a2918b1ec9661fd09d5cb4da41e9079f
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 04:20:26 2020 +0700
    
        Replace fs::basename() with fs::path::stem()
    
    commit 177eb8c607821480372a0d65f341c47d5fa521bc
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 03:54:50 2020 +0700
    
        Replace fs::extension() with fs::path::extension()
    
    commit 25b3752c778343189a37a542e753b0cadb928e06
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 03:36:07 2020 +0700
    
        Use path() accessor of fs::directory_iterator
    
        We can't rely on implicit conversion to path() any longer, so explicitly
        use the accessor.
    
        Also use range-based for loops for iterating, as this results in much
        simpler code.
    
    commit 7f1c52b3783a7c60fc70bc2e8e96930bf7f476f3
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 03:12:51 2020 +0700
    
        Use fs::path::replace_extension() instead of fs::change_extension()
    
    commit 9968b41d50833239993d1da493f114786f71f286
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 02:49:02 2020 +0700
    
        Replace boost [system_]complete() with std::fs::absolute()
    
    commit 5974ae42c599f47a291faa5960f5e2c09ca2b297
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Sat Oct 3 09:52:06 2020 +0700
    
        Replace Boost.Filesystem headers with path.hpp
    
    commit 214c424995290c8f2fd4827ed3a20eb676911762
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Sat Oct 3 09:40:15 2020 +0700
    
        Remove namespace fs as the alias to boost::filesystem
    
    commit 9b6bf1812ab8f0489635670c3b11477fcef59f28
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Thu Sep 17 02:10:37 2020 +0700
    
        Remove initialize_filesystem()
    
    commit 1bae2aa51271c06ba91fe85a9cff7d96b7becb93
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Fri Feb 26 17:37:56 2021 +0100
    
        Delete fs::ifstream and ofstream move ctors
    
        These ctors don't exist because they're deleted in the corresponding
        base classes, and explicitly defaulting them is misleading (because it
        might lead one to believe that they are available, when this is not the
        case) and results in -Wdefaulted-function-deleted from clang.
    
        Just delete them explicitly for clarity and to avoid the warnings.
    
    commit d72f6683b19174027a00d79920d08090c09d6b60
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Sat Oct 3 10:39:27 2020 +0700
    
        Implement our own file streams
    
    commit 78bc047493f1a5f1b1903c76104db5a5cdd35cac
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Sat Apr 24 19:42:49 2021 +0200
    
        Avoid warnings about deprecated std::filesystem::u8path()
    
        This C++17 function has already been deprecated in C++20 and some
        standard library implementations have been updated to discourage its
        use (MSVS 2019, clang 12), however we can't easily avoid using it
        completely currently, as other implementations don't include the C++20
        replacement for it yet (clang 10), so just suppress the warning for now.
    
    commit b1505c8179db736a6a91ad840af58ad47553720c
    Author: Vadim Zeitlin <vadim@tt-solutions.com>
    Date:   Fri Nov 27 22:55:47 2020 +0100
    
        Make fs::path compile with both C++17 and C++20 std::filesystem
    
        The return type of u8string() and generic_u8string() functions has
        changed in an incompatible way in C++20 compared to C++17 as they now
        return std::u8string, i.e. the specialization of std::basic_string<> for
        char8_t, rather std::string, i.e. the specialization for char, and
        char_t and char are incompatible types in spite of usually having the
        same representation.
    
        Fix this simply by reinterpreting char8_t string as char one, if
        necessary, as we already assume that all strings are encoded using UTF-8
        (which includes all ASCII strings as a special case of UTF-8 encoding).
    
    commit 17140a7e71dc45355f1cc0d20c8f4a450768a480
    Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
    Date:   Sat Oct 3 09:57:24 2020 +0700
    
        Implement our own fs::path class
    
        Do this instead of just aliasing std::Filesystem::path in order to
        provide consistent semantics in C++17 and C++20 and to be able to
        customize its conversion to string (notably, avoid quoting).
---
 README.auto                    |  17 --
 actuarial_table.cpp            |   9 +-
 authenticity.cpp               |   4 +-
 authenticity.hpp               |   3 +-
 authenticity_test.cpp          |  34 +--
 bcc_5_5_1.make                 |   6 -
 cache_file_reads.hpp           |  10 +-
 cache_file_reads_test.cpp      |   6 +-
 ce_product_name.cpp            |  13 +-
 ce_skin_name.cpp               |  13 +-
 census_view.cpp                |   5 +-
 config.hpp                     |   6 -
 configurable_settings.cpp      |  28 +-
 configurable_settings_test.cpp |   8 +-
 configure.ac                   |  12 +-
 data_directory.cpp             |   6 +-
 dbdict.cpp                     |  16 +-
 dbdict.hpp                     |   3 +-
 debian/lmi.substvars           |   2 +-
 emit_ledger.cpp                |  10 +-
 emit_ledger.hpp                |   3 +-
 file_command_wx.cpp            |  14 +-
 fund_data.cpp                  |   5 +-
 fund_data.hpp                  |   3 +-
 generate_product_files.cpp     |   3 -
 global_settings.cpp            |   2 +-
 global_settings.hpp            |   8 +-
 global_settings_test.cpp       |  27 +-
 gpt_server.cpp                 |   8 +-
 gpt_server.hpp                 |   3 +-
 gpt_state.cpp                  |   3 +-
 group_values.hpp               |   3 +-
 icon_monger.cpp                |   4 +-
 illustrator.cpp                |   5 +-
 illustrator.hpp                |   3 +-
 input_test.cpp                 |   4 -
 ledger_evaluator.cpp           |   4 +-
 ledger_evaluator.hpp           |   3 +-
 ledger_pdf.hpp                 |   3 +-
 ledger_test.cpp                |   4 -
 lingo.cpp                      |   4 +-
 lingo.hpp                      |   3 +-
 main_cgi.cpp                   |   3 -
 main_cli.cpp                   |   7 +-
 main_common.cpp                |   3 -
 main_common_non_wx.cpp         |   3 -
 main_wx.cpp                    |   2 -
 main_wx_test.cpp               |  12 +-
 md5sum.hpp                     |   3 +-
 md5sum_test.cpp                |   4 +-
 mec_server.cpp                 |   8 +-
 mec_server.hpp                 |   3 +-
 mec_state.cpp                  |   3 +-
 msw_common.make                |  10 -
 name_value_pairs_test.cpp      |   9 +-
 objects.make                   |  40 +--
 path.hpp                       | 566 +++++++++++++++++++++++++++++++++++++++++
 path_utility.cpp               | 132 ++--------
 path_utility.hpp               |  18 +-
 path_utility_test.cpp          |  83 +++---
 pchlist.hpp                    |   5 +-
 pdf_command.hpp                |   3 +-
 posix_fhs.make                 |   7 -
 preferences_model.cpp          |  12 +-
 premium_tax_test.cpp           |   4 -
 product_data.cpp               |  11 +-
 product_data.hpp               |   3 +-
 product_file_test.cpp          |   7 +-
 rate_table.cpp                 |  25 +-
 rate_table.hpp                 |   3 +-
 rate_table_test.cpp            |   4 +-
 rate_table_tool.cpp            |  12 +-
 rounding_rules.cpp             |   3 +-
 rounding_rules.hpp             |   3 +-
 skeleton.cpp                   |  12 +-
 stratified_charges.hpp         |   3 +-
 test_coding_rules.cpp          |  10 +-
 view_ex.cpp                    |   9 +-
 workhorse.make                 |  10 -
 wx_test_benchmark_census.cpp   |  14 +-
 wx_test_case.hpp               |   3 +-
 wx_test_config_settings.cpp    |   3 +-
 wx_test_default_update.cpp     |   3 +-
 wx_test_expiry_dates.cpp       |   4 +-
 wx_test_output.hpp             |   5 +-
 wx_test_output_pdf.hpp         |   3 +-
 xml_serializable.hpp           |   3 +-
 xml_serializable.tpp           |   5 +-
 88 files changed, 789 insertions(+), 639 deletions(-)

diff --git a/README.auto b/README.auto
index 1dc0d20..b78a53b 100644
--- a/README.auto
+++ b/README.auto
@@ -59,21 +59,6 @@ a) wxWidgets: create any directory (it will be called 
wx-build below),
         wxWidgets with debugging enabled (highly recommended during
         development!).
 
-b) boost: static boost_filesystem library is available as a standard cygwin
-        package but if you want to use shared libraries or use mingw32, you
-        need to build this library yourself (the rest of boost classes used by
-        lmi are headers only and don't have to be built at all) using the
-        standard instruction from http://www.boost.org/
-
-        Notice that if you don't have shared boost libraries, libtool won't be
-        able to build shared liblmi and so using it will be just a waste of a
-        couple of dozens of megabytes.
-
-        Under Unix, at the time of this writing (2005-11-01) Debian has boost
-        packages built with g++ 3.3 but they are not binary compatible with g++
-        3.4/4.0 so if you use the latter you *must* build from source or you
-        get mysterious run-time crashes.
-
 2. Build system setup
 ---------------------
 
@@ -105,8 +90,6 @@ useful ones are:
 
     --prefix=/opt/lmi           to install /opt and not default /usr/local
     --with-wxdir=$wx-build      to use uninstalled wx version from $wx-build
-    --with-boost-filesystem-src to compile a custom boost_filesystem library
-                                using boost sources
     --enable-debug              to enable debugging (asserts...)
     --disable-shared            to build static libraries only (for deployment)
 
diff --git a/actuarial_table.cpp b/actuarial_table.cpp
index e9edad5..3d7cfab 100644
--- a/actuarial_table.cpp
+++ b/actuarial_table.cpp
@@ -29,13 +29,10 @@
 #include "deserialize_cast.hpp"
 #include "miscellany.hpp"
 #include "oecumenic_enumerations.hpp"   // methuselah
+#include "path.hpp"
 #include "path_utility.hpp"             // fs::path inserter
 #include "ssize_lmi.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <algorithm>                    // max(), min()
 #if 202002 <= __cplusplus
 #   include <bit>                       // endian
@@ -207,7 +204,7 @@ void actuarial_table::find_table()
     LMI_ASSERT(0 != table_number_);
 
     fs::path index_path(filename_);
-    index_path = fs::change_extension(index_path, ".ndx");
+    index_path.replace_extension(".ndx");
     fs::ifstream index_ifs(index_path, ios_in_binary());
     if(!index_ifs)
         {
@@ -297,7 +294,7 @@ void actuarial_table::parse_table()
     LMI_ASSERT(-1 == max_select_age_);
 
     fs::path data_path(filename_);
-    data_path = fs::change_extension(data_path, ".dat");
+    data_path.replace_extension(".dat");
     fs::ifstream data_ifs(data_path, ios_in_binary());
     if(!data_ifs)
         {
diff --git a/authenticity.cpp b/authenticity.cpp
index 77de707..9480191 100644
--- a/authenticity.cpp
+++ b/authenticity.cpp
@@ -30,12 +30,10 @@
 #include "handle_exceptions.hpp"        // report_exception()
 #include "md5.hpp"
 #include "md5sum.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"             // fs::path inserter
 #include "timer.hpp"
 
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/operations.hpp>
-
 #include <cstdio>                       // fclose(), fopen()
 #include <cstdlib>                      // exit(), EXIT_FAILURE
 #include <cstring>                      // memcpy()
diff --git a/authenticity.hpp b/authenticity.hpp
index 1ce2f30..74dee17 100644
--- a/authenticity.hpp
+++ b/authenticity.hpp
@@ -25,10 +25,9 @@
 #include "config.hpp"
 
 #include "calendar_date.hpp"
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 
 /// Permit running the system iff data files and date are valid.
diff --git a/authenticity_test.cpp b/authenticity_test.cpp
index 4c8d386..22eafec 100644
--- a/authenticity_test.cpp
+++ b/authenticity_test.cpp
@@ -28,14 +28,11 @@
 #include "md5.hpp"
 #include "md5sum.hpp"
 #include "miscellany.hpp"
+#include "path.hpp"
 #include "system_command.hpp"
 #include "test_tools.hpp"
 #include "unwind.hpp"                   // scoped_unwind_toggler
 
-#include <boost/filesystem/convenience.hpp> // basename()
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <cstdio>                       // remove()
 #include <cstring>                      // memcpy(), strlen()
 #include <fstream>
@@ -280,20 +277,12 @@ void PasskeyTest::CheckNominal(char const* file, int 
line) const
 /// tested because it's common and problematic. This test assumes that
 /// an 'F:' drive exists and is not the "current" drive; it is skipped
 /// if no 'F:' drive exists.
-///
-/// BOOST !! This test traps an exception that boost-1.33.1 can throw
-/// if exists("F:/") returns true but ::GetFileAttributesA() fails.
-/// That's supposed to be impossible because the is_directory()
-/// documentation says:
-///   "Throws: if !exists(ph)"
-/// but it can be reproduced by placing an unformatted disk in "F:".
-
 void PasskeyTest::TestFromAfar() const
 {
     CheckNominal(__FILE__, __LINE__);
 
-    std::string const tmp = "/tmp/" + fs::basename(__FILE__);
-    fs::path const remote_dir_0(fs::complete(tmp));
+    fs::path const tmp = "/tmp" / fs::path{__FILE__}.stem();
+    fs::path const remote_dir_0(fs::absolute(tmp));
     fs::create_directory(remote_dir_0);
     LMI_TEST(fs::exists(remote_dir_0) && fs::is_directory(remote_dir_0));
     LMI_TEST_EQUAL(0, chdir(remote_dir_0.string().c_str()));
@@ -308,26 +297,13 @@ void PasskeyTest::TestFromAfar() const
 #if defined LMI_MSW
     CheckNominal(__FILE__, __LINE__);
 
-    fs::path const remote_dir_1(fs::complete(fs::path("F:/", fs::native)));
+    fs::path const remote_dir_1(fs::absolute("F:/"));
     if(!fs::exists(remote_dir_1))
         {
         goto done;
         }
 
-    try
-        {
-        LMI_TEST(fs::is_directory(remote_dir_1));
-        }
-    catch(std::exception const& e)
-        {
-        std::string s(e.what());
-        if(contains(s, "boost::filesystem::is_directory"))
-            {
-            LMI_TEST(false);
-            goto done;
-            }
-        throw;
-        }
+    LMI_TEST(fs::is_directory(remote_dir_1));
 
     LMI_TEST_EQUAL(0, chdir(remote_dir_1.string().c_str()));
     LMI_TEST_EQUAL(remote_dir_1.string(), fs::current_path().string());
diff --git a/bcc_5_5_1.make b/bcc_5_5_1.make
index bf6b3ab..cce1668 100644
--- a/bcc_5_5_1.make
+++ b/bcc_5_5_1.make
@@ -121,11 +121,6 @@ LDFLAGS := \
   -L$(bcc_lib_dir) /ap /c /E0 /m /Tpe /V4.0 /w /w-dup /w-dpl \
   --startup-file $(bcc_lib_dir)/c0x32.obj import32.lib cw32i.lib \
 
-# The borland compiler can't handle the boost filesystem code, but it
-# can limp through some tests by pretending that code doesn't exist.
-
-boost_filesystem_objects :=
-
 # The borland compiler rejects some conforming code, generating many
 # spurious and distracting diagnostics; it fails utterly to build
 # these tests:
@@ -255,7 +250,6 @@ bcc_5_5_1.make:: ;
                                   CXXFLAGS='$(CXXFLAGS)' \
                                         LD='$(LD)' \
                                    LDFLAGS='$(LDFLAGS)' \
-                  boost_filesystem_objects='$(boost_filesystem_objects)' \
                 excluded_unit_test_targets='$(excluded_unit_test_targets)' \
                                    GNU_CPP='$(GNU_CPP)' \
                                    GNU_CXX='$(GNU_CXX)' \
diff --git a/cache_file_reads.hpp b/cache_file_reads.hpp
index 2251363..f4e359f 100644
--- a/cache_file_reads.hpp
+++ b/cache_file_reads.hpp
@@ -25,9 +25,7 @@
 #include "config.hpp"
 
 #include "assert_lmi.hpp"
-
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
+#include "path.hpp"
 
 #include <ctime>                        // time_t
 #include <map>
@@ -71,7 +69,7 @@ class file_cache
     retrieved_type retrieve_or_reload(fs::path const& filename)
         {
         // Throws if !exists(filename).
-        std::time_t const write_time = fs::last_write_time(filename);
+        auto const write_time = fs::last_write_time(filename);
 
         auto i = cache_.lower_bound(filename);
         if
@@ -102,8 +100,8 @@ class file_cache
 
     struct record
     {
-        retrieved_type data;
-        std::time_t    write_time;
+        retrieved_type     data;
+        fs::file_time_type write_time;
     };
 
     std::map<fs::path,record> cache_;
diff --git a/cache_file_reads_test.cpp b/cache_file_reads_test.cpp
index 9fb48ee..c9e519a 100644
--- a/cache_file_reads_test.cpp
+++ b/cache_file_reads_test.cpp
@@ -25,12 +25,10 @@
 
 #include "istream_to_string.hpp"
 #include "miscellany.hpp"               // ios_in_binary()
+#include "path.hpp"
 #include "test_tools.hpp"
 #include "timer.hpp"
 
-#include <boost/filesystem/exception.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <fstream>
 
 class X
@@ -83,7 +81,7 @@ void cache_file_reads_test::test_preconditions()
     // The file must exist.
     LMI_TEST_THROW
         (X::read_via_cache("no_such_file")
-        ,boost::filesystem::filesystem_error
+        ,std::filesystem::filesystem_error
         ,lmi_test::what_regex("no_such_file")
         );
 }
diff --git a/ce_product_name.cpp b/ce_product_name.cpp
index af3e7c9..9e829be 100644
--- a/ce_product_name.cpp
+++ b/ce_product_name.cpp
@@ -28,13 +28,10 @@
 #include "contains.hpp"
 #include "facets.hpp"
 #include "global_settings.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"             // fs::path inserter
 #include "ssize_lmi.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <algorithm>                    // find()
 #include <istream>
 #include <ostream>
@@ -45,15 +42,13 @@ std::vector<std::string> fetch_product_names()
 {
     fs::path path(global_settings::instance().data_directory());
     std::vector<std::string> names;
-    fs::directory_iterator i(path);
-    fs::directory_iterator end_i;
-    for(; i != end_i; ++i)
+    for(auto const& de : fs::directory_iterator(path))
         {
-        if(".policy" != fs::extension(*i) || is_directory(*i))
+        if(".policy" != de.path().extension() || de.is_directory())
             {
             continue;
             }
-        names.push_back(basename(*i));
+        names.push_back(de.path().stem().string());
         }
 
     if(names.empty())
diff --git a/ce_skin_name.cpp b/ce_skin_name.cpp
index c232ff1..b4d9ebe 100644
--- a/ce_skin_name.cpp
+++ b/ce_skin_name.cpp
@@ -29,13 +29,10 @@
 #include "facets.hpp"
 #include "global_settings.hpp"
 #include "miscellany.hpp"               // begins_with()
+#include "path.hpp"
 #include "path_utility.hpp"             // fs::path inserter
 #include "ssize_lmi.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <algorithm>                    // find()
 
 namespace
@@ -44,15 +41,13 @@ std::vector<std::string> fetch_skin_names()
 {
     fs::path path(global_settings::instance().data_directory());
     std::vector<std::string> names;
-    fs::directory_iterator i(path);
-    fs::directory_iterator end_i;
-    for(; i != end_i; ++i)
+    for(auto const& de : fs::directory_iterator(path))
         {
-        if(is_directory(*i) || ".xrc" != fs::extension(*i))
+        if(de.is_directory() || ".xrc" != de.path().extension())
             {
             continue;
             }
-        std::string const name(i->leaf());
+        std::string const name(de.path().filename().string());
         if(!begins_with(name, "skin"))
             {
             continue;
diff --git a/census_view.cpp b/census_view.cpp
index 9ee061d..35cffe3 100644
--- a/census_view.cpp
+++ b/census_view.cpp
@@ -41,6 +41,7 @@
 #include "ledger.hpp"
 #include "ledger_text_formats.hpp"
 #include "miscellany.hpp"               // is_ok_for_cctype(), 
ios_out_app_binary()
+#include "path.hpp"
 #include "path_utility.hpp"             // unique_filepath()
 #include "rtti_lmi.hpp"                 // lmi::TypeInfo
 #include "safely_dereference_as.hpp"
@@ -50,8 +51,6 @@
 #include "wx_new.hpp"
 #include "wx_utility.hpp"               // class ClipboardEx
 
-#include <boost/filesystem/convenience.hpp> // basename()
-
 #include <wx/datectrl.h>
 #include <wx/grid.h>
 #include <wx/headercol.h>               // wxCOL_WIDTH_DEFAULT
@@ -2000,7 +1999,7 @@ void CensusView::DoCopyCensus() const
     configurable_settings const& c = configurable_settings::instance();
     std::string const& print_dir = c.print_directory();
     std::string const& tsv_ext = c.spreadsheet_file_extension();
-    std::string const f = fs::basename(base_filename()) + ".census.cns";
+    fs::path const f = 
fs::path{base_filename()}.replace_extension(".census.cns");
     fs::path const g(modify_directory(f, print_dir));
     std::string file_name = unique_filepath(g, tsv_ext).string();
     std::ofstream ofs(file_name.c_str(), ios_out_app_binary());
diff --git a/config.hpp b/config.hpp
index e847c5e..8c6e8e9 100644
--- a/config.hpp
+++ b/config.hpp
@@ -25,12 +25,6 @@
 #ifndef config_hpp
 #define config_hpp
 
-#if defined __cplusplus
-// Namespace alii.
-namespace boost {namespace filesystem {} }
-namespace fs = boost::filesystem;
-#endif // defined __cplusplus
-
 // The msw platform-identifying macro that its vendor encourages
 // people to use contains the word "win". I don't consider a non-free
 // operating system a win, and won't advertise it as such by writing
diff --git a/configurable_settings.cpp b/configurable_settings.cpp
index 679204a..580baf2 100644
--- a/configurable_settings.cpp
+++ b/configurable_settings.cpp
@@ -34,10 +34,6 @@
 #include "path_utility.hpp"             // validate_directory(), 
validate_filepath()
 #include "platform_dependent.hpp"       // access()
 
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <iterator>                     // istream_iterator
 #include <sstream>
 #include <stdexcept>
@@ -122,7 +118,7 @@ std::string const& configuration_filepath()
         }
 
     validate_filepath(filename, "Configurable-settings file");
-    complete_path = fs::system_complete(filename).string();
+    complete_path = fs::absolute(filename).string();
     return complete_path;
 }
 
@@ -146,32 +142,18 @@ configurable_settings::configurable_settings()
     ascribe_members();
     load();
 
-    try
-        {
-        default_input_filename_ = 
fs::system_complete(default_input_filename_).string();
-// Performing this test seems like a good idea, but it would flag
-// an empty path as an error.
-//      validate_filepath(default_input_filename_, "Default input file");
-        }
-    catch(...)
-        {
-        report_exception();
-        // Silently replace invalid path with an empty string,
-        // which will produce an informative diagnostic when
-        // a default is needed.
-        default_input_filename_ = {};
-        }
+    default_input_filename_ = fs::absolute(default_input_filename_  ).string();
+    print_directory_        = remove_alien_msw_root(print_directory_).string();
+    print_directory_        = fs::absolute(print_directory_         ).string();
 
     try
         {
-        print_directory_ = remove_alien_msw_root(print_directory_).string();
-        print_directory_ = fs::system_complete(print_directory_).string();
         validate_directory(print_directory_, "Print directory");
         }
     catch(...)
         {
         report_exception();
-        print_directory_ = fs::system_complete(AddDataDir(".")).string();
+        print_directory_ = fs::absolute(AddDataDir(".")).string();
         warning()
             << "If possible, data directory '"
             << print_directory_
diff --git a/configurable_settings_test.cpp b/configurable_settings_test.cpp
index 28a8ae9..0ebf300 100644
--- a/configurable_settings_test.cpp
+++ b/configurable_settings_test.cpp
@@ -24,12 +24,9 @@
 #include "configurable_settings.hpp"
 
 #include "miscellany.hpp"               // ios_out_trunc_binary()
-#include "path_utility.hpp"             // initialize_filesystem()
+#include "path.hpp"
 #include "test_tools.hpp"
 
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/path.hpp>
-
 class configurable_settings_test
 {
   public:
@@ -97,9 +94,6 @@ void configurable_settings_test::test_backward_compatibility()
 
 int test_main(int, char*[])
 {
-    // Absolute paths require "native" name-checking policy for msw.
-    initialize_filesystem();
-
     configurable_settings_test::test();
 
     return EXIT_SUCCESS;
diff --git a/configure.ac b/configure.ac
index 0c083ee..4febcda 100644
--- a/configure.ac
+++ b/configure.ac
@@ -373,12 +373,11 @@ AC_CHECK_HEADER([boost/type_traits.hpp],
 
 dnl The default boost library name should be used unless otherwise specified
 dnl via --with-boost-tookit options, in which case we need to add
-dnl toolkit suffix to the library name (example -lboost_filesystem-gcc-mt).
+dnl toolkit suffix to the library name (example -lboost_regex-gcc-mt).
 if test "x$lmi_boost_toolkit" != "x"; then
     lmi_boost_toolkit="-$lmi_boost_toolkit"
 fi
 boost_libsystem="boost_system$lmi_boost_toolkit"
-boost_libfs="boost_filesystem$lmi_boost_toolkit"
 boost_libregex="boost_regex$lmi_boost_toolkit"
 
 save_CPPFLAGS=$CPPFLAGS
@@ -406,13 +405,6 @@ dnl usually when we want to check for a library we use 
AC_CHECK_LIB and main()
 dnl but since under mingw with -pedantic and -std= options test does not pass
 dnl we are forced to use a bit more sophisticated construct
 
-LIBS="$LIBS $BOOST_LIBS -l$boost_libfs"
-AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <boost/filesystem/operations.hpp>]],
-    [[boost::filesystem::current_path()]])],
-    [],
-    [AC_MSG_FAILURE([Boost filesystem library $boost_libfs not found, 
$errmsg])]
-)
-
 LIBS="$save_LIBS -l$boost_libregex"
 AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <boost/regex.hpp>]],
     [[boost::regex *r]])],
@@ -424,7 +416,7 @@ LDFLAGS=$save_LDFLAGS
 LIBS=$save_LIBS
 CPPFLAGS=$save_CPPFLAGS
 
-BOOST_LIBS="-l$boost_libfs -l$boost_libregex $BOOST_LIBS"
+BOOST_LIBS="-l$boost_libregex $BOOST_LIBS"
 
 dnl contains flags needed to link to externally or internally built
 dnl boost libraries
diff --git a/data_directory.cpp b/data_directory.cpp
index 2346745..09dd3de 100644
--- a/data_directory.cpp
+++ b/data_directory.cpp
@@ -25,15 +25,13 @@
 
 #include "assert_lmi.hpp"
 #include "global_settings.hpp"
-
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/path.hpp>
+#include "path.hpp"
 
 //============================================================================
 std::string AddDataDir(std::string const& a_filename)
 {
     fs::path path(a_filename);
-    LMI_ASSERT(a_filename == path.leaf());
+    LMI_ASSERT(a_filename == path.filename());
 
     path = global_settings::instance().data_directory() / path;
     return path.string();
diff --git a/dbdict.cpp b/dbdict.cpp
index 8bd7635..44fcf3b 100644
--- a/dbdict.cpp
+++ b/dbdict.cpp
@@ -37,15 +37,12 @@
 #include "miscellany.hpp"
 #include "my_proem.hpp"                 // ::write_proem()
 #include "oecumenic_enumerations.hpp"
+#include "path.hpp"
 #include "premium_tax.hpp"              // 
premium_tax_rates_for_life_insurance()
 #include "sample.hpp"                   // superior::lingo
 #include "xml_lmi.hpp"
 #include "xml_serialize.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/operations.hpp>
-
 #include <vector>
 
 template class xml_serializable<DBDictionary>;
@@ -1615,19 +1612,18 @@ void DBDictionary::InitAntediluvian()
 void print_databases()
 {
     fs::path path(global_settings::instance().data_directory());
-    fs::directory_iterator i(path);
-    fs::directory_iterator end_i;
-    for(; i != end_i; ++i)
+    for(auto const& e : fs::directory_iterator(path))
         {
-        if(is_directory(*i) || ".database" != fs::extension(*i))
+        if(e.is_directory() || ".database" != e.path().extension())
             {
             continue;
             }
         try
             {
-            DBDictionary const z(i->string());
+            DBDictionary const z(e.path().string());
 
-            fs::path out_file = fs::change_extension(*i, ".dbt");
+            fs::path out_file{e.path()};
+            out_file.replace_extension(".dbt");
             fs::ofstream os(out_file, ios_out_trunc_binary());
             for(auto const& j : z.member_names())
                 {
diff --git a/dbdict.hpp b/dbdict.hpp
index 1bdd844..3337fd2 100644
--- a/dbdict.hpp
+++ b/dbdict.hpp
@@ -27,11 +27,10 @@
 #include "any_member.hpp"
 #include "cache_file_reads.hpp"
 #include "dbvalue.hpp"
+#include "path.hpp"
 #include "so_attributes.hpp"
 #include "xml_serializable.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 
 /// Cached product database.
diff --git a/debian/lmi.substvars b/debian/lmi.substvars
index cc0f028..2a19c45 100644
--- a/debian/lmi.substvars
+++ b/debian/lmi.substvars
@@ -1 +1 @@
-shlibs:Depends=libboost-filesystem1.32.0, libc6 (>= 2.3.5-1), libgcc1 (>= 
1:4.0.1), libncurses5 (>= 5.4-5), libstdc++6 (>= 4.0.2), libxml2 (>= 2.6.21), 
zlib1g (>= 1:1.2.1)
+shlibs:Depends=libc6 (>= 2.3.5-1), libgcc1 (>= 1:4.0.1), libncurses5 (>= 
5.4-5), libstdc++6 (>= 4.0.2), libxml2 (>= 2.6.21), zlib1g (>= 1:1.2.1)
diff --git a/emit_ledger.cpp b/emit_ledger.cpp
index 95508ca..8dd7ce2 100644
--- a/emit_ledger.cpp
+++ b/emit_ledger.cpp
@@ -33,12 +33,10 @@
 #include "ledger_pdf.hpp"
 #include "ledger_text_formats.hpp"
 #include "miscellany.hpp"               // ios_out_trunc_binary()
+#include "path.hpp"
 #include "path_utility.hpp"             // unique_filepath()
 #include "timer.hpp"
 
-#include <boost/filesystem/convenience.hpp> // change_extension()
-#include <boost/filesystem/fstream.hpp>
-
 #include <iostream>
 #include <string>
 
@@ -125,7 +123,7 @@ double ledger_emitter::emit_cell
     if(emission_ & mce_emit_test_data)
         {
         fs::ofstream ofs
-            (fs::change_extension(cell_filepath, ".test")
+            (fs::path{cell_filepath}.replace_extension(".test")
             ,ios_out_trunc_binary()
             );
         ledger.Spew(ofs);
@@ -152,7 +150,7 @@ double ledger_emitter::emit_cell
         fs::path out_file =
             cell_filepath.string() == c.custom_input_0_filename()
             ? c.custom_output_0_filename()
-            : fs::change_extension(cell_filepath, ".test0")
+            : fs::path{cell_filepath}.replace_extension(".test0")
             ;
         custom_io_0_write(ledger, out_file.string());
         }
@@ -162,7 +160,7 @@ double ledger_emitter::emit_cell
         fs::path out_file =
             cell_filepath.string() == c.custom_input_1_filename()
             ? c.custom_output_1_filename()
-            : fs::change_extension(cell_filepath, ".test1")
+            : fs::path{cell_filepath}.replace_extension(".test1")
             ;
         custom_io_1_write(ledger, out_file.string());
         }
diff --git a/emit_ledger.hpp b/emit_ledger.hpp
index 43c4157..e46da9c 100644
--- a/emit_ledger.hpp
+++ b/emit_ledger.hpp
@@ -25,10 +25,9 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <memory>                       // unique_ptr
 
 class Ledger;
diff --git a/file_command_wx.cpp b/file_command_wx.cpp
index 192ed2c..45b5915 100644
--- a/file_command_wx.cpp
+++ b/file_command_wx.cpp
@@ -25,9 +25,7 @@
 
 #include "alert.hpp"
 #include "force_linking.hpp"
-
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/path.hpp>
+#include "path.hpp"
 
 #include <wx/mimetype.h>
 #include <wx/utils.h>                   // wxExecute()
@@ -47,7 +45,7 @@ void concrete_file_command
     )
 {
     fs::path path(file);
-    std::string extension = fs::extension(path);
+    std::string const extension = path.extension().string();
 
     std::unique_ptr<wxFileType> const ft
         (wxTheMimeTypesManager->GetFileTypeFromExtension(extension)
@@ -65,7 +63,7 @@ void concrete_file_command
         okay = ft->GetOpenCommand
             (&cmd
             ,wxFileType::MessageParameters
-                (path.native_file_string()
+                (wxString::FromUTF8(path.string())
                 ,""
                 )
             );
@@ -75,7 +73,7 @@ void concrete_file_command
         okay = ft->GetPrintCommand
             (&cmd
             ,wxFileType::MessageParameters
-                (path.native_file_string()
+                (wxString::FromUTF8(path.string())
                 ,""
                 )
             );
@@ -92,7 +90,7 @@ void concrete_file_command
             << "Unable to determine command to '"
             << action
             << "' file '"
-            << path.native_file_string()
+            << path
             << "'."
             << LMI_FLUSH
             ;
@@ -104,7 +102,7 @@ void concrete_file_command
             << "Unable to '"
             << action
             << "' file '"
-            << path.native_file_string()
+            << path
             << "'. Return code: '"
             << okay
             << "'."
diff --git a/fund_data.cpp b/fund_data.cpp
index 702cd65..25ad3ec 100644
--- a/fund_data.cpp
+++ b/fund_data.cpp
@@ -27,13 +27,12 @@
 #include "assert_lmi.hpp"
 #include "data_directory.hpp"
 #include "my_proem.hpp"                 // ::write_proem()
+#include "path.hpp"
 #include "platform_dependent.hpp"       // access()
 #include "ssize_lmi.hpp"
 #include "xml_lmi.hpp"
 #include "xml_serialize.hpp"
 
-#include <boost/filesystem/convenience.hpp> // basename()
-
 //============================================================================
 FundInfo::FundInfo
     (double             ScalarIMF
@@ -120,7 +119,7 @@ void FundData::Write(std::string const& a_Filename) const
     xml_lmi::xml_document document(xml_root_name());
     xml::element& root = document.root_node();
 
-    ::write_proem(document, fs::basename(fs::path(a_Filename)));
+    ::write_proem(document, fs::path{a_Filename}.stem().string());
 
     xml_lmi::set_attr(root, "version", "0");
     xml_serialize::to_xml(root, FundInfo_);
diff --git a/fund_data.hpp b/fund_data.hpp
index 08ad26b..8d0811d 100644
--- a/fund_data.hpp
+++ b/fund_data.hpp
@@ -25,10 +25,9 @@
 #include "config.hpp"
 
 #include "cache_file_reads.hpp"
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 #include <vector>
 
diff --git a/generate_product_files.cpp b/generate_product_files.cpp
index 28bae33..541351b 100644
--- a/generate_product_files.cpp
+++ b/generate_product_files.cpp
@@ -25,7 +25,6 @@
 #include "fund_data.hpp"
 #include "lingo.hpp"
 #include "main_common.hpp"
-#include "path_utility.hpp"             // initialize_filesystem()
 #include "product_data.hpp"
 #include "rounding_rules.hpp"
 #include "stratified_charges.hpp"
@@ -35,8 +34,6 @@
 
 int try_main(int, char*[])
 {
-    initialize_filesystem();
-
     std::cout << "Generating product files." << std::endl;
 
     DBDictionary       ::write_database_files ();
diff --git a/global_settings.cpp b/global_settings.cpp
index 73079aa..bfb5008 100644
--- a/global_settings.cpp
+++ b/global_settings.cpp
@@ -84,7 +84,7 @@ void global_settings::set_regression_testing(bool b)
 void global_settings::set_data_directory(std::string const& s)
 {
     validate_directory(s, "Data directory");
-    data_directory_ = fs::system_complete(s);
+    data_directory_ = fs::absolute(s);
 }
 
 void global_settings::set_prospicience_date(calendar_date const& d)
diff --git a/global_settings.hpp b/global_settings.hpp
index 626c534..e389c84 100644
--- a/global_settings.hpp
+++ b/global_settings.hpp
@@ -25,11 +25,9 @@
 #include "config.hpp"
 
 #include "calendar_date.hpp"
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/operations.hpp> // fs::system_complete()
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 
 /// Design notes for class global_settings.
@@ -57,7 +55,7 @@
 /// products before approval.
 ///
 /// data_directory_: Path to data files, initialized to ".", not an
-/// empty string. Reason: objects of the boost filesystem library's
+/// empty string. Reason: objects of the std::filesystem library's
 /// path class are created from these strings, which, if the strings
 /// were empty, would trigger exceptions when passed to that library's
 /// directory_iterator ctor.
@@ -101,7 +99,7 @@ class LMI_SO global_settings final
     std::string pyx_                 {};
     bool custom_io_0_                {false};
     bool regression_testing_         {false};
-    fs::path data_directory_         {fs::system_complete(".")};
+    fs::path data_directory_         {fs::absolute(".")};
     calendar_date prospicience_date_ {last_yyyy_date()};
 };
 
diff --git a/global_settings_test.cpp b/global_settings_test.cpp
index 92cef09..e900277 100644
--- a/global_settings_test.cpp
+++ b/global_settings_test.cpp
@@ -22,14 +22,10 @@
 #include "pchfile.hpp"
 
 #include "global_settings.hpp"
+#include "path.hpp"
 
-#include "path_utility.hpp"             // initialize_filesystem()
 #include "test_tools.hpp"
 
-#include <boost/filesystem/exception.hpp>
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 void test_directory_exceptions()
 {
     // Test an exception for each 'directory' member to make sure
@@ -37,8 +33,7 @@ void test_directory_exceptions()
     // reported.
 
     // String values assigned to 'directory' data members must be
-    // valid "directory paths" as defined in the boost filesystem
-    // documentation. In particular:
+    // valid "directory paths". In particular:
 
     // Such string values must not be empty.
 
@@ -78,10 +73,6 @@ void test_directory_exceptions()
 
 int test_main(int, char*[])
 {
-    // Absolute paths require "native" name-checking policy for msw.
-
-    initialize_filesystem();
-
     // Initial values of 'directory' data members must be valid: the
     // operations tested here are required not to throw.
 
@@ -91,24 +82,14 @@ int test_main(int, char*[])
 
     fs::path path(global_settings::instance().data_directory());
 
-    fs::directory_iterator i(path);
+    fs::directory_iterator const i(path);
 
-    LMI_TEST(exists(*i));
+    LMI_TEST(i->exists());
 
     // Certain other operations are required to throw.
 
     test_directory_exceptions();
 
-    // Attempting to set a default name-checking policy after creating
-    // an instance of class global_settings should throw. Test this in
-    // order to guard against changes to the boost filesystem library.
-
-    LMI_TEST_THROW
-        (fs::path::default_name_check(fs::native)
-        ,fs::filesystem_error
-        ,""
-        );
-
     // 'ash_nazg' implies 'mellon'.
     global_settings::instance().set_mellon(false);
     LMI_TEST(!global_settings::instance().mellon());
diff --git a/gpt_server.cpp b/gpt_server.cpp
index 0570362..0629d5a 100644
--- a/gpt_server.cpp
+++ b/gpt_server.cpp
@@ -44,6 +44,7 @@
 #include "mc_enum_types_aux.hpp"        // mc_state_from_string()
 #include "miscellany.hpp"               // each_equal(), ios_out_trunc_binary()
 #include "oecumenic_enumerations.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"             // unique_filepath(), fs::path inserter
 #include "premium_tax.hpp"
 #include "product_data.hpp"
@@ -54,9 +55,6 @@
 #include "timer.hpp"
 #include "value_cast.hpp"
 
-#include <boost/filesystem/convenience.hpp> // extension(), change_extension()
-#include <boost/filesystem/fstream.hpp>
-
 #include <algorithm>                    // min()
 #include <iostream>
 #include <string>
@@ -480,7 +478,7 @@ gpt_server::gpt_server(mcenum_emission emission) : 
emission_(emission)
 
 bool gpt_server::operator()(fs::path const& file_path)
 {
-    std::string const extension = fs::extension(file_path);
+    std::string const extension = file_path.extension().string();
     if(".gpt" == extension)
         {
         Timer timer;
@@ -510,7 +508,7 @@ bool gpt_server::operator()(fs::path const& file_path, 
gpt_input const& z)
     timer.restart();
     if(mce_emit_test_data & emission_)
         {
-        state_.save(fs::change_extension(file_path, ".gpt.xml"));
+        state_.save(fs::path{file_path}.replace_extension(".gpt.xml"));
         }
     seconds_for_output_       = timer.stop().elapsed_seconds();
     conditionally_show_timings_on_stdout();
diff --git a/gpt_server.hpp b/gpt_server.hpp
index a872f7f..54962ef 100644
--- a/gpt_server.hpp
+++ b/gpt_server.hpp
@@ -26,10 +26,9 @@
 
 #include "gpt_state.hpp"
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 class gpt_input;
 
 /// Guideline premium test server.
diff --git a/gpt_state.cpp b/gpt_state.cpp
index 84195a7..92a6452 100644
--- a/gpt_state.cpp
+++ b/gpt_state.cpp
@@ -27,11 +27,10 @@
 #include "alert.hpp"
 #include "contains.hpp"
 #include "miscellany.hpp"               // htmlize()
+#include "path.hpp"
 #include "value_cast.hpp"
 #include "xml_lmi.hpp"
 
-#include <boost/filesystem/fstream.hpp>
-
 #include <limits>
 #include <sstream>
 #include <vector>
diff --git a/group_values.hpp b/group_values.hpp
index ac31faa..0ceeea1 100644
--- a/group_values.hpp
+++ b/group_values.hpp
@@ -25,10 +25,9 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <memory>                       // shared_ptr
 #include <vector>
 
diff --git a/icon_monger.cpp b/icon_monger.cpp
index 90fc67d..8ac47b6 100644
--- a/icon_monger.cpp
+++ b/icon_monger.cpp
@@ -26,11 +26,9 @@
 #include "alert.hpp"
 #include "contains.hpp"
 #include "data_directory.hpp"           // AddDataDir()
+#include "path.hpp"
 #include "path_utility.hpp"             // fs::path inserter
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <wx/image.h>
 
 #include <sstream>
diff --git a/illustrator.cpp b/illustrator.cpp
index cf51c9f..bf8256b 100644
--- a/illustrator.cpp
+++ b/illustrator.cpp
@@ -34,13 +34,12 @@
 #include "input.hpp"
 #include "ledgervalues.hpp"
 #include "multiple_cell_document.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"             // fs::path inserter
 #include "platform_dependent.hpp"       // access()
 #include "single_cell_document.hpp"
 #include "timer.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-
 #include <iostream>
 #include <string>
 
@@ -54,7 +53,7 @@ illustrator::illustrator(mcenum_emission emission)
 
 bool illustrator::operator()(fs::path const& file_path)
 {
-    std::string const extension = fs::extension(file_path);
+    std::string const extension = file_path.extension().string();
     if(".cns" == extension)
         {
         Timer timer;
diff --git a/illustrator.hpp b/illustrator.hpp
index e761d7d..d553791 100644
--- a/illustrator.hpp
+++ b/illustrator.hpp
@@ -25,10 +25,9 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <memory>                       // shared_ptr
 #include <vector>
 
diff --git a/input_test.cpp b/input_test.cpp
index 50b84a9..1973da0 100644
--- a/input_test.cpp
+++ b/input_test.cpp
@@ -37,7 +37,6 @@
 #include "global_settings.hpp"
 #include "miscellany.hpp"
 #include "oecumenic_enumerations.hpp"
-#include "path_utility.hpp"             // initialize_filesystem()
 #include "test_tools.hpp"
 #include "timer.hpp"
 #include "xml_lmi.hpp"
@@ -579,9 +578,6 @@ void input_test::mete_ill_xsd()
 
 int test_main(int, char*[])
 {
-    // Absolute paths require "native" name-checking policy for msw.
-    initialize_filesystem();
-
     // Location of '*.xsd' files.
     global_settings::instance().set_data_directory("/opt/lmi/data");
 
diff --git a/ledger_evaluator.cpp b/ledger_evaluator.cpp
index a5c0ce9..60b8147 100644
--- a/ledger_evaluator.cpp
+++ b/ledger_evaluator.cpp
@@ -40,14 +40,12 @@
 #include "mc_enum_aux.hpp"              // mc_e_vector_to_string_vector()
 #include "miscellany.hpp"               // each_equal(), ios_out_trunc_binary()
 #include "oecumenic_enumerations.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"             // fs::path inserter
 #include "ssize_lmi.hpp"
 #include "value_cast.hpp"
 #include "version.hpp"
 
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <functional>                   // minus
 #include <map>
 #include <numeric>                      // iota()
diff --git a/ledger_evaluator.hpp b/ledger_evaluator.hpp
index eb646f4..4e6db94 100644
--- a/ledger_evaluator.hpp
+++ b/ledger_evaluator.hpp
@@ -24,10 +24,9 @@
 
 #include "config.hpp"
 
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 #include <unordered_map>
 #include <utility>                      // move()
diff --git a/ledger_pdf.hpp b/ledger_pdf.hpp
index 364fe82..005d855 100644
--- a/ledger_pdf.hpp
+++ b/ledger_pdf.hpp
@@ -23,8 +23,7 @@
 #define ledger_pdf_hpp
 
 #include "config.hpp"
-
-#include <boost/filesystem/path.hpp>
+#include "path.hpp"
 
 #include <string>
 
diff --git a/ledger_test.cpp b/ledger_test.cpp
index d978ccb..5e85076 100644
--- a/ledger_test.cpp
+++ b/ledger_test.cpp
@@ -26,7 +26,6 @@
 #include "ledger_invariant.hpp"
 #include "ledger_variant.hpp"
 
-#include "path_utility.hpp"             // initialize_filesystem()
 #include "test_tools.hpp"
 #include "timer.hpp"
 
@@ -97,9 +96,6 @@ void ledger_test::test_speed()
 
 int test_main(int, char*[])
 {
-    // Absolute paths require "native" name-checking policy for msw.
-    initialize_filesystem();
-
     ledger_test::test();
 
     return EXIT_SUCCESS;
diff --git a/lingo.cpp b/lingo.cpp
index 79f9056..aa8cb62 100644
--- a/lingo.cpp
+++ b/lingo.cpp
@@ -31,8 +31,6 @@
 #include "xml_lmi.hpp"
 #include "xml_serialize.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-
 /// Construct from filename.
 
 lingo::lingo(fs::path const& filename)
@@ -653,7 +651,7 @@ void lingo::write_lingo_files()
 
     fs::path const path(AddDataDir("sample.lingo"));
     xml_lmi::xml_document document(xml_root_name());
-    write_proem(document, fs::basename(path));
+    write_proem(document, path.stem().string());
     xml::element& root = document.root_node();
     xml_lmi::set_attr(root, "version", class_version());
     xml_serialize::to_xml(root, enumerative_map);
diff --git a/lingo.hpp b/lingo.hpp
index 4a2e405..d8ce551 100644
--- a/lingo.hpp
+++ b/lingo.hpp
@@ -25,11 +25,10 @@
 #include "config.hpp"
 
 #include "cache_file_reads.hpp"
+#include "path.hpp"
 #include "so_attributes.hpp"
 #include "xml_lmi_fwd.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 #include <unordered_map>
 
diff --git a/main_cgi.cpp b/main_cgi.cpp
index 85002a9..7b3112c 100644
--- a/main_cgi.cpp
+++ b/main_cgi.cpp
@@ -42,7 +42,6 @@
 #include "main_common.hpp"
 #include "mc_enum_type_enums.hpp"       // mcenum_emission
 #include "miscellany.hpp"
-#include "path_utility.hpp"
 #include "platform_dependent.hpp"       // putenv() [GWC]
 #include "ssize_lmi.hpp"
 #include "timer.hpp"
@@ -88,8 +87,6 @@ void ShowCensusOutput(Input const&, std::string const&, bool);
 int try_main(int argc, char* argv[])
 {
   try {
-    initialize_filesystem();
-
     global_settings::instance().set_data_directory("/opt/lmi/data");
 
     gLogFile.rdbuf()->open
diff --git a/main_cli.cpp b/main_cli.cpp
index 78e0bc5..22ae566 100644
--- a/main_cli.cpp
+++ b/main_cli.cpp
@@ -43,15 +43,13 @@
 #include "mc_enum_types_aux.hpp"        // allowed_strings_emission(), 
mc_emission_from_string()
 #include "mec_server.hpp"
 #include "miscellany.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"
 #include "so_attributes.hpp"
 #include "timer.hpp"
 #include "value_cast.hpp"
 #include "verify_products.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <algorithm>                    // for_each()
 #include <cmath>                        // fabs()
 #include <cstdio>                       // printf()
@@ -376,7 +374,7 @@ void process_command_line(int argc, char* argv[])
                 {
                 LMI_ASSERT(nullptr != getopt_long.optarg);
                 std::string const s(getopt_long.optarg);
-                std::string const e = fs::extension(s);
+                std::string const e = fs::path{s}.extension().string();
                 if(".cns" == e || ".ill" == e || ".ini" == e || ".inix" == e)
                     {
                     illustrator_names.push_back(getopt_long.optarg);
@@ -506,7 +504,6 @@ void process_command_line(int argc, char* argv[])
 
 int try_main(int argc, char* argv[])
 {
-    initialize_filesystem();
     process_command_line(argc, argv);
     return EXIT_SUCCESS;
 }
diff --git a/main_common.cpp b/main_common.cpp
index 43eb5aa..ca60cf3 100644
--- a/main_common.cpp
+++ b/main_common.cpp
@@ -59,9 +59,6 @@ extern "C" unsigned int _get_output_format(void) {return 1;}
 /// Common application initialization.
 ///
 /// Also see the similar code in 'cpp_main.cpp' (for unit tests).
-///
-/// Don't initialize boost::filesystem here, to avoid creating a
-/// dependency on its object files for applications that don't use it.
 
 void initialize_application()
 {
diff --git a/main_common_non_wx.cpp b/main_common_non_wx.cpp
index 26fd19f..77140e5 100644
--- a/main_common_non_wx.cpp
+++ b/main_common_non_wx.cpp
@@ -38,9 +38,6 @@
 /// Exception: for msw at least, wx doesn't use main(). The way
 /// diagnostic messages are displayed for wx is different enough to
 /// warrant a parallel implementation.
-///
-/// Don't initialize boost::filesystem here, to avoid creating a
-/// dependency on its object files for applications that don't use it.
 
 int main(int argc, char* argv[])
 {
diff --git a/main_wx.cpp b/main_wx.cpp
index 8a6f2a3..357f267 100644
--- a/main_wx.cpp
+++ b/main_wx.cpp
@@ -36,7 +36,6 @@
 #include "force_linking.hpp"
 #include "handle_exceptions.hpp"        // report_exception()
 #include "main_common.hpp"              // initialize_application()
-#include "path_utility.hpp"             // initialize_filesystem()
 #include "skeleton.hpp"
 
 #include <wx/init.h>                    // wxEntry()
@@ -88,7 +87,6 @@ int WINAPI WinMain
     try
         {
         initialize_application();
-        initialize_filesystem();
 #if !defined LMI_MSW
         result = wxEntry(argc, argv);
 #else  // defined LMI_MSW
diff --git a/main_wx_test.cpp b/main_wx_test.cpp
index 6402501..337eb43 100644
--- a/main_wx_test.cpp
+++ b/main_wx_test.cpp
@@ -28,7 +28,7 @@
 #include "force_linking.hpp"
 #include "handle_exceptions.hpp"        // stealth_exception
 #include "main_common.hpp"              // initialize_application()
-#include "path_utility.hpp"             // initialize_filesystem()
+#include "path.hpp"
 #include "skeleton.hpp"
 #include "ssize_lmi.hpp"                // sstrlen()
 #include "wx_test_case.hpp"
@@ -44,9 +44,6 @@
 #include <wx/uiaction.h>
 #include <wx/wfstream.h>
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <algorithm>                    // sort()
 #include <cstring>                      // strcmp()
 #include <exception>                    // uncaught_exceptions()
@@ -422,7 +419,7 @@ bool application_test::process_command_line(int& argc, 
char* argv[])
         {
         warning()
             << "Test files path '"
-            << test_files_path_.native_file_string()
+            << test_files_path_
             << "' doesn't exist."
             << std::flush
             ;
@@ -430,7 +427,7 @@ bool application_test::process_command_line(int& argc, 
char* argv[])
         }
     else
         {
-        test_files_path_ = fs::system_complete(test_files_path_);
+        test_files_path_ = fs::absolute(test_files_path_);
         }
 
     return true;
@@ -573,7 +570,7 @@ fs::path wx_base_test_case::get_test_files_path() const
 std::string
 wx_base_test_case::get_test_file_path_for(std::string const& basename) const
 {
-    return (get_test_files_path() / basename).native_file_string();
+    return (get_test_files_path() / basename).string();
 }
 
 bool wx_base_test_case::is_distribution_test() const
@@ -947,7 +944,6 @@ void SkeletonTest::RunTheTests()
 int main(int argc, char* argv[])
 {
     initialize_application();
-    initialize_filesystem();
 
     if(!application_test::instance().process_command_line(argc, argv))
         {
diff --git a/md5sum.hpp b/md5sum.hpp
index 4f98e77..16c4791 100644
--- a/md5sum.hpp
+++ b/md5sum.hpp
@@ -23,8 +23,7 @@
 #define md5sum_hpp
 
 #include "config.hpp"
-
-#include <boost/filesystem/path.hpp>
+#include "path.hpp"
 
 #include <climits>                      // CHAR_BIT
 #include <iosfwd>
diff --git a/md5sum_test.cpp b/md5sum_test.cpp
index cdc4023..650ad03 100644
--- a/md5sum_test.cpp
+++ b/md5sum_test.cpp
@@ -22,11 +22,9 @@
 #include "pchfile.hpp"
 
 #include "md5sum.hpp"
+#include "path.hpp"
 #include "test_tools.hpp"
 
-#include <boost/filesystem/operations.hpp> // fs::exists()
-#include <boost/filesystem/path.hpp>
-
 #include <cstdio>                       // remove()
 #include <fstream>
 #include <ios>                          // ios_base
diff --git a/mec_server.cpp b/mec_server.cpp
index 3d8a314..b9cd2a9 100644
--- a/mec_server.cpp
+++ b/mec_server.cpp
@@ -43,6 +43,7 @@
 #include "mec_xml_document.hpp"
 #include "miscellany.hpp"               // each_equal(), ios_out_trunc_binary()
 #include "oecumenic_enumerations.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"             // unique_filepath(), fs::path inserter
 #include "premium_tax.hpp"
 #include "product_data.hpp"
@@ -53,9 +54,6 @@
 #include "timer.hpp"
 #include "value_cast.hpp"
 
-#include <boost/filesystem/convenience.hpp> // extension(), change_extension()
-#include <boost/filesystem/fstream.hpp>
-
 #include <algorithm>                    // min()
 #include <iostream>
 #include <string>
@@ -461,7 +459,7 @@ mec_server::mec_server(mcenum_emission emission) : 
emission_(emission)
 
 bool mec_server::operator()(fs::path const& file_path)
 {
-    std::string const extension = fs::extension(file_path);
+    std::string const extension = file_path.extension().string();
     if(".mec" == extension)
         {
         Timer timer;
@@ -491,7 +489,7 @@ bool mec_server::operator()(fs::path const& file_path, 
mec_input const& z)
     timer.restart();
     if(mce_emit_test_data & emission_)
         {
-        state_.save(fs::change_extension(file_path, ".mec.xml"));
+        state_.save(fs::path{file_path}.replace_extension(".mec.xml"));
         }
     seconds_for_output_       = timer.stop().elapsed_seconds();
     conditionally_show_timings_on_stdout();
diff --git a/mec_server.hpp b/mec_server.hpp
index 042e391..68164b5 100644
--- a/mec_server.hpp
+++ b/mec_server.hpp
@@ -26,10 +26,9 @@
 
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
 #include "mec_state.hpp"
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 class mec_input;
 
 /// MEC-testing server.
diff --git a/mec_state.cpp b/mec_state.cpp
index 91afc5f..09cf004 100644
--- a/mec_state.cpp
+++ b/mec_state.cpp
@@ -27,11 +27,10 @@
 #include "alert.hpp"
 #include "contains.hpp"
 #include "miscellany.hpp"               // htmlize()
+#include "path.hpp"
 #include "value_cast.hpp"
 #include "xml_lmi.hpp"
 
-#include <boost/filesystem/fstream.hpp>
-
 #include <limits>
 #include <sstream>
 #include <vector>
diff --git a/msw_common.make b/msw_common.make
index f31d5cb..f465519 100644
--- a/msw_common.make
+++ b/msw_common.make
@@ -42,16 +42,6 @@ platform_defines := \
 
 platform_gui_ldflags := -mwindows
 
-# In addition to other reasons for treating these libraries as mere
-# collections of source files, there's a specific problem with boost.
-# The build system provided by boost produces library names such as
-# 'libboost_filesystem-mgw.a', which violates the rule here
-#   http://www.boost.org/more/lib_guide.htm#Directory_structure
-# because it contains a hyphen, which causes problems with borland
-# tools, apparently because it looks like an option prefix.
-
-platform_boost_libraries :=
-
 platform_cgicc_libraries :=
 
 
################################################################################
diff --git a/name_value_pairs_test.cpp b/name_value_pairs_test.cpp
index 59fe4b2..69ee8ab 100644
--- a/name_value_pairs_test.cpp
+++ b/name_value_pairs_test.cpp
@@ -24,20 +24,17 @@
 #include "name_value_pairs.hpp"
 
 #include "miscellany.hpp"
+#include "path.hpp"
 #include "test_tools.hpp"
 
-#include <boost/filesystem/convenience.hpp> // basename()
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <cstdio>                       // remove()
 #include <fstream>
 #include <string>
 
 int test_main(int, char*[])
 {
-    std::string const tmp = "/tmp/" + fs::basename(__FILE__);
-    fs::path const tmpdir(fs::complete(tmp));
+    std::string const tmp = "/tmp/" + fs::path{__FILE__}.stem().string();
+    fs::path const tmpdir(fs::absolute(tmp));
     fs::create_directory(tmpdir);
 
     std::string filename0(tmp + "/eraseme");
diff --git a/objects.make b/objects.make
index 02047a3..fa5ef42 100644
--- a/objects.make
+++ b/objects.make
@@ -25,19 +25,13 @@
 # is reached through 'vpath' directives. See the rationale in
 # 'workhorse.make'.
 
-# Boost filesystem and regex libraries. The other boost libraries that
+# Boost regex library. The other boost libraries that
 # lmi requires are implemented entirely in headers.
 #
 # As for listing the object files here, the regex author says:
 #   http://groups.google.com/group/boost-list/msg/7f925ca50d69384b
 # | add the libs/regex/src/*.cpp files to your project
 
-boost_filesystem_objects := \
-  convenience.o \
-  exception.o \
-  path_posix_windows.o \
-  operations_posix_windows.o \
-
 boost_regex_objects := \
   c_regex_traits.o \
   cpp_regex_traits.o \
@@ -65,7 +59,7 @@ boost_regex_objects := \
 # run correctly.
 
 ifneq (,$(USE_SO_ATTRIBUTES))
-  duplicated_objects = $(boost_filesystem_objects)
+  duplicated_objects =
 endif
 
 # GNU cgicc.
@@ -118,7 +112,6 @@ cgicc_3_1_4_objects = \
 # have them as libraries.
 
 ifdef HAVE_THIRD_PARTY_LIBRARIES
-  boost_filesystem_objects :=
   boost_regex_objects :=
   cgicc_objects :=
 endif
@@ -170,7 +163,6 @@ cli_objects := \
 # Illustrations: files shared by the antediluvian and production branches.
 
 common_common_objects := \
-  $(boost_filesystem_objects) \
   actuarial_table.o \
   alert.o \
   calendar_date.o \
@@ -508,7 +500,6 @@ account_value_test$(EXEEXT): \
   account_value_test.o \
 
 actuarial_table_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   actuarial_table.o \
   actuarial_table_test.o \
@@ -521,7 +512,6 @@ alert_test$(EXEEXT): \
   alert_test.o \
 
 any_member_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   any_member_test.o \
   calendar_date.o \
@@ -537,7 +527,6 @@ assert_lmi_test$(EXEEXT): \
 
 # MD5 !! Remove "timer.o" below.
 authenticity_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   authenticity.o \
   authenticity_test.o \
@@ -558,7 +547,6 @@ bourn_cast_test$(EXEEXT): \
   timer.o \
 
 cache_file_reads_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   cache_file_reads_test.o \
   timer.o \
@@ -586,7 +574,6 @@ commutation_functions_test$(EXEEXT): \
   timer.o \
 
 configurable_settings_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   configurable_settings.o \
@@ -661,7 +648,6 @@ getopt_test$(EXEEXT): \
   getopt_test.o \
 
 global_settings_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   global_settings.o \
@@ -671,7 +657,6 @@ global_settings_test$(EXEEXT): \
   path_utility.o \
 
 gpt_cf_triad_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   commutation_functions.o \
@@ -708,7 +693,6 @@ ieee754_test$(EXEEXT): \
   ieee754_test.o \
 
 input_sequence_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   global_settings.o \
@@ -720,7 +704,6 @@ input_sequence_test$(EXEEXT): \
   path_utility.o \
 
 input_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   ce_product_name.o \
@@ -769,7 +752,6 @@ interpolate_string_test$(EXEEXT): \
   interpolate_string_test.o \
 
 irc7702_tables_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   commutation_functions.o \
@@ -782,7 +764,6 @@ irc7702_tables_test$(EXEEXT): \
   path_utility.o \
 
 irc7702a_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   global_settings.o \
@@ -801,7 +782,6 @@ istream_to_string_test$(EXEEXT): \
   timer.o \
 
 ledger_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   configurable_settings.o \
@@ -846,7 +826,6 @@ math_functions_test$(EXEEXT): \
   timer.o \
 
 mc_enum_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   ce_product_name.o \
@@ -861,7 +840,6 @@ mc_enum_test$(EXEEXT): \
   path_utility.o \
 
 md5sum_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   md5.o \
   md5sum.o \
@@ -883,7 +861,6 @@ mortality_rates_test$(EXEEXT): \
   mortality_rates_test.o \
 
 name_value_pairs_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   global_settings.o \
@@ -898,7 +875,6 @@ ncnnnpnn_test$(EXEEXT): \
   ncnnnpnn_test.o \
 
 numeric_io_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   global_settings.o \
@@ -909,7 +885,6 @@ numeric_io_test$(EXEEXT): \
   timer.o \
 
 path_utility_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   global_settings.o \
@@ -920,7 +895,6 @@ path_utility_test$(EXEEXT): \
   wine_workarounds.o \
 
 premium_tax_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   data_directory.o \
@@ -946,7 +920,6 @@ premium_tax_test$(EXEEXT): \
   xml_lmi.o \
 
 print_matrix_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   cso_table.o \
@@ -957,7 +930,6 @@ print_matrix_test$(EXEEXT): \
   print_matrix_test.o \
 
 product_file_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   data_directory.o \
@@ -995,7 +967,6 @@ progress_meter_test$(EXEEXT): \
   timer.o \
 
 rate_table_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   crc32.o \
@@ -1072,7 +1043,6 @@ timer_test$(EXEEXT): \
   timer_test.o \
 
 tn_range_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   datum_base.o \
@@ -1085,7 +1055,6 @@ tn_range_test$(EXEEXT): \
   tn_range_test_aux.o \
 
 value_cast_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   facets.o \
@@ -1105,7 +1074,6 @@ wx_new_test$(EXEEXT): \
   wx_new_test.o \
 
 xml_serialize_test$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(common_test_objects) \
   calendar_date.o \
   global_settings.o \
@@ -1137,7 +1105,6 @@ elapsed_time$(EXEEXT): \
 # MD5 !! Obviate this by rewriting those unit tests.
 lmi_md5sum$(EXEEXT): POST_LINK_COMMAND = $(INSTALL) -m 0775 $@ $(localbindir)
 lmi_md5sum$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(main_auxiliary_common_objects) \
   getopt.o \
   md5.o \
@@ -1146,7 +1113,6 @@ lmi_md5sum$(EXEEXT): \
 
 # MD5 !! Remove "timer.o" below.
 generate_passkey$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(main_auxiliary_common_objects) \
   authenticity.o \
   calendar_date.o \
@@ -1166,7 +1132,6 @@ ihs_crc_comp$(EXEEXT): \
   ihs_crc_comp.o \
 
 rate_table_tool$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(main_auxiliary_common_objects) \
   calendar_date.o \
   crc32.o \
@@ -1182,7 +1147,6 @@ rate_table_tool$(EXEEXT): \
 test_coding_rules_test := PERFORM=$(PERFORM) 
$(srcdir)/test_coding_rules_test.sh
 test_coding_rules$(EXEEXT): POST_LINK_COMMAND = $(test_coding_rules_test)
 test_coding_rules$(EXEEXT): \
-  $(boost_filesystem_objects) \
   $(boost_regex_objects) \
   $(main_auxiliary_common_objects) \
   miscellany.o \
diff --git a/path.hpp b/path.hpp
new file mode 100644
index 0000000..38312fd
--- /dev/null
+++ b/path.hpp
@@ -0,0 +1,566 @@
+// The file system path class for lmi.
+//
+// Copyright (C) 2020, 2021 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// https://savannah.nongnu.org/projects/lmi
+// email: <gchicares@sbcglobal.net>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+#ifndef path_hpp
+#define path_hpp
+
+#include "config.hpp"
+
+#include <filesystem>
+#include <fstream>
+#include <ostream>
+#include <string>
+#include <system_error> // std::error_code
+
+namespace fs
+{
+
+/// Make several standard classes and functions available in this namespace.
+
+using std::filesystem::directory_entry;
+using std::filesystem::directory_iterator;
+using std::filesystem::file_time_type;
+using std::filesystem::filesystem_error;
+
+using std::filesystem::create_directory;
+using std::filesystem::exists;
+using std::filesystem::is_directory;
+using std::filesystem::last_write_time;
+using std::filesystem::remove;
+using std::filesystem::rename;
+
+/// Class representing the file system path.
+///
+/// This class is as similar as possible to std::filesystem::path, while
+/// being different from it in two crucial aspects:
+///
+///  1. Having a different class allows to provide a more user-friendly
+///     operator<<() for it which does not quote the path, as the standard
+///     class does.
+///
+///  2. Our class always uses UTF-8 encoding for all strings, whether we use
+///     C++17 or C++20, while the standard class was changed in an incompatible
+///     way in the latter standard version, might change again in the future,
+///     and in the meanwhile the behaviour of the existing implementations of
+///     the standard library depends on the exact version and is also subject
+///     to change.
+///
+/// Unfortunately this does require duplicating the standard class here, but
+/// this class is guaranteed to provide a (strict, as we don't implement some
+/// of the parts that we don't need at all) subset of std::filesystem::path
+/// functionality, so when the problems above are not relevant any longer, it
+/// should be possible to simply replace it with a using declaration making the
+/// standard class available in this namespace.
+
+class path
+{
+  public:
+    /// Constructors and destructor.
+
+    path() noexcept = default;
+
+    path(path const& p)
+        :path_{p.path_}
+        {
+        }
+
+    path(path&& p) noexcept
+        :path_{std::move(p.path_)}
+        {
+        }
+
+    path(std::filesystem::path const& p)
+        :path_{p}
+        {
+        }
+
+    path(std::filesystem::path&& p) noexcept
+        :path_{std::move(p)}
+        {
+        }
+
+    path(std::string const& source)
+        :path_{from_u8path(source)}
+        {
+        }
+
+    path(char const* source)
+        :path_{from_u8path(source)}
+        {
+        }
+
+    ~path() = default;
+
+    /// Assignments.
+
+    path& operator=(path const& p)
+        {
+        path_ = p.path_;
+        return *this;
+        }
+
+    path& operator=(path&& p) noexcept
+        {
+        path_ = std::move(p.path_);
+        return *this;
+        }
+
+    path& operator=(std::filesystem::path const& p) noexcept
+        {
+        path_ = p;
+        return *this;
+        }
+
+    path& operator=(std::filesystem::path&& p) noexcept
+        {
+        path_ = std::move(p);
+        return *this;
+        }
+
+    path& operator=(std::string const& source)
+        {
+        path_ = from_u8path(source);
+        return *this;
+        }
+
+    path& operator=(char const* source)
+        {
+        path_ = from_u8path(source);
+        return *this;
+        }
+
+    /// Appends.
+
+    path& operator/=(path const& p)
+        {
+        path_ /= p.path_;
+        return *this;
+        }
+
+    path& operator/=(std::string const& source)
+        {
+        path_ /= source;
+        return *this;
+        }
+
+    /// Modifiers.
+
+    void clear() noexcept
+        {
+        path_.clear();
+        }
+
+    path& make_preferred()
+        {
+        path_.make_preferred();
+        return *this;
+        }
+
+    path& remove_filename()
+        {
+        path_.remove_filename();
+        return *this;
+        }
+
+    path& replace_filename(path const& replacement)
+        {
+        path_.replace_filename(replacement.path_);
+        return *this;
+        }
+
+    path& replace_extension(path const& replacement = path())
+        {
+        path_.replace_extension(replacement.path_);
+        return *this;
+        }
+
+    void swap(path& rhs) noexcept
+        {
+        path_.swap(rhs.path_);
+        }
+
+    /// Native format observer.
+
+    operator std::filesystem::path() const
+        {
+        return path_;
+        }
+
+    /// The function is used only in native_path(). Returns the UTF-8 string
+    /// with the native separators ('\\' under Windows).
+    /// Note that the corresponding function doesn't exist in
+    /// std::filesystem::path class.
+
+    std::string native_string() const
+        {
+        // make_preferred() changes the path, so make copy of path_.
+        std::filesystem::path tmp{path_};
+        return u8string_as_string(tmp.make_preferred().u8string());
+        }
+
+    /// Returns the UTF-8 encoded string in the lexically normalized generic
+    /// format. The functionality differs from the standard one to use the
+    /// short and simple function name which is used in most of cases.
+
+    std::string string() const
+        {
+        return u8string_as_string(path_.lexically_normal().generic_u8string());
+        }
+
+    /// Generation.
+
+    path lexically_normal() const
+        {
+        return path_.lexically_normal();
+        }
+
+    path lexically_relative(path const& base) const
+        {
+        return path_.lexically_relative(base.path_);
+        }
+
+    path lexically_proximate(path const& base) const
+        {
+        return path_.lexically_proximate(base.path_);
+        }
+
+    /// Decomposition.
+
+    path root_name() const
+        {
+        return path_.root_name();
+        }
+
+    path root_directory() const
+        {
+        return path_.root_directory();
+        }
+
+    path root_path() const
+        {
+        return path_.root_path();
+        }
+
+    path relative_path() const
+        {
+        return path_.relative_path();
+        }
+
+    path parent_path() const
+        {
+        return path_.parent_path();
+        }
+
+    path filename() const
+        {
+        return path_.filename();
+        }
+
+    path stem() const
+        {
+        return path_.stem();
+        }
+
+    path extension() const
+        {
+        return path_.extension();
+        }
+
+    /// Query.
+
+    [[nodiscard]] bool empty() const noexcept
+        {
+        return path_.empty();
+        }
+
+    [[nodiscard]] bool has_root_name() const
+        {
+        return path_.has_root_name();
+        }
+
+    [[nodiscard]] bool has_root_directory() const
+        {
+        return path_.has_root_directory();
+        }
+
+    [[nodiscard]] bool has_root_path() const
+        {
+        return path_.has_root_path();
+        }
+
+    [[nodiscard]] bool has_relative_path() const
+        {
+        return path_.has_relative_path();
+        }
+
+    [[nodiscard]] bool has_parent_path() const
+        {
+        return path_.has_parent_path();
+        }
+
+    [[nodiscard]] bool has_filename() const
+        {
+        return path_.has_filename();
+        }
+
+    [[nodiscard]] bool has_stem() const
+        {
+        return path_.has_stem();
+        }
+
+    [[nodiscard]] bool has_extension() const
+        {
+        return path_.has_extension();
+        }
+
+    [[nodiscard]] bool is_absolute() const
+        {
+        return path_.is_absolute();
+        }
+
+    [[nodiscard]] bool is_relative() const
+        {
+        return path_.is_relative();
+        }
+
+  private:
+    std::filesystem::path path_;
+
+#if defined __cpp_char8_t
+    static std::string u8string_as_string(std::u8string const& s8)
+        {
+        // In C++20 u8string is a specialization of basic_string<> for char8_t
+        // which is a different type from char, hence u8string cannot be used
+        // for basically anything. In lmi we assume that all non-ASCII strings
+        // use UTF-8 encoding, so we simply reuse u8string contents as normal
+        // char string. Note that this cast is safe because of special property
+        // of char pointers that can be used to iterate over any buffer and
+        // that u8string contents can always be stored in string (unlike vice
+        // versa).
+        //
+        // Also note that the input string can't contain embedded NULs here, as
+        // they're not allowed in file paths, hence there is no need to use
+        // size.
+        return reinterpret_cast<char const*>(s8.c_str());
+        }
+#endif // defined __cpp_char8_t
+
+    // Until C++20 u8string() and generic_u8string() return std::string, so
+    // there is no need to do anything and, hopefully, the compiler will just
+    // optimize this function call away.
+    //
+    // Note that we define this overload even when using C++20, as some
+    // std::filesystem implementations haven't been updated to return
+    // std::u8string from path::u8string() (which some have already been), so
+    // it's simpler to always define it and let the compiler select the
+    // appropriate overload to call.
+    static std::string u8string_as_string(std::string const& s8)
+        {
+        return s8;
+        }
+
+    // Provide wrapper for u8path() C++17 function deprecated in C++20:
+    // normally we should just use std::filesystem::path ctor from char8_t
+    // string here, but not all implementations provide it right now (notably
+    // libc++ used by clang 10 in the CI builds does not), so keep using
+    // u8path() for now, and just disable the deprecation warning for it.
+    template<typename T>
+    static std::filesystem::path from_u8path(T arg)
+        {
+#if defined LMI_CLANG
+#   pragma clang diagnostic push
+#   pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif // defined LMI_CLANG
+#if defined LMI_MSC
+#   pragma warning(push)
+#   pragma warning(disable : 4996)
+#endif // defined LMI_MSC
+
+        return std::filesystem::u8path(arg);
+
+#if defined LMI_MSC
+#   pragma warning(pop)
+#endif // defined LMI_MSC
+#if defined LMI_CLANG
+#   pragma clang diagnostic pop
+#endif // defined LMI_CLANG
+        }
+
+    friend bool operator==(path const& lhs, path const& rhs) noexcept;
+    friend bool operator!=(path const& lhs, path const& rhs) noexcept;
+    friend bool operator<(path const& lhs, path const& rhs) noexcept;
+    friend bool operator<=(path const& lhs, path const& rhs) noexcept;
+    friend bool operator>(path const& lhs, path const& rhs) noexcept;
+    friend bool operator>=(path const& lhs, path const& rhs) noexcept;
+    friend path operator/(path const& lhs, path const& rhs);
+    friend class ifstream;
+    friend class ofstream;
+};
+
+/// Non-member operators.
+
+inline bool operator==(path const& lhs, path const& rhs) noexcept
+{
+    return lhs.path_ == rhs.path_;
+}
+
+inline bool operator!=(path const& lhs, path const& rhs) noexcept
+{
+    return lhs.path_ != rhs.path_;
+}
+
+inline bool operator<(path const& lhs, path const& rhs) noexcept
+{
+    return lhs.path_ < rhs.path_;
+}
+
+inline bool operator<=(path const& lhs, path const& rhs) noexcept
+{
+    return lhs.path_ <= rhs.path_;
+}
+
+inline bool operator>(path const& lhs, path const& rhs) noexcept
+{
+    return lhs.path_ > rhs.path_;
+}
+
+inline bool operator>=(path const& lhs, path const& rhs) noexcept
+{
+    return lhs.path_ >= rhs.path_;
+}
+
+inline path operator/(path const& lhs, path const& rhs)
+{
+    return lhs.path_ / rhs.path_;
+}
+
+template<class CharT, class Traits>
+inline std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, path const& p)
+{
+    return os << p.string();
+}
+
+/// Provide wrappers of the functions in std::filesystem returning standard
+/// path objects returning the same objects of our own type.
+
+inline path absolute(path const& p)
+{
+    return std::filesystem::absolute(p);
+}
+
+inline path absolute(path const& p, std::error_code& ec)
+{
+    return std::filesystem::absolute(p, ec);
+}
+
+inline path current_path()
+{
+    return std::filesystem::current_path();
+}
+
+inline path current_path(std::error_code& ec)
+{
+    return std::filesystem::current_path(ec);
+}
+
+/// File stream classes working with fs::path.
+///
+/// These classes are equivalents of the standard classes with the same name
+/// that can be constructed from std::filesystem::path objects, but not from
+/// fs::path objects in a context in which implicit conversions, such as those
+/// performed by fs::path operator std::filesystem::path(), are disabled. I.e.
+/// these classes allow the following code to compile
+///
+/// fs::path p = ...;
+/// fs::ifstream ifs{p};
+///
+/// while with std::ifstream only
+///
+/// std::ifstream ifs(p);
+///
+/// could be used or an explicit conversion would be required.
+///
+/// Another advantage of using these classes is that, like fs::path itself,
+/// they interpret all strings as being in UTF-8, while the standard file
+/// streams use the current locale encoding for them.
+
+class ifstream final
+    :public std::ifstream
+{
+  public:
+    ifstream() = default;
+
+    explicit ifstream
+        (path const& p
+        ,std::ios_base::openmode mode = std::ios_base::in
+        )
+        :std::ifstream(p.path_, mode)
+        {
+        }
+
+    ifstream(ifstream const&) = delete;
+    ifstream(ifstream&&) = delete;
+
+    void open
+        (path const& p
+        ,std::ios_base::openmode mode = std::ios_base::in
+        )
+        {
+            std::ifstream::open
+                (p.path_
+                ,mode
+                );
+        }
+};
+
+class ofstream final
+    :public std::ofstream
+{
+  public:
+    ofstream() = default;
+
+    explicit ofstream
+        (path const& p
+        ,std::ios_base::openmode mode = std::ios_base::out
+        )
+        :std::ofstream(p.path_, mode)
+        {
+        }
+
+    ofstream(ofstream const&) = delete;
+    ofstream(ofstream&&) = delete;
+
+    void open
+        (path const& p
+        ,std::ios_base::openmode mode = std::ios_base::out
+        )
+        {
+        std::ofstream::open
+            (p.path_
+            ,mode
+            );
+        }
+};
+
+} // namespace fs
+
+#endif // path_hpp
diff --git a/path_utility.cpp b/path_utility.cpp
index ebeb749..b013266 100644
--- a/path_utility.cpp
+++ b/path_utility.cpp
@@ -27,86 +27,27 @@
 #include "assert_lmi.hpp"
 #include "global_settings.hpp"
 #include "miscellany.hpp"               // iso_8601_datestamp_terse()
-
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/exception.hpp>
-#include <boost/filesystem/operations.hpp>
+#include "path.hpp"
 
 #include <cctype>                       // isalnum()
 #include <exception>
 #include <iomanip>
 #include <sstream>
 
-/// Preserve initial path and set "native" name-checking policy for
-/// boost filesystem library.
-///
-/// Applications that end users would normally run should call this
-/// function during initialization--before using this boost library
-/// in any other way, to ensure uniform name checking (which enables
-/// them to use nonportable paths, as some demand), and to make it
-/// potentially possible to protect them somewhat from the strange
-/// effects of inadvertent changes to the current working directory.
-/// As boost's documentation notes, msw may resolve relative paths as
-///   "complete( path, kinky ), where kinky is the current directory
-///   for the [path's] drive. This will be the current directory of
-///   that drive the last time it was set, and thus may well be
-///   residue left over from some prior program run by the command
-///   processor! Although these semantics are often useful, they are
-///   also very error-prone, and certainly deserve to be called
-///   'kinky'."
-/// although it's unclear whether there's any way to get msw to do
-/// this exactly when end users desire it and not otherwise.
-///
-/// Call this function during initialization for any program that
-/// could be passed a path argument, even if the argument is a
-/// portable path. Motivating case: MSYS's bash translated it to a
-/// nonportable path; e.g., if this function wasn't called, then
-///   --data_path='/opt/lmi/data'
-/// engendered this diagnostic:
-///   boost::filesystem::path: [line split for readability]
-///     invalid name "C:" in path: "C:/msys/1.0/opt/lmi/data"
-/// Keep doing this for future-proofing even though MSYS is no longer
-/// supported.
-///
-/// This function is not called in the initialization routine used by
-/// all programs, because simple command-line tools should not be
-/// forced to depend on this boost library.
-///
-/// Resist the urge to write its simple implementation inline because
-/// that may fail with gcc on msw--see:
-///   http://article.gmane.org/gmane.comp.gnu.mingw.user/18633
-///     [2006-01-14T11:55:49Z from Greg Chicares]
-///
-/// The boost documentation says:
-///   "The preferred implementation would be to call initial_path()
-///   during program initialization, before the call to main().
-///   This is, however, not possible with changing the C++ runtime
-///   library."
-/// One could wish that they had expressed that in code instead of
-/// commentary: std::cout manages to work this way by using the
-/// so-called "nifty counter" technique, which perhaps ought to be
-/// used here.
-
-void initialize_filesystem()
-{
-    fs::path::default_name_check(fs::native);
-    fs::initial_path();
-}
-
 /// Change '/path/to/file' to '/some/other/place/file'.
 ///
-/// Motivation: It is anomalous that boost permits this:
+/// Motivation: It is anomalous that std::filesystem permits this:
 ///   path file("/bin/sh";
 ///   path dir ("/usr/bin");
-///   dir / path; // returns "/usr/bin/bin/sh"
-/// where true == file.is_complete().
+///   dir / path; // returns "/bin/sh"
+/// where true == file.is_absolute().
 ///
 /// Arguably the arguments should be given in the opposite order:
 ///   modify_directory("sh", "/usr/bin") // present order
 ///   modify_directory("/usr/bin", "sh") // opposite order
-/// because the path precedes the leaf in canonical form. However,
-/// fs::change_extension() uses the present argument order:
-///   function(original, new_part)
+/// because the path precedes the filename in canonical form. However,
+/// fs::path::replace_extension() uses the present argument order:
+///   original.replace_extension(new_part)
 /// and in a nondegenerate case such as:
 ///   modify_directory("/bin/sh", "/usr/bin") // present order
 /// simply means "change the directory of /bin/sh to /usr/bin", while
@@ -117,26 +58,25 @@ void initialize_filesystem()
 /// evokes chdir(2) and cd(1).
 ///
 /// Asserted precondition:
-///   - 'original_filepath' is not empty (i.e., true == has_leaf())
+///   - 'original_filepath' is not empty (i.e., true == has_filename())
 /// It is notably not required that 'supplied_directory' name an
 /// actual existing directory.
 ///
-/// Boost provides no way to test whether a path has the form of a
-/// directory. Its fs::is_directory() asks the operating system:
+/// std::filesystem provides no way to test whether a path has the form
+/// of a directory. Its fs::is_directory() asks the operating system:
 ///   is_directory("/usr/lib")
 /// returns 'true' iff the OS reports that such a directory exists;
 /// but the same function call would return 'false' after
 ///   rm -rf /usr/lib ; touch /usr/lib
-/// Notably, path("/bin/sh/") succeeds, silently discarding the
-/// trailing '/'.
+/// Notably, path("/bin/sh/") fails because it hasn't the filename.
 
 fs::path modify_directory
     (fs::path const& original_filepath
     ,fs::path const& supplied_directory
     )
 {
-    LMI_ASSERT(original_filepath.has_leaf());
-    return supplied_directory / fs::path(original_filepath.leaf());
+    LMI_ASSERT(original_filepath.has_filename());
+    return supplied_directory / original_filepath.filename();
 }
 
 /// Return a filename appropriate for posix as well as msw.
@@ -161,14 +101,6 @@ fs::path modify_directory
 /// in case an end user types something like
 ///   Crime and/or Punishment
 /// with no intention of denoting a path.
-///
-/// Although portable_filename() would be a better name, that would be
-/// confusing because the boost filesystem library already provides
-/// boolean predicates like portable_file_name(), where Myers
-///   http://www.cantrip.org/coding-standard2.html
-/// would prefer a predicate phrase like is_portable_file_name():
-/// cf. std::isalnum(), std::numeric_limits::is_signed(), and even
-/// boost::filesystem::is_complete().
 
 std::string orthodox_filename(std::string const& original_filename)
 {
@@ -265,16 +197,15 @@ std::string serial_extension
 /// output filenames simpler and more regular, yet doesn't suppress
 /// any information that would actually be useful.
 ///
-/// Preconditions: census input filepath is nonempty and has a leaf.
-/// It's not apparent how a nonempty path could fail to have a leaf,
-/// but presumably boost has some undocumented reason.
+/// Preconditions: census input filepath is nonempty and has a filename.
+/// For example `path/without/name/` is nonempty but hasn't the filename.
 ///
 /// Any extension or path is discarded from the input census filepath;
-/// only the filename leaf is used.
+/// only the filename is used.
 ///
 /// It is necessary to call orthodox_filename() on the insured's name
 /// in case it contains a character (probably whitespace) that might
-/// fail a boost::filesystem name check.
+/// fail a std::filesystem name check.
 
 fs::path serial_file_path
     (fs::path    const& exemplar
@@ -284,7 +215,7 @@ fs::path serial_file_path
     )
 {
     LMI_ASSERT(!exemplar.empty());
-    LMI_ASSERT(exemplar.has_leaf());
+    LMI_ASSERT(exemplar.has_filename());
     std::string s(serial_extension(serial_number, extension));
     if
         (  !personal_name.empty()
@@ -293,7 +224,7 @@ fs::path serial_file_path
         {
         s = '.' + orthodox_filename(personal_name) + s;
         }
-    return fs::change_extension(exemplar.leaf(), s);
+    return fs::path{exemplar}.filename().replace_extension(s);
 }
 
 /// Create a unique file path, following input as closely as possible.
@@ -321,8 +252,7 @@ fs::path serial_file_path
 ///
 /// A try-block is necessary because fs::remove() can throw. The
 /// postcondition is asserted explicitly at the end of the try-block
-/// because that boost function's semantics have changed between
-/// versions, and its documentation is still unclear in boost-1.34:
+/// because that fs::remove() documentation is still unclear:
 /// apparently it mustn't fail without throwing, yet it doesn't throw
 /// on an operation that must fail, like removing a file that's locked
 /// by another process as in the motivating example above.
@@ -338,7 +268,7 @@ fs::path unique_filepath
     )
 {
     fs::path filepath(original_filepath);
-    filepath = fs::change_extension(filepath, supplied_extension);
+    filepath.replace_extension(supplied_extension);
     if(!fs::exists(filepath))
         {
         return filepath;
@@ -351,10 +281,10 @@ fs::path unique_filepath
         }
     catch(std::exception const&)
         {
-        std::string basename  = fs::basename (filepath);
-        std::string extension = fs::extension(filepath);
+        std::string basename  = filepath.stem().string();
+        std::string const extension = filepath.extension().string();
         basename += '-' + iso_8601_datestamp_terse() + extension;
-        filepath = filepath.branch_path() / basename;
+        filepath = filepath.parent_path() / basename;
         if(fs::exists(filepath))
             {
             alarum()
@@ -386,10 +316,6 @@ namespace
 /// appropriate here, std::runtime_error (via alarum()) is chosen
 /// because the 'a_path' argument may be specified by users.
 ///
-/// Exceptions thrown from the boost filesystem library on path
-/// assignment are caught in order to rethrow with 'context'
-/// prepended.
-///
 /// Design alternative: instead of calling this function from
 /// validate_directory() and validate_filepath(), eliminate those
 /// functions and call this directly with an 'is_directory' argument.
@@ -401,15 +327,7 @@ void validate_path
     ,std::string const& context
     )
 {
-    fs::path path;
-    try
-        {
-        path = a_path;
-        }
-    catch(fs::filesystem_error const& e)
-        {
-        alarum() << context << ": " << e.what() << LMI_FLUSH;
-        }
+    fs::path const path{a_path};
 
     if(path.empty())
         {
diff --git a/path_utility.hpp b/path_utility.hpp
index dcf9d89..8291629 100644
--- a/path_utility.hpp
+++ b/path_utility.hpp
@@ -24,15 +24,12 @@
 
 #include "config.hpp"
 
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <ostream>
 #include <string>
 
-LMI_SO void initialize_filesystem(); // Listed first because of its importance.
-
 LMI_SO fs::path modify_directory
     (fs::path const& original_filepath
     ,fs::path const& supplied_directory
@@ -68,17 +65,4 @@ LMI_SO void validate_filepath
     ,std::string const& context
     );
 
-namespace boost
-{
-namespace filesystem
-{
-
-inline std::ostream& operator<<(std::ostream& os, fs::path const& z)
-{
-    return os << z.string();
-}
-
-} // namespace filesystem
-} // namespace boost
-
 #endif // path_utility_hpp
diff --git a/path_utility_test.cpp b/path_utility_test.cpp
index fd7c73a..5f298de 100644
--- a/path_utility_test.cpp
+++ b/path_utility_test.cpp
@@ -24,16 +24,11 @@
 #include "path_utility.hpp"
 
 #include "miscellany.hpp"
+#include "path.hpp"
 #include "platform_dependent.hpp"       // access()
 #include "test_tools.hpp"
 #include "wine_workarounds.hpp"         // running_under_wine()
 
-#include <boost/filesystem/convenience.hpp> // basename()
-#include <boost/filesystem/exception.hpp>
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <cstdio>                       // remove()
 #include <fstream>
 #include <sstream>
@@ -76,15 +71,20 @@ void test_modify_directory()
     LMI_TEST_EQUAL("sh"           , modify_directory("sh"     , ""        
).string());
     LMI_TEST_EQUAL("sh"           , modify_directory("/bin/sh", ""        
).string());
 
-    // Arguably this should be forbidden:
+    // This is forbidden, consistently with the observed behaviour:
     //   $ls /bin/sh/
     //   ls: cannot access '/bin/sh/': Not a directory
-    LMI_TEST_EQUAL("/bin/sh"      , modify_directory("sh/"    , "/bin/"   
).string());
+    // because "sh/" doesn't have the filename.
+    LMI_TEST_THROW
+        (modify_directory("sh/", "/bin/")
+        ,std::runtime_error
+        ,"Assertion 'original_filepath.has_filename()' failed."
+        );
 
     LMI_TEST_THROW
         (modify_directory("", "/bin")
         ,std::runtime_error
-        ,"Assertion 'original_filepath.has_leaf()' failed."
+        ,"Assertion 'original_filepath.has_filename()' failed."
         );
 }
 
@@ -173,9 +173,9 @@ void test_unique_filepath_with_normal_filenames()
     // as a substitute for the nonstandard mkstemp() is a bad idea.
     // See:
     //   https://lists.nongnu.org/archive/html/lmi/2020-08/msg00015.html
-    fs::path const u = unique_filepath("/tmp/" + fs::basename(__FILE__), "");
+    fs::path const u = unique_filepath("/tmp/" + 
fs::path{__FILE__}.stem().string(), "");
     std::string const tmp = u.string();
-    fs::path const tmpdir(fs::complete(tmp));
+    fs::path const tmpdir(fs::absolute(tmp));
     fs::create_directory(tmpdir);
 
     // These tests would fail if read-only files with the following
@@ -268,9 +268,7 @@ void test_unique_filepath_with_normal_filenames()
     // They return nonzero, and do not remove the directory. The
     // reason is that the msw C library's remove() function doesn't
     // delete directories; it sets errno to 13, which means EACCESS,
-    // and _doserrno to 5, which might mean EIO. The boost:filesystem
-    // msw implementation calls RemoveDirectoryA() instead of the C
-    // remove() function in this case. The std::filesystem::remove()
+    // and _doserrno to 5, which might mean EIO. The std::filesystem::remove()
     // specification in C++17 (N4659) [30.10.15.30] says:
     //   "the file p is removed as if by POSIX remove()".
     // Therefore, use the filesystem function to remove the directory:
@@ -295,19 +293,14 @@ void test_unique_filepath_with_ludicrous_filenames()
     fs::path path2 = unique_filepath(fs::path(""), "");
     LMI_TEST_EQUAL(path2.string(), "");
 
-#if defined LMI_MSW
-    // fs::change_extension()'s argument is ".[extension]", so ".."
+    // fs::replace_extension()'s argument is ".[extension]", so ".."
     // represents a '.' extension-delimiter followed by an extension
-    // consisting of a single '.'. When fs::change_extension() is
+    // consisting of a single '.'. When fs::replace_extension() is
     // called by unique_filepath() here, adding that extension to ".."
-    // yields "...", which is forbidden by msw, but allowed (although
-    // of course discouraged) by posix.
-    LMI_TEST_THROW
-        (unique_filepath(fs::path(".."), "..")
-        ,fs::filesystem_error
-        ,""
-        );
-#endif // defined LMI_MSW
+    // yields "...." path, which won't work if it is actually used by msw,
+    // but is still allowed (although of course discouraged).
+    fs::path path3 = unique_filepath(fs::path(".."), "..");
+    LMI_TEST_EQUAL(path3.string(), "....");
 }
 
 void test_path_inserter()
@@ -337,7 +330,7 @@ void test_path_validation()
     // Create a file and a directory to test.
     //
     // Another test that calls fs::create_directory() uses an absolute
-    // path that's uniquified and canonicalized with fs::complete().
+    // path that's uniquified and canonicalized with fs::absolute().
     // This call uses a relative path, with no such safeguards; this
     // being a unit test, it is appropriate to retain some fragility.
     // If one user runs this test, and the directory created here
@@ -371,7 +364,7 @@ void test_path_validation()
     LMI_TEST_THROW
         (validate_filepath("<|>", context)
         ,std::runtime_error
-        ,lmi_test::what_regex("invalid name \"<|>\" in path")
+        ,"Unit test file '<|>' not found."
         );
 #endif // defined LMI_MSW
 
@@ -408,35 +401,49 @@ void test_path_validation()
     fs::remove("path_utility_test_dir");
 }
 
-/// Demonstrate a boost::filesystem oddity.
+/// Demonstrate that "root name" part is handled differently by std::filesystem
+/// library under different platforms.
 ///
 /// A print directory is specified in 'configurable_settings.xml', and
 /// managed by 'preferences_model.cpp'. Using an msw build of lmi to
 /// change its value endues it with a 'root-name'. Subsequently using
 /// a posix build of lmi does not remove the 'root-name'; instead, it
 /// does something bizarre, viz.:
-///   fs::system_complete(/opt/lmi/data) returns:
+///   fs::absolute(/opt/lmi/data) returns:
 ///   /opt/lmi/data
 /// as expected, but
-///   fs::system_complete(Z:/opt/lmi/data) bizarrely returns:
+///   fs::absolute(Z:/opt/lmi/data) bizarrely returns:
 ///   /opt/lmi/gcc_x86_64-pc-linux-gnu/build/ship/Z:/opt/lmi/data
 /// or something like that, depending on the build directory.
 
 void test_oddities()
 {
+    // The exact value of the root name doesn't matter under POSIX systems but
+    // under MSW we must use the actual root name, and not the hard-coded "Z:",
+    // as this is what absolute() uses for completing the path and comparisons
+    // below would fail under this platform unless the root name actually
+    // happens to be "Z:".
+    std::string root_name = fs::current_path().root_name().string();
+    if(root_name.empty())
+        {
+        // Root name not used under this platform, just use something 
non-empty.
+        root_name = "Z:";
+        }
+    LMI_TEST_EQUAL  (root_name.size(), 2);
+
     std::string const z0 = "/opt/lmi/data";
-    std::string const z1 = "Z:/opt/lmi/data";
+    std::string const z1 = root_name + "/opt/lmi/data";
     std::string const z2 = remove_alien_msw_root(z1).string();
 #if defined LMI_POSIX
-    LMI_TEST_EQUAL  (z0, fs::system_complete(z0).string());
-    LMI_TEST_UNEQUAL(z0, fs::system_complete(z1).string());
+    LMI_TEST_EQUAL  (z0, fs::absolute(z0).string());
+    LMI_TEST_UNEQUAL(z0, fs::absolute(z1).string());
     LMI_TEST_EQUAL  (z0, z2);
-    LMI_TEST_EQUAL  (z0, fs::system_complete(z2).string());
+    LMI_TEST_EQUAL  (z0, fs::absolute(z2).string());
 #elif defined LMI_MSW
-    LMI_TEST_EQUAL  (z1, fs::system_complete(z0).string());
-    LMI_TEST_EQUAL  (z1, fs::system_complete(z1).string());
+    LMI_TEST_EQUAL  (z1, fs::absolute(z0).string());
+    LMI_TEST_EQUAL  (z1, fs::absolute(z1).string());
     LMI_TEST_EQUAL  (z1, z2);
-    LMI_TEST_EQUAL  (z1, fs::system_complete(z2).string());
+    LMI_TEST_EQUAL  (z1, fs::absolute(z2).string());
 #else  // Unknown platform.
     throw "Unrecognized platform."
 #endif // Unknown platform.
@@ -444,8 +451,6 @@ void test_oddities()
 
 int test_main(int, char*[])
 {
-    initialize_filesystem();
-
     test_modify_directory();
     test_orthodox_filename();
     test_serial_file_path();
diff --git a/pchlist.hpp b/pchlist.hpp
index 6d20259..fa4bc5e 100644
--- a/pchlist.hpp
+++ b/pchlist.hpp
@@ -78,6 +78,7 @@
 #   include "numeric_io_traits.hpp"
 #   include "oecumenic_enumerations.hpp"
 #   include "outlay.hpp"
+#   include "path.hpp"
 #   include "path_utility.hpp"
 #   include "platform_dependent.hpp"
 #   include "round_to.hpp"
@@ -97,10 +98,6 @@
 #   include "yare_input.hpp"
 #   include "zero.hpp"
 
-#   include <boost/filesystem/convenience.hpp>
-#   include <boost/filesystem/operations.hpp>
-#   include <boost/filesystem/path.hpp>
-
 #   include <cstddef>
 #   include <cstdlib>
 #   include <exception>
diff --git a/pdf_command.hpp b/pdf_command.hpp
index 267c99a..9a85b0b 100644
--- a/pdf_command.hpp
+++ b/pdf_command.hpp
@@ -24,10 +24,9 @@
 
 #include "config.hpp"
 
+#include "path.hpp"
 #include "so_attributes.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 class Ledger;
 
 typedef void (*pdf_command_fp_type)(Ledger const&, fs::path const&);
diff --git a/posix_fhs.make b/posix_fhs.make
index 8e3b84c..c1b308c 100644
--- a/posix_fhs.make
+++ b/posix_fhs.make
@@ -30,13 +30,6 @@ PERFORM :=
 
 EXTRA_LIBS := -ldw -lunwind -ldl
 
-platform_boost_libraries := \
-  -lboost_filesystem-gcc \
-
-# The libraries referenced above may be used if desired, but are not
-# necessary because lmi compiles their source code to object files.
-platform_boost_libraries :=
-
 AR      := ar
 CC      := gcc
 CPP     := cpp
diff --git a/preferences_model.cpp b/preferences_model.cpp
index 63514c8..8268da3 100644
--- a/preferences_model.cpp
+++ b/preferences_model.cpp
@@ -30,9 +30,6 @@
 #include "ssize_lmi.hpp"
 #include "value_cast.hpp"
 
-#include <boost/filesystem/operations.hpp> // fs::system_complete()
-#include <boost/filesystem/path.hpp>
-
 #include <sstream>
 #include <vector>
 
@@ -56,7 +53,7 @@ bool is_calculation_summary_column_name(std::string const& 
member_name)
 std::string generic_path(std::string const& s)
 {
 #if defined LMI_MSW
-    return fs::system_complete(fs::path(s)).string();
+    return fs::absolute(fs::path(s)).string();
 #else  // !defined LMI_MSW
     return remove_alien_msw_root(s).string();
 #endif // !defined LMI_MSW
@@ -74,16 +71,11 @@ std::string generic_path(std::string const& s)
 /// counterpart generic_path() are used to translate between the two
 /// styles, so that backward slashes are sequestered in the GUI and do
 /// not flow into 'configurable_settings.xml'.
-///
-/// At least with the version of boost currently used (2016-06),
-/// native_file_string() and native_directory_string() are identical,
-/// so there is no need to differentiate between directories and
-/// filepaths.
 
 std::string native_path(std::string const& s)
 {
 #if defined LMI_MSW
-    return fs::system_complete(fs::path(s)).native_file_string();
+    return fs::absolute(fs::path(s)).native_string();
 #else  // !defined LMI_MSW
     return s;
 #endif // !defined LMI_MSW
diff --git a/premium_tax_test.cpp b/premium_tax_test.cpp
index 545bdb4..a89fd0c 100644
--- a/premium_tax_test.cpp
+++ b/premium_tax_test.cpp
@@ -27,7 +27,6 @@
 #include "database.hpp"
 #include "dbdict.hpp"
 #include "global_settings.hpp"
-#include "path_utility.hpp"             // initialize_filesystem()
 #include "product_data.hpp"
 #include "stratified_charges.hpp"
 #include "test_tools.hpp"
@@ -133,9 +132,6 @@ void premium_tax_test::test_rates()
 
 int test_main(int, char*[])
 {
-    // Absolute paths require "native" name-checking policy for msw.
-    initialize_filesystem();
-
     premium_tax_test::test();
 
     return EXIT_SUCCESS;
diff --git a/product_data.cpp b/product_data.cpp
index 056ff5e..2ef5f3b 100644
--- a/product_data.cpp
+++ b/product_data.cpp
@@ -30,10 +30,9 @@
 #include "data_directory.hpp"           // AddDataDir()
 #include "map_lookup.hpp"
 #include "my_proem.hpp"                 // ::write_proem()
+#include "path.hpp"
 #include "xml_serialize.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-
 #include <vector>
 
 template class xml_serializable<product_data>;
@@ -936,9 +935,7 @@ void product_data::write_policy_files()
 /// Somewhat arbitrarily, forbid '.' in product names. There's no real
 /// need to allow that, and it would complicate the code. A product
 /// name like "ul.with.variable.funds" could too easily be mistaken
-/// for a '.funds' file. The boost filesystem portability guidelines
-/// suggest "Do not use more that [sic] one period in a file name",
-/// and extensions are added to product names to create file names.
+/// for a '.funds' file.
 ///
 /// Rejected alternative: take a 'ce_product_name' argument instead.
 /// That would constrain the argument in a natural way, but would
@@ -950,8 +947,8 @@ void product_data::write_policy_files()
 std::string filename_from_product_name(std::string const& product_name)
 {
     fs::path path(product_name);
-    LMI_ASSERT(product_name == fs::basename(path));
-    path = fs::change_extension(path, ".policy");
+    LMI_ASSERT(product_name == path.stem());
+    path.replace_extension(".policy");
     return AddDataDir(path.string());
 }
 
diff --git a/product_data.hpp b/product_data.hpp
index c7bd1c4..4447c87 100644
--- a/product_data.hpp
+++ b/product_data.hpp
@@ -26,11 +26,10 @@
 
 #include "any_member.hpp"
 #include "cache_file_reads.hpp"
+#include "path.hpp"
 #include "so_attributes.hpp"
 #include "xml_serializable.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 
 /// A single product datum: a string with an optional gloss.
diff --git a/product_file_test.cpp b/product_file_test.cpp
index 4c0739b..555c3be 100644
--- a/product_file_test.cpp
+++ b/product_file_test.cpp
@@ -33,12 +33,10 @@
 
 #include "data_directory.hpp"           // AddDataDir()
 #include "global_settings.hpp"
-#include "path_utility.hpp"             // initialize_filesystem()
+#include "path.hpp"
 #include "test_tools.hpp"
 #include "timer.hpp"                    // TimeAnAliquot()
 
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 #include <utility>                      // move()
 
@@ -191,9 +189,6 @@ void product_file_test::assay_speed()
 
 int test_main(int, char*[])
 {
-    // Absolute paths require "native" name-checking policy for msw.
-    initialize_filesystem();
-
     product_file_test::test();
     return EXIT_SUCCESS;
 }
diff --git a/rate_table.cpp b/rate_table.cpp
index 93260fa..57db9de 100644
--- a/rate_table.cpp
+++ b/rate_table.cpp
@@ -27,13 +27,10 @@
 #include "bourn_cast.hpp"
 #include "crc32.hpp"
 #include "miscellany.hpp"               // ios_in_binary(), 
ios_out_trunc_binary()
+#include "path.hpp"
 #include "path_utility.hpp"
 #include "value_cast.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/exception.hpp>
-#include <boost/filesystem/fstream.hpp>
-
 #include <algorithm>                    // count()
 #if 202002 <= __cplusplus
 #   include <bit>                       // endian
@@ -195,19 +192,11 @@ inline bool stream_read(std::istream& is, void* data, 
std::size_t length)
 // there is no way to handle these errors anyhow, e.g. when we're trying to
 // clean up while handling a previous exception and so can't let another one
 // propagate.
-//
-// BOOST !! Use "ec" argument with later versions instead of throwing and
-// catching the exception.
 void remove_nothrow(fs::path const& path)
 {
-    try
-        {
-        fs::remove(path);
-        }
-    catch(fs::filesystem_error const&)
-        {
-        // Intentionally ignore.
-        }
+    std::error_code ec;
+    fs::remove(path, ec);
+    // Intentionally ignore the error code value.
 }
 
 // Helper function wrapping std::strtoull() and hiding its peculiarities:
@@ -2349,12 +2338,12 @@ class database_impl final
   public:
     static fs::path get_index_path(fs::path const& path)
         {
-        return fs::change_extension(path, ".ndx");
+        return fs::path{path}.replace_extension(".ndx");
         }
 
     static fs::path get_data_path(fs::path const& path)
         {
-        return fs::change_extension(path, ".dat");
+        return fs::path{path}.replace_extension(".dat");
         }
 
     explicit database_impl(fs::path const& path);
@@ -2872,7 +2861,7 @@ void database_impl::save(fs::path const& path)
                 ,char     const* description
                 ,char     const* extension
                 )
-                :path_ {fs::change_extension(path, extension)}
+                :path_ {fs::path{path}.replace_extension(extension)}
                 ,temp_path_
                     {fs::exists(path_)
                         ? unique_filepath(path_, extension + 
std::string(".tmp"))
diff --git a/rate_table.hpp b/rate_table.hpp
index 7207346..18948dc 100644
--- a/rate_table.hpp
+++ b/rate_table.hpp
@@ -23,8 +23,7 @@
 #define rate_table_hpp
 
 #include "config.hpp"
-
-#include <boost/filesystem/path.hpp>
+#include "path.hpp"
 
 #include <cstddef>                      // size_t
 #include <cstdint>
diff --git a/rate_table_test.cpp b/rate_table_test.cpp
index 9b325d6..af328d5 100644
--- a/rate_table_test.cpp
+++ b/rate_table_test.cpp
@@ -25,12 +25,10 @@
 
 #include "assert_lmi.hpp"
 #include "miscellany.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"
 #include "test_tools.hpp"
 
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/operations.hpp>
-
 #include <fstream>
 #include <iomanip>                      // setw(), setfill()
 #include <ios>
diff --git a/rate_table_tool.cpp b/rate_table_tool.cpp
index 3601ff1..760cc40 100644
--- a/rate_table_tool.cpp
+++ b/rate_table_tool.cpp
@@ -25,12 +25,10 @@
 #include "getopt.hpp"
 #include "license.hpp"
 #include "main_common.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"
 #include "rate_table.hpp"
 
-#include <boost/filesystem/convenience.hpp> // extension()
-#include <boost/filesystem/operations.hpp>  // is_directory(), 
directory_iterator
-
 #include <algorithm>                    // sort()
 #include <cstdio>                       // fflush()
 #include <cstdlib>                      // atoi()
@@ -145,13 +143,11 @@ void merge
         // to verify than equivalence: databases created this way from
         // the same data on different machines have identical md5sums.
         std::vector<fs::path> table_names;
-        fs::directory_iterator i(path_to_merge);
-        fs::directory_iterator const eod;
-        for(; i != eod; ++i)
+        for(auto const& de : fs::directory_iterator(path_to_merge))
             {
-            if(".rates" == fs::extension(*i))
+            if(".rates" == de.path().extension())
                 {
-                table_names.push_back(*i);
+                table_names.push_back(de.path());
                 }
             }
         std::sort(table_names.begin(), table_names.end());
diff --git a/rounding_rules.cpp b/rounding_rules.cpp
index a0dd519..cb36460 100644
--- a/rounding_rules.cpp
+++ b/rounding_rules.cpp
@@ -28,10 +28,9 @@
 #include "assert_lmi.hpp"
 #include "data_directory.hpp"           // AddDataDir()
 #include "my_proem.hpp"                 // ::write_proem()
+#include "path.hpp"
 #include "xml_serialize.hpp"
 
-#include <boost/filesystem/convenience.hpp>
-
 template class xml_serializable<rounding_rules>;
 
 namespace xml_serialize
diff --git a/rounding_rules.hpp b/rounding_rules.hpp
index 3f2070c..4030d69 100644
--- a/rounding_rules.hpp
+++ b/rounding_rules.hpp
@@ -28,11 +28,10 @@
 #include "cache_file_reads.hpp"
 #include "mc_enum.hpp"
 #include "mc_enum_types.hpp"
+#include "path.hpp"
 #include "so_attributes.hpp"
 #include "xml_serializable.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 
 /// Parameters of a rounding rule.
diff --git a/skeleton.cpp b/skeleton.cpp
index d3f57da..9296e27 100644
--- a/skeleton.cpp
+++ b/skeleton.cpp
@@ -65,6 +65,7 @@
 #include "miscellany.hpp"
 #include "msw_workarounds.hpp"          // PreloadDesignatedDlls()
 #include "mvc_controller.hpp"
+#include "path.hpp"
 #include "path_utility.hpp"             // fs::path inserter
 #include "policy_document.hpp"
 #include "policy_view.hpp"
@@ -82,9 +83,6 @@
 #include "wx_new.hpp"
 #include "wx_utility.hpp"               // class ClipboardEx
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
 #include <wx/artprov.h>
 #include <wx/config.h>
 #include <wx/cshelp.h>
@@ -515,16 +513,16 @@ void Skeleton::UponHelp(wxCommandEvent&)
     std::string const canonical_url("https://lmi.nongnu.org/user_manual.html";);
 
     std::string s(AddDataDir("user_manual.html"));
-    fs::path p(fs::system_complete(fs::path(s)));
+    fs::path p(fs::absolute(fs::path(s)));
     if(fs::exists(p))
         {
-        s = "file://" + p.native_file_string();
+        s = "file://" + p.string();
         }
     else
         {
         warning()
             << "A local copy of the user manual should have been placed here:"
-            << "\n    " << p.native_file_string()
+            << "\n    " << p
             << "\nbut was not. Try reinstalling."
             << '\n'
             << "\nMeanwhile, the online user manual will be used if possible."
@@ -536,7 +534,7 @@ void Skeleton::UponHelp(wxCommandEvent&)
     bool r = false;
     {
     wxLogNull x;
-    r = wxLaunchDefaultBrowser(s);
+    r = wxLaunchDefaultBrowser(wxString::FromUTF8(s));
     }
     if(!r)
         {
diff --git a/stratified_charges.hpp b/stratified_charges.hpp
index dbf2d5a..85909c6 100644
--- a/stratified_charges.hpp
+++ b/stratified_charges.hpp
@@ -27,11 +27,10 @@
 #include "any_member.hpp"
 #include "cache_file_reads.hpp"
 #include "mc_enum_type_enums.hpp"
+#include "path.hpp"
 #include "so_attributes.hpp"
 #include "xml_serializable.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <string>
 #include <vector>
 
diff --git a/test_coding_rules.cpp b/test_coding_rules.cpp
index 5a1868a..92052e6 100644
--- a/test_coding_rules.cpp
+++ b/test_coding_rules.cpp
@@ -26,13 +26,9 @@
 #include "istream_to_string.hpp"
 #include "main_common.hpp"
 #include "miscellany.hpp"               // begins_with(), split_into_lines()
+#include "path.hpp"
 #include "ssize_lmi.hpp"
 
-#include <boost/filesystem/convenience.hpp> // fs::extension()
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/operations.hpp>  // fs::exists(), fs::is_directory()
-#include <boost/filesystem/path.hpp>
-
 #include <algorithm>                    // is_sorted()
 #include <ctime>
 #include <iomanip>
@@ -136,8 +132,8 @@ class file final
 file::file(std::string const& file_path)
     :path_      {file_path}
     ,full_name_ {file_path}
-    ,leaf_name_ {path_.leaf()}
-    ,extension_ {fs::extension(path_)}
+    ,leaf_name_ {path_.filename().string()}
+    ,extension_ {path_.extension().string()}
     ,phylum_    {e_no_phylum}
 {
     if(!fs::exists(path_))
diff --git a/view_ex.cpp b/view_ex.cpp
index a2be564..db32b53 100644
--- a/view_ex.cpp
+++ b/view_ex.cpp
@@ -43,12 +43,11 @@
 #include "alert.hpp"
 #include "assert_lmi.hpp"
 #include "docmanager_ex.hpp"
+#include "path.hpp"
 #include "safely_dereference_as.hpp"
 #include "skeleton.hpp"                 // Skeleton::CreateChildFrame()
 #include "wx_new.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <wx/app.h>                     // GetInstance()
 #include <wx/dc.h>
 #include <wx/icon.h>
@@ -200,14 +199,14 @@ void ViewEx::OnDraw(wxDC*)
 ///
 /// Using wxDocument::GetUserReadableName() means the name can be
 /// altered by calling wxDocument::SetTitle(). By default, the title
-/// is the filename with no path. The call to leaf() guarantees that
+/// is the filename with no path. The call to filename() guarantees that
 /// the result is pathless, even if e.g. the title has been set to the
-/// document's full filepath. If leaf() is empty, then a name that
+/// document's full filepath. If filename() is empty, then a name that
 /// recognizably should never be uttered is returned.
 
 std::string ViewEx::base_filename() const
 {
     std::string 
t(GetDocument()->GetUserReadableName().ToStdString(wxConvUTF8));
     fs::path path(t);
-    return path.has_leaf() ? path.leaf() : std::string("Hastur");
+    return path.has_filename() ? path.filename().string() : 
std::string("Hastur");
 }
diff --git a/workhorse.make b/workhorse.make
index db46d03..018a00a 100644
--- a/workhorse.make
+++ b/workhorse.make
@@ -592,14 +592,6 @@ bourn_cast_test.o: gcc_common_extra_warnings += \
 
 # Some boost-1.33.1 libraries are incompatible with many warnings.
 
-$(boost_filesystem_objects): gcc_common_extra_warnings += \
-  -Wno-deprecated-declarations \
-  -Wno-old-style-cast \
-  -Wno-unused-macros \
-  -Wno-unused-parameter \
-  -Wno-useless-cast \
-  -Wno-zero-as-null-pointer-constant \
-
 $(boost_regex_objects): gcc_common_extra_warnings += \
   -Wno-conversion \
   -Wno-duplicated-branches \
@@ -661,7 +653,6 @@ $(wno_conv_objects): gcc_common_extra_warnings += 
-Wno-conversion -Wfloat-conver
 
 wno_sign_conv_objects := \
   $(boost_dependent_objects) \
-  $(boost_filesystem_objects) \
   $(boost_regex_objects) \
   $(wx_dependent_objects) \
   crc32.o \
@@ -775,7 +766,6 @@ $(product_file_sources): tutelary_flag += 
$(product_file_flags)
 #   http://boost.org/more/faq.htm
 
 REQUIRED_LIBS := \
-  $(platform_boost_libraries) \
   $(xml_libraries) \
 
 wx_ldflags = \
diff --git a/wx_test_benchmark_census.cpp b/wx_test_benchmark_census.cpp
index 3638dc1..d3d4f37 100644
--- a/wx_test_benchmark_census.cpp
+++ b/wx_test_benchmark_census.cpp
@@ -22,6 +22,7 @@
 #include "pchfile_wx.hpp"
 
 #include "assert_lmi.hpp"
+#include "path.hpp"
 #include "wx_test_case.hpp"
 #include "wx_test_statusbar.hpp"
 
@@ -31,8 +32,6 @@
 #include <wx/testing.h>
 #include <wx/uiaction.h>
 
-#include <boost/filesystem/operations.hpp>
-
 #include <cmath>                        // fabs()
 #include <iostream>
 
@@ -44,13 +43,13 @@ class census_benchmark
   public:
     explicit census_benchmark(fs::path const& path)
         :status_ {get_main_window_statusbar()}
-        ,name_   {path.leaf()}
+        ,name_   {wxString::FromUTF8(path.filename().string())}
         {
         wxUIActionSimulator z;
         z.Char('o', wxMOD_CONTROL); // "File|Open"
         wxTEST_DIALOG
             (wxYield()
-            ,wxExpectModal<wxFileDialog>(path.native_file_string())
+            ,wxExpectModal<wxFileDialog>(wxString::FromUTF8(path.string()))
             );
         wxYield();
         }
@@ -136,15 +135,14 @@ class census_benchmark
 
 LMI_WX_TEST_CASE(benchmark_census)
 {
-    fs::directory_iterator const end_i;
-    for(fs::directory_iterator i(get_test_files_path()); i != end_i; ++i)
+    for(auto const& de : fs::directory_iterator(get_test_files_path()))
         {
-        if(!wxString(i->leaf()).Matches("MSEC*.cns"))
+        
if(!wxString::FromUTF8(de.path().filename().string()).Matches("MSEC*.cns"))
             {
             continue;
             }
 
-        census_benchmark b(*i);
+        census_benchmark b(de.path());
 
         {
         // Ensure that the window doesn't stay opened (and possibly affects
diff --git a/wx_test_case.hpp b/wx_test_case.hpp
index bb2494c..fa494bf 100644
--- a/wx_test_case.hpp
+++ b/wx_test_case.hpp
@@ -23,8 +23,7 @@
 #define wx_test_case_hpp
 
 #include "config.hpp"
-
-#include <boost/filesystem/path.hpp>
+#include "path.hpp"
 
 /// Base class for the test case objects.
 ///
diff --git a/wx_test_config_settings.cpp b/wx_test_config_settings.cpp
index 02fbc12..b4e6c6a 100644
--- a/wx_test_config_settings.cpp
+++ b/wx_test_config_settings.cpp
@@ -23,10 +23,9 @@
 
 #include "assert_lmi.hpp"
 #include "configurable_settings.hpp"
+#include "path.hpp"
 #include "wx_test_case.hpp"
 
-#include <boost/filesystem/operations.hpp>
-
 /*
     Test configurable_settings.xml file.
 
diff --git a/wx_test_default_update.cpp b/wx_test_default_update.cpp
index 2f3c01e..89662ca 100644
--- a/wx_test_default_update.cpp
+++ b/wx_test_default_update.cpp
@@ -24,6 +24,7 @@
 #include "assert_lmi.hpp"
 #include "configurable_settings.hpp"
 #include "mvc_controller.hpp"
+#include "path.hpp"
 #include "wx_test_case.hpp"
 #include "wx_test_new.hpp"
 #include "wx_test_statusbar.hpp"
@@ -34,8 +35,6 @@
 #include <wx/testing.h>
 #include <wx/uiaction.h>
 
-#include <boost/filesystem/operations.hpp>
-
 /// Make sure the default input file can be opened, modified, and saved.
 ///
 /// Run this test only if the '--distribution' option is given.
diff --git a/wx_test_expiry_dates.cpp b/wx_test_expiry_dates.cpp
index 58818f0..11a55dc 100644
--- a/wx_test_expiry_dates.cpp
+++ b/wx_test_expiry_dates.cpp
@@ -24,13 +24,11 @@
 #include "assert_lmi.hpp"
 #include "calendar_date.hpp"
 #include "global_settings.hpp"
+#include "path.hpp"
 #include "version.hpp"
 #include "wx_test_case.hpp"
 #include "wx_test_date.hpp"
 
-#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/operations.hpp>
-
 #include <iostream>
 
 /// Validate dates in the 'expiry' file.
diff --git a/wx_test_output.hpp b/wx_test_output.hpp
index 9bb1f49..7143fb5 100644
--- a/wx_test_output.hpp
+++ b/wx_test_output.hpp
@@ -23,8 +23,7 @@
 #define wx_test_output_hpp
 
 #include "config.hpp"
-
-#include <boost/filesystem/operations.hpp>
+#include "path.hpp"
 
 /// Class helping to check for the expected output file existence.
 ///
@@ -57,7 +56,7 @@ class output_file_existence_checker
         return fs::exists(path_);
         }
 
-    std::string const& path() const
+    std::string path() const
         {
         return path_.string();
         }
diff --git a/wx_test_output_pdf.hpp b/wx_test_output_pdf.hpp
index e0dac4c..cb9a51d 100644
--- a/wx_test_output_pdf.hpp
+++ b/wx_test_output_pdf.hpp
@@ -25,10 +25,9 @@
 #include "config.hpp"
 
 #include "configurable_settings.hpp"
+#include "path.hpp"
 #include "wx_test_output.hpp"
 
-#include <boost/filesystem/operations.hpp>
-
 /// Specialized version of output_file_existence_checker for the output PDF
 /// files: it takes just the base name of the file, without neither the
 /// directory part nor the .pdf extension, in its ctor and also takes care of
diff --git a/xml_serializable.hpp b/xml_serializable.hpp
index d081201..9b137f7 100644
--- a/xml_serializable.hpp
+++ b/xml_serializable.hpp
@@ -24,11 +24,10 @@
 
 #include "config.hpp"
 
+#include "path.hpp"
 #include "so_attributes.hpp"
 #include "xml_lmi_fwd.hpp"
 
-#include <boost/filesystem/path.hpp>
-
 #include <list>
 #include <map>
 #include <string>
diff --git a/xml_serializable.tpp b/xml_serializable.tpp
index 103f955..954d538 100644
--- a/xml_serializable.tpp
+++ b/xml_serializable.tpp
@@ -24,11 +24,10 @@
 #include "alert.hpp"
 #include "any_member.hpp"               // MemberSymbolTable<>
 #include "contains.hpp"
+#include "path.hpp"
 #include "platform_dependent.hpp"       // access()
 #include "xml_lmi.hpp"
 
-#include <boost/filesystem/convenience.hpp> // basename()
-
 #include <xmlwrapp/nodes_view.h>
 
 #include <algorithm>                    // copy(), find()
@@ -69,7 +68,7 @@ template<typename T>
 void xml_serializable<T>::save(fs::path const& path) const
 {
     xml_lmi::xml_document document(xml_root_name());
-    write_proem(document, fs::basename(path));
+    write_proem(document, path.stem().string());
     immit_members_into(document.root_node());
     document.save(path.string());
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]