]> git.armaanb.net Git - gen-shell.git/commitdiff
removed libshared dependency
authorArmaan Bhojwani <3fb650a9-b47e-4604-a282-1dd91953b2ee@anonaddy.me>
Tue, 27 Oct 2020 13:40:51 +0000 (09:40 -0400)
committerArmaan Bhojwani <3fb650a9-b47e-4604-a282-1dd91953b2ee@anonaddy.me>
Tue, 27 Oct 2020 13:40:51 +0000 (09:40 -0400)
65 files changed:
AUTHORS [deleted file]
README.md
src/CMakeLists.txt
src/diag.cpp [deleted file]
src/help.cpp [deleted file]
src/libshared/AUTHORS [deleted file]
src/libshared/CMakeLists.txt [deleted file]
src/libshared/LICENSE [deleted file]
src/libshared/cmake.h.in [deleted file]
src/libshared/cmake/CXXSniffer.cmake [deleted file]
src/libshared/src/Args.cpp [deleted file]
src/libshared/src/Args.h [deleted file]
src/libshared/src/CMakeLists.txt [deleted file]
src/libshared/src/Color.cpp [deleted file]
src/libshared/src/Color.h [deleted file]
src/libshared/src/Composite.cpp [deleted file]
src/libshared/src/Composite.h [deleted file]
src/libshared/src/Configuration.cpp [deleted file]
src/libshared/src/Configuration.h [deleted file]
src/libshared/src/Datetime.cpp [deleted file]
src/libshared/src/Datetime.h [deleted file]
src/libshared/src/Duration.cpp [deleted file]
src/libshared/src/Duration.h [deleted file]
src/libshared/src/FS.cpp [deleted file]
src/libshared/src/FS.h [deleted file]
src/libshared/src/JSON.cpp [deleted file]
src/libshared/src/JSON.h [deleted file]
src/libshared/src/Lexer.cpp [deleted file]
src/libshared/src/Lexer.h [deleted file]
src/libshared/src/Log.cpp [deleted file]
src/libshared/src/Log.h [deleted file]
src/libshared/src/Msg.cpp [deleted file]
src/libshared/src/Msg.h [deleted file]
src/libshared/src/PEG.cpp [deleted file]
src/libshared/src/PEG.h [deleted file]
src/libshared/src/Packrat.cpp [deleted file]
src/libshared/src/Packrat.h [deleted file]
src/libshared/src/Palette.cpp [deleted file]
src/libshared/src/Palette.h [deleted file]
src/libshared/src/Pig.cpp [deleted file]
src/libshared/src/Pig.h [deleted file]
src/libshared/src/README [deleted file]
src/libshared/src/RX.cpp [deleted file]
src/libshared/src/RX.h [deleted file]
src/libshared/src/SAX.cpp [deleted file]
src/libshared/src/Table.cpp [deleted file]
src/libshared/src/Table.h [deleted file]
src/libshared/src/Timer.cpp [deleted file]
src/libshared/src/Timer.h [deleted file]
src/libshared/src/Tree.cpp [deleted file]
src/libshared/src/Tree.h [deleted file]
src/libshared/src/format.cpp [deleted file]
src/libshared/src/format.h [deleted file]
src/libshared/src/ip.cpp [deleted file]
src/libshared/src/lex.cpp [deleted file]
src/libshared/src/shared.cpp [deleted file]
src/libshared/src/shared.h [deleted file]
src/libshared/src/unicode.cpp [deleted file]
src/libshared/src/unicode.h [deleted file]
src/libshared/src/utf8.cpp [deleted file]
src/libshared/src/utf8.h [deleted file]
src/libshared/src/wcwidth6.cpp [deleted file]
src/main.cpp
src/prompt.cpp
src/shell.cpp [deleted file]

diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644 (file)
index e05dce9..0000000
--- a/AUTHORS
+++ /dev/null
@@ -1,30 +0,0 @@
-Gen-shell is created by Armaan Bhojwani
-
-Tasksh was made by the following people:
-  The development of tasksh was made possible by the significant contributions of
-  the following people:
-  
-    Paul Beckingham    (Principal Author)
-    Federico Hernandez (Principal Author)
-    Dirk Deimeke       (Technical Advisor & Evangelist)
-  
-  The following submitted code, packages or analysis, and deserve special thanks:
-  
-    Jörg Krause
-    Ben Boeckel
-    ilove zfs
-    Paul Fenwick
-  
-  Thanks to the following, who submitted detailed bug reports and excellent
-  suggestions:
-  
-    Kevin Gunn
-    Fidel Mato
-    David Stahl
-    David Patrick
-    jonbobbly
-    hosaka
-    Lars Kumbier
-    Iain R. Learmonth
-    Eric Hymowitz
-    bjonnh
index ead6bf44bdc06f7e3a6b9c23697455d85725c73c..72a4662cfbbc6c001606f5f2d9f9738468f14955 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # gen-shell
 ![Jenkins](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fbuild.bhojwani.org%2Fjob%2Fgen-shell%2F) 
-A work in progress generic shell forked form [taskshell](https://github.com/GothenburgBitFactory/taskshell)
+A work in progress generic shell. This is a very reduced fork of [taskshell](https://github.com/GothenburgBitFactory/taskshell)
 
 ## Installation
 Binaries can be downloaded [from here](https://build.bhojwani.org/job/gen-shell/lastSuccessfulBuild/artifact/build/src/gen-shell). Note that these binaries are compiled against libreadline7, so if your system only has libreadline8, you should symlink 8 to 7 with `sudo ln -s /usr/lib/x86_64-linux-gnu/libreadline.so.8.0 /usr/lib/x86_64-linux-gnu/libreadline.so.7`. This isn't a great solution, but it gets the job done.
index d16e9867340aef4bbc2d486fcd2f0303175c0cb2..9d48f226223d4eadcfc11d71fb2a18d2dfe095ba 100644 (file)
@@ -4,28 +4,25 @@ include_directories (${CMAKE_SOURCE_DIR}
                      ${CMAKE_SOURCE_DIR}/src/libshared/src
                      ${TASKSH_INCLUDE_DIRS})
 
-set (tasksh_SRCS diag.cpp
-                 help.cpp
-                 prompt.cpp
-                 shell.cpp)
+set (tasksh_SRCS prompt.cpp)
 
-set (libshared_SRCS libshared/src/Color.cpp         libshared/src/Color.h
-                    libshared/src/Datetime.cpp      libshared/src/Datetime.h
-                    libshared/src/Duration.cpp      libshared/src/Duration.h
-                    libshared/src/FS.cpp            libshared/src/FS.h
-                    libshared/src/Lexer.cpp         libshared/src/Lexer.h
-                    libshared/src/Pig.cpp           libshared/src/Pig.h
-                    libshared/src/shared.cpp        libshared/src/shared.h
-                    libshared/src/format.cpp        libshared/src/format.h
-                    libshared/src/unicode.cpp       libshared/src/unicode.h
-                    libshared/src/utf8.cpp          libshared/src/utf8.h
-                    libshared/src/wcwidth6.cpp)
+set (libshared_SRCS libshared/src/Color.cpp         libshared/src/Color.h
+                    libshared/src/Datetime.cpp      libshared/src/Datetime.h
+                    libshared/src/Duration.cpp      libshared/src/Duration.h
+                    libshared/src/FS.cpp            libshared/src/FS.h
+                    libshared/src/Lexer.cpp         libshared/src/Lexer.h
+                    libshared/src/Pig.cpp           libshared/src/Pig.h
+                    libshared/src/shared.cpp        libshared/src/shared.h
+                    libshared/src/format.cpp        libshared/src/format.h
+                    libshared/src/unicode.cpp       libshared/src/unicode.h
+                    libshared/src/utf8.cpp          libshared/src/utf8.h
+                    libshared/src/wcwidth6.cpp)
 
 add_library (tasksh    STATIC ${tasksh_SRCS})
-add_library (libshared STATIC ${libshared_SRCS})
+add_library (libshared STATIC ${libshared_SRCS})
 add_executable (gen-sh_executable main.cpp)
 
-target_link_libraries (gen-sh_executable tasksh libshared ${GEN-SHELL_LIBRARIES})
+target_link_libraries (gen-sh_executable tasksh ${GEN-SHELL_LIBRARIES})
 
 set_property (TARGET gen-sh_executable PROPERTY OUTPUT_NAME "gen-shell")
 
diff --git a/src/diag.cpp b/src/diag.cpp
deleted file mode 100644 (file)
index 54c5184..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez, 2020 Armaan Bhojwani.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <iostream>
-#include <string>
-#include <vector>
-#include <cstring>
-#include <stdlib.h>
-#include <FS.h>
-#include <Color.h>
-#include <shared.h>
-#include <format.h>
-
-#ifdef HAVE_READLINE
-#include <readline/readline.h>
-#include <readline/history.h>
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-int cmdDiagnostics ()
-{
-  Color bold ("bold");
-
-  std::cout << "\n"
-            << bold.colorize (PACKAGE_STRING)
-            << "\n"
-            << "   " << "Platform: " << osName ()
-            << "\n\n";
-
-  // Compiler.
-  std::cout << bold.colorize ("Compiler")
-            << "\n"
-#ifdef __VERSION__
-            << "    " << "Version: "
-            << __VERSION__ << "\n"
-#endif
-            << "       " << "Caps:"
-#ifdef __STDC__
-            << " +stdc"
-#endif
-#ifdef __STDC_HOSTED__
-            << " +stdc_hosted"
-#endif
-#ifdef __STDC_VERSION__
-            << " +" << __STDC_VERSION__
-#endif
-#ifdef _POSIX_VERSION
-            << " +" << _POSIX_VERSION
-#endif
-#ifdef _POSIX2_C_VERSION
-            << " +" << _POSIX2_C_VERSION
-#endif
-#ifdef _ILP32
-            << " +ILP32"
-#endif
-#ifdef _LP64
-            << " +LP64"
-#endif
-            << " +c"      << 8 * sizeof (char)
-            << " +i"      << 8 * sizeof (int)
-            << " +l"      << 8 * sizeof (long)
-            << " +vp"     << 8 * sizeof (void*)
-            << " +time_t" << 8 * sizeof (time_t)
-            << "\n";
-
-  // Compiler compliance level.
-  std::cout << " Compliance: "
-            << cppCompliance ()
-            << "\n\n";
-
-  std::cout << bold.colorize ("Build Features")
-            << "\n";
-
-  std::cout << "libreadline: "
-#ifdef HAVE_READLINE
-#ifdef RL_VERSION_MAJOR
-            << RL_VERSION_MAJOR << "." << RL_VERSION_MINOR
-#elif defined RL_READLINE_VERSION
-            << "0x" << std::hex << RL_READLINE_VERSION
-#endif
-#else
-            << "n/a"
-#endif
-            << "\n";
-
-  std::cout << " Build type: "
-#ifdef CMAKE_BUILD_TYPE
-            << CMAKE_BUILD_TYPE
-#else
-            << "-"
-#endif
-            << "\n\n";
-
-  std::cout << bold.colorize ("Configuration")
-            << "\n";
-
-  auto env = getenv ("TASKRC");
-  std::cout << "     TASKRC: "
-            << (env ? env : "")
-            << "\n";
-
-  env = getenv ("TASKDATA");
-  std::cout << "   TASKDATA: "
-            << (env ? env : "")
-            << "\n";
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/help.cpp b/src/help.cpp
deleted file mode 100644 (file)
index be2ede2..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez, 2020 Armaan Bhojwani.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <iostream>
-
-////////////////////////////////////////////////////////////////////////////////
-int cmdHelp ()
-{
-  std::cout << '\n'
-            << "A generic shell";
-  return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/AUTHORS b/src/libshared/AUTHORS
deleted file mode 100644 (file)
index 8aab4e2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-The development of libshared was made possible by the significant contributions
-of the following people:
-
-  Paul Beckingham    (Principal Author)
-  Federico Hernandez (Principal Author)
-
-The following submitted code, packages or analysis, and deserve special thanks:
-
-  Lynoure Braakman
-  Jörg Krause
-  Ben Boeckel
-  Iain R. Learmonth
-  Toyam Cox
-
-Thanks to the following, who submitted detailed bug reports and excellent
-suggestions:
-
-  Sunil Joshi
-  Ellington Santos
-  Yury Vidineev
-  hosaka
diff --git a/src/libshared/CMakeLists.txt b/src/libshared/CMakeLists.txt
deleted file mode 100644 (file)
index c1fccb2..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-cmake_minimum_required (VERSION 2.8)
-set (CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required
-set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
-set (HAVE_CMAKE true)
-
-project (shared)
-include (CXXSniffer)
-
-set (PROJECT_VERSION "1.0.0")
-
-set (PACKAGE "${PROJECT_NAME}")
-set (VERSION "${PROJECT_VERSION}")
-set (PACKAGE_BUGREPORT "support@taskwarrior.org")
-set (PACKAGE_NAME "${PACKAGE}")
-set (PACKAGE_TARNAME "${PACKAGE}")
-set (PACKAGE_VERSION "${VERSION}")
-set (PACKAGE_STRING "${PACKAGE} ${VERSION}")
-
-message ("-- Configuring cmake.h")
-configure_file (
-  ${CMAKE_SOURCE_DIR}/cmake.h.in
-  ${CMAKE_SOURCE_DIR}/cmake.h)
-
-add_subdirectory (src)
-if (EXISTS ${CMAKE_SOURCE_DIR}/test)
-  add_subdirectory (test EXCLUDE_FROM_ALL)
-endif (EXISTS ${CMAKE_SOURCE_DIR}/test)
-
diff --git a/src/libshared/LICENSE b/src/libshared/LICENSE
deleted file mode 100644 (file)
index 4cd3104..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-libshared
-
-Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-http://www.opensource.org/licenses/mit-license.php
diff --git a/src/libshared/cmake.h.in b/src/libshared/cmake.h.in
deleted file mode 100644 (file)
index 92d4b9b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* cmake.h.in. Creates cmake.h during a cmake run */
-
-/* Package information */
-#define PACKAGE           "${PACKAGE}"
-#define VERSION           "${VERSION}"
-#define PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}"
-#define PACKAGE_NAME      "${PACKAGE_NAME}"
-#define PACKAGE_TARNAME   "${PACKAGE_TARNAME}"
-#define PACKAGE_VERSION   "${PACKAGE_VERSION}"
-#define PACKAGE_STRING    "${PACKAGE_STRING}"
-
-#define CMAKE_BUILD_TYPE  "${CMAKE_BUILD_TYPE}"
-
-/* Compiling platform */
-#cmakedefine LINUX
-#cmakedefine DARWIN
-#cmakedefine CYGWIN
-#cmakedefine FREEBSD
-#cmakedefine OPENBSD
-#cmakedefine NETBSD
-#cmakedefine SOLARIS
-#cmakedefine KFREEBSD
-#cmakedefine GNUHURD
-#cmakedefine UNKNOWN
-
-/* Found tm.tm_gmtoff struct member */
-#cmakedefine HAVE_TM_GMTOFF
-
-/* Found st.st_birthtime struct member */
-#cmakedefine HAVE_ST_BIRTHTIME
-
-/* Functions */
-#cmakedefine HAVE_GET_CURRENT_DIR_NAME
-#cmakedefine HAVE_TIMEGM
-#cmakedefine HAVE_UUID_UNPARSE_LOWER
-
diff --git a/src/libshared/cmake/CXXSniffer.cmake b/src/libshared/cmake/CXXSniffer.cmake
deleted file mode 100644 (file)
index cf6482a..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-message ("-- Configuring C++11")
-message ("-- System: ${CMAKE_SYSTEM_NAME}")
-
-include (CheckCXXCompilerFlag)
-
-# NOTE: Phase out -std=gnu++0x and --std=c++0x as soon as realistically possible.
-CHECK_CXX_COMPILER_FLAG("-std=c++11"   _HAS_CXX11)
-CHECK_CXX_COMPILER_FLAG("-std=c++0x"   _HAS_CXX0X)
-CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" _HAS_GNU0X)
-
-if (_HAS_CXX11)
-  set (_CXX11_FLAGS "-std=c++11")
-elseif (_HAS_CXX0X)
-  message (WARNING "Enabling -std=c++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option.  Consider upgrading.")
-  set (_CXX11_FLAGS "-std=c++0x")
-elseif (_HAS_GNU0X)
-  message (WARNING "Enabling -std=gnu++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option. Consider upgrading.")
-  set (_CXX11_FLAGS "-std=gnu++0x")
-else (_HAS_CXX11)
- message (FATAL_ERROR "C++11 support missing. Try upgrading your C++ compiler.")
-endif (_HAS_CXX11)
-
-if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-  set (LINUX true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-  set (DARWIN true)
-  set (_CXX11_FLAGS "${_CXX11_FLAGS} -stdlib=libc++")
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD")
-  set (KFREEBSD true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
-  set (FREEBSD true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
-  set (OPENBSD true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
-  set (NETBSD true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
-  set (SOLARIS true)
-elseif (${CMAKE_SYSTEM_NAME} STREQUAL "GNU")
-  set (GNUHURD true)
-elseif (${CMAKE_SYSTEM_NAME} STREQUAL "CYGWIN")
-  set (CYGWIN true)
-  # NOTE: Not setting -std=gnu++0x leads to compile errors even with
-  #       GCC 4.8.3, and debugging those leads to insanity. Adding this
-  #       workaround instead of fixing Cygwin.
-  set (_CXX11_FLAGS "-std=gnu++0x")
-else (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-  set (UNKNOWN true)
-endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-set (CMAKE_CXX_FLAGS "${_CXX11_FLAGS} ${CMAKE_CXX_FLAGS}")
-set (CMAKE_CXX_FLAGS "-Wall -Wextra -Wsign-compare -Wreturn-type ${CMAKE_CXX_FLAGS}")
diff --git a/src/libshared/src/Args.cpp b/src/libshared/src/Args.cpp
deleted file mode 100644 (file)
index 0c396f0..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2012 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Args.h>
-#include <shared.h>
-#include <sstream>
-#include <string.h>
-
-////////////////////////////////////////////////////////////////////////////////
-void Args::addOption (const std::string& name, bool defaultValue)
-{
-  _options[name] = defaultValue;
-  _optionCount[name] = 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Args::addNamed (const std::string& name, const std::string& defaultValue)
-{
-  _named[name] = defaultValue;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Args::limitPositionals (int limit)
-{
-  _limit = limit;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Args::enableNegatives ()
-{
-  _negatives = true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Args::scan (int argc, const char** argv)
-{
-  for (int i = 1; i < argc; ++i)
-  {
-    // Is an option or named arg.
-    if (argv[i][0] == '-' && strlen (argv[i]) > 1)
-    {
-      auto name = ltrim (argv[i], "-");
-
-      std::string canonical;
-      if (canonicalizeOption (name, canonical))
-      {
-        bool negated = _negatives && name.find ("no") == 0;
-        _options[canonical] = ! negated;
-        _optionCount[canonical]++;
-      }
-
-      else if (canonicalizeNamed (name, canonical))
-      {
-        if (i >= argc)
-          throw std::string ("Argument '" + canonical + "' has no value.");
-
-        ++i;
-        _named[canonical] = argv[i];
-      }
-
-      else
-        throw std::string ("Unrecognized argument '" + name + "'.");
-    }
-
-    // Or a positional.
-    else
-    {
-      _positionals.push_back (argv[i]);
-      if (_limit != -1 &&
-          static_cast <int> (_positionals.size ()) > _limit)
-        throw std::string ("Too many positional arguments.");
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Args::getOption (const std::string& name) const
-{
-  if (_options.find (name) == _options.end ())
-    return false;
-
-  return _options.at (name);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Args::getOptionCount (const std::string& name) const
-{
-  if (_optionCount.find (name) == _optionCount.end ())
-    return false;
-
-  return _optionCount.at (name);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Args::getNamed (const std::string& name) const
-{
-  if (_named.find (name) == _named.end ())
-    return "";
-
-  return _named.at (name);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Args::getPositionalCount () const
-{
-  return static_cast <int> (_positionals.size ());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Args::getPositional (int n) const
-{
-  return _positionals.at (n);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Assuming "abc" is a declared option, support the following canonicalization:
-//
-//   abc --> abc (exact match always canonicalizes)
-//    ab --> abc (if unique)
-//     a --> abc (if unique)
-// noabc --> abc (exact negation match always canonicalizes)
-//  noab --> abc (if unique)
-//   noa --> abc (if unique)
-//
-bool Args::canonicalizeOption (const std::string& partial, std::string& canonical) const
-{
-  bool negated = _negatives && partial.find ("no") == 0;
-
-  // Look for exact positive or negative matches first, which should succeed
-  // regardless of any longer partial matches.
-  if (_options.find (partial) != _options.end ())
-  {
-    canonical = partial;
-    return true;
-  }
-
-  if (negated &&
-      _options.find (partial.substr (2)) != _options.end ())
-  {
-    canonical = partial.substr (2);
-    return true;
-  }
-
-  // Iterate over all options, and look for partial matches.  If there is only
-  // one, we have canonicalization.
-  std::vector <std::string> candidates;
-  for (const auto& option : _options)
-  {
-    if (option.first.find (partial) == 0 ||
-        (negated && option.first.find (partial, 2) == 2))
-    {
-      candidates.push_back (option.first);
-    }
-  }
-
-  if (candidates.size () == 1)
-  {
-    canonical = candidates[0];
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Assuming "abc" is a declared name, support the following canonicalization:
-//
-//   abc --> abc (exact match always canonicalizes)
-//    ab --> abc (if unique)
-//     a --> abc (if unique)
-//
-bool Args::canonicalizeNamed (const std::string& partial, std::string& canonical) const
-{
-  // Look for exact positive or negative matches first, which should succeed
-  // regardless of longer partial matches.
-  if (_named.find (partial) != _named.end ())
-  {
-    canonical = partial;
-    return true;
-  }
-
-  // Iterate over all options, and look for partial matches.  If there is only
-  // one, we have canonicalization.
-  std::vector <std::string> candidates;
-  for (const auto& name : _named)
-    if (name.first.find (partial) == 0)
-      candidates.push_back (name.first);
-
-  if (candidates.size () == 1)
-  {
-    canonical = candidates[0];
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Args::dump () const
-{
-  std::stringstream out;
-  out << "Args\n"
-      << "  Options\n";
-  for (const auto& arg : _options)
-    out << "    " << arg.first << " = " << arg.second << " (" << _optionCount.at (arg.first) << ")\n";
-
-  out << "  Named\n";
-  for (const auto& arg : _named)
-    out << "    " << arg.first << " = " << arg.second << '\n';
-
-  out << "  Positionals\n"
-      << "    limit = " << _limit << '\n';
-  for (const auto& arg : _positionals)
-    out << "    " << arg << '\n';
-
-  out << "  Negatives\n"
-      << "    enabled = " << _negatives << '\n';
-
-  return out.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Args.h b/src/libshared/src/Args.h
deleted file mode 100644 (file)
index 84a0070..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2012 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_ARGS
-#define INCLUDED_ARGS
-
-#include <string>
-#include <vector>
-#include <map>
-
-class Args
-{
-public:
-  Args () = default;
-
-  void addOption (const std::string&, bool defaultValue = true);
-  void addNamed  (const std::string&, const std::string& defaultValue = "");
-  void limitPositionals (int);
-  void enableNegatives ();
-
-  void scan (int, const char**);
-
-  bool getOption (const std::string&) const;
-  int getOptionCount (const std::string&) const;
-  std::string getNamed (const std::string&) const;
-  int getPositionalCount () const;
-  std::string getPositional (int) const;
-
-  std::string dump () const;
-
-private:
-  bool canonicalizeOption (const std::string&, std::string&) const;
-  bool canonicalizeNamed (const std::string&, std::string&) const;
-
-private:
-  std::map <std::string, bool>        _options     {};
-  std::map <std::string, int>         _optionCount {};
-  std::map <std::string, std::string> _named       {};
-  std::vector <std::string>           _positionals {};
-  int                                 _limit       {-1};
-  bool                                _negatives   {false};
-};
-
-#endif
-
diff --git a/src/libshared/src/CMakeLists.txt b/src/libshared/src/CMakeLists.txt
deleted file mode 100644 (file)
index 8b3ec70..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-cmake_minimum_required (VERSION 2.8)
-include_directories (${CMAKE_SOURCE_DIR}
-                     ${CMAKE_SOURCE_DIR}/src)
-
-set (shared_HEADERS Args.h
-                    Color.h
-                    Composite.h
-                    Configuration.h
-                    Datetime.h
-                    Duration.h
-                    FS.h
-                    JSON.h
-                    Lexer.h
-                    Log.h
-                    Msg.h
-                    Packrat.h
-                    Palette.h
-                    PEG.h
-                    Pig.h
-                    RX.h
-                    Table.h
-                    Timer.h
-                    Tree.h
-                    shared.h
-                    format.h
-                    unicode.h
-                    utf8.h)
-
-set (shared_SRCS Args.cpp
-                 Color.cpp
-                 Composite.cpp
-                 Configuration.cpp
-                 Datetime.cpp
-                 Duration.cpp
-                 FS.cpp
-                 JSON.cpp
-                 Lexer.cpp
-                 Log.cpp
-                 Msg.cpp
-                 Packrat.cpp
-                 Palette.cpp
-                 PEG.cpp
-                 Pig.cpp
-                 RX.cpp
-                 SAX.cpp
-                 Table.cpp
-                 Timer.cpp
-                 Tree.cpp
-                 format.cpp
-                 ip.cpp
-                 shared.cpp
-                 unicode.cpp
-                 utf8.cpp
-                 wcwidth6.cpp
-                 ${shared_HEADERS})
-
-add_library (shared STATIC ${shared_SRCS})
-
-set (CMAKE_INSTALL_LIBDIR lib CACHE PATH "Output directory for libraries")
-install (TARGETS shared DESTINATION lib)
-install (FILES ${shared_HEADERS} DESTINATION include)
-
-add_executable (lex_executable lex.cpp)
-target_link_libraries (lex_executable shared)
-set_property (TARGET lex_executable PROPERTY OUTPUT_NAME "lex")
diff --git a/src/libshared/src/Color.cpp b/src/libshared/src/Color.cpp
deleted file mode 100644 (file)
index 0673d81..0000000
+++ /dev/null
@@ -1,682 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Color.h>
-#include <sstream>
-#include <vector>
-#include <cstdlib>
-#include <shared.h>
-#include <format.h>
-
-// uint to string lookup table for Color::_colorize()
-// _colorize() gets called _a lot_, having this lookup table is a cheap
-// performance optimization.
-const char *colorstring[] = {
-    "0",   "1",   "2",   "3",   "4",   "5",   "6",   "7",   "8",   "9",
-   "10",  "11",  "12",  "13",  "14",  "15",  "16",  "17",  "18",  "19",
-   "20",  "21",  "22",  "23",  "24",  "25",  "26",  "27",  "28",  "29",
-   "30",  "31",  "32",  "33",  "34",  "35",  "36",  "37",  "38",  "39",
-   "40",  "41",  "42",  "43",  "44",  "45",  "46",  "47",  "48",  "49",
-   "50",  "51",  "52",  "53",  "54",  "55",  "56",  "57",  "58",  "59",
-   "60",  "61",  "62",  "63",  "64",  "65",  "66",  "67",  "68",  "69",
-   "70",  "71",  "72",  "73",  "74",  "75",  "76",  "77",  "78",  "79",
-   "80",  "81",  "82",  "83",  "84",  "85",  "86",  "87",  "88",  "89",
-   "90",  "91",  "92",  "93",  "94",  "95",  "96",  "97",  "98",  "99",
-  "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
-  "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
-  "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
-  "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
-  "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
-  "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
-  "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
-  "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
-  "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
-  "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
-  "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
-  "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
-  "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
-  "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
-  "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
-  "250", "251", "252", "253", "254", "255"
-};
-
-////////////////////////////////////////////////////////////////////////////////
-static struct
-{
-  Color::color_id id;
-  std::string english_name;
-  int index;                    // offset red=3 (therefore fg=33, bg=43)
-} allColors[] =
-{
-  // Color.h enum    English     Index
-  { Color::nocolor,  "none",     0},
-  { Color::black,    "black",    1}, // fg 29+0  bg 39+0
-  { Color::red,      "red",      2},
-  { Color::green,    "green",    3},
-  { Color::yellow,   "yellow",   4},
-  { Color::blue,     "blue",     5},
-  { Color::magenta,  "magenta",  6},
-  { Color::cyan,     "cyan",     7},
-  { Color::white,    "white",    8},
-
-};
-
-#define NUM_COLORS (sizeof (allColors) / sizeof (allColors[0]))
-
-////////////////////////////////////////////////////////////////////////////////
-Color::Color ()
-: _value (0)
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Color::Color (const Color& other)
-{
-  _value = other._value;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Color::Color (unsigned int c)
-: _value (0)
-{
-  if (!(c & _COLOR_HASFG)) _value &= ~_COLOR_FG;
-  if (!(c & _COLOR_HASBG)) _value &= ~_COLOR_BG;
-
-  _value = c & (_COLOR_256 | _COLOR_HASBG | _COLOR_HASFG |_COLOR_UNDERLINE |
-                _COLOR_INVERSE | _COLOR_BOLD | _COLOR_BRIGHT | _COLOR_BG |
-                _COLOR_FG);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Supports the following constructs:
-//   [bright] [color] [on color] [bright] [underline]
-//
-// Where [color] is one of:
-//   black
-//   red
-//   ...
-//   grayN  0 <= N <= 23       fg 38;5;232 + N              bg 48;5;232 + N
-//   greyN  0 <= N <= 23       fg 38;5;232 + N              bg 48;5;232 + N
-//   colorN 0 <= N <= 255      fg 38;5;N                    bg 48;5;N
-//   rgbRGB 0 <= R,G,B <= 5    fg 38;5;16 + R*36 + G*6 + B  bg 48;5;16 + R*36 + G*6 + B
-Color::Color (const std::string& spec)
-: _value (0)
-{
-  // Split spec into words.
-  auto words = split (spec, ' ');
-
-  // Construct the color as two separate colors, then blend them later.  This
-  // make it possible to declare a color such as "color1 on black", and have
-  // the upgrade work properly.
-  unsigned int fg_value = 0;
-  unsigned int bg_value = 0;
-
-  bool bg = false;
-  int index;
-  for (auto& word : words)
-  {
-    word = lowerCase (trim (word));
-
-         if (word == "bold")      fg_value |= _COLOR_BOLD;
-    else if (word == "bright")    bg_value |= _COLOR_BRIGHT;
-    else if (word == "underline") fg_value |= _COLOR_UNDERLINE;
-    else if (word == "inverse")   fg_value |= _COLOR_INVERSE;
-    else if (word == "on")        bg = true;
-
-    // X where X is one of black, red, blue ...
-    else if ((index = find (word)) != -1)
-    {
-      if (index)
-      {
-        if (bg)
-        {
-          bg_value |= _COLOR_HASBG;
-          bg_value |= index << 8;
-        }
-        else
-        {
-          fg_value |= _COLOR_HASFG;
-          fg_value |= index;
-        }
-      }
-    }
-
-    // greyN/grayN, where 0 <= N <= 23.
-    else if (! word.compare (0, 4, "grey", 4) ||
-             ! word.compare (0, 4, "gray", 4))
-    {
-      index = strtol (word.substr (4).c_str (), nullptr, 10);
-      if (index < 0 || index > 23)
-        throw format ("The color '{1}' is not recognized.", word);
-
-      if (bg)
-      {
-        bg_value |= _COLOR_HASBG;
-        bg_value |= (index + 232) << 8;
-        bg_value |= _COLOR_256;
-      }
-      else
-      {
-        fg_value |= _COLOR_HASFG;
-        fg_value |= index + 232;
-        fg_value |= _COLOR_256;
-      }
-    }
-
-    // rgbRGB, where 0 <= R,G,B <= 5.
-    else if (! word.compare (0, 3, "rgb", 3))
-    {
-      index = strtol (word.substr (3).c_str (), nullptr, 10);
-      if (word.length () != 6 ||
-          index < 0 || index > 555)
-        throw format ("The color '{1}' is not recognized.", word);
-
-      int r = strtol (word.substr (3, 1).c_str (), nullptr, 10);
-      int g = strtol (word.substr (4, 1).c_str (), nullptr, 10);
-      int b = strtol (word.substr (5, 1).c_str (), nullptr, 10);
-      if (r < 0 || r > 5 ||
-          g < 0 || g > 5 ||
-          b < 0 || b > 5)
-        throw format ("The color '{1}' is not recognized.", word);
-
-      index = 16 + r*36 + g*6 + b;
-
-      if (bg)
-      {
-        bg_value |= _COLOR_HASBG;
-        bg_value |= index << 8;
-        bg_value |= _COLOR_256;
-      }
-      else
-      {
-        fg_value |= _COLOR_HASFG;
-        fg_value |= index;
-        fg_value |= _COLOR_256;
-      }
-    }
-
-    // colorN, where 0 <= N <= 255.
-    else if (! word.compare (0, 5, "color", 5))
-    {
-      index = strtol (word.substr (5).c_str (), nullptr, 10);
-      if (index < 0 || index > 255)
-        throw format ("The color '{1}' is not recognized.", word);
-
-      upgrade ();
-
-      if (bg)
-      {
-        bg_value |= _COLOR_HASBG;
-        bg_value |= index << 8;
-        bg_value |= _COLOR_256;
-      }
-      else
-      {
-        fg_value |= _COLOR_HASFG;
-        fg_value |= index;
-        fg_value |= _COLOR_256;
-      }
-    }
-    else if (word != "")
-      throw format ("The color '{1}' is not recognized.", word);
-  }
-
-  // Now combine the fg and bg into a single color.
-  _value = fg_value;
-  blend (Color (bg_value));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Color::Color (color_id fg)
-: _value (0)
-{
-  if (fg != Color::nocolor)
-  {
-    _value |= _COLOR_HASFG;
-    _value |= fg;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Color::Color (color_id fg, color_id bg, bool underline, bool bold, bool bright)
-: _value (0)
-{
-  _value |= ((underline ? 1 : 0) << 18)
-         |  ((bold      ? 1 : 0) << 17)
-         |  ((bright    ? 1 : 0) << 16);
-
-  if (bg != Color::nocolor)
-  {
-    _value |= _COLOR_HASBG;
-    _value |= (bg << 8);
-  }
-
-  if (fg != Color::nocolor)
-  {
-    _value |= _COLOR_HASFG;
-    _value |= fg;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Color::operator std::string () const
-{
-  std::string description;
-  if (_value & _COLOR_BOLD) description += "bold";
-
-  if (_value & _COLOR_UNDERLINE)
-    description += std::string (description.length () ? " " : "") + "underline";
-
-  if (_value & _COLOR_INVERSE)
-    description += std::string (description.length () ? " " : "") + "inverse";
-
-  if (_value & _COLOR_HASFG)
-    description += std::string (description.length () ? " " : "") + fg ();
-
-  if (_value & _COLOR_HASBG)
-  {
-    description += std::string (description.length () ? " " : "") + "on";
-
-    if (_value & _COLOR_BRIGHT)
-      description += std::string (description.length () ? " " : "") + "bright";
-
-    description += " " + bg ();
-  }
-
-  return description;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Color::operator int () const
-{
-  return (int) _value;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// If 'other' has styles that are compatible, merge them into this.  Colors in
-// other take precedence.
-void Color::blend (const Color& other)
-{
-  if (!other.nontrivial ())
-    return;
-
-  Color c (other);
-  _value |= (c._value & _COLOR_UNDERLINE);    // Always inherit underline.
-  _value |= (c._value & _COLOR_INVERSE);      // Always inherit inverse.
-
-  // 16 <-- 16.
-  if (!(_value   & _COLOR_256) &&
-      !(c._value & _COLOR_256))
-  {
-    _value |= (c._value & _COLOR_BOLD);       // Inherit bold.
-    _value |= (c._value & _COLOR_BRIGHT);     // Inherit bright.
-
-    if (c._value & _COLOR_HASFG)
-    {
-      _value |= _COLOR_HASFG;                 // There is now a color.
-      _value &= ~_COLOR_FG;                   // Remove previous color.
-      _value |= (c._value & _COLOR_FG);       // Apply other color.
-    }
-
-    if (c._value & _COLOR_HASBG)
-    {
-      _value |= _COLOR_HASBG;                 // There is now a color.
-      _value &= ~_COLOR_BG;                   // Remove previous color.
-      _value |= (c._value & _COLOR_BG);       // Apply other color.
-    }
-
-    return;
-  }
-  else
-  {
-    // Upgrade either color, if necessary.
-    if (!(_value   & _COLOR_256)) upgrade ();
-    if (!(c._value & _COLOR_256)) c.upgrade ();
-
-    // 256 <-- 256.
-    if (c._value & _COLOR_HASFG)
-    {
-      _value |= _COLOR_HASFG;                  // There is now a color.
-      _value &= ~_COLOR_FG;                    // Remove previous color.
-      _value |= (c._value & _COLOR_FG);        // Apply other color.
-    }
-
-    if (c._value & _COLOR_HASBG)
-    {
-      _value |= _COLOR_HASBG;                  // There is now a color.
-      _value &= ~_COLOR_BG;                    // Remove previous color.
-      _value |= (c._value & _COLOR_BG);        // Apply other color.
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Color::upgrade ()
-{
-  if (!(_value & _COLOR_256))
-  {
-    if (_value & _COLOR_HASFG)
-    {
-      bool bold = _value & _COLOR_BOLD;
-      unsigned int fg = _value & _COLOR_FG;
-      _value &= ~_COLOR_FG;
-      _value &= ~_COLOR_BOLD;
-      _value |= (bold ? fg + 7 : fg - 1);
-    }
-
-    if (_value & _COLOR_HASBG)
-    {
-      bool bright = _value & _COLOR_BRIGHT;
-      unsigned int bg = (_value & _COLOR_BG) >> 8;
-      _value &= ~_COLOR_BG;
-      _value &= ~_COLOR_BRIGHT;
-      _value |= (bright ? bg + 7 : bg - 1) << 8;
-    }
-
-    _value |= _COLOR_256;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Color::colorize (const std::string& input) const
-{
-  std::string result;
-  _colorize (result, input);
-  return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Sample color codes:
-//   red                  \033[31m
-//   bold red             \033[91m
-//   underline red        \033[4;31m
-//   bold underline red   \033[1;4;31m
-//
-//   on red               \033[41m
-//   on bright red        \033[101m
-//
-//   256 fg               \033[38;5;Nm
-//   256 bg               \033[48;5;Nm
-void Color::_colorize (std::string &result, const std::string& input) const
-{
-  if (!nontrivial ())
-  {
-    result += input;
-    return;
-  }
-
-  int count = 0;
-
-  // 256 color
-  if (_value & _COLOR_256)
-  {
-    if (_value & _COLOR_UNDERLINE)
-      result += "\033[4m";
-
-    if (_value & _COLOR_INVERSE)
-      result += "\033[7m";
-
-    if (_value & _COLOR_HASFG)
-    {
-      result += "\033[38;5;";
-      result += colorstring[(_value & _COLOR_FG)];
-      result += 'm';
-    }
-
-    if (_value & _COLOR_HASBG)
-    {
-      result += "\033[48;5;";
-      result += colorstring[((_value & _COLOR_BG) >> 8)];
-      result += 'm';
-    }
-
-    result += input;
-    result += "\033[0m";
-  }
-
-  // 16 color
-  else
-  {
-    result += "\033[";
-
-    if (_value & _COLOR_BOLD)
-    {
-      if (count++) result += ';';
-      result += '1';
-    }
-
-    if (_value & _COLOR_UNDERLINE)
-    {
-      if (count++) result += ';';
-      result += '4';
-    }
-
-    if (_value & _COLOR_INVERSE)
-    {
-      if (count++) result += ';';
-      result += '7';
-    }
-
-    if (_value & _COLOR_HASFG)
-    {
-      if (count++) result += ';';
-      result += colorstring[(29 + (_value & _COLOR_FG))];
-    }
-
-    if (_value & _COLOR_HASBG)
-    {
-      if (count++) result += ';';
-      result += colorstring[((_value & _COLOR_BRIGHT ? 99 : 39) + ((_value & _COLOR_BG) >> 8))];
-    }
-
-    result += 'm';
-    result += input;
-    result += "\033[0m";
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Remove color codes from a string.
-std::string Color::strip (const std::string& input)
-{
-  int length = input.length ();
-  bool inside = false;
-  std::string output;
-  for (int i = 0; i < length; ++i)
-  {
-    if (inside)
-    {
-      if (input[i] == 'm')
-        inside = false;
-    }
-    else
-    {
-      if (input[i] == 033)
-        inside = true;
-      else
-        output += input[i];
-    }
-  }
-
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Color::colorize (const std::string& input, const std::string& spec)
-{
-  Color c (spec);
-  return c.colorize (input);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Color::code () const
-{
-  if (! nontrivial ())
-    return "";
-
-  std::string result;
-
-  // 256 color
-  if (_value & _COLOR_256)
-  {
-    if (_value & _COLOR_UNDERLINE)
-      result += "\033[4m";
-
-    if (_value & _COLOR_INVERSE)
-      result += "\033[7m";
-
-    if (_value & _COLOR_HASFG)
-    {
-      result += "\033[38;5;";
-      result += colorstring[(_value & _COLOR_FG)];
-      result += 'm';
-    }
-
-    if (_value & _COLOR_HASBG)
-    {
-      result += "\033[48;5;";
-      result += colorstring[((_value & _COLOR_BG) >> 8)];
-      result += 'm';
-    }
-  }
-
-  // 16 color
-  else
-  {
-    int count = 0;
-    result += "\033[";
-
-    if (_value & _COLOR_BOLD)
-    {
-      if (count++) result += ';';
-      result += '1';
-    }
-
-    if (_value & _COLOR_UNDERLINE)
-    {
-      if (count++) result += ';';
-      result += '4';
-    }
-
-    if (_value & _COLOR_INVERSE)
-    {
-      if (count++) result += ';';
-      result += '7';
-    }
-
-    if (_value & _COLOR_HASFG)
-    {
-      if (count++) result += ';';
-      result += colorstring[(29 + (_value & _COLOR_FG))];
-    }
-
-    if (_value & _COLOR_HASBG)
-    {
-      if (count++) result += ';';
-      result += colorstring[((_value & _COLOR_BRIGHT ? 99 : 39) + ((_value & _COLOR_BG) >> 8))];
-    }
-
-    result += 'm';
-  }
-
-  return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Color::end () const
-{
-  if (nontrivial ())
-    return "\033[0m";
-
-  return "";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Color::nontrivial () const
-{
-  return _value != 0 ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Color::find (const std::string& input)
-{
-  for (unsigned int i = 0; i < NUM_COLORS; ++i)
-    if (allColors[i].english_name == input)
-      return (int) i;
-
-  return -1;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Color::fg () const
-{
-  int index = _value & _COLOR_FG;
-
-  if (_value & _COLOR_256)
-  {
-    if (_value & _COLOR_HASFG)
-    {
-      std::stringstream s;
-      s << "color" << (_value & _COLOR_FG);
-      return s.str ();
-    }
-  }
-  else
-  {
-    for (unsigned int i = 0; i < NUM_COLORS; ++i)
-      if (allColors[i].index == index)
-        return allColors[i].english_name;
-  }
-
-  return "";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Color::bg () const
-{
-  int index = (_value & _COLOR_BG) >> 8;
-
-  if (_value & _COLOR_256)
-  {
-    if (_value & _COLOR_HASBG)
-    {
-      std::stringstream s;
-      s << "color" << ((_value & _COLOR_BG) >> 8);
-      return s.str ();
-    }
-  }
-  else
-  {
-    for (unsigned int i = 0; i < NUM_COLORS; ++i)
-      if (allColors[i].index == index)
-        return allColors[i].english_name;
-  }
-
-  return "";
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Color.h b/src/libshared/src/Color.h
deleted file mode 100644 (file)
index d8393c2..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_COLOR
-#define INCLUDED_COLOR
-
-#include <string>
-
-#define _COLOR_INVERSE   0x00400000  // Inverse attribute.
-#define _COLOR_256       0x00200000  // 256-color mode.
-#define _COLOR_HASBG     0x00100000  // Has background color (all values taken).
-#define _COLOR_HASFG     0x00080000  // Has foreground color (all values taken).
-#define _COLOR_UNDERLINE 0x00040000  // General underline attribute.
-#define _COLOR_BOLD      0x00020000  // 16-color bold attribute.
-#define _COLOR_BRIGHT    0x00010000  // 16-color bright background attribute.
-#define _COLOR_BG        0x0000FF00  // 8-bit background color index.
-#define _COLOR_FG        0x000000FF  // 8-bit foreground color index.
-
-class Color
-{
-public:
-  enum color_id {nocolor = 0, black, red, green, yellow, blue, magenta, cyan, white};
-
-  Color ();
-  Color (const Color&);
-  Color (unsigned int);                         // 256 | INVERSE | UNDERLINE | BOLD | BRIGHT | (BG << 8) | FG
-  Color (const std::string&);                   // "red on bright black"
-  Color (color_id);                             // fg.
-  Color (color_id, color_id, bool, bool, bool); // fg, bg, underline, bold, bright
-  operator std::string () const;
-  operator int () const;
-
-  void upgrade ();
-  void blend (const Color&);
-
-  std::string colorize (const std::string&) const;
-  static std::string colorize (const std::string&, const std::string&);
-  void _colorize (std::string&, const std::string&) const;
-  static std::string strip (const std::string&);
-
-  std::string code () const;
-  std::string end () const;
-
-  bool nontrivial () const;
-
-private:
-  int find (const std::string&);
-  std::string fg () const;
-  std::string bg () const;
-
-private:
-  unsigned int _value;
-};
-
-#endif
diff --git a/src/libshared/src/Composite.cpp b/src/libshared/src/Composite.cpp
deleted file mode 100644 (file)
index 98bd49c..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Composite.h>
-#include <utf8.h>
-#include <sstream>
-#include <stack>
-
-////////////////////////////////////////////////////////////////////////////////
-// Initially assume no text, but infinite virtual space.
-//
-// Ållow overlay placement of arbitrary text at any offset, real or virtual, and
-// using a specific color.
-//
-// For example:
-//   Composite c;
-//   c.add ("aaaaaaaaaa",  2, Color ("..."));    // Layer 1
-//   c.add ("bbbbb",       5, Color ("..."));    // Layer 2
-//   c.add ("c",          15, Color ("..."));    // Layer 3
-//
-//   _layers = { std::make_tuple ("aaaaaaaaaa",  2, Color ("...")),
-//               std::make_tuple ("bbbbb",       5, Color ("...")),
-//               std::make_tuple ("c",          15, Color ("..."))};
-//
-void Composite::add (
-  const std::string& text,
-  std::string::size_type offset,
-  const Color& color)
-{
-  _layers.push_back (std::make_tuple (text, offset, color));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Merge the layers of text and color into one string.
-//
-// For example:
-//   Composite c;
-//   c.add ("aaaaaaaaaa",  2, Color ("..."));    // Layer 1
-//   c.add ("bbbbb",       5, Color ("..."));    // Layer 2
-//   c.add ("c",          15, Color ("..."));    // Layer 3
-//
-//   _layers = { std::make_tuple ("aaaaaaaaaa",  2, Color ("...")),
-//               std::make_tuple ("bbbbb",       5, Color ("...")),
-//               std::make_tuple ("c",          15, Color ("..."))};
-//
-// Arrange strings conceptually:
-//              111111
-//    0123456789012345     // Position
-//
-//      aaaaaaaaaa         // Layer 1
-//         bbbbb           // Layer 2
-//                   c     // Layer 3
-//
-// Walk all strings left to right, selecting the character and color from the
-// highest numbered layer. Emit color codes only on edge detection.
-//
-std::string Composite::str () const
-{
-  // The strings are broken into a vector of int, for UTF8 support.
-  std::vector <int> characters;
-  std::vector <int> colors;
-  for (unsigned int layer = 0; layer < _layers.size (); ++layer)
-  {
-    auto text   = std::get <0> (_layers[layer]);
-    auto offset = std::get <1> (_layers[layer]);
-    auto len    = utf8_text_length (text);
-
-    // Make sure the vectors are large enough to support a write operator[].
-    if (characters.size () < offset + len)
-    {
-      characters.resize (offset + len, 32);
-      colors.resize     (offset + len, 0);
-    }
-
-    // Copy in the layer characters and color indexes.
-    std::string::size_type cursor = 0;
-    int character;
-    int count = 0;
-    while ((character = utf8_next_char (text, cursor)))
-    {
-      characters[offset + count] = character;
-      colors    [offset + count] = layer + 1;
-      ++count;
-    }
-  }
-
-  // Now walk the character and color vector, emitting every character and
-  // every detected color change.
-  std::stringstream out;
-  int prev_color = 0;
-  for (unsigned int i = 0; i < characters.size (); ++i)
-  {
-    // A change in color triggers a code emit.
-    if (prev_color != colors[i])
-    {
-      if (prev_color)
-        out << std::get <2> (_layers[prev_color - 1]).end ();
-
-      if (colors[i])
-        out << std::get <2> (_layers[colors[i] - 1]).code ();
-      else
-        out << std::get <2> (_layers[prev_color - 1]).end ();
-
-      prev_color = colors[i];
-    }
-
-    out << utf8_character (characters[i]);
-  }
-
-  // Terminate the color codes, if necessary.
-  if (prev_color)
-    out << std::get <2> (_layers[prev_color - 1]).end ();
-
-  return out.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// So the same instance can be reused.
-void Composite::clear ()
-{
-  _layers.clear ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Composite.h b/src/libshared/src/Composite.h
deleted file mode 100644 (file)
index 7309c51..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_COMPOSITE
-#define INCLUDED_COMPOSITE
-
-#include <Color.h>
-#include <vector>
-#include <string>
-#include <tuple>
-
-class Composite
-{
-public:
-  Composite () = default;
-  void add (const std::string&, std::string::size_type, const Color&);
-  std::string str () const;
-  void clear ();
-
-private:
-  std::vector <std::tuple <std::string, std::string::size_type, Color>> _layers;
-};
-
-#endif
diff --git a/src/libshared/src/Configuration.cpp b/src/libshared/src/Configuration.cpp
deleted file mode 100644 (file)
index fc9331c..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Configuration.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <FS.h>
-#include <JSON.h>
-#include <shared.h>
-#include <format.h>
-
-////////////////////////////////////////////////////////////////////////////////
-bool setVariableInFile (
-  const std::string& file,
-  const std::string& name,
-  const std::string& value)
-{
-  // Read the file contents.
-  std::vector <std::string> contents;
-  File::read (file, contents);
-
-  bool found = false;
-  bool change = false;
-
-  for (auto& line : contents)
-  {
-    // If there is a comment on the line, it must follow the pattern.
-    auto comment = line.find ('#');
-    auto pos     = line.find (name + '=');
-
-    if (pos != std::string::npos &&
-        (comment == std::string::npos ||
-         comment > pos))
-    {
-      found = true;
-      if (comment != std::string::npos)
-        line = name + '=' + value + ' ' + line.substr (comment);
-      else
-        line = name + '=' + value;
-
-      change = true;
-    }
-  }
-
-  // Not found, so append instead.
-  if (! found)
-  {
-    contents.push_back (name + '=' + value);
-    change = true;
-  }
-
-  if (change)
-    File::write (file, contents);
-
-  return change;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool unsetVariableInFile (
-  const std::string& file,
-  const std::string& name)
-{
-  // Read configuration file.
-  std::vector <std::string> contents;
-  File::read (file, contents);
-
-  bool change = false;
-
-  for (auto line = contents.begin (); line != contents.end (); )
-  {
-    bool lineDeleted = false;
-
-    // If there is a comment on the line, it must follow the pattern.
-    auto comment = line->find ('#');
-    auto pos     = line->find (name + '=');
-
-    if (pos != std::string::npos &&
-        (comment == std::string::npos ||
-         comment > pos))
-    {
-      // vector::erase method returns a valid iterator to the next object
-      line = contents.erase (line);
-      lineDeleted = true;
-      change = true;
-    }
-
-    if (! lineDeleted)
-      line++;
-  }
-
-  if (change)
-    File::write (file, contents);
-
-  return change;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Read the Configuration file and populate the *this map.  The file format is
-// simply lines with name=value pairs.  Whitespace between name, = and value is
-// not tolerated, but blank lines and comments starting with # are allowed.
-//
-// Nested files are now supported, with the following construct:
-//   include /absolute/path/to/file
-//
-void Configuration::load (const std::string& file, int nest /* = 1 */)
-{
-  if (nest > 10)
-    throw std::string ("Configuration files may only be nested to 10 levels.");
-
-  // Read the file, then parse the contents.
-  File config (file);
-
-  if (nest == 1)
-    _original_file = config;
-
-  if (config.exists () &&
-      config.readable ())
-  {
-    std::string contents;
-    if (File::read (file, contents) && contents.length ())
-      parse (contents, nest);
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Write the Configuration file.
-void Configuration::save ()
-{
-  std::string contents;
-  for (const auto& i : *this)
-    contents += i.first + "=" + i.second + '\n';
-
-  File::write (_original_file, contents);
-  _dirty = false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Configuration::parse (const std::string& input, int nest /* = 1 */)
-{
-  // Shortcut case for default constructor.
-  if (input.length () == 0)
-    return;
-
-  // Parse each line.
-  for (auto& line : split (input, '\n'))
-  {
-    // Remove comments.
-    auto pound = line.find ('#');
-    if (pound != std::string::npos)
-      line = line.substr (0, pound);
-
-    // Skip empty lines.
-    line = trim (line);
-    if (line.length () > 0)
-    {
-      auto equal = line.find ('=');
-      if (equal != std::string::npos)
-      {
-        std::string key   = trim (line.substr (0, equal));
-        std::string value = trim (line.substr (equal+1, line.length () - equal));
-
-        (*this)[key] = json::decode (value);
-      }
-      else
-      {
-        auto include = line.find ("include");
-        if (include != std::string::npos)
-        {
-          Path included (trim (line.substr (include + 7)));
-          if (included.is_absolute ())
-          {
-            if (included.readable ())
-              load (included, nest + 1);
-            else
-              throw format ("Could not read include file '{1}'.", included._data);
-          }
-          else
-            throw format ("Can only include files with absolute paths, not '{1}'", included._data);
-        }
-        else
-          throw format ("Malformed entry '{1}' in config file.", line);
-      }
-    }
-  }
-
-  _dirty = true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Configuration::has (const std::string& key) const
-{
-  return (*this).find (key) != (*this).end ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Return the configuration value given the specified key.
-std::string Configuration::get (const std::string& key) const
-{
-  auto found = find (key);
-  if (found != end ())
-    return found->second;
-
-  return "";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Configuration::getInteger (const std::string& key) const
-{
-  auto found = find (key);
-  if (found != end ())
-    return strtoimax (found->second.c_str (), nullptr, 10);
-
-  return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-double Configuration::getReal (const std::string& key) const
-{
-  auto found = find (key);
-  if (found != end ())
-    return strtod (found->second.c_str (), nullptr);
-
-  return 0.0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Configuration::getBoolean (const std::string& key) const
-{
-  auto found = find (key);
-  if (found != end ())
-  {
-    auto value = lowerCase (found->second);
-    if (value == "true"   ||
-        value == "1"      ||
-        value == "y"      ||
-        value == "yes"    ||
-        value == "on")
-      return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Configuration::set (const std::string& key, const int value)
-{
-  (*this)[key] = format (value);
-  _dirty = true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Configuration::set (const std::string& key, const double value)
-{
-  (*this)[key] = format (value, 1, 8);
-  _dirty = true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Configuration::set (const std::string& key, const std::string& value)
-{
-  (*this)[key] = value;
-  _dirty = true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Autovivification is ok here.
-void Configuration::setIfBlank (const std::string& key, const std::string& value)
-{
-  if ((*this)[key] == "")
-  {
-    (*this)[key] = value;
-    _dirty = true;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Provide a vector of all configuration keys.
-std::vector <std::string> Configuration::all () const
-{
-  std::vector <std::string> items;
-  for (const auto& it : *this)
-    items.push_back (it.first);
-
-  return items;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Configuration::file () const
-{
-  return _original_file._data;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Configuration::dirty ()
-{
-  return _dirty;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Configuration.h b/src/libshared/src/Configuration.h
deleted file mode 100644 (file)
index 067affe..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_CONFIGURATION
-#define INCLUDED_CONFIGURATION
-
-#include <map>
-#include <vector>
-#include <string>
-#include <FS.h>
-
-bool setVariableInFile   (const std::string&, const std::string&, const std::string&);
-bool unsetVariableInFile (const std::string&, const std::string&);
-
-class Configuration : public std::map <std::string, std::string>
-{
-public:
-  void load  (const std::string&, int nest = 1);
-  void save ();
-  void parse (const std::string&, int nest = 1);
-
-  bool        has        (const std::string&) const;
-  std::string get        (const std::string&) const;
-  int         getInteger (const std::string&) const;
-  double      getReal    (const std::string&) const;
-  bool        getBoolean (const std::string&) const;
-
-  void set (const std::string&, const int);
-  void set (const std::string&, const double);
-  void set (const std::string&, const std::string&);
-  void setIfBlank (const std::string&, const std::string&);
-  std::vector <std::string> all () const;
-
-  std::string file () const;
-
-  bool dirty ();
-
-private:
-  File _original_file {};
-  bool _dirty         {false};
-};
-
-#endif
diff --git a/src/libshared/src/Datetime.cpp b/src/libshared/src/Datetime.cpp
deleted file mode 100644 (file)
index 726d9dc..0000000
+++ /dev/null
@@ -1,3787 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Datetime.h>
-#include <algorithm>
-#include <iostream>
-#include <sstream>
-#include <iomanip>
-#include <cassert>
-#include <stdlib.h>
-#include <shared.h>
-#include <format.h>
-#include <unicode.h>
-#include <utf8.h>
-
-static std::vector <std::string> dayNames {
-  "sunday",
-  "monday",
-  "tuesday",
-  "wednesday",
-  "thursday",
-  "friday",
-  "saturday"};
-
-static std::vector <std::string> monthNames {
-  "january",
-  "february",
-  "march",
-  "april",
-  "may",
-  "june",
-  "july",
-  "august",
-  "september",
-  "october",
-  "november",
-  "december"};
-
-int Datetime::weekstart = 1; // Monday, per ISO-8601.
-int Datetime::minimumMatchLength = 3;
-bool Datetime::isoEnabled            = true;
-bool Datetime::standaloneDateEnabled = true;
-bool Datetime::standaloneTimeEnabled = true;
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime::Datetime ()
-{
-  clear ();
-  _date = time (nullptr);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime::Datetime (const std::string& input, const std::string& format)
-{
-  clear ();
-  std::string::size_type start = 0;
-  if (! parse (input, start, format))
-    throw ::format ("'{1}' is not a valid date in the '{2}' format.", input, format);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime::Datetime (const time_t t)
-{
-  clear ();
-  _date = t;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime::Datetime (const int y, const int m, const int d)
-{
-  // Protect against arguments being passed in the wrong order.
-  assert (y >= 1969 && y < 2100);
-  assert (m >= 1 && m <= 12);
-  assert (d >= 1 && d <= 31);
-
-  clear ();
-
-  // Error if not valid.
-  struct tm t {};
-  t.tm_isdst = -1;   // Requests that mktime determine summer time effect.
-  t.tm_mday  = d;
-  t.tm_mon   = m - 1;
-  t.tm_year  = y - 1900;
-
-  _date = mktime (&t);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime::Datetime (const int y,  const int m,  const int d,
-                    const int hr, const int mi, const int se)
-{
-  // Protect against arguments being passed in the wrong order.
-  assert (y >= 1969 && y < 2100);
-  assert (m >= 1 && m <= 12);
-  assert (d >= 1 && d <= 31);
-  assert (hr >= 0 && hr <= 24);
-  assert (mi >= 0 && mi < 60);
-  assert (se >= 0 && se < 60);
-
-  clear ();
-
-  // Error if not valid.
-  struct tm t {};
-  t.tm_isdst = -1;   // Requests that mktime determine summer time effect.
-  t.tm_mday  = d;
-  t.tm_mon   = m - 1;
-  t.tm_year  = y - 1900;
-  t.tm_hour  = hr;
-  t.tm_min   = mi;
-  t.tm_sec   = se;
-
-  _date = mktime (&t);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse (
-  const std::string& input,
-  std::string::size_type& start,
-  const std::string& format)
-{
-  auto i = start;
-  Pig pig (input);
-  if (i)
-    pig.skipN (static_cast <int> (i));
-
-  auto checkpoint = pig.cursor ();
-
-  // Parse epoch first, as it's the most common scenario.
-  if (parse_epoch (pig))
-  {
-    // ::validate and ::resolve are not needed in this case.
-    start = pig.cursor ();
-    return true;
-  }
-
-  if (parse_formatted (pig, format))
-  {
-    // Check the values and determine time_t.
-    if (validate ())
-    {
-      start = pig.cursor ();
-      resolve ();
-      return true;
-    }
-  }
-
-  // Allow parse_date_time and parse_date_time_ext regardless of
-  // Datetime::isoEnabled setting, because these formats are relied upon by
-  // the 'import' command, JSON parser and hook system.
-  if (parse_date_time_ext   (pig) || // Strictest first.
-      parse_date_time       (pig) ||
-      (Datetime::isoEnabled &&
-       (                                    parse_date_ext      (pig)  ||
-        (Datetime::standaloneDateEnabled && parse_date          (pig)) ||
-                                            parse_time_utc_ext  (pig)  ||
-                                            parse_time_utc      (pig)  ||
-                                            parse_time_off_ext  (pig)  ||
-                                            parse_time_off      (pig)  ||
-                                            parse_time_ext      (pig)  ||
-        (Datetime::standaloneTimeEnabled && parse_time          (pig)) // Time last, as it is the most permissive.
-       )
-      )
-     )
-  {
-    // Check the values and determine time_t.
-    if (validate ())
-    {
-      start = pig.cursor ();
-      resolve ();
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-
-  if (parse_named (pig))
-  {
-    // ::validate and ::resolve are not needed in this case.
-    start = pig.cursor ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Datetime::clear ()
-{
-  _year    = 0;
-  _month   = 0;
-  _week    = 0;
-  _weekday = 0;
-  _julian  = 0;
-  _day     = 0;
-  _seconds = 0;
-  _offset  = 0;
-  _utc     = false;
-  _date    = 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_formatted (Pig& pig, const std::string& format)
-{
-  // Short-circuit on missing format.
-  if (format == "")
-    return false;
-
-  auto checkpoint = pig.cursor ();
-
-  int month  {-1};   // So we can check later.
-  int day    {-1};
-  int year   {-1};
-  int hour   {-1};
-  int minute {-1};
-  int second {-1};
-
-  // For parsing, unused.
-  int wday   {-1};
-  int week   {-1};
-
-  for (unsigned int f = 0; f < format.length (); ++f)
-  {
-    switch (format[f])
-    {
-    case 'm':
-      if (pig.getDigit (month))
-      {
-        if (month == 0)
-          pig.getDigit (month);
-
-        if (month == 1)
-          if (pig.getDigit (month))
-            month += 10;
-      }
-      else
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'M':
-      if (! pig.getDigit2 (month))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'd':
-      if (pig.getDigit (day))
-      {
-        if (day == 0)
-          pig.getDigit (day);
-
-        if (day == 1 || day == 2 || day == 3)
-        {
-          int tens = day;
-          if (pig.getDigit (day))
-            day += 10 * tens;
-        }
-      }
-      else
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'D':
-      if (! pig.getDigit2 (day))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'y':
-      if (! pig.getDigit2 (year))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      year += 2000;
-      break;
-
-    case 'Y':
-      if (! pig.getDigit4 (year))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'h':
-      if (pig.getDigit (hour))
-      {
-        if (hour == 0)
-          pig.getDigit (hour);
-
-        if (hour == 1 || hour == 2)
-        {
-          int tens = hour;
-          if (pig.getDigit (hour))
-            hour += 10 * tens;
-        }
-      }
-      else
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'H':
-      if (! pig.getDigit2 (hour))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'n':
-      if (pig.getDigit (minute))
-      {
-        if (minute == 0)
-          pig.getDigit (minute);
-
-        if (minute < 6)
-        {
-          int tens = minute;
-          if (pig.getDigit (minute))
-            minute += 10 * tens;
-        }
-      }
-      else
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'N':
-      if (! pig.getDigit2 (minute))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 's':
-      if (pig.getDigit (second))
-      {
-        if (second == 0)
-          pig.getDigit (second);
-
-        if (second < 6)
-        {
-          int tens = second;
-          if (pig.getDigit (second))
-            second += 10 * tens;
-        }
-      }
-      else
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'S':
-      if (! pig.getDigit2 (second))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'v':
-      if (pig.getDigit (week))
-      {
-        if (week == 0)
-          pig.getDigit (week);
-
-        if (week < 6)
-        {
-          int tens = week;
-          if (pig.getDigit (week))
-            week += 10 * tens;
-        }
-      }
-      else
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'V':
-      if (! pig.getDigit2 (week))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-
-    case 'a':
-      wday = Datetime::dayOfWeek (pig.str ().substr (0, 3));
-      if (wday == -1)
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-
-      pig.skipN (3);
-      break;
-
-    case 'A':
-      {
-        std::string dayName;
-        if (pig.getUntil (format[f + 1], dayName))
-        {
-          wday = Datetime::dayOfWeek (dayName);
-          if (wday == -1)
-          {
-            pig.restoreTo (checkpoint);
-            return false;
-          }
-        }
-      }
-      break;
-
-    case 'b':
-      month = Datetime::monthOfYear (pig.str ().substr (0, 3));
-      if (month == -1)
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-
-      pig.skipN (3);
-      break;
-
-    case 'B':
-      {
-        std::string monthName;
-        if (pig.getUntil (format[f + 1], monthName))
-        {
-          month = Datetime::monthOfYear (monthName);
-          if (month == -1)
-          {
-            pig.restoreTo (checkpoint);
-            return false;
-          }
-        }
-      }
-      break;
-
-    default:
-      if (! pig.skip (format[f]))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-      break;
-    }
-  }
-
-  // It is possible that the format='Y-M-D', and the input is Y-M-DTH:N:SZ, and
-  // this should not be considered a match.
-  if (! pig.eos () && ! unicodeWhitespace (pig.peek ()))
-  {
-    pig.restoreTo (checkpoint);
-    return false;
-  }
-
-  // Missing values are filled in from the current date.
-  if (year == -1)
-  {
-    Datetime now;
-    year = now.year ();
-    if (month == -1)
-    {
-      month = now.month ();
-      if (day == -1)
-      {
-        day = now.day ();
-        if (hour == -1)
-        {
-          hour = now.hour ();
-          if (minute == -1)
-          {
-            minute = now.minute ();
-            if (second == -1)
-              second = now.second ();
-          }
-        }
-      }
-    }
-  }
-
-  // Any remaining undefined values are assigned defaults.
-  if (month  == -1) month  = 1;
-  if (day    == -1) day    = 1;
-  if (hour   == -1) hour   = 0;
-  if (minute == -1) minute = 0;
-  if (second == -1) second = 0;
-
-  _year    = year;
-  _month   = month;
-  _day     = day;
-  _seconds = (hour * 3600) + (minute * 60) + second;
-
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Note how these are all single words.
-//
-// Examples and descriptions, assuming now == 2017-03-05T12:34:56.
-//
-//                  Example              Notes
-//                  -------------------  ------------------
-//   now            2017-03-05T12:34:56  Unaffected
-//   yesterday      2017-03-04T00:00:00  Unaffected
-//   today          2017-03-05T00:00:00  Unaffected
-//   tomorrow       2017-03-06T00:00:00  Unaffected
-//   <ordinal> 12th 2017-03-12T00:00:00
-//   <day> monday   2017-03-06T00:00:00
-//   <month> april  2017-04-01T00:00:00
-//   later          2038-01-18T00:00:00  Unaffected
-//   someday        2038-01-18T00:00:00  Unaffected
-//   sopd           2017-03-04T00:00:00  Unaffected
-//   sod            2017-03-05T00:00:00  Unaffected
-//   sond           2017-03-06T00:00:00  Unaffected
-//   eopd           2017-03-05T00:00:00  Unaffected
-//   eod            2017-03-06T00:00:00  Unaffected
-//   eond           2017-03-07T00:00:00  Unaffected
-//   sopw           2017-02-26T00:00:00  Unaffected
-//   sow            2017-03-05T00:00:00  Unaffected
-//   sonw           2017-03-12T00:00:00  Unaffected
-//   eopw           2017-03-05T00:00:00  Unaffected
-//   eow            2017-03-12T00:00:00  Unaffected
-//   eonw           2017-03-19T00:00:00  Unaffected
-//   sopww          2017-02-27T00:00:00  Unaffected
-//   soww           2017-03-06T00:00:00
-//   sonww          2017-03-06T00:00:00  Unaffected
-//   eopww          2017-03-03T00:00:00  Unaffected
-//   eoww           2017-03-10T00:00:00
-//   eonww          2017-03-17T00:00:00  Unaffected
-//   sopm           2017-02-01T00:00:00  Unaffected
-//   som            2017-03-01T00:00:00  Unaffected
-//   sonm           2017-04-01T00:00:00  Unaffected
-//   eopm           2017-03-01T00:00:00  Unaffected
-//   eom            2017-04-01T00:00:00  Unaffected
-//   eonm           2017-05-01T00:00:00  Unaffected
-//   sopq           2017-10-01T00:00:00  Unaffected
-//   soq            2017-01-01T00:00:00  Unaffected
-//   sonq           2017-04-01T00:00:00  Unaffected
-//   eopq           2017-01-01T00:00:00  Unaffected
-//   eoq            2017-04-01T00:00:00  Unaffected
-//   eonq           2017-07-01T00:00:00  Unaffected
-//   sopy           2016-01-01T00:00:00  Unaffected
-//   soy            2017-01-01T00:00:00  Unaffected
-//   sony           2018-01-01T00:00:00  Unaffected
-//   eopy           2017-01-01T00:00:00  Unaffected
-//   eoy            2018-01-01T00:00:00  Unaffected
-//   eony           2019-01-01T00:00:00  Unaffected
-//   easter         2017-04-16T00:00:00
-//   eastermonday   2017-04-16T00:00:00
-//   ascension      2017-05-25T00:00:00
-//   pentecost      2017-06-04T00:00:00
-//   goodfriday     2017-04-14T00:00:00
-//   midsommar      2017-06-24T00:00:00  midnight, 1st Saturday after 20th June
-//   midsommarafton 2017-06-23T00:00:00  midnight, 1st Friday after 19th June
-//   juhannus       2017-06-23T00:00:00  midnight, 1st Friday after 19th June
-//
-bool Datetime::parse_named (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  // Experimental handling of date phrases, such as "first monday in march".
-  // Note that this requires that phrases are deliminted by EOS or WS.
-  std::string token;
-  std::vector <std::string> tokens;
-  while (pig.getUntilWS (token))
-  {
-    tokens.push_back (token);
-    if (! pig.skipWS ())
-      break;
-  }
-
-/*
-  // This grpoup contains "1st monday ..." which must be processed before
-  // initializeOrdinal below.
-  if (initializeNthDayInMonth (tokens))
-  {
-    return true;
-  }
-*/
-
-  // Restoration necessary because of the tokenization.
-  pig.restoreTo (checkpoint);
-
-  if (initializeNow            (pig) ||
-      initializeYesterday      (pig) ||
-      initializeToday          (pig) ||
-      initializeTomorrow       (pig) ||
-      initializeOrdinal        (pig) ||
-      initializeDayName        (pig) ||
-      initializeMonthName      (pig) ||
-      initializeLater          (pig) ||
-      initializeSopd           (pig) ||
-      initializeSod            (pig) ||
-      initializeSond           (pig) ||
-      initializeEopd           (pig) ||
-      initializeEod            (pig) ||
-      initializeEond           (pig) ||
-      initializeSopw           (pig) ||
-      initializeSow            (pig) ||
-      initializeSonw           (pig) ||
-      initializeEopw           (pig) ||
-      initializeEow            (pig) ||
-      initializeEonw           (pig) ||
-      initializeSopww          (pig) ||  // Must appear after sopw
-      initializeSonww          (pig) ||  // Must appear after sonw
-      initializeSoww           (pig) ||  // Must appear after sow
-      initializeEopww          (pig) ||  // Must appear after eopw
-      initializeEonww          (pig) ||  // Must appear after eonw
-      initializeEoww           (pig) ||  // Must appear after eow
-      initializeSopm           (pig) ||
-      initializeSom            (pig) ||
-      initializeSonm           (pig) ||
-      initializeEopm           (pig) ||
-      initializeEom            (pig) ||
-      initializeEonm           (pig) ||
-      initializeSopq           (pig) ||
-      initializeSoq            (pig) ||
-      initializeSonq           (pig) ||
-      initializeEopq           (pig) ||
-      initializeEoq            (pig) ||
-      initializeEonq           (pig) ||
-      initializeSopy           (pig) ||
-      initializeSoy            (pig) ||
-      initializeSony           (pig) ||
-      initializeEopy           (pig) ||
-      initializeEoy            (pig) ||
-      initializeEony           (pig) ||
-      initializeEaster         (pig) ||
-      initializeMidsommar      (pig) ||
-      initializeMidsommarafton (pig) ||
-      initializeInformalTime   (pig))
-  {
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Valid epoch values are unsigned integers after 1980-01-01T00:00:00Z. This
-// restriction means that '12' will not be identified as an epoch date.
-bool Datetime::parse_epoch (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  int epoch {};
-  if (pig.getDigits (epoch)             &&
-      ! unicodeLatinAlpha (pig.peek ()) &&
-      epoch >= 315532800)
-  {
-    _date = static_cast <time_t> (epoch);
-    //std::cout << "# parse_epoch \e[33msucceed\e[0m " << pig.dump () << "\n";
-    return true;
-  }
-
-  //std::cout << "# parse_epoch fail\n";
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// date_ext 'T' time_utc_ext 'Z'
-// date_ext 'T' time_off_ext
-// date_ext 'T' time_ext
-bool Datetime::parse_date_time_ext (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (parse_date_ext (pig) &&
-      pig.skip ('T')       &&
-      (parse_time_utc_ext (pig) ||
-       parse_time_off_ext (pig) ||
-       parse_time_ext     (pig)))
-  {
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// YYYY-MM-DD
-// YYYY-MM
-// YYYY-DDD
-// YYYY-Www-D
-// YYYY-Www
-bool Datetime::parse_date_ext (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  int year {};
-  if (parse_year (pig, year) &&
-      pig.skip ('-'))
-  {
-    auto checkpointYear = pig.cursor ();
-
-    int month {};
-    int day {};
-    int julian {};
-
-    if (pig.skip ('W') &&
-        parse_week (pig, _week))
-    {
-      if (pig.skip ('-') &&
-          pig.getDigit (_weekday))
-      {
-        // What is happening here - must be something to do?
-      }
-
-      if (! unicodeLatinDigit (pig.peek ()))
-      {
-        _year = year;
-        return true;
-      }
-    }
-
-    pig.restoreTo (checkpointYear);
-
-    if (parse_month (pig, month) &&
-        pig.skip ('-')           &&
-        parse_day (pig, day)     &&
-        ! unicodeLatinDigit (pig.peek ()))
-    {
-      _year = year;
-      _month = month;
-      _day = day;
-      return true;
-    }
-
-    pig.restoreTo (checkpointYear);
-
-    if (parse_julian (pig, julian) &&
-        ! unicodeLatinDigit (pig.peek ()))
-    {
-      _year = year;
-      _julian = julian;
-      return true;
-    }
-
-    pig.restoreTo (checkpointYear);
-
-    if (parse_month (pig, month) &&
-        pig.peek () != '-'       &&
-        ! unicodeLatinDigit (pig.peek ()))
-    {
-      _year = year;
-      _month = month;
-      _day = 1;
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ±hh[:mm]
-bool Datetime::parse_off_ext (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  int sign = pig.peek ();
-  if (sign == '+' || sign == '-')
-  {
-    pig.skipN (1);
-
-    int hour {0};
-    int minute {0};
-
-    if (parse_off_hour (pig, hour))
-    {
-      if (pig.skip (':'))
-      {
-        if (! parse_off_minute (pig, minute))
-        {
-          pig.restoreTo (checkpoint);
-          return false;
-        }
-      }
-
-      _offset = (hour * 3600) + (minute * 60);
-      if (sign == '-')
-        _offset = - _offset;
-
-      if (! unicodeLatinDigit (pig.peek ()))
-        return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// hh:mm[:ss]
-bool Datetime::parse_time_ext (Pig& pig, bool terminated)
-{
-  auto checkpoint = pig.cursor ();
-
-  int hour {};
-  int minute {};
-  if (parse_hour (pig, hour) &&
-      pig.skip (':')         &&
-      parse_minute (pig, minute))
-  {
-    if (pig.skip (':'))
-    {
-      int second {};
-      if (parse_second (pig, second) &&
-          ! unicodeLatinDigit (pig.peek ()) &&
-          (! terminated || (pig.peek () != '-' && pig.peek () != '+')))
-      {
-        _seconds = (hour * 3600) + (minute * 60) + second;
-        return true;
-      }
-
-      pig.restoreTo (checkpoint);
-      return false;
-    }
-
-    auto following = pig.peek ();
-    if (! unicodeLatinDigit (following)    &&
-        (! terminated || (following != '+' && following != '-')) &&
-        following != 'A'                   &&
-        following != 'a'                   &&
-        following != 'P'                   &&
-        following != 'p')
-    {
-      _seconds = (hour * 3600) + (minute * 60);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// time-ext 'Z'
-bool Datetime::parse_time_utc_ext (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (parse_time_ext (pig, false) &&
-      pig.skip ('Z'))
-  {
-    if (! unicodeLatinDigit (pig.peek ()))
-    {
-      _utc = true;
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// time-ext off-ext
-bool Datetime::parse_time_off_ext (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (parse_time_ext (pig, false) &&
-      parse_off_ext (pig))
-  {
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// YYYYMMDDTHHMMSSZ
-// YYYYMMDDTHHMMSS
-bool Datetime::parse_date_time (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (parse_date (pig) &&
-      pig.skip ('T')   &&
-      (parse_time_utc (pig) ||
-       parse_time_off (pig) ||
-       parse_time     (pig)))
-  {
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// YYYYWww
-// YYYYDDD
-// YYYYMMDD
-// YYYYMM
-bool Datetime::parse_date (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  int year {};
-  int month {};
-  int julian {};
-  int week {};
-  int weekday {};
-  int day {};
-  if (parse_year (pig, year))
-  {
-    auto checkpointYear = pig.cursor ();
-
-    if (pig.skip ('W') &&
-        parse_week (pig, week))
-    {
-      if (pig.getDigit (weekday))
-        _weekday = weekday;
-
-      if (! unicodeLatinDigit (pig.peek ()))
-      {
-        _year = year;
-        _week = week;
-        return true;
-      }
-    }
-
-    pig.restoreTo (checkpointYear);
-
-    if (parse_julian (pig, julian) &&
-        ! unicodeLatinDigit (pig.peek ()))
-    {
-      _year = year;
-      _julian = julian;
-      return true;
-    }
-
-    pig.restoreTo (checkpointYear);
-
-    if (parse_month (pig, month))
-    {
-      if (parse_day (pig, day))
-      {
-        if (! unicodeLatinDigit (pig.peek ()))
-        {
-          _year = year;
-          _month = month;
-          _day = day;
-          return true;
-        }
-      }
-      else
-      {
-        if (! unicodeLatinDigit (pig.peek ()))
-        {
-          _year = year;
-          _month = month;
-          _day = 1;
-          return true;
-        }
-      }
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// <time> Z
-bool Datetime::parse_time_utc (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (parse_time (pig, false) &&
-      pig.skip ('Z'))
-  {
-    _utc = true;
-    if (! unicodeLatinDigit (pig.peek ()))
-      return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// <time> <off>
-bool Datetime::parse_time_off (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (parse_time (pig, false) &&
-      parse_off (pig))
-  {
-    auto terminator = pig.peek ();
-    if (terminator != '-' && ! unicodeLatinDigit (terminator))
-    {
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// hhmmss
-// hhmm
-bool Datetime::parse_time (Pig& pig, bool terminated)
-{
-  auto checkpoint = pig.cursor ();
-
-  int hour {};
-  int minute {};
-  if (parse_hour (pig, hour) &&
-      parse_minute (pig, minute))
-  {
-    int second {};
-    parse_second (pig, second);
-
-    auto terminator = pig.peek ();
-    if (! terminated ||
-        (! unicodeLatinDigit (terminator) && terminator != '-' && terminator != '+'))
-    {
-      _seconds = (hour * 3600) + (minute * 60) + second;
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ±hhmm
-// ±hh
-bool Datetime::parse_off (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  int sign = pig.peek ();
-  if (sign == '+' || sign == '-')
-  {
-    pig.skipN (1);
-
-    int hour {};
-    if (parse_off_hour (pig, hour))
-    {
-      int minute {};
-      parse_off_minute (pig, minute);
-
-      if (! unicodeLatinDigit (pig.peek ()))
-      {
-        _offset = (hour * 3600) + (minute * 60);
-        if (sign == '-')
-          _offset = - _offset;
-
-        return true;
-      }
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_year (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int year;
-  if (pig.getDigit4 (year) &&
-      year > 1969)
-  {
-    value = year;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_month (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int month;
-  if (pig.getDigit2 (month) &&
-      month > 0             &&
-      month <= 12)
-  {
-    value = month;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_week (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int week;
-  if (pig.getDigit2 (week) &&
-      week > 0             &&
-      week <= 53)
-  {
-    value = week;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_julian (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int julian;
-  if (pig.getDigit3 (julian) &&
-      julian > 0             &&
-      julian <= 366)
-  {
-    value = julian;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_day (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int day;
-  if (pig.getDigit2 (day) &&
-      day > 0             &&
-      day <= 31)
-  {
-    value = day;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_weekday (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int weekday;
-  if (pig.getDigit (weekday) &&
-      weekday >= 1           &&
-      weekday <= 7)
-  {
-    value = weekday;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_hour (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int hour;
-  if (pig.getDigit2 (hour) &&
-      hour >= 0            &&
-      hour < 24)
-  {
-    value = hour;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_minute (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int minute;
-  if (pig.getDigit2 (minute) &&
-      minute >= 0            &&
-      minute < 60)
-  {
-    value = minute;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_second (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int second;
-  if (pig.getDigit2 (second) &&
-      second >= 0            &&
-      second < 60)
-  {
-    value = second;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_off_hour (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int hour;
-  if (pig.getDigit2 (hour) &&
-      hour >= 0            &&
-      hour <= 12)
-  {
-    value = hour;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::parse_off_minute (Pig& pig, int& value)
-{
-  auto checkpoint = pig.cursor ();
-
-  int minute;
-  if (pig.getDigit2 (minute) &&
-      minute >= 0            &&
-      minute < 60)
-  {
-    value = minute;
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// now [ !<alpha> && !<digit> ]
-bool Datetime::initializeNow (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("now"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      _date = time (nullptr);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// yesterday/abbrev  [ !<alpha> && !<digit> ]
-bool Datetime::initializeYesterday (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  std::string token;
-  if (pig.skipPartial ("yesterday", token) &&
-      token.length () >= static_cast <std::string::size_type> (Datetime::minimumMatchLength))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      t->tm_mday -= 1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// today/abbrev  [ !<alpha> && !<digit> ]
-bool Datetime::initializeToday (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  std::string token;
-  if (pig.skipPartial ("today", token) &&
-      token.length () >= static_cast <std::string::size_type> (Datetime::minimumMatchLength))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// tomcorrow/abbrev  [ !<alpha> && !<digit> ]
-bool Datetime::initializeTomorrow (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  std::string token;
-  if (pig.skipPartial ("tomorrow", token) &&
-      token.length () >= static_cast <std::string::size_type> (Datetime::minimumMatchLength))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday++;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// <digit>+ [ "st" | "nd" | "rd" | "th" ] [ !<alpha> && !<digit> ]
-bool Datetime::initializeOrdinal (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  int number = 0;
-  if (pig.getDigits (number) &&
-      number > 0             &&
-      number <= 31)
-  {
-    int character1;
-    int character2;
-    if (pig.getCharacter (character1)     &&
-        pig.getCharacter (character2)     &&
-        ! unicodeLatinAlpha (pig.peek ()) &&
-        ! unicodeLatinDigit (pig.peek ()))
-    {
-      int remainder1 = number % 10;
-      int remainder2 = number % 100;
-      if ((remainder2 != 11 && remainder1 == 1 && character1 == 's' && character2 == 't') ||
-          (remainder2 != 12 && remainder1 == 2 && character1 == 'n' && character2 == 'd') ||
-          (remainder2 != 13 && remainder1 == 3 && character1 == 'r' && character2 == 'd') ||
-          ((remainder2 == 11 ||
-            remainder2 == 12 ||
-            remainder2 == 13 ||
-            remainder1 == 0 ||
-            remainder1 > 3) && character1 == 't' && character2 == 'h'))
-      {
-        time_t now = time (nullptr);
-        struct tm* t = localtime (&now);
-
-        int y = t->tm_year + 1900;
-        int m = t->tm_mon + 1;
-        int d = t->tm_mday;
-
-        // If it is this month.
-        if (d < number &&
-            number <= daysInMonth (y, m))
-        {
-          t->tm_hour = t->tm_min = t->tm_sec = 0;
-          t->tm_mon  = m - 1;
-          t->tm_mday = number;
-          t->tm_year = y - 1900;
-          t->tm_isdst = -1;
-          _date = mktime (t);
-        }
-        else
-        {
-          if (++m > 12)
-          {
-            m = 1;
-            y++;
-          }
-
-          t->tm_hour = t->tm_min = t->tm_sec = 0;
-          t->tm_mon  = m - 1;
-          t->tm_mday = number;
-          t->tm_year = y - 1900;
-          t->tm_isdst = -1;
-          _date = mktime (t);
-        }
-
-        return true;
-      }
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sunday/abbrev [ !<alpha> && !<digit> && !: && != ]
-bool Datetime::initializeDayName (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  std::string token;
-  for (int day = 0; day <= 7; ++day)   // Deliberate <= so that 'sunday' is either 0 or 7.
-  {
-    if (pig.skipPartial (dayNames[day % 7], token) &&
-        token.length () >= static_cast <std::string::size_type> (Datetime::minimumMatchLength))
-    {
-      auto following = pig.peek ();
-      if (! unicodeLatinAlpha (following) &&
-          ! unicodeLatinDigit (following) &&
-          following != ':' &&
-          following != '=')
-      {
-        time_t now = time (nullptr);
-        struct tm* t = localtime (&now);
-
-        if (t->tm_wday >= day)
-          t->tm_mday += day - t->tm_wday + 7;
-        else
-          t->tm_mday += day - t->tm_wday;
-
-        t->tm_hour = t->tm_min = t->tm_sec = 0;
-        t->tm_isdst = -1;
-        _date = mktime (t);
-        return true;
-      }
-    }
-
-    pig.restoreTo (checkpoint);
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// january/abbrev [ !<alpha> && !<digit> && !: && != ]
-bool Datetime::initializeMonthName (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  std::string token;
-  for (int month = 0; month < 12; ++month)
-  {
-    if (pig.skipPartial (monthNames[month], token) &&
-        token.length () >= static_cast <std::string::size_type> (Datetime::minimumMatchLength))
-    {
-      auto following = pig.peek ();
-      if (! unicodeLatinAlpha (following) &&
-          ! unicodeLatinDigit (following) &&
-          following != ':' &&
-          following != '=')
-      {
-        time_t now = time (nullptr);
-        struct tm* t = localtime (&now);
-
-        if (t->tm_mon >= month)
-          t->tm_year++;
-
-        t->tm_mon = month;
-        t->tm_mday = 1;
-        t->tm_hour = t->tm_min = t->tm_sec = 0;
-        t->tm_isdst = -1;
-        _date = mktime (t);
-        return true;
-      }
-    }
-
-    pig.restoreTo (checkpoint);
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// later/abbrev  [ !<alpha> && !<digit> ]
-// someday/abbrev  [ !<alpha> && !<digit> ]
-bool Datetime::initializeLater (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  std::string token;
-  if ((pig.skipPartial ("later", token) &&
-      token.length () >= static_cast <std::string::size_type> (Datetime::minimumMatchLength))
-
-      ||
-
-     (pig.skipPartial ("someday", token) &&
-      token.length () >= static_cast <std::string::size_type> (std::max (Datetime::minimumMatchLength, 4))))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_year = 138;
-      t->tm_mon = 0;
-      t->tm_mday = 18;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sopd [ !<alpha> && !<digit> ]
-bool Datetime::initializeSopd (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sopd"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      t->tm_mday -= 1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sod [ !<alpha> && !<digit> ]
-bool Datetime::initializeSod (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sod"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sond [ !<alpha> && !<digit> ]
-bool Datetime::initializeSond (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sond"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday++;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eopd [ !<alpha> && !<digit> ]
-bool Datetime::initializeEopd (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eopd"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eod [ !<alpha> && !<digit> ]
-bool Datetime::initializeEod (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eod"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday++;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eond [ !<alpha> && !<digit> ]
-bool Datetime::initializeEond (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eond"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday += 2;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sopw [ !<alpha> && !<digit> ]
-bool Datetime::initializeSopw (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sopw"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-
-      int extra = (t->tm_wday + 6) % 7;
-      t->tm_mday -= extra;
-      t->tm_mday -= 7;
-
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sow [ !<alpha> && !<digit> ]
-bool Datetime::initializeSow (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sow"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-
-      int extra = (t->tm_wday + 6) % 7;
-      t->tm_mday -= extra;
-
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sonw [ !<alpha> && !<digit> ]
-bool Datetime::initializeSonw (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sonw"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-
-      int extra = (t->tm_wday + 6) % 7;
-      t->tm_mday -= extra;
-      t->tm_mday += 7;
-
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eopw [ !<alpha> && !<digit> ]
-bool Datetime::initializeEopw (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eopw"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-
-      int extra = (t->tm_wday + 6) % 7;
-      t->tm_mday -= extra;
-
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eow [ !<alpha> && !<digit> ]
-bool Datetime::initializeEow (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eow"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-
-      int extra = (t->tm_wday + 6) % 7;
-      t->tm_mday -= extra;
-      t->tm_mday += 7;
-
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eonw [ !<alpha> && !<digit> ]
-bool Datetime::initializeEonw (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eonw"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday += 15 - t->tm_wday;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sopww [ !<alpha> && !<digit> ]
-bool Datetime::initializeSopww (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sopww"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday += -6 - t->tm_wday;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// soww [ !<alpha> && !<digit> ]
-bool Datetime::initializeSoww (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("soww"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday += 8 - t->tm_wday;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sonww [ !<alpha> && !<digit> ]
-bool Datetime::initializeSonww (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sonww"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday += 8 - t->tm_wday;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eopww [ !<alpha> && !<digit> ]
-bool Datetime::initializeEopww (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eopww"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday -= (t->tm_wday + 1) % 7;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eoww [ !<alpha> && !<digit> ]
-bool Datetime::initializeEoww (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eoww"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday += 6 - t->tm_wday;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eonww [ !<alpha> && !<digit> ]
-bool Datetime::initializeEonww (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eonww"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mday += 13 - t->tm_wday;
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sopm [ !<alpha> && !<digit> ]
-bool Datetime::initializeSopm (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sopm"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-
-      if (t->tm_mon == 0)
-      {
-        t->tm_year--;
-        t->tm_mon = 11;
-      }
-      else
-        t->tm_mon--;
-
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// som [ !<alpha> && !<digit> ]
-bool Datetime::initializeSom (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("som"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sonm [ !<alpha> && !<digit> ]
-bool Datetime::initializeSonm (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sonm"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-
-      t->tm_mon++;
-      if (t->tm_mon > 11)
-      {
-        t->tm_year++;
-        t->tm_mon = 0;
-      }
-
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eopm [ !<alpha> && !<digit> ]
-bool Datetime::initializeEopm (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eopm"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eom [ !<alpha> && !<digit> ]
-bool Datetime::initializeEom (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eom"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-
-      t->tm_mon++;
-      if (t->tm_mon > 11)
-      {
-        t->tm_year++;
-        t->tm_mon = 0;
-      }
-
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eonm [ !<alpha> && !<digit> ]
-bool Datetime::initializeEonm (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eonm"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mday = 1;
-      t->tm_mon += 2;
-      if (t->tm_mon > 11)
-      {
-        t->tm_year++;
-        t->tm_mon -= 12;
-      }
-
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sopq [ !<alpha> && !<digit> ]
-bool Datetime::initializeSopq (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sopq"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mon -= t->tm_mon % 3;
-      t->tm_mon -= 3;
-      if (t->tm_mon < 0)
-      {
-        t->tm_mon += 12;
-        t->tm_year--;
-      }
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// soq [ !<alpha> && !<digit> ]
-bool Datetime::initializeSoq (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("soq"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mon -= t->tm_mon % 3;
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sonq [ !<alpha> && !<digit> ]
-bool Datetime::initializeSonq (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sonq"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mon += 3 - (t->tm_mon % 3);
-      if (t->tm_mon > 11)
-      {
-        t->tm_mon -= 12;
-        ++t->tm_year;
-      }
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eopq [ !<alpha> && !<digit> ]
-bool Datetime::initializeEopq (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eopq"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mon -= t->tm_mon % 3;
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eoq [ !<alpha> && !<digit> ]
-bool Datetime::initializeEoq (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eoq"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_mon += 3 - (t->tm_mon % 3);
-      if (t->tm_mon > 11)
-      {
-        t->tm_mon -= 12;
-        ++t->tm_year;
-      }
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eonq [ !<alpha> && !<digit> ]
-bool Datetime::initializeEonq (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eonq"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mon += 6 - (t->tm_mon % 3);
-      if (t->tm_mon > 11)
-      {
-        t->tm_mon -= 12;
-        ++t->tm_year;
-      }
-
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sopy [ !<alpha> && !<digit> ]
-bool Datetime::initializeSopy (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sopy"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mon = 0;
-      t->tm_mday = 1;
-      t->tm_year--;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// soy [ !<alpha> && !<digit> ]
-bool Datetime::initializeSoy (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("soy"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mon = 0;
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sony [ !<alpha> && !<digit> ]
-bool Datetime::initializeSony (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("sony"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mon = 0;
-      t->tm_mday = 1;
-      t->tm_year++;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eopy [ !<alpha> && !<digit> ]
-bool Datetime::initializeEopy (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eopy"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mon = 0;
-      t->tm_mday = 1;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eoy [ !<alpha> && !<digit> ]
-bool Datetime::initializeEoy (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eoy"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mon = 0;
-      t->tm_mday = 1;
-      t->tm_year++;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// eony [ !<alpha> && !<digit> ]
-bool Datetime::initializeEony (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("eony"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      t->tm_hour = t->tm_min = t->tm_sec = 0;
-      t->tm_mon = 0;
-      t->tm_mday = 1;
-      t->tm_year += 2;
-      t->tm_isdst = -1;
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// easter       [ !<alpha> && !<digit> ]
-// eastermonday [ !<alpha> && !<digit> ]
-// ascension    [ !<alpha> && !<digit> ]
-// pentecost    [ !<alpha> && !<digit> ]
-// goodfriday   [ !<alpha> && !<digit> ]
-bool Datetime::initializeEaster (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  std::vector <std::string> holidays = {"eastermonday", "easter", "ascension", "pentecost", "goodfriday"};
-  std::vector <int>         offsets  = {             1,        0,          39,          49,           -2};
-
-  std::string token;
-  for (int holiday = 0; holiday < 5; ++holiday)
-  {
-   if (pig.skipLiteral (holidays[holiday]) &&
-       ! unicodeLatinAlpha (pig.peek ()) &&
-       ! unicodeLatinDigit (pig.peek ()))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      easter (t);
-      _date = mktime (t);
-
-      // If the result is earlier this year, then recalc for next year.
-      if (_date < now)
-      {
-        t = localtime (&now);
-        t->tm_year++;
-        easter (t);
-      }
-
-      // Adjust according to holiday-specific offsets.
-      t->tm_mday += offsets[holiday];
-
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// midsommar [ !<alpha> && !<digit> ]
-bool Datetime::initializeMidsommar (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("midsommar"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-      midsommar (t);
-      _date = mktime (t);
-
-      // If the result is earlier this year, then recalc for next year.
-      if (_date < now)
-      {
-        t = localtime (&now);
-        t->tm_year++;
-        midsommar (t);
-      }
-
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// midsommarafton [ !<alpha> && !<digit> ]
-// juhannus [ !<alpha> && !<digit> ]
-bool Datetime::initializeMidsommarafton (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skipLiteral ("midsommarafton") ||
-      pig.skipLiteral ("juhannus"))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-      midsommarafton (t);
-      _date = mktime (t);
-
-      // If the result is earlier this year, then recalc for next year.
-      if (_date < now)
-      {
-        t = localtime (&now);
-        t->tm_year++;
-        midsommarafton (t);
-      }
-
-      _date = mktime (t);
-      return true;
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 8am
-// 8a
-// 8:30am
-// 8:30a
-// 8:30
-//
-// \d+ [ : \d{2} ] [ am | a | pm | p ] [ !<alpha> && !<digit> && !: && !+ && !- ]
-//
-bool Datetime::initializeInformalTime (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  int digit = 0;
-  bool needDesignator = true;   // Require am/pm.
-  bool haveDesignator = false;  // Provided am/pm.
-  if (pig.getDigit (digit))
-  {
-    int hours = digit;
-    if (pig.getDigit (digit))
-      hours = 10 * hours + digit;
-
-    int minutes = 0;
-    int seconds = 0;
-    if (pig.skip (':'))
-    {
-      if (! pig.getDigit2 (minutes))
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-
-      if (pig.skip (':'))
-      {
-        if (! pig.getDigits (seconds))
-        {
-          pig.restoreTo (checkpoint);
-          return false;
-        }
-      }
-
-      needDesignator = false;
-    }
-
-    if (pig.skipLiteral ("am") ||
-        pig.skipLiteral ("a"))
-    {
-      haveDesignator = true;
-      if (hours == 12)
-        hours = 0;
-    }
-
-    else if (pig.skipLiteral ("pm") ||
-             pig.skipLiteral ("p"))
-    {
-      // Note: '12pm is an exception:
-      //  12am = 0h
-      //  11am = 11h + 12h
-      //  12pm = 12h
-      //  1pm  = 1h + 12h
-      if (hours != 12)
-        hours += 12;
-
-      haveDesignator = true;
-    }
-
-    // Informal time needs to be terminated.
-    auto following = pig.peek ();
-    if (unicodeLatinAlpha (following) ||
-        unicodeLatinDigit (following) ||
-        following == ':'              ||
-        following == '-'              ||
-        following == '+')
-    {
-      pig.restoreTo (checkpoint);
-      return false;
-    }
-
-    if (haveDesignator || ! needDesignator)
-    {
-      // Midnight today + hours:minutes:seconds.
-      time_t now = time (nullptr);
-      struct tm* t = localtime (&now);
-
-      int now_seconds  = (t->tm_hour * 3600) + (t->tm_min * 60) + t->tm_sec;
-      int calc_seconds = (hours      * 3600) + (minutes   * 60) + seconds;
-
-      if (calc_seconds < now_seconds)
-        ++t->tm_mday;
-
-      // Basic validation.
-      if (hours   >= 0 && hours   < 24 &&
-          minutes >= 0 && minutes < 60 &&
-          seconds >= 0 && seconds < 60)
-      {
-        t->tm_hour = hours;
-        t->tm_min = minutes;
-        t->tm_sec = seconds;
-        t->tm_isdst = -1;
-        _date = mktime (t);
-
-        return true;
-      }
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Datetime::easter (struct tm* t) const
-{
-  int Y = t->tm_year + 1900;
-  int a = Y % 19;
-  int b = Y / 100;
-  int c = Y % 100;
-  int d = b / 4;
-  int e = b % 4;
-  int f = (b + 8) / 25;
-  int g = (b - f + 1) / 3;
-  int h = (19 * a + b - d - g + 15) % 30;
-  int i = c / 4;
-  int k = c % 4;
-  int L = (32 + 2 * e + 2 * i - h - k) % 7;
-  int m = (a + 11 * h + 22 * L) / 451;
-  int month = (h + L - 7 * m + 114) / 31;
-  int day = ((h + L - 7 * m + 114) % 31) + 1;
-
-  t->tm_isdst = -1;   // Requests that mktime determine summer time effect.
-  t->tm_mday  = day;
-  t->tm_mon   = month - 1;
-  t->tm_year  = Y - 1900;
-  t->tm_isdst = -1;
-  t->tm_hour = t->tm_min = t->tm_sec = 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Datetime::midsommar (struct tm* t) const
-{
-  t->tm_mon = 5;                          // June.
-  t->tm_mday = 20;                        // Saturday after 20th.
-  t->tm_hour = t->tm_min = t->tm_sec = 0; // Midnight.
-  t->tm_isdst = -1;                       // Probably DST, but check.
-
-  time_t then = mktime (t);               // Obtain the weekday of June 20th.
-  struct tm* mid = localtime (&then);
-  t->tm_mday += 6 - mid->tm_wday;         // How many days after 20th.
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Datetime::midsommarafton (struct tm* t) const
-{
-  t->tm_mon = 5;                          // June.
-  t->tm_mday = 19;                        // Saturday after 20th.
-  t->tm_hour = t->tm_min = t->tm_sec = 0; // Midnight.
-  t->tm_isdst = -1;                       // Probably DST, but check.
-
-  time_t then = mktime (t);               // Obtain the weekday of June 19th.
-  struct tm* mid = localtime (&then);
-  t->tm_mday += 5 - mid->tm_wday;         // How many days after 19th.
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Suggested date expressions:
-//   {ordinal} {day} in|of {month}
-//   last|past|next|this {day}
-//   last|past|next|this {month}
-//   last|past|next|this week
-//   last|past|next|this month
-//   last|past|next|this weekend
-//   last|past|next|this year
-//   {day} last|past|next|this week
-//   {day} [at] {time}
-//   {time} {day}
-//
-// Candidates:
-//   <dayname> <time>
-//   <time>
-//   tue 9am
-//   Friday before easter
-//   3 days before eom
-//   in the morning
-//   am|pm
-//   4pm
-//   noon
-//   midnight
-//   tomorrow in one year
-//   in two weeks
-//   2 weeks from now
-//   2 weeks ago tuesday
-//   thursday in 2 weeks
-//   last day next month
-//   10 days from today
-//   thursday before last weekend in may
-//   friday last full week in may
-//   3rd wednesday this month
-//   3 weeks after 2nd tuesday next month
-//   100 days from the beginning of the month
-//   10 days after last monday
-//   sunday in the evening
-//   in 6 hours
-//   6 in the morning
-//   kl 18
-//   feb 11
-//   11 feb
-//   2011-02-08
-//   11/19/2011
-//   next business day
-//   new moon
-//   full moon
-//   in 28 days
-//   3rd quarter
-//   week 23
-//   {number} {unit}
-//   - {number} {unit}
-//   {ordinal} {unit} in {larger-unit}
-//   end of day tomorrow
-//   end of {day}
-//   by {day}
-//   first thing {day}
-//
-
-////////////////////////////////////////////////////////////////////////////////
-// <ordinal> <weekday> in|of <month>
-bool Datetime::initializeNthDayInMonth (const std::vector <std::string>& tokens)
-{
-  if (tokens.size () == 4)
-  {
-    int ordinal {0};
-    if (isOrdinal (tokens[0], ordinal))
-    {
-      auto day = Datetime::dayOfWeek (tokens[1]);
-      if (day != -1)
-      {
-        if (tokens[2] == "in" ||
-            tokens[2] == "of")
-        {
-          auto month = Datetime::monthOfYear (tokens[3]);
-          if (month != -1)
-          {
-            std::cout << "# ordinal=" << ordinal << " day=" << day << " in month=" << month << '\n';
-
-            // TODO Assume 1st of the month
-            // TODO Assume current year
-            // TODO Determine the day
-            // TODO Project forwards/backwards, to the desired day
-            // TODO Add ((ordinal - 1) * 7) days
-
-            return true;
-          }
-        }
-      }
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::isOrdinal (const std::string& token, int& ordinal)
-{
-  Pig p (token);
-  int number;
-  std::string suffix;
-  if (p.getDigits (number) &&
-      p.getRemainder (suffix))
-  {
-    if (((number >= 11 || number <= 13) && suffix == "th") ||
-        (number % 10 == 1               && suffix == "st") ||
-        (number % 10 == 2               && suffix == "nd") ||
-        (number % 10 == 3               && suffix == "rd") ||
-        (                                  suffix == "th"))
-    {
-      ordinal = number;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Validation via simple range checking.
-bool Datetime::validate ()
-{
-  // _year;
-  if ((_year    && (_year    <   1900 || _year    >                                  2200)) ||
-      (_month   && (_month   <      1 || _month   >                                    12)) ||
-      (_week    && (_week    <      1 || _week    >                                    53)) ||
-      (_weekday && (_weekday <      0 || _weekday >                                     6)) ||
-      (_julian  && (_julian  <      1 || _julian  >          Datetime::daysInYear (_year))) ||
-      (_day     && (_day     <      1 || _day     > Datetime::daysInMonth (_year, _month))) ||
-      (_seconds && (_seconds <      1 || _seconds >                                 86400)) ||
-      (_offset  && (_offset  < -86400 || _offset  >                                 86400)))
-    return false;
-
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// int tm_sec;       seconds (0 - 60)
-// int tm_min;       minutes (0 - 59)
-// int tm_hour;      hours (0 - 23)
-// int tm_mday;      day of month (1 - 31)
-// int tm_mon;       month of year (0 - 11)
-// int tm_year;      year - 1900
-// int tm_wday;      day of week (Sunday = 0)
-// int tm_yday;      day of year (0 - 365)
-// int tm_isdst;     is summer time in effect?
-// char *tm_zone;    abbreviation of timezone name
-// long tm_gmtoff;   offset from UTC in seconds
-void Datetime::resolve ()
-{
-  // Don't touch the original values.
-  int year    = _year;
-  int month   = _month;
-  int week    = _week;
-  int weekday = _weekday;
-  int julian  = _julian;
-  int day     = _day;
-  int seconds = _seconds;
-  int offset  = _offset;
-  bool utc    = _utc;
-
-  // Get current time.
-  time_t now = time (nullptr);
-
-  // A UTC offset needs to be accommodated.  Once the offset is subtracted,
-  // only local and UTC times remain.
-  if (offset)
-  {
-    seconds -= offset;
-    now -= offset;
-    utc = true;
-  }
-
-  // Get 'now' in the relevant location.
-  struct tm* t_now = utc ? gmtime (&now) : localtime (&now);
-
-  int seconds_now = (t_now->tm_hour * 3600) +
-                    (t_now->tm_min  *   60) +
-                     t_now->tm_sec;
-
-  // Project forward one day if the specified seconds are earlier in the day
-  // than the current seconds.
-  // TODO This does not cover the inverse case of subtracting 86400.
-  if (year    == 0           &&
-      month   == 0           &&
-      day     == 0           &&
-      week    == 0           &&
-      weekday == 0           &&
-      seconds < seconds_now)
-  {
-    seconds += 86400;
-  }
-
-  // Convert week + weekday --> julian.
-  if (week)
-  {
-    julian = (week * 7) + weekday - dayOfWeek (year, 1, 4) - 3;
-  }
-
-  // Provide default values for year, month, day.
-  else
-  {
-    // Default values for year, month, day:
-    //
-    // y   m   d  -->  y   m   d
-    // y   m   -  -->  y   m   1
-    // y   -   -  -->  y   1   1
-    // -   -   -  -->  now now now
-    //
-    if (year == 0)
-    {
-      year  = t_now->tm_year + 1900;
-      month = t_now->tm_mon + 1;
-      day   = t_now->tm_mday;
-    }
-    else
-    {
-      if (month == 0)
-      {
-        month = 1;
-        day   = 1;
-      }
-      else if (day == 0)
-        day = 1;
-    }
-  }
-
-  if (julian)
-  {
-    month = 1;
-    day = julian;
-  }
-
-  struct tm t {};
-  t.tm_isdst = -1;  // Requests that mktime/gmtime determine summer time effect.
-  t.tm_year = year - 1900;
-  t.tm_mon = month - 1;
-  t.tm_mday = day;
-
-  if (seconds > 86400)
-  {
-    int days = seconds / 86400;
-    t.tm_mday += days;
-    seconds %= 86400;
-  }
-
-  t.tm_hour = seconds / 3600;
-  t.tm_min = (seconds % 3600) / 60;
-  t.tm_sec = seconds % 60;
-
-  _date = utc ? timegm (&t) : mktime (&t);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-time_t Datetime::toEpoch () const
-{
-  return _date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Datetime::toEpochString () const
-{
-  return format ("{1}", _date);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 19980119T070000Z =  YYYYMMDDThhmmssZ
-std::string Datetime::toISO () const
-{
-  struct tm* t = gmtime (&_date);
-
-  std::stringstream iso;
-  iso << std::setw (4) << std::setfill ('0') << t->tm_year + 1900
-      << std::setw (2) << std::setfill ('0') << t->tm_mon + 1
-      << std::setw (2) << std::setfill ('0') << t->tm_mday
-      << 'T'
-      << std::setw (2) << std::setfill ('0') << t->tm_hour
-      << std::setw (2) << std::setfill ('0') << t->tm_min
-      << std::setw (2) << std::setfill ('0') << t->tm_sec
-      << 'Z';
-
-  return iso.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 1998-01-19T07:00:00 =  YYYY-MM-DDThh:mm:ss
-std::string Datetime::toISOLocalExtended () const
-{
-  struct tm* t = localtime (&_date);
-
-  std::stringstream iso;
-  iso << std::setw (4) << std::setfill ('0') << t->tm_year + 1900
-      << '-'
-      << std::setw (2) << std::setfill ('0') << t->tm_mon + 1
-      << '-'
-      << std::setw (2) << std::setfill ('0') << t->tm_mday
-      << 'T'
-      << std::setw (2) << std::setfill ('0') << t->tm_hour
-      << ':'
-      << std::setw (2) << std::setfill ('0') << t->tm_min
-      << ':'
-      << std::setw (2) << std::setfill ('0') << t->tm_sec;
-
-  return iso.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-double Datetime::toJulian () const
-{
-  return (_date / 86400.0) + 2440587.5;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Datetime::toYMD (int& y, int& m, int& d) const
-{
-  struct tm* t = localtime (&_date);
-
-  m = t->tm_mon + 1;
-  d = t->tm_mday;
-  y = t->tm_year + 1900;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string Datetime::toString (const std::string& format) const
-{
-  std::stringstream formatted;
-  for (unsigned int i = 0; i < format.length (); ++i)
-  {
-    int c = format[i];
-    switch (c)
-    {
-    case 'm': formatted                                        << month ();               break;
-    case 'M': formatted << std::setw (2) << std::setfill ('0') << month ();               break;
-    case 'd': formatted                                        << day ();                 break;
-    case 'D': formatted << std::setw (2) << std::setfill ('0') << day ();                 break;
-    case 'y': formatted << std::setw (2) << std::setfill ('0') << (year () % 100);        break;
-    case 'Y': formatted                                        << year ();                break;
-    case 'a': formatted                                        << Datetime::dayNameShort (dayOfWeek ()); break;
-    case 'A': formatted                                        << Datetime::dayName (dayOfWeek ());      break;
-    case 'b': formatted                                        << Datetime::monthNameShort (month ());   break;
-    case 'B': formatted                                        << Datetime::monthName (month ());        break;
-    case 'v': formatted                                        << week ();                break;
-    case 'V': formatted << std::setw (2) << std::setfill ('0') << week ();                break;
-    case 'h': formatted                                        << hour ();                break;
-    case 'H': formatted << std::setw (2) << std::setfill ('0') << hour ();                break;
-    case 'n': formatted                                        << minute ();              break;
-    case 'N': formatted << std::setw (2) << std::setfill ('0') << minute ();              break;
-    case 's': formatted                                        << second ();              break;
-    case 'S': formatted << std::setw (2) << std::setfill ('0') << second ();              break;
-    case 'j': formatted                                        << dayOfYear ();           break;
-    case 'J': formatted << std::setw (3) << std::setfill ('0') << dayOfYear ();           break;
-    case 'w': formatted                                        << dayOfWeek ();           break;
-    default:  formatted                                        << static_cast <char> (c); break;
-    }
-  }
-
-  return formatted.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime Datetime::startOfDay () const
-{
-  return Datetime (year (), month (), day ());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime Datetime::startOfWeek () const
-{
-  Datetime sow (_date);
-  sow -= (dayOfWeek () * 86400);
-  return Datetime (sow.year (), sow.month (), sow.day ());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime Datetime::startOfMonth () const
-{
-  return Datetime (year (), month (), 1);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime Datetime::startOfYear () const
-{
-  return Datetime (year (), 1, 1);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::valid (const std::string& input, const std::string& format)
-{
-  try
-  {
-    Datetime test (input, format);
-  }
-
-  catch (...)
-  {
-    return false;
-  }
-
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::valid (
-  const int y, const int m, const int d,
-  const int hr, const int mi, const int se)
-{
-  if (hr < 0 || hr > 24)
-    return false;
-
-  if (mi < 0 || mi > 59)
-    return false;
-
-  if (se < 0 || se > 59)
-    return false;
-
-  if (hr == 24 &&
-      (mi != 0 ||
-       se != 0))
-    return false;
-
-  return Datetime::valid (y, m, d);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::valid (const int y, const int m, const int d)
-{
-  // Check that the year is valid.
-  if (y < 0)
-    return false;
-
-  // Check that the month is valid.
-  if (m < 1 || m > 12)
-    return false;
-
-  // Finally check that the days fall within the acceptable range for this
-  // month, and whether or not this is a leap year.
-  if (d < 1 || d > Datetime::daysInMonth (y, m))
-    return false;
-
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Julian
-bool Datetime::valid (const int y, const int d)
-{
-  // Check that the year is valid.
-  if (y < 0)
-    return false;
-
-  if (d < 1 || d > Datetime::daysInYear (y))
-    return false;
-
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-bool Datetime::leapYear (int year)
-{
-  return ((! (year % 4)) && (year % 100)) ||
-         ! (year % 400);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-int Datetime::daysInMonth (int year, int month)
-{
-  // Protect against arguments being passed in the wrong order.
-  assert (year >= 1969 && year < 2100);
-  assert (month >= 1 && month <= 31);
-
-  static int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-  if (month == 2 && Datetime::leapYear (year))
-    return 29;
-
-  return days[month - 1];
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-int Datetime::daysInYear (int year)
-{
-  return Datetime::leapYear (year) ? 366 : 365;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-std::string Datetime::monthName (int month)
-{
-  assert (month > 0);
-  assert (month <= 12);
-  return upperCaseFirst (monthNames[month - 1]);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-std::string Datetime::monthNameShort (int month)
-{
-  assert (month > 0);
-  assert (month <= 12);
-  return upperCaseFirst (monthNames[month - 1]).substr (0, 3);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-std::string Datetime::dayName (int dow)
-{
-  assert (dow >= 0);
-  assert (dow <= 6);
-  return upperCaseFirst (dayNames[dow]);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-std::string Datetime::dayNameShort (int dow)
-{
-  assert (dow >= 0);
-  assert (dow <= 6);
-  return upperCaseFirst (dayNames[dow]).substr (0, 3);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-int Datetime::dayOfWeek (const std::string& input)
-{
-  if (Datetime::minimumMatchLength== 0)
-    Datetime::minimumMatchLength = 3;
-
-  for (unsigned int i = 0; i < dayNames.size (); ++i)
-    if (closeEnough (dayNames[i], input, Datetime::minimumMatchLength))
-       return i;
-
-  return -1;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Using Zeller's Congruence.
-// Static
-int Datetime::dayOfWeek (int year, int month, int day)
-{
-  int adj = (14 - month) / 12;
-  int m = month + 12 * adj - 2;
-  int y = year - adj;
-  return (day + (13 * m - 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-int Datetime::monthOfYear (const std::string& input)
-{
-  if (Datetime::minimumMatchLength== 0)
-    Datetime::minimumMatchLength = 3;
-
-  for (unsigned int i = 0; i < monthNames.size (); ++i)
-    if (closeEnough (monthNames[i], input, Datetime::minimumMatchLength))
-       return i + 1;
-
-  return -1;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-int Datetime::length (const std::string& format)
-{
-  int len = 0;
-  for (auto& i : format)
-  {
-    switch (i)
-    {
-    case 'm':
-    case 'M':
-    case 'd':
-    case 'D':
-    case 'y':
-    case 'v':
-    case 'V':
-    case 'h':
-    case 'H':
-    case 'n':
-    case 'N':
-    case 's':
-    case 'S': len += 2;  break;
-    case 'b':
-    case 'j':
-    case 'J':
-    case 'a': len += 3;  break;
-    case 'Y': len += 4;  break;
-    case 'A':
-    case 'B': len += 10; break;
-
-    // Calculate the width, don't assume a single character width.
-    default:  len += mk_wcwidth (i); break;
-    }
-  }
-
-  return len;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Datetime::month () const
-{
-  struct tm* t = localtime (&_date);
-  return t->tm_mon + 1;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Datetime::week () const
-{
-  struct tm* t = localtime (&_date);
-
-  char weekStr[3];
-  if (Datetime::weekstart == 0)
-    strftime (weekStr, sizeof (weekStr), "%U", t);
-  else if (Datetime::weekstart == 1)
-    strftime (weekStr, sizeof (weekStr), "%V", t);
-  else
-    throw std::string ("The week may only start on a Sunday or Monday.");
-
-  int weekNumber = strtol (weekStr, nullptr, 10);
-  if (weekstart == 0)
-    weekNumber += 1;
-
-  return weekNumber;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Datetime::day () const
-{
-  struct tm* t = localtime (&_date);
-  return t->tm_mday;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Datetime::year () const
-{
-  struct tm* t = localtime (&_date);
-  return t->tm_year + 1900;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Datetime::dayOfWeek () const
-{
-  struct tm* t = localtime (&_date);
-  return t->tm_wday;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Datetime::dayOfYear () const
-{
-  struct tm* t = localtime (&_date);
-  return t->tm_yday + 1;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Datetime::hour () const
-{
-  struct tm* t = localtime (&_date);
-  return t->tm_hour;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Datetime::minute () const
-{
-  struct tm* t = localtime (&_date);
-  return t->tm_min;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Datetime::second () const
-{
-  struct tm* t = localtime (&_date);
-  return t->tm_sec;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::operator== (const Datetime& rhs) const
-{
-  return rhs._date == _date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::operator!= (const Datetime& rhs) const
-{
-  return rhs._date != _date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::operator< (const Datetime& rhs) const
-{
-  return _date < rhs._date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::operator> (const Datetime& rhs) const
-{
-  return _date > rhs._date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::operator<= (const Datetime& rhs) const
-{
-  return _date <= rhs._date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::operator>= (const Datetime& rhs) const
-{
-  return _date >= rhs._date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::sameHour (const Datetime& rhs) const
-{
-  return year ()  == rhs.year ()  &&
-         month () == rhs.month () &&
-         day ()   == rhs.day ()   &&
-         hour ()  == rhs.hour ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::sameDay (const Datetime& rhs) const
-{
-  return year ()  == rhs.year ()  &&
-         month () == rhs.month () &&
-         day ()   == rhs.day ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::sameWeek (const Datetime& rhs) const
-{
-  return year () == rhs.year () &&
-         week () == rhs.week ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::sameMonth (const Datetime& rhs) const
-{
-  return year ()  == rhs.year () &&
-         month () == rhs.month ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::sameQuarter (const Datetime& rhs) const
-{
-  return year () == rhs.year () &&
-         ((month () - 1) / 3) == ((rhs.month () - 1) / 3);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Datetime::sameYear (const Datetime& rhs) const
-{
-  return year () == rhs.year ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime Datetime::operator+ (const int delta)
-{
-  return Datetime (_date + delta);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime Datetime::operator- (const int delta)
-{
-  return Datetime (_date - delta);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime& Datetime::operator+= (const int delta)
-{
-  _date += (time_t) delta;
-  return *this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Datetime& Datetime::operator-= (const int delta)
-{
-  _date -= (time_t) delta;
-  return *this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-time_t Datetime::operator- (const Datetime& rhs)
-{
-  return _date - rhs._date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Prefix decrement by one day.
-void Datetime::operator-- ()
-{
-  Datetime yesterday = startOfDay () - 1;
-  yesterday = Datetime (yesterday.year (),
-                        yesterday.month (),
-                        yesterday.day (),
-                        hour (),
-                        minute (),
-                        second ());
-  _date = yesterday._date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Postfix decrement by one day.
-void Datetime::operator-- (int)
-{
-  Datetime yesterday = startOfDay () - 1;
-  yesterday = Datetime (yesterday.year (),
-                        yesterday.month (),
-                        yesterday.day (),
-                        hour (),
-                        minute (),
-                        second ());
-  _date = yesterday._date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Prefix increment by one day.
-void Datetime::operator++ ()
-{
-  Datetime tomorrow = (startOfDay () + 90001).startOfDay ();
-  tomorrow = Datetime (tomorrow.year (),
-                       tomorrow.month (),
-                       tomorrow.day (),
-                       hour (),
-                       minute (),
-                       second ());
-  _date = tomorrow._date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Postfix increment by one day.
-void Datetime::operator++ (int)
-{
-  Datetime tomorrow = (startOfDay () + 90001).startOfDay ();
-  tomorrow = Datetime (tomorrow.year (),
-                       tomorrow.month (),
-                       tomorrow.day (),
-                       hour (),
-                       minute (),
-                       second ());
-  _date = tomorrow._date;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Datetime.h b/src/libshared/src/Datetime.h
deleted file mode 100644 (file)
index 1b9b82a..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_DATETIME
-#define INCLUDED_DATETIME
-
-#include <string>
-#include <ctime>
-#include <Pig.h>
-
-class Datetime
-{
-public:
-  static int weekstart;
-  static int minimumMatchLength;
-  static bool isoEnabled;
-  static bool standaloneDateEnabled;
-  static bool standaloneTimeEnabled;
-
-  Datetime ();
-  Datetime (const std::string&, const std::string& format = "");
-  Datetime (time_t);
-  Datetime (const int, const int, const int);
-  Datetime (const int, const int, const int, const int, const int, const int);
-  bool parse (const std::string&, std::string::size_type&, const std::string& format = "");
-  time_t toEpoch () const;
-  std::string toEpochString () const;
-  std::string toISO () const;
-  std::string toISOLocalExtended () const;
-  double toJulian () const;
-  void toYMD (int&, int&, int&) const;
-  const std::string toString (const std::string& format = "Y-M-D") const;
-
-  Datetime startOfDay () const;
-  Datetime startOfWeek () const;
-  Datetime startOfMonth () const;
-  Datetime startOfYear () const;
-
-  static bool valid (const std::string&, const std::string& format = "");
-  static bool valid (const int, const int, const int, const int, const int, const int);
-  static bool valid (const int, const int, const int);
-  static bool valid (const int, const int);
-  static bool leapYear (int);
-  static int daysInMonth (int, int);
-  static int daysInYear (int);
-  static std::string monthName (int);
-  static std::string monthNameShort (int);
-  static std::string dayName (int);
-  static std::string dayNameShort (int);
-  static int dayOfWeek (const std::string&);
-  static int dayOfWeek (int, int, int);
-  static int monthOfYear (const std::string&);
-  static int length (const std::string&);
-
-  int month () const;
-  int week () const;
-  int day () const;
-  int year () const;
-  int dayOfWeek () const;
-  int dayOfYear () const;
-  int hour () const;
-  int minute () const;
-  int second () const;
-
-  bool operator==  (const Datetime&) const;
-  bool operator!=  (const Datetime&) const;
-  bool operator<   (const Datetime&) const;
-  bool operator>   (const Datetime&) const;
-  bool operator<=  (const Datetime&) const;
-  bool operator>=  (const Datetime&) const;
-  bool sameHour    (const Datetime&) const;
-  bool sameDay     (const Datetime&) const;
-  bool sameWeek    (const Datetime&) const;
-  bool sameMonth   (const Datetime&) const;
-  bool sameQuarter (const Datetime&) const;
-  bool sameYear    (const Datetime&) const;
-  Datetime operator+  (const int);
-  Datetime operator-  (const int);
-  Datetime& operator+= (const int);
-  Datetime& operator-= (const int);
-  time_t operator- (const Datetime&);
-  void operator--  ();    // Prefix
-  void operator--  (int); // Postfix
-  void operator++  ();    // Prefix
-  void operator++  (int); // Postfix
-
-private:
-  void clear ();
-  bool parse_formatted     (Pig&, const std::string&);
-  bool parse_named         (Pig&);
-  bool parse_epoch         (Pig&);
-  bool parse_date_time_ext (Pig&);
-  bool parse_date_ext      (Pig&);
-  bool parse_off_ext       (Pig&);
-  bool parse_time_ext      (Pig&, bool terminated = true);
-  bool parse_time_utc_ext  (Pig&);
-  bool parse_time_off_ext  (Pig&);
-  bool parse_date_time     (Pig&);
-  bool parse_date          (Pig&);
-  bool parse_time_utc      (Pig&);
-  bool parse_time_off      (Pig&);
-  bool parse_time          (Pig&, bool terminated = true);
-  bool parse_off           (Pig&);
-
-  bool parse_year          (Pig&, int&);
-  bool parse_month         (Pig&, int&);
-  bool parse_week          (Pig&, int&);
-  bool parse_julian        (Pig&, int&);
-  bool parse_day           (Pig&, int&);
-  bool parse_weekday       (Pig&, int&);
-  bool parse_hour          (Pig&, int&);
-  bool parse_minute        (Pig&, int&);
-  bool parse_second        (Pig&, int&);
-  bool parse_off_hour      (Pig&, int&);
-  bool parse_off_minute    (Pig&, int&);
-
-  bool initializeNow            (Pig&);
-  bool initializeYesterday      (Pig&);
-  bool initializeToday          (Pig&);
-  bool initializeTomorrow       (Pig&);
-  bool initializeOrdinal        (Pig&);
-  bool initializeDayName        (Pig&);
-  bool initializeMonthName      (Pig&);
-  bool initializeLater          (Pig&);
-  bool initializeSopd           (Pig&);
-  bool initializeSod            (Pig&);
-  bool initializeSond           (Pig&);
-  bool initializeEopd           (Pig&);
-  bool initializeEod            (Pig&);
-  bool initializeEond           (Pig&);
-  bool initializeSopw           (Pig&);
-  bool initializeSow            (Pig&);
-  bool initializeSonw           (Pig&);
-  bool initializeEopw           (Pig&);
-  bool initializeEow            (Pig&);
-  bool initializeEonw           (Pig&);
-  bool initializeSopww          (Pig&);
-  bool initializeSonww          (Pig&);
-  bool initializeSoww           (Pig&);
-  bool initializeEopww          (Pig&);
-  bool initializeEonww          (Pig&);
-  bool initializeEoww           (Pig&);
-  bool initializeSopm           (Pig&);
-  bool initializeSom            (Pig&);
-  bool initializeSonm           (Pig&);
-  bool initializeEopm           (Pig&);
-  bool initializeEom            (Pig&);
-  bool initializeEonm           (Pig&);
-  bool initializeSopq           (Pig&);
-  bool initializeSoq            (Pig&);
-  bool initializeSonq           (Pig&);
-  bool initializeEopq           (Pig&);
-  bool initializeEoq            (Pig&);
-  bool initializeEonq           (Pig&);
-  bool initializeSopy           (Pig&);
-  bool initializeSoy            (Pig&);
-  bool initializeSony           (Pig&);
-  bool initializeEopy           (Pig&);
-  bool initializeEoy            (Pig&);
-  bool initializeEony           (Pig&);
-  bool initializeEaster         (Pig&);
-  bool initializeMidsommar      (Pig&);
-  bool initializeMidsommarafton (Pig&);
-  bool initializeInformalTime   (Pig&);
-  void easter (struct tm*) const;
-  void midsommar (struct tm*) const;
-  void midsommarafton (struct tm*) const;
-
-  bool initializeNthDayInMonth  (const std::vector <std::string>&);
-
-  bool isOrdinal (const std::string&, int&);
-
-  bool validate ();
-  void resolve ();
-  std::string dump () const;
-
-public:
-  int _year    {0};
-  int _month   {0};
-  int _week    {0};
-  int _weekday {0};
-  int _julian  {0};
-  int _day     {0};
-  int _seconds {0};
-  int _offset  {0};
-  bool _utc    {false};
-  time_t _date {0};
-};
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Duration.cpp b/src/libshared/src/Duration.cpp
deleted file mode 100644 (file)
index fee8afe..0000000
+++ /dev/null
@@ -1,552 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Duration.h>
-#include <unicode.h>
-#include <sstream>
-#include <iomanip>
-#include <vector>
-
-bool Duration::standaloneSecondsEnabled = true;
-
-#define DAY    86400
-#define HOUR    3600
-#define MINUTE    60
-#define SECOND     1
-
-static struct
-{
-  std::string unit;
-  int seconds;
-  bool standalone;
-} durations[] =
-{
-  // These are sorted by first character, then length, so that Pig::getOneOf
-  // returns a maximal match.
-  {"annual",     365 * DAY,    true },
-  {"biannual",   730 * DAY,    true },
-  {"bimonthly",   61 * DAY,    true },
-  {"biweekly",    14 * DAY,    true },
-  {"biyearly",   730 * DAY,    true },
-  {"daily",        1 * DAY,    true },
-  {"days",         1 * DAY,    false},
-  {"day",          1 * DAY,    true },
-  {"d",            1 * DAY,    false},
-  {"fortnight",   14 * DAY,    true },
-  {"hours",        1 * HOUR,   false},
-  {"hour",         1 * HOUR,   true },
-  {"hrs",          1 * HOUR,   false},
-  {"hr",           1 * HOUR,   true },
-  {"h",            1 * HOUR,   false},
-  {"minutes",      1 * MINUTE, false},
-  {"minute",       1 * MINUTE, true },
-  {"mins",         1 * MINUTE, false},
-  {"min",          1 * MINUTE, true },
-  {"monthly",     30 * DAY,    true },
-  {"months",      30 * DAY,    false},
-  {"month",       30 * DAY,    true },
-  {"mnths",       30 * DAY,    false},
-  {"mths",        30 * DAY,    false},
-  {"mth",         30 * DAY,    true },
-  {"mos",         30 * DAY,    false},
-  {"mo",          30 * DAY,    true },
-  {"m",           30 * DAY,    false},
-  {"quarterly",   91 * DAY,    true },
-  {"quarters",    91 * DAY,    false},
-  {"quarter",     91 * DAY,    true },
-  {"qrtrs",       91 * DAY,    false},
-  {"qrtr",        91 * DAY,    true },
-  {"qtrs",        91 * DAY,    false},
-  {"qtr",         91 * DAY,    true },
-  {"q",           91 * DAY,    false},
-  {"semiannual", 183 * DAY,    true },
-  {"sennight",    14 * DAY,    false},
-  {"seconds",      1 * SECOND, false},
-  {"second",       1 * SECOND, true },
-  {"secs",         1 * SECOND, false},
-  {"sec",          1 * SECOND, true },
-  {"s",            1 * SECOND, false},
-  {"weekdays",     1 * DAY,    true },
-  {"weekly",       7 * DAY,    true },
-  {"weeks",        7 * DAY,    false},
-  {"week",         7 * DAY,    true },
-  {"wks",          7 * DAY,    false},
-  {"wk",           7 * DAY,    true },
-  {"w",            7 * DAY,    false},
-  {"yearly",     365 * DAY,    true },
-  {"years",      365 * DAY,    false},
-  {"year",       365 * DAY,    true },
-  {"yrs",        365 * DAY,    false},
-  {"yr",         365 * DAY,    true },
-  {"y",          365 * DAY,    false},
-};
-
-#define NUM_DURATIONS (sizeof (durations) / sizeof (durations[0]))
-
-////////////////////////////////////////////////////////////////////////////////
-Duration::Duration ()
-{
-  clear ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Duration::Duration (const std::string& input)
-{
-  clear ();
-  std::string::size_type idx = 0;
-  parse (input, idx);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Duration::Duration (time_t input)
-{
-  clear ();
-  _period = input;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Duration::operator< (const Duration& other)
-{
-  return _period < other._period;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Duration::operator> (const Duration& other)
-{
-  return _period > other._period;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Duration::operator<= (const Duration& other)
-{
-  return _period <= other._period;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Duration::operator>= (const Duration& other)
-{
-  return _period >= other._period;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Duration::toString () const
-{
-  std::stringstream s;
-  s << _period;
-  return s.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-time_t Duration::toTime_t () const
-{
-  return _period;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Duration::parse (const std::string& input, std::string::size_type& start)
-{
-  auto i = start;
-  Pig pig (input);
-  if (i)
-    pig.skipN (static_cast <int> (i));
-
-  if (Duration::standaloneSecondsEnabled && parse_seconds (pig))
-  {
-    // ::resolve is not needed in this case.
-    start = pig.cursor ();
-    return true;
-  }
-
-  else if (parse_designated (pig) ||
-           parse_weeks (pig)      ||
-           parse_units (pig))
-  {
-    start = pig.cursor ();
-    resolve ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Duration::parse_seconds (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  int epoch {};
-  if (pig.getDigits (epoch)             &&
-      ! unicodeLatinAlpha (pig.peek ()) &&
-      (epoch == 0 ||
-       epoch > 60))
-  {
-    _period = static_cast <time_t> (epoch);
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 'P' [nn 'Y'] [nn 'M'] [nn 'D'] ['T' [nn 'H'] [nn 'M'] [nn 'S']]
-bool Duration::parse_designated (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skip ('P') &&
-      ! pig.eos ())
-  {
-    int value;
-    pig.save ();
-    if (pig.getDigits (value) && pig.skip ('Y'))
-      _year = value;
-    else
-      pig.restore ();
-
-    pig.save ();
-    if (pig.getDigits (value) && pig.skip ('M'))
-      _month = value;
-    else
-      pig.restore ();
-
-    pig.save ();
-    if (pig.getDigits (value) && pig.skip ('D'))
-      _day = value;
-    else
-      pig.restore ();
-
-    if (pig.skip ('T') &&
-        ! pig.eos ())
-    {
-      pig.save ();
-      if (pig.getDigits (value) && pig.skip ('H'))
-        _hours = value;
-      else
-        pig.restore ();
-
-      pig.save ();
-      if (pig.getDigits (value) && pig.skip ('M'))
-        _minutes = value;
-      else
-        pig.restore ();
-
-      pig.save ();
-      if (pig.getDigits (value) && pig.skip ('S'))
-        _seconds = value;
-      else
-        pig.restore ();
-    }
-
-    auto following = pig.peek ();
-    if (pig.cursor () - checkpoint >= 3   &&
-        ! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-      return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 'P' [nn 'W']
-bool Duration::parse_weeks (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.skip ('P') &&
-      ! pig.eos ())
-  {
-    int value;
-    pig.save ();
-    if (pig.getDigits (value) && pig.skip ('W'))
-      _weeks = value;
-    else
-      pig.restore ();
-
-    auto following = pig.peek ();
-    if (pig.cursor () - checkpoint >= 3   &&
-        ! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-      return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Duration::parse_units (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  // Static and so preserved between calls.
-  static std::vector <std::string> units;
-  if (units.size () == 0)
-    for (unsigned int i = 0; i < NUM_DURATIONS; i++)
-      units.push_back (durations[i].unit);
-
-  double number;
-  std::string unit;
-  if (pig.getOneOf (units, unit))
-  {
-    auto following = pig.peek ();
-    if (! unicodeLatinAlpha (following) &&
-        ! unicodeLatinDigit (following))
-    {
-      for (unsigned int i = 0; i < NUM_DURATIONS; i++)
-      {
-        if (durations[i].unit == unit &&
-            durations[i].standalone)
-        {
-          _period = static_cast <int> (durations[i].seconds);
-          return true;
-        }
-      }
-    }
-    else
-      pig.restoreTo (checkpoint);
-  }
-
-  else if (pig.getDecimal (number))
-  {
-    pig.skipWS ();
-    if (pig.getOneOf (units, unit))
-    {
-      // The "d" unit is a special case, because it is the only one that can
-      // legitimately occur at the beginning of a UUID, and be followed by an
-      // operator:
-      //
-      //   1111111d-0000-0000-0000-000000000000
-      //
-      // Because Lexer::isDuration is higher precedence than Lexer::isUUID,
-      // the above UUID looks like:
-      //
-      //   <1111111d> <-> ...
-      //   duration   op  ...
-      //
-      // So as a special case, durations, with units of "d" are rejected if the
-      // quantity exceeds 10000.
-      //
-      if (unit == "d" && number > 10000.0)
-      {
-        pig.restoreTo (checkpoint);
-        return false;
-      }
-
-      auto following = pig.peek ();
-      if (! unicodeLatinAlpha (following) &&
-          ! unicodeLatinDigit (following))
-      {
-        // Linear lookup - should instead be logarithmic.
-        double seconds = 1;
-        for (unsigned int i = 0; i < NUM_DURATIONS; i++)
-        {
-          if (durations[i].unit == unit)
-          {
-            seconds = durations[i].seconds;
-            _period = static_cast <int> (number * static_cast <double> (seconds));
-            return true;
-          }
-        }
-      }
-    }
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Duration::clear ()
-{
-  _year    = 0;
-  _month   = 0;
-  _weeks   = 0;
-  _day     = 0;
-  _hours   = 0;
-  _minutes = 0;
-  _seconds = 0;
-  _period  = 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string Duration::format () const
-{
-  if (_period)
-  {
-    time_t t = _period;
-    int seconds = t % 60; t /= 60;
-    int minutes = t % 60; t /= 60;
-    int hours   = t % 24; t /= 24;
-    int days    = t;
-
-    std::stringstream s;
-    if (days)
-      s << days << "d ";
-
-    s << hours
-      << ':'
-      << std::setw (2) << std::setfill ('0') << minutes
-      << ':'
-      << std::setw (2) << std::setfill ('0') << seconds;
-
-    return s.str ();
-  }
-  else
-  {
-    return "0:00:00";
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string Duration::formatHours () const
-{
-  if (_period)
-  {
-    time_t t = _period;
-    int seconds = t % 60; t /= 60;
-    int minutes = t % 60; t /= 60;
-    int hours   = t;
-
-    std::stringstream s;
-    s << hours
-      << ':'
-      << std::setw (2) << std::setfill ('0') << minutes
-      << ':'
-      << std::setw (2) << std::setfill ('0') << seconds;
-
-    return s.str ();
-  }
-  else
-  {
-    return "0:00:00";
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string Duration::formatISO () const
-{
-  if (_period)
-  {
-    time_t t = _period;
-    int seconds = t % 60; t /= 60;
-    int minutes = t % 60; t /= 60;
-    int hours   = t % 24; t /= 24;
-    int days    = t;
-
-    std::stringstream s;
-    s << 'P';
-    if (days)   s << days   << 'D';
-
-    if (hours || minutes || seconds)
-    {
-      s << 'T';
-      if (hours)   s << hours   << 'H';
-      if (minutes) s << minutes << 'M';
-      if (seconds) s << seconds << 'S';
-    }
-
-    return s.str ();
-  }
-  else
-  {
-    return "PT0S";
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Range      Representation
-// ---------  ---------------------
-// >= 365d    {n.n}y
-// >= 90d     {n}mo
-// >= 14d     {n}w
-// >= 1d      {n}d
-// >= 1h      {n}h
-// >= 1min    {n}min
-//            {n}s
-//
-const std::string Duration::formatVague (bool padding) const
-{
-  float days = (float) _period / 86400.0;
-
-  std::stringstream formatted;
-       if (_period >= 86400 * 365) formatted << std::fixed << std::setprecision (1) << (days / 365) << (padding ? "y  " : "y");
-  else if (_period >= 86400 * 90)  formatted << static_cast <int> (days / 30)       << (padding ? "mo " : "mo");
-  else if (_period >= 86400 * 14)  formatted << static_cast <int> (days / 7)        << (padding ? "w  " : "w");
-  else if (_period >= 86400)       formatted << static_cast <int> (days)            << (padding ? "d  " : "d");
-  else if (_period >= 3600)        formatted << static_cast <int> (_period / 3600)  << (padding ? "h  " : "h");
-  else if (_period >= 60)          formatted << static_cast <int> (_period / 60)    << "min";  // Longest suffix - no padding
-  else if (_period >= 1)           formatted << static_cast <int> (_period)         << (padding ? "s  " : "s");
-
-  return formatted.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Duration::days () const
-{
-  return _period / 86400;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Duration::hours () const
-{
-  return _period / 3600;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Duration::minutes () const
-{
-  return _period / 60;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Duration::seconds () const
-{
-  return _period;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Allow un-normalized values.
-void Duration::resolve ()
-{
-  if (! _period)
-  {
-    if (_weeks)
-      _period = (_weeks * 7 * 86400);
-    else
-      _period = (_year  * 365 * 86400) +
-                (_month  * 30 * 86400) +
-                (_day         * 86400) +
-                (_hours       *  3600) +
-                (_minutes     *    60) +
-                _seconds;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Duration.h b/src/libshared/src/Duration.h
deleted file mode 100644 (file)
index 5fb607a..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_DURATION
-#define INCLUDED_DURATION
-
-#include <Pig.h>
-#include <string>
-#include <time.h>
-
-class Duration
-{
-public:
-  static bool standaloneSecondsEnabled;
-
-  Duration ();
-  Duration (const std::string&);
-  Duration (time_t);
-  bool operator< (const Duration&);
-  bool operator> (const Duration&);
-  bool operator<= (const Duration&);
-  bool operator>= (const Duration&);
-  std::string toString () const;
-  time_t toTime_t () const;
-  bool parse (const std::string&, std::string::size_type&);
-  bool parse_seconds (Pig&);
-  bool parse_designated (Pig&);
-  bool parse_weeks (Pig&);
-  bool parse_units (Pig&);
-  const std::string format () const;
-  const std::string formatHours () const;
-  const std::string formatISO () const;
-  const std::string formatVague (bool padding = false) const;
-
-  int days () const;
-  int hours () const;
-  int minutes () const;
-  int seconds () const;
-
-private:
-  void clear ();
-  void resolve ();
-  std::string dump () const;
-
-public:
-  int _year      {0};
-  int _month     {0};
-  int _weeks     {0};
-  int _day       {0};
-  int _hours     {0};
-  int _minutes   {0};
-  int _seconds   {0};
-  time_t _period {0};
-};
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/FS.cpp b/src/libshared/src/FS.cpp
deleted file mode 100644 (file)
index 1036062..0000000
+++ /dev/null
@@ -1,1025 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <FS.h>
-#include <fstream>
-#include <glob.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <pwd.h>
-#include <cstdio>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <string.h>
-#include <shared.h>
-#include <format.h>
-
-#if defined SOLARIS || defined NETBSD || defined FREEBSD || !defined(__GLIBC__)
-#include <limits.h>
-#endif
-
-#if defined __APPLE__
-#include <sys/syslimits.h>
-#endif
-
-// Fixes build with musl libc.
-#ifndef GLOB_TILDE
-#define GLOB_TILDE 0
-#endif
-
-#ifndef GLOB_BRACE
-#define GLOB_BRACE 0
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-Path::Path ()
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Path::Path (const Path& other)
-{
-  if (this != &other)
-  {
-    _original = other._original;
-    _data     = other._data;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Path::Path (const std::string& in)
-{
-  _original = in;
-  _data     = expand (in);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Path& Path::operator= (const Path& other)
-{
-  if (this != &other)
-  {
-    this->_original = other._original;
-    this->_data     = other._data;
-  }
-
-  return *this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Path::operator== (const Path& other)
-{
-  return _data == other._data;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Path& Path::operator+= (const std::string& dir)
-{
-  _data += '/' + dir;
-  return *this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Path::operator std::string () const
-{
-  return _data;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Path::name () const
-{
-  if (_data.length ())
-  {
-    auto slash = _data.rfind ('/');
-    if (slash != std::string::npos)
-      return _data.substr (slash + 1, std::string::npos);
-  }
-
- return _data;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Path::parent () const
-{
-  if (_data.length ())
-  {
-    auto slash = _data.rfind ('/');
-    if (slash != std::string::npos)
-      return _data.substr (0, slash);
-  }
-
-  return "";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Path::extension () const
-{
-  if (_data.length ())
-  {
-    auto dot = _data.rfind ('.');
-    if (dot != std::string::npos)
-      return _data.substr (dot + 1, std::string::npos);
-  }
-
-  return "";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Path::exists () const
-{
-  return access (_data.c_str (), F_OK) ? false : true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Path::is_directory () const
-{
-  if (exists ())
-  {
-    struct stat s {};
-    if (stat (_data.c_str (), &s))
-      throw format ("stat error {1}: {2}", errno, strerror (errno));
-
-    return S_ISDIR (s.st_mode);
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Path::is_absolute () const
-{
-  if (_data.length () && _data[0] == '/')
-    return true;
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Path::is_link () const
-{
-  struct stat s {};
-  if (lstat (_data.c_str (), &s))
-    throw format ("lstat error {1}: {2}", errno, strerror (errno));
-
-  return S_ISLNK (s.st_mode);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// EACCES is a permissions problem which is exactly what this method is trying
-// to determine.
-bool Path::readable () const
-{
-  auto status = access (_data.c_str (), R_OK);
-  if (status == -1 && errno != EACCES)
-    throw format ("access error {1}: {2}", errno, strerror (errno));
-
-  return status ? false : true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// EACCES is a permissions problem which is exactly what this method is trying
-// to determine.
-bool Path::writable () const
-{
-  auto status = access (_data.c_str (), W_OK);
-  if (status == -1 && errno != EACCES)
-    throw format ("access error {1}: {2}", errno, strerror (errno));
-
-  return status ? false : true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// EACCES is a permissions problem which is exactly what this method is trying
-// to determine.
-bool Path::executable () const
-{
-  auto status = access (_data.c_str (), X_OK);
-  if (status == -1 && errno != EACCES)
-    throw format ("access error {1}: {2}", errno, strerror (errno));
-
-  return status ? false : true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Path::rename (const std::string& new_name)
-{
-  auto expanded = expand (new_name);
-  if (_data != expanded)
-  {
-    if (std::rename (_data.c_str (), expanded.c_str ()) == 0)
-    {
-      _data = expanded;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ~      --> /home/user
-// ~foo/x --> /home/foo/s
-// ~/x    --> /home/foo/x
-// ./x    --> $PWD/x
-// x      --> $PWD/x
-std::string Path::expand (const std::string& in)
-{
-  std::string copy = in;
-
-  auto tilde = copy.find ('~');
-  std::string::size_type slash;
-
-  if (tilde != std::string::npos)
-  {
-    const char *home = getenv("HOME");
-    if (home == nullptr)
-    {
-      struct passwd* pw = getpwuid (getuid ());
-      home = pw->pw_dir;
-    }
-
-    // Convert: ~ --> /home/user
-    if (copy.length () == 1)
-      copy = home;
-
-    // Convert: ~/x --> /home/user/x
-    else if (copy.length () > tilde + 1 &&
-             copy[tilde + 1] == '/')
-    {
-      copy.replace (tilde, 1, home);
-    }
-
-    // Convert: ~foo/x --> /home/foo/x
-    else if ((slash = copy.find ('/', tilde)) != std::string::npos)
-    {
-      std::string name = copy.substr (tilde + 1, slash - tilde - 1);
-      struct passwd* pw = getpwnam (name.c_str ());
-      if (pw)
-        copy.replace (tilde, slash - tilde, pw->pw_dir);
-    }
-  }
-
-  // Relative paths
-  else if (in.length () > 2 &&
-           in.substr (0, 2) == "./")
-  {
-    copy = Directory::cwd () + in.substr (1);
-  }
-  else if (in.length () > 1 &&
-           in[0] != '.' &&
-           in[0] != '/')
-  {
-    copy = Directory::cwd () + '/' + in;
-  }
-
-  return copy;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::vector <std::string> Path::glob (const std::string& pattern)
-{
-  std::vector <std::string> results;
-
-  glob_t g;
-#ifdef SOLARIS
-  if (!::glob (pattern.c_str (), GLOB_ERR, nullptr, &g))
-#else
-  if (!::glob (pattern.c_str (), GLOB_ERR | GLOB_BRACE | GLOB_TILDE, nullptr, &g))
-#endif
-    for (int i = 0; i < (int) g.gl_pathc; ++i)
-      results.push_back (g.gl_pathv[i]);
-
-  globfree (&g);
-  return results;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-File::File ()
-: Path::Path ()
-, _fh (nullptr)
-, _h (-1)
-, _locked (false)
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-File::File (const Path& other)
-: Path::Path (other)
-, _fh (nullptr)
-, _h (-1)
-, _locked (false)
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-File::File (const File& other)
-: Path::Path (other)
-, _fh (nullptr)
-, _h (-1)
-, _locked (false)
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-File::File (const std::string& in)
-: Path::Path (in)
-, _fh (nullptr)
-, _h (-1)
-, _locked (false)
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-File::~File ()
-{
-  if (_fh)
-    close ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-File& File::operator= (const File& other)
-{
-  if (this != &other)
-    Path::operator= (other);
-
-  _locked = false;
-  return *this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::create (int mode /* = 0640 */)
-{
-  if (open ())
-  {
-    fchmod (_h, mode);
-    close ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::remove () const
-{
-  return unlink (_data.c_str ()) == 0 ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string File::removeBOM (const std::string& input)
-{
-  if (input[0] && input[0] == '\xEF' &&
-      input[1] && input[1] == '\xBB' &&
-      input[2] && input[2] == '\xBF')
-    return input.substr (3);
-
-  return input;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::open ()
-{
-  if (_data != "")
-  {
-    if (! _fh)
-    {
-      bool already_exists = exists ();
-      if (already_exists)
-        if (!readable () || !writable ())
-          throw std::string (format ("Insufficient permissions for '{1}'.", _data));
-
-      _fh = fopen (_data.c_str (), (already_exists ? "r+" : "w+"));
-      if (_fh)
-      {
-        _h = fileno (_fh);
-        _locked = false;
-        return true;
-      }
-      else
-        throw format ("fopen error {1}: {2}", errno, strerror (errno));
-    }
-    else
-      return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void File::close ()
-{
-  if (_fh)
-  {
-    if (_locked)
-      unlock ();
-
-    if (fclose (_fh))
-      throw format ("fclose error {1}: {2}", errno, strerror (errno));
-
-    _fh = nullptr;
-    _h = -1;
-    _locked = false;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::lock ()
-{
-  _locked = false;
-  if (_fh && _h != -1)
-  {
-#ifdef FREEBSD
-                    // l_type   l_whence  l_start  l_len  l_pid  l_sysid
-    struct flock fl = {F_WRLCK, SEEK_SET, 0,       0,     0,     0 };
-#else
-                    // l_type   l_whence  l_start  l_len  l_pid
-    struct flock fl = {F_WRLCK, SEEK_SET, 0,       0,     0 };
-#endif
-    fl.l_pid = getpid ();
-    if (fcntl (_h, F_SETLKW, &fl) == 0)
-      _locked = true;
-  }
-
-  return _locked;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void File::unlock ()
-{
-  if (_locked)
-  {
-#ifdef FREEBSD
-                    // l_type   l_whence  l_start  l_len  l_pid  l_sysid
-    struct flock fl = {F_WRLCK, SEEK_SET, 0,       0,     0,     0 };
-#else
-                    // l_type   l_whence  l_start  l_len  l_pid
-    struct flock fl = {F_WRLCK, SEEK_SET, 0,       0,     0 };
-#endif
-    fl.l_pid = getpid ();
-
-    fcntl (_h, F_SETLK, &fl);
-    _locked = false;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Opens if necessary.
-void File::read (std::string& contents)
-{
-  contents = "";
-  contents.reserve (size ());
-
-  std::ifstream in (_data.c_str ());
-  if (in.good ())
-  {
-    bool first = true;
-    std::string line;
-    line.reserve (512 * 1024);
-    while (getline (in, line))
-    {
-      // Detect forbidden BOM on first line.
-      if (first)
-      {
-        line = File::removeBOM (line);
-        first = false;
-      }
-
-      contents += line + '\n';
-    }
-
-    in.close ();
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Opens if necessary.
-void File::read (std::vector <std::string>& contents)
-{
-  contents.clear ();
-
-  std::ifstream in (_data.c_str ());
-  if (in.good ())
-  {
-    bool first = true;
-    std::string line;
-    line.reserve (512 * 1024);
-    while (getline (in, line))
-    {
-      // Detect forbidden BOM on first line.
-      if (first)
-      {
-        line = File::removeBOM (line);
-        first = false;
-      }
-
-      contents.push_back (line);
-    }
-
-    in.close ();
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Opens if necessary.
-void File::append (const std::string& line)
-{
-  if (!_fh)
-    open ();
-
-  if (_fh)
-  {
-    fseek (_fh, 0, SEEK_END);
-
-    if (fputs (line.c_str (), _fh) == EOF)
-      throw format ("fputs error {1}: {2}", errno, strerror (errno));
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Opens if necessary.
-void File::append (const std::vector <std::string>& lines)
-{
-  if (!_fh)
-    open ();
-
-  if (_fh)
-  {
-    fseek (_fh, 0, SEEK_END);
-
-    for (auto& line : lines)
-      if (fputs (line.c_str (), _fh) == EOF)
-        throw format ("fputs error {1}: {2}", errno, strerror (errno));
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void File::write_raw (const std::string& line)
-{
-  if (!_fh)
-    open ();
-
-  if (_fh)
-    if (fputs (line.c_str (), _fh) == EOF)
-      throw format ("fputs error {1}: {2}", errno, strerror (errno));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void File::truncate ()
-{
-  if (!_fh)
-    open ();
-
-  if (_fh)
-    if (ftruncate (_h, 0))
-      throw format ("ftruncate error {1}: {2}", errno, strerror (errno));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//  S_IFMT          0170000  type of file
-//         S_IFIFO  0010000  named pipe (fifo)
-//         S_IFCHR  0020000  character special
-//         S_IFDIR  0040000  directory
-//         S_IFBLK  0060000  block special
-//         S_IFREG  0100000  regular
-//         S_IFLNK  0120000  symbolic link
-//         S_IFSOCK 0140000  socket
-//         S_IFWHT  0160000  whiteout
-//  S_ISUID         0004000  set user id on execution
-//  S_ISGID         0002000  set group id on execution
-//  S_ISVTX         0001000  save swapped text even after use
-//  S_IRUSR         0000400  read permission, owner
-//  S_IWUSR         0000200  write permission, owner
-//  S_IXUSR         0000100  execute/search permission, owner
-mode_t File::mode ()
-{
-  struct stat s;
-  if (stat (_data.c_str (), &s))
-    throw format ("stat error {1}: {2}", errno, strerror (errno));
-
-  return s.st_mode;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-size_t File::size () const
-{
-  struct stat s;
-  if (stat (_data.c_str (), &s))
-    throw format ("stat error {1}: {2}", errno, strerror (errno));
-
-  return s.st_size;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-time_t File::mtime () const
-{
-  struct stat s;
-  if (stat (_data.c_str (), &s))
-    throw format ("stat error {1}: {2}", errno, strerror (errno));
-
-  return s.st_mtime;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-time_t File::ctime () const
-{
-  struct stat s;
-  if (stat (_data.c_str (), &s))
-    throw format ("stat error {1}: {2}", errno, strerror (errno));
-
-  return s.st_ctime;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-time_t File::btime () const
-{
-  struct stat s;
-  if (stat (_data.c_str (), &s))
-    throw format ("stat error {1}: {2}", errno, strerror (errno));
-
-#ifdef HAVE_ST_BIRTHTIME
-  return s.st_birthtime;
-#else
-  return s.st_ctime;
-#endif
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::create (const std::string& name, int mode /* = 0640 */)
-{
-  std::string full_name = expand (name);
-  std::ofstream out (full_name.c_str ());
-  if (out.good ())
-  {
-    out.close ();
-    if (chmod (full_name.c_str (), mode))
-      throw format ("chmod error {1}: {2}", errno, strerror (errno));
-
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::read (const std::string& name, std::string& contents)
-{
-  contents = "";
-
-  std::ifstream in (name.c_str ());
-  if (in.good ())
-  {
-    bool first = true;
-    std::string line;
-    line.reserve (1024);
-    while (getline (in, line))
-    {
-      // Detect forbidden BOM on first line.
-      if (first)
-      {
-        line = File::removeBOM (line);
-        first = false;
-      }
-
-      contents += line + '\n';
-    }
-
-    in.close ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::read (const std::string& name, std::vector <std::string>& contents)
-{
-  contents.clear ();
-
-  std::ifstream in (name.c_str ());
-  if (in.good ())
-  {
-    bool first = true;
-    std::string line;
-    line.reserve (1024);
-    while (getline (in, line))
-    {
-      // Detect forbidden BOM on first line.
-      if (first)
-      {
-        line = File::removeBOM (line);
-        first = false;
-      }
-
-      contents.push_back (line);
-    }
-
-    in.close ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::write (const std::string& name, const std::string& contents)
-{
-  std::ofstream out (expand (name).c_str (),
-                     std::ios_base::out | std::ios_base::trunc);
-  if (out.good ())
-  {
-    out << contents;
-    out.close ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::write (
-  const std::string& name,
-  const std::vector <std::string>& lines,
-  bool addNewlines /* = true */)
-{
-  std::ofstream out (expand (name).c_str (),
-                     std::ios_base::out | std::ios_base::trunc);
-  if (out.good ())
-  {
-    for (auto& line : lines)
-    {
-      out << line;
-
-      if (addNewlines)
-        out << '\n';
-    }
-
-    out.close ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::remove (const std::string& name)
-{
-  return unlink (expand (name).c_str ()) == 0 ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::copy (const std::string& from, const std::string& to)
-{
-  // 'from' must exist.
-  if (! access (from.c_str (), F_OK))
-  {
-    std::ifstream src (from, std::ios::binary);
-    std::ofstream dst (to,   std::ios::binary);
-
-    dst << src.rdbuf ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool File::move (const std::string& from, const std::string& to)
-{
-  auto expanded = expand (to);
-  if (from != expanded)
-    if (std::rename (from.c_str (), to.c_str ()) == 0)
-      return true;
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Directory::Directory ()
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Directory::Directory (const Directory& other)
-: File::File (other)
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Directory::Directory (const File& other)
-: File::File (other)
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Directory::Directory (const Path& other)
-: File::File (other)
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Directory::Directory (const std::string& in)
-: File::File (in)
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-Directory& Directory::operator= (const Directory& other)
-{
-  if (this != &other)
-    File::operator= (other);
-
-  return *this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Directory::create (int mode /* = 0755 */)
-{
-  // No error handling because we want failure to be silent, somewhat emulating
-  // "mkdir -p".
-  return mkdir (_data.c_str (), mode) == 0 ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Directory::remove () const
-{
-  return remove_directory (_data);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Directory::remove_directory (const std::string& dir) const
-{
-  DIR* dp = opendir (dir.c_str ());
-  if (dp != nullptr)
-  {
-    struct dirent* de;
-    while ((de = readdir (dp)) != nullptr)
-    {
-      if (! strcmp (de->d_name, ".") ||
-          ! strcmp (de->d_name, ".."))
-        continue;
-
-#if defined (SOLARIS) || defined (HAIKU)
-      struct stat s;
-      if (lstat ((dir + '/' + de->d_name).c_str (), &s))
-        throw format ("lstat error {1}: {2}", errno, strerror (errno));
-
-      if (S_ISDIR (s.st_mode))
-        remove_directory (dir + '/' + de->d_name);
-      else
-        unlink ((dir + '/' + de->d_name).c_str ());
-#else
-      if (de->d_type == DT_UNKNOWN)
-      {
-        struct stat s;
-        if (lstat ((dir + '/' + de->d_name).c_str (), &s))
-          throw format ("lstat error {1}: {2}", errno, strerror (errno));
-
-        if (S_ISDIR (s.st_mode))
-          de->d_type = DT_DIR;
-      }
-      if (de->d_type == DT_DIR)
-        remove_directory (dir + '/' + de->d_name);
-      else
-        unlink ((dir + '/' + de->d_name).c_str ());
-#endif
-    }
-
-    closedir (dp);
-  }
-
-  return rmdir (dir.c_str ()) ? false : true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::vector <std::string> Directory::list ()
-{
-  std::vector <std::string> files;
-  list (_data, files, false);
-  return files;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::vector <std::string> Directory::listRecursive ()
-{
-  std::vector <std::string> files;
-  list (_data, files, true);
-  return files;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Directory::cwd ()
-{
-#ifdef HAVE_GET_CURRENT_DIR_NAME
-  char *buf = get_current_dir_name ();
-  if (buf == nullptr)
-    throw std::bad_alloc ();
-  std::string result (buf);
-  free (buf);
-  return result;
-#else
-  char buf[PATH_MAX];
-  getcwd (buf, PATH_MAX - 1);
-  return std::string (buf);
-#endif
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Directory::up ()
-{
-  if (_data == "/")
-    return false;
-
-  auto slash = _data.rfind ('/');
-  if (slash == 0)
-  {
-    _data = "/";  // Root dir should retain the slash.
-    return true;
-  }
-  else if (slash != std::string::npos)
-  {
-    _data = _data.substr (0, slash);
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Directory::cd () const
-{
-  return chdir (_data.c_str ()) == 0 ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Directory::list (
-  const std::string& base,
-  std::vector <std::string>& results,
-  bool recursive)
-{
-  DIR* dp = opendir (base.c_str ());
-  if (dp != nullptr)
-  {
-    struct dirent* de;
-    while ((de = readdir (dp)) != nullptr)
-    {
-      if (!strcmp (de->d_name, ".") ||
-          !strcmp (de->d_name, ".."))
-        continue;
-
-#if defined (SOLARIS) || defined (HAIKU)
-      struct stat s;
-      if (stat ((base + '/' + de->d_name).c_str (), &s))
-        throw format ("stat error {1}: {2}", errno, strerror (errno));
-
-      if (recursive && S_ISDIR (s.st_mode))
-        list (base + '/' + de->d_name, results, recursive);
-      else
-        results.push_back (base + '/' + de->d_name);
-#else
-      if (recursive && de->d_type == DT_UNKNOWN)
-      {
-        struct stat s;
-        if (lstat ((base + '/' + de->d_name).c_str (), &s))
-          throw format ("lstat error {1}: {2}", errno, strerror (errno));
-
-        if (S_ISDIR (s.st_mode))
-          de->d_type = DT_DIR;
-      }
-      if (recursive && de->d_type == DT_DIR)
-        list (base + '/' + de->d_name, results, recursive);
-      else
-        results.push_back (base + '/' + de->d_name);
-#endif
-    }
-
-    closedir (dp);
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/FS.h b/src/libshared/src/FS.h
deleted file mode 100644 (file)
index e2c4560..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_FS
-#define INCLUDED_FS
-
-#include <stdio.h>
-#include <string>
-#include <vector>
-#include <sys/stat.h>
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-class Path
-{
-public:
-  Path ();
-  explicit Path (const Path&);
-  Path (const std::string&);
-
-  Path& operator= (const Path&);
-  bool operator== (const Path&);
-  Path& operator+= (const std::string&);
-  operator std::string () const;
-
-  std::string name () const;
-  std::string parent () const;
-  std::string extension () const;
-  bool exists () const;
-  bool is_directory () const;
-  bool is_absolute () const;
-  bool is_link () const;
-  bool readable () const;
-  bool writable () const;
-  bool executable () const;
-  bool rename (const std::string&);
-
-  // Statics
-  static std::string expand (const std::string&);
-  static std::vector<std::string> glob (const std::string&);
-
-public:
-  std::string _original;
-  std::string _data;
-};
-
-class File : public Path
-{
-public:
-  File ();
-  explicit File (const Path&);
-  explicit File (const File&);
-  File (const std::string&);
-  virtual ~File ();
-
-  File& operator= (const File&);
-
-  virtual bool create (int mode = 0640);
-  virtual bool remove () const;
-
-  bool open ();
-  void close ();
-
-  bool lock ();
-  void unlock ();
-
-  void read (std::string&);
-  void read (std::vector <std::string>&);
-
-  void append (const std::string&);
-  void append (const std::vector <std::string>&);
-  void write_raw (const std::string&);
-
-  void truncate ();
-
-  virtual mode_t mode ();
-  virtual size_t size () const;
-  virtual time_t mtime () const;
-  virtual time_t ctime () const;
-  virtual time_t btime () const;
-
-  static bool create (const std::string&, int mode = 0640);
-  static bool read (const std::string&, std::string&);
-  static bool read (const std::string&, std::vector <std::string>&);
-  static bool write (const std::string&, const std::string&);
-  static bool write (const std::string&, const std::vector <std::string>&, bool addNewlines = true);
-  static bool remove (const std::string&);
-  static bool copy (const std::string&, const std::string&);
-  static bool move (const std::string&, const std::string&);
-  static std::string removeBOM (const std::string&);
-
-private:
-  FILE* _fh;
-  int   _h;
-  bool  _locked;
-};
-
-class Directory : public File
-{
-public:
-  Directory ();
-  explicit Directory (const Directory&);
-  explicit Directory (const File&);
-  explicit Directory (const Path&);
-  Directory (const std::string&);
-
-  Directory& operator= (const Directory&);
-
-  virtual bool create (int mode = 0755);
-  virtual bool remove () const;
-
-  std::vector <std::string> list ();
-  std::vector <std::string> listRecursive ();
-
-  static std::string cwd ();
-  bool up ();
-  bool cd () const;
-
-private:
-  void list (const std::string&, std::vector <std::string>&, bool);
-  bool remove_directory (const std::string&) const;
-};
-
-#endif
diff --git a/src/libshared/src/JSON.cpp b/src/libshared/src/JSON.cpp
deleted file mode 100644 (file)
index d9db45f..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <JSON.h>
-#include <shared.h>
-#include <format.h>
-#include <utf8.h>
-
-const char *json_encode[] = {
-  "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
-   "\\b",  "\\t",  "\\n", "\x0b",  "\\f",  "\\r", "\x0e", "\x0f",
-  "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
-  "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f",
-  "\x20", "\x21", "\\\"", "\x23", "\x24", "\x25", "\x26", "\x27",
-  "\x28", "\x29", "\x2a", "\x2b", "\x2c", "\x2d", "\x2e",  "\\/",
-  "\x30", "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37",
-  "\x38", "\x39", "\x3a", "\x3b", "\x3c", "\x3d", "\x3e", "\x3f",
-  "\x40", "\x41", "\x42", "\x43", "\x44", "\x45", "\x46", "\x47",
-  "\x48", "\x49", "\x4a", "\x4b", "\x4c", "\x4d", "\x4e", "\x4f",
-  "\x50", "\x51", "\x52", "\x53", "\x54", "\x55", "\x56", "\x57",
-  "\x58", "\x59", "\x5a", "\x5b", "\\\\", "\x5d", "\x5e", "\x5f",
-  "\x60", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67",
-  "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f",
-  "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77",
-  "\x78", "\x79", "\x7a", "\x7b", "\x7c", "\x7d", "\x7e", "\x7f",
-  "\x80", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87",
-  "\x88", "\x89", "\x8a", "\x8b", "\x8c", "\x8d", "\x8e", "\x8f",
-  "\x90", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97",
-  "\x98", "\x99", "\x9a", "\x9b", "\x9c", "\x9d", "\x9e", "\x9f",
-  "\xa0", "\xa1", "\xa2", "\xa3", "\xa4", "\xa5", "\xa6", "\xa7",
-  "\xa8", "\xa9", "\xaa", "\xab", "\xac", "\xad", "\xae", "\xaf",
-  "\xb0", "\xb1", "\xb2", "\xb3", "\xb4", "\xb5", "\xb6", "\xb7",
-  "\xb8", "\xb9", "\xba", "\xbb", "\xbc", "\xbd", "\xbe", "\xbf",
-  "\xc0", "\xc1", "\xc2", "\xc3", "\xc4", "\xc5", "\xc6", "\xc7",
-  "\xc8", "\xc9", "\xca", "\xcb", "\xcc", "\xcd", "\xce", "\xcf",
-  "\xd0", "\xd1", "\xd2", "\xd3", "\xd4", "\xd5", "\xd6", "\xd7",
-  "\xd8", "\xd9", "\xda", "\xdb", "\xdc", "\xdd", "\xde", "\xdf",
-  "\xe0", "\xe1", "\xe2", "\xe3", "\xe4", "\xe5", "\xe6", "\xe7",
-  "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef",
-  "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7",
-  "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff"
-};
-
-////////////////////////////////////////////////////////////////////////////////
-json::value* json::value::parse (Pig& pig)
-{
-  json::value* v;
-  if ((v = json::object::parse  (pig)) ||
-      (v = json::array::parse   (pig)) ||
-      (v = json::string::parse  (pig)) ||
-      (v = json::number::parse  (pig)) ||
-      (v = json::literal::parse (pig)))
-    return v;
-
-  return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::jtype json::value::type ()
-{
-  return json::j_value;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string json::value::dump () const
-{
-  return "<value>";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::string::string (const std::string& other)
-{
-  _data = other;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::string* json::string::parse (Pig& pig)
-{
-  std::string value;
-  if (pig.getQuoted ('"', value))
-  {
-    json::string* s = new json::string ();
-    s->_data = value;
-    return s;
-  }
-
-  return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::jtype json::string::type ()
-{
-  return json::j_string;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string json::string::dump () const
-{
-  return std::string ("\"") + _data + '"';
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::number* json::number::parse (Pig& pig)
-{
-  double d;
-  if (pig.getNumber (d))
-  {
-    json::number* s = new json::number ();
-    s->_dvalue = d;
-    return s;
-  }
-
-  return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::jtype json::number::type ()
-{
-  return json::j_number;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string json::number::dump () const
-{
-  return format (_dvalue);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::number::operator double () const
-{
-  return _dvalue;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::literal* json::literal::parse (Pig& pig)
-{
-  if (pig.skipLiteral ("null"))
-  {
-    json::literal* s = new json::literal ();
-    s->_lvalue = nullvalue;
-    return s;
-  }
-  else if (pig.skipLiteral ("false"))
-  {
-    json::literal* s = new json::literal ();
-    s->_lvalue = falsevalue;
-    return s;
-  }
-  else if (pig.skipLiteral ("true"))
-  {
-    json::literal* s = new json::literal ();
-    s->_lvalue = truevalue;
-    return s;
-  }
-
-  return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::jtype json::literal::type ()
-{
-  return json::j_literal;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string json::literal::dump () const
-{
-       if (_lvalue == nullvalue)  return "null";
-  else if (_lvalue == falsevalue) return "false";
-  else                            return "true";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::array::~array ()
-{
-  for (auto& i : _data)
-    delete i;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::array* json::array::parse (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  pig.skipWS ();
-  if (pig.skip ('['))
-  {
-    pig.skipWS ();
-
-    json::array* arr = new json::array ();
-
-    json::value* value;
-    if ((value = json::value::parse (pig)))
-    {
-      arr->_data.push_back (value);
-      value = NULL; // Not a leak.  Looks like a leak.
-      pig.skipWS ();
-      while (pig.skip (','))
-      {
-        pig.skipWS ();
-
-        if ((value = json::value::parse (pig)))
-        {
-          arr->_data.push_back (value);
-          pig.skipWS ();
-        }
-        else
-        {
-          delete arr;
-          throw format ("Error: missing value after ',' at position {1}", (int) pig.cursor ());
-        }
-      }
-    }
-
-    if (pig.skip (']'))
-      return arr;
-    else
-      throw format ("Error: missing ']' at position {1}", (int) pig.cursor ());
-
-    delete arr;
-  }
-
-  pig.restoreTo (checkpoint);
-  return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::jtype json::array::type ()
-{
-  return json::j_array;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string json::array::dump () const
-{
-  std::string output;
-  output += '[';
-
-  for (auto i = _data.begin (); i != _data.end (); ++i)
-  {
-    if (i != _data.begin ())
-      output += ',';
-
-    output += (*i)->dump ();
-  }
-
-  output += ']';
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::object::~object ()
-{
-  for (auto& i : _data)
-    delete i.second;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::object* json::object::parse (Pig& pig)
-{
-  auto checkpoint = pig.cursor ();
-
-  pig.skipWS ();
-  if (pig.skip ('{'))
-  {
-    pig.skipWS ();
-
-    json::object* obj = new json::object ();
-
-    std::string name;
-    json::value* value;
-    if (json::object::parse_pair (pig, name, value))
-    {
-      obj->_data.insert (std::pair <std::string, json::value*> (name, value));
-      value = NULL; // Not a leak.  Looks like a leak.
-
-      pig.skipWS ();
-      while (pig.skip (','))
-      {
-        pig.skipWS ();
-
-        if (json::object::parse_pair (pig, name, value))
-        {
-          obj->_data.insert (std::pair <std::string, json::value*> (name, value));
-          pig.skipWS ();
-        }
-        else
-        {
-          delete obj;
-          throw format ("Error: missing value after ',' at position {1}", (int) pig.cursor ());
-        }
-      }
-    }
-
-    if (pig.skip ('}'))
-      return obj;
-    else
-      throw format ("Error: missing '}' at position {1}", (int) pig.cursor ());
-
-    delete obj;
-  }
-
-  pig.restoreTo (checkpoint);
-  return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool json::object::parse_pair (
-  Pig& pig,
-  std::string& name,
-  json::value*& val)
-{
-  auto checkpoint = pig.cursor ();
-
-  if (pig.getQuoted ('"', name))
-  {
-    pig.skipWS ();
-    if (pig.skip (':'))
-    {
-      pig.skipWS ();
-      if ((val = json::value::parse (pig)))
-        return true;
-      else
-        throw format ("Error: missing value at position {1}", (int) pig.cursor ());
-    }
-    else
-      throw format ("Error: missing ':' at position {1}", (int) pig.cursor ());
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::jtype json::object::type ()
-{
-  return json::j_object;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string json::object::dump () const
-{
-  std::string output;
-  output += '{';
-
-  for (auto i = _data.begin (); i != _data.end (); ++i)
-  {
-    if (i != _data.begin ())
-      output += ',';
-
-    output += '"' + i->first + "\":";
-    output += i->second->dump ();
-  }
-
-  output += '}';
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-json::value* json::parse (const std::string& input)
-{
-  json::value* root = NULL;
-
-  Pig n (input);
-  n.skipWS ();
-
-       if (n.peek () == '{') root = json::object::parse (n);
-  else if (n.peek () == '[') root = json::array::parse (n);
-  else
-    throw format ("Error: expected '{' or '[' at position {1}", (int) n.cursor ());
-
-  // Check for end condition.
-  n.skipWS ();
-  if (!n.eos ())
-  {
-    delete root;
-    throw format ("Error: extra characters found at position {1}", (int) n.cursor ());
-  }
-
-  return root;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string json::encode (const std::string& input)
-{
-  std::string output;
-  output.reserve ((input.size () * 6) / 5);  // 20% increase.
-
-  auto last = input.begin ();
-  for (auto i = input.begin (); i != input.end (); ++i)
-  {
-    switch (*i)
-    {
-    // Simple translations.
-    case  '"':
-    case '\\':
-    case  '/':
-    case '\b':
-    case '\f':
-    case '\n':
-    case '\r':
-    case '\t':
-      output.append (last, i);
-      output += json_encode[(unsigned char)(*i)];
-      last = i + 1;
-
-    // Default NOP.
-    }
-  }
-
-  output.append (last, input.end ());
-
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string json::decode (const std::string& input)
-{
-  std::string output;
-  output.reserve (input.size ());  // Same size.
-
-  size_t pos = 0;
-
-  while (pos < input.length ())
-  {
-    if (input[pos] == '\\')
-    {
-      ++pos;
-      switch (input[pos])
-      {
-        // Simple translations.
-        case '"':  output += '"';  break;
-        case '\\': output += '\\'; break;
-        case '/':  output += '/';  break;
-        case 'b':  output += '\b'; break;
-        case 'f':  output += '\f'; break;
-        case 'n':  output += '\n'; break;
-        case 'r':  output += '\r'; break;
-        case 't':  output += '\t'; break;
-
-        // Compose a UTF8 unicode character.
-        case 'u':
-          output += utf8_character (utf8_codepoint (input.substr (++pos)));
-          pos += 3;
-          break;
-
-        // If it is an unrecognized sequence, do nothing.
-        default:
-          output += '\\';
-          output += input[pos];
-          break;
-      }
-      ++pos;
-    }
-    else
-    {
-      size_t next_backslash = input.find ('\\', pos);
-      output.append (input, pos, next_backslash - pos);
-      pos = next_backslash;
-    }
-  }
-
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/JSON.h b/src/libshared/src/JSON.h
deleted file mode 100644 (file)
index 7a7465e..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_JSON
-#define INCLUDED_JSON
-
-#include <map>
-#include <vector>
-#include <string>
-#include <Pig.h>
-
-namespace json
-{
-  enum jtype
-  {
-    j_value,    // 0
-    j_object,   // 1
-    j_array,    // 2
-    j_string,   // 3
-    j_number,   // 4
-    j_literal   // 5
-  };
-
-  class value
-  {
-  public:
-    value () {}
-    virtual ~value () {}
-    static value* parse (Pig&);
-    virtual jtype type ();
-    virtual std::string dump () const;
-  };
-
-  class string : public value
-  {
-  public:
-    string () {}
-    string (const std::string&);
-    ~string () {}
-    static string* parse (Pig&);
-    jtype type ();
-    std::string dump () const;
-
-  public:
-    std::string _data;
-  };
-
-  class number : public value
-  {
-  public:
-    number () : _dvalue (0.0) {}
-    ~number () {}
-    static number* parse (Pig&);
-    jtype type ();
-    std::string dump () const;
-    operator double () const;
-
-  public:
-    double _dvalue;
-  };
-
-  class literal : public value
-  {
-  public:
-    literal () : _lvalue (none) {}
-    ~literal () {}
-    static literal* parse (Pig&);
-    jtype type ();
-    std::string dump () const;
-
-  public:
-    enum literal_value {none, nullvalue, falsevalue, truevalue};
-    literal_value _lvalue;
-  };
-
-  class array : public value
-  {
-  public:
-    array () {}
-    ~array ();
-    static array* parse (Pig&);
-    jtype type ();
-    std::string dump () const;
-
-  public:
-    std::vector <value*> _data;
-  };
-
-  class object : public value
-  {
-  public:
-    object () {}
-    ~object ();
-    static object* parse (Pig&);
-    static bool parse_pair (Pig&, std::string&, value*&);
-    jtype type ();
-    std::string dump () const;
-
-  public:
-    std::map <std::string, value*> _data;
-  };
-
-  // Parser entry point.
-  value* parse (const std::string&);
-
-  // Encode/decode for JSON entities.
-  std::string encode (const std::string&);
-  std::string decode (const std::string&);
-
-  class SAX
-  {
-  public:
-    class Sink
-    {
-    public:
-      virtual void eventDocStart () {}
-      virtual void eventDocEnd () {}
-      virtual void eventObjectStart () {}
-      virtual void eventObjectEnd (int) {}
-      virtual void eventArrayStart () {}
-      virtual void eventArrayEnd (int) {}
-      virtual void eventName (const std::string&) {}
-      virtual void eventValueNull () {}
-      virtual void eventValueBool (bool) {}
-      virtual void eventValueInt (int64_t) {}
-      virtual void eventValueUint (uint64_t) {}
-      virtual void eventValueDouble (double) {}
-      virtual void eventValueString (const std::string&) {}
-    };
-
-    bool parse (const std::string&, json::SAX::Sink&);
-
-  private:
-    void ignoreWhitespace (const std::string&, std::string::size_type&);
-    bool isObject         (const std::string&, std::string::size_type&, SAX::Sink&);
-    bool isArray          (const std::string&, std::string::size_type&, SAX::Sink&);
-    bool isPair           (const std::string&, std::string::size_type&, SAX::Sink&);
-    bool isValue          (const std::string&, std::string::size_type&, SAX::Sink&);
-    bool isKey            (const std::string&, std::string::size_type&, SAX::Sink&);
-    bool isString         (const std::string&, std::string::size_type&, SAX::Sink&);
-    bool isStringValue    (const std::string&, std::string::size_type&, std::string&);
-    bool isNumber         (const std::string&, std::string::size_type&, SAX::Sink&);
-    bool isInt            (const std::string&, std::string::size_type&, std::string&);
-    bool isFrac           (const std::string&, std::string::size_type&, std::string&);
-    bool isDigits         (const std::string&, std::string::size_type&);
-    bool isDecDigit       (int);
-    bool isHexDigit       (int);
-    int  hexToInt         (int);
-    int  hexToInt         (int, int, int, int);
-    bool isExp            (const std::string&, std::string::size_type&, std::string&);
-    bool isE              (const std::string&, std::string::size_type&);
-    bool isBool           (const std::string&, std::string::size_type&, SAX::Sink&);
-    bool isNull           (const std::string&, std::string::size_type&, SAX::Sink&);
-    bool isLiteral        (const std::string&, char, std::string::size_type&);
-    void error            (const std::string&, std::string::size_type);
-  };
-}
-
-#endif
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Lexer.cpp b/src/libshared/src/Lexer.cpp
deleted file mode 100644 (file)
index 95512a8..0000000
+++ /dev/null
@@ -1,943 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2013 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Lexer.h>
-#include <Datetime.h>
-#include <Duration.h>
-#include <algorithm>
-#include <tuple>
-#include <ctype.h>
-#include <unicode.h>
-#include <utf8.h>
-
-static const std::string uuid_pattern = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
-static const unsigned int uuid_min_length = 8;
-
-std::string Lexer::dateFormat = "";
-
-////////////////////////////////////////////////////////////////////////////////
-Lexer::Lexer (const std::string& text)
-: _text (text)
-, _eos (text.size ())
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// When a Lexer object is constructed with a string, this method walks through
-// the stream of low-level tokens.
-bool Lexer::token (std::string& token, Lexer::Type& type)
-{
-  // Eat white space.
-  while (unicodeWhitespace (_text[_cursor]))
-    utf8_next_char (_text, _cursor);
-
-  // Terminate at EOS.
-  if (isEOS ())
-    return false;
-
-  if (isString    (token, type, "'\"") ||
-      isUUID      (token, type, true)  ||
-      isDate      (token, type)        ||
-      isDuration  (token, type)        ||
-      isURL       (token, type)        ||
-      isHexNumber (token, type)        ||
-      isNumber    (token, type)        ||
-      isPath      (token, type)        ||
-      isPattern   (token, type)        ||
-      isOperator  (token, type)        ||
-      isWord      (token, type))
-    return true;
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::vector <std::tuple <std::string, Lexer::Type>> Lexer::tokenize (const std::string& input)
-{
-  std::vector <std::tuple <std::string, Lexer::Type>> tokens;
-
-  std::string token;
-  Lexer::Type type;
-  Lexer lexer (input);
-  while (lexer.token (token, type))
-    tokens.push_back (std::make_tuple (token, type));
-
-  return tokens;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// No L10N - these are for internal purposes.
-const std::string Lexer::typeName (const Lexer::Type& type)
-{
-  switch (type)
-  {
-  case Lexer::Type::uuid:         return "uuid";
-  case Lexer::Type::number:       return "number";
-  case Lexer::Type::hex:          return "hex";
-  case Lexer::Type::string:       return "string";
-  case Lexer::Type::url:          return "url";
-  case Lexer::Type::path:         return "path";
-  case Lexer::Type::pattern:      return "pattern";
-  case Lexer::Type::op:           return "op";
-  case Lexer::Type::word:         return "word";
-  case Lexer::Type::date:         return "date";
-  case Lexer::Type::duration:     return "duration";
-  }
-
-  return "unknown";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::number
-//   \d+
-//   [ . \d+ ]
-//   [ e|E [ +|- ] \d+ [ . \d+ ] ]
-//   not followed by non-operator.
-bool Lexer::isNumber (std::string& token, Lexer::Type& type)
-{
-  std::size_t marker = _cursor;
-
-  if (unicodeLatinDigit (_text[marker]))
-  {
-    ++marker;
-    while (unicodeLatinDigit (_text[marker]))
-      utf8_next_char (_text, marker);
-
-    if (_text[marker] == '.')
-    {
-      ++marker;
-      if (unicodeLatinDigit (_text[marker]))
-      {
-        ++marker;
-        while (unicodeLatinDigit (_text[marker]))
-          utf8_next_char (_text, marker);
-      }
-    }
-
-    if (_text[marker] == 'e' ||
-        _text[marker] == 'E')
-    {
-      ++marker;
-
-      if (_text[marker] == '+' ||
-          _text[marker] == '-')
-        ++marker;
-
-      if (unicodeLatinDigit (_text[marker]))
-      {
-        ++marker;
-        while (unicodeLatinDigit (_text[marker]))
-          utf8_next_char (_text, marker);
-
-        if (_text[marker] == '.')
-        {
-          ++marker;
-          if (unicodeLatinDigit (_text[marker]))
-          {
-            ++marker;
-            while (unicodeLatinDigit (_text[marker]))
-              utf8_next_char (_text, marker);
-          }
-        }
-      }
-    }
-
-    // Lookahread: !<unicodeWhitespace> | !<isSingleCharOperator>
-    // If there is an immediately consecutive character, that is not an operator, fail.
-    if (_eos > marker &&
-        ! unicodeWhitespace (_text[marker]) &&
-        ! isSingleCharOperator (_text[marker]))
-      return false;
-
-    token = _text.substr (_cursor, marker - _cursor);
-    type = Lexer::Type::number;
-    _cursor = marker;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::number
-//   \d+
-bool Lexer::isInteger (std::string& token, Lexer::Type& type)
-{
-  std::size_t marker = _cursor;
-
-  if (unicodeLatinDigit (_text[marker]))
-  {
-    ++marker;
-    while (unicodeLatinDigit (_text[marker]))
-      utf8_next_char (_text, marker);
-
-    token = _text.substr (_cursor, marker - _cursor);
-    type = Lexer::Type::number;
-    _cursor = marker;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Lexer::isSingleCharOperator (int c)
-{
-  return c == '+' ||  // Addition
-         c == '-' ||  // Subtraction or unary minus = ambiguous
-         c == '*' ||  // Multiplication
-         c == '/' ||  // Diviѕion
-         c == '(' ||  // Precedence open parenthesis
-         c == ')' ||  // Precedence close parenthesis
-         c == '<' ||  // Less than
-         c == '>' ||  // Greater than
-         c == '^' ||  // Exponent
-         c == '!' ||  // Unary not
-         c == '%' ||  // Modulus
-         c == '=' ||  // Partial match
-         c == '~';    // Pattern match
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Lexer::isDoubleCharOperator (int c0, int c1, int c2)
-{
-  return (c0 == '=' && c1 == '=')                        ||
-         (c0 == '!' && c1 == '=')                        ||
-         (c0 == '<' && c1 == '=')                        ||
-         (c0 == '>' && c1 == '=')                        ||
-         (c0 == 'o' && c1 == 'r' && isBoundary (c1, c2)) ||
-         (c0 == '|' && c1 == '|')                        ||
-         (c0 == '&' && c1 == '&')                        ||
-         (c0 == '!' && c1 == '~');
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Lexer::isTripleCharOperator (int c0, int c1, int c2, int c3)
-{
-  return (c0 == 'a' && c1 == 'n' && c2 == 'd' && isBoundary (c2, c3)) ||
-         (c0 == 'x' && c1 == 'o' && c2 == 'r' && isBoundary (c2, c3)) ||
-         (c0 == '!' && c1 == '=' && c2 == '=');
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Lexer::isBoundary (int left, int right)
-{
-  // EOS
-  if (right == '\0')                                         return true;
-
-  // XOR
-  if (unicodeLatinAlpha (left) != unicodeLatinAlpha (right)) return true;
-  if (unicodeLatinDigit (left) != unicodeLatinDigit (right)) return true;
-  if (unicodeWhitespace (left) != unicodeWhitespace (right)) return true;
-
-  // OR
-  if (isPunctuation (left) || isPunctuation (right))         return true;
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Lexer::isHardBoundary (int left, int right)
-{
-  // EOS
-  if (right == '\0')
-    return true;
-
-  // FILTER operators that don't need to be surrounded by whitespace.
-  if (left == '(' ||
-      left == ')' ||
-      right == '(' ||
-      right == ')')
-    return true;
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Lexer::isPunctuation (int c)
-{
-  return isprint (c)   &&
-         c != ' '      &&
-         c != '@'      &&
-         c != '#'      &&
-         c != '$'      &&
-         c != '_'      &&
-         ! unicodeLatinDigit (c) &&
-         ! unicodeLatinAlpha (c);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Assumes that quotes is a string containing a non-trivial set of quote
-// characters.
-std::string Lexer::dequote (const std::string& input, const std::string& quotes)
-{
-  if (input.length () > 1)
-  {
-    int quote = input[0];
-    if (quotes.find (quote) != std::string::npos)
-    {
-      size_t len = input.length ();
-      if (quote == input[len - 1])
-        return input.substr (1, len - 2);
-    }
-  }
-
-  return input;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Detects characters in an input string that indicate quotes were required, or
-// escapes, to get them past the shell.
-bool Lexer::wasQuoted (const std::string& input)
-{
-  if (input.find_first_of (" \t()<>&~") != std::string::npos)
-    return true;
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Lexer::isEOS () const
-{
-  return _cursor >= _eos;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Converts '0'     -> 0
-//          '9'     -> 9
-//          'a'/'A' -> 10
-//          'f'/'F' -> 15
-int Lexer::hexToInt (int c)
-{
-       if (c >= '0' && c <= '9') return (c - '0');
-  else if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
-  else                           return (c - 'A' + 10);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Lexer::hexToInt (int c0, int c1)
-{
-  return (hexToInt (c0) << 4) + hexToInt (c1);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Lexer::hexToInt (int c0, int c1, int c2, int c3)
-{
-  return (hexToInt (c0) << 12) +
-         (hexToInt (c1) << 8)  +
-         (hexToInt (c2) << 4)  +
-          hexToInt (c3);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Lexer::trimLeft (const std::string& in, const std::string& t /*= " "*/)
-{
-  std::string::size_type ws = in.find_first_not_of (t);
-  if (ws > 0)
-  {
-    std::string out {in};
-    return out.erase (0, ws);
-  }
-
-  return in;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Lexer::trimRight (const std::string& in, const std::string& t /*= " "*/)
-{
-  std::string out {in};
-  return out.erase (in.find_last_not_of (t) + 1);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Lexer::trim (const std::string& in, const std::string& t /*= " "*/)
-{
-  return trimLeft (trimRight (in, t), t);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::string
-//   '|"
-//   [ U+XXXX | \uXXXX | \" | \' | \\ | \/ | \b | \f | \n | \r | \t | . ]
-//   '|"
-bool Lexer::isString (std::string& token, Lexer::Type& type, const std::string& quotes)
-{
-  if (_enableString)
-  {
-    std::size_t marker = _cursor;
-    if (readWord (_text, quotes, marker, token))
-    {
-      type = Lexer::Type::string;
-      _cursor = marker;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::date
-//   <Datetime> (followed by eos, WS, operator)
-bool Lexer::isDate (std::string& token, Lexer::Type& type)
-{
-  if (_enableDate)
-  {
-    // Try an ISO date parse.
-    std::size_t i = _cursor;
-    Datetime d;
-    if (d.parse (_text, i, Lexer::dateFormat) &&
-        (i >= _eos ||
-         unicodeWhitespace (_text[i]) ||
-         isSingleCharOperator (_text[i])))
-    {
-      type = Lexer::Type::date;
-      token = _text.substr (_cursor, i - _cursor);
-      _cursor = i;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::duration
-//   <Duration> (followed by eos, WS, operator)
-bool Lexer::isDuration (std::string& token, Lexer::Type& type)
-{
-  if (_enableDuration)
-  {
-    std::size_t marker = _cursor;
-
-    std::string extractedToken;
-    Lexer::Type extractedType;
-    if (isOperator(extractedToken, extractedType))
-    {
-      _cursor = marker;
-      return false;
-    }
-
-    marker = _cursor;
-    Duration dur;
-    if (dur.parse (_text, marker) &&
-        (marker >= _eos ||
-         unicodeWhitespace (_text[marker]) ||
-         isSingleCharOperator (_text[marker])))
-    {
-      type = Lexer::Type::duration;
-      token = _text.substr (_cursor, marker - _cursor);
-      _cursor = marker;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::uuid
-//   XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
-//   XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX
-//   XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
-//   XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX
-//   ...
-//   XXXXXXXX-XX
-//   XXXXXXXX-X
-//   XXXXXXXX-
-//   XXXXXXXX
-//   Followed only by EOS, whitespace, or single character operator.
-bool Lexer::isUUID (std::string& token, Lexer::Type& type, bool endBoundary)
-{
-  if (_enableUUID)
-  {
-    std::size_t marker = _cursor;
-
-    // Greedy.
-    std::size_t i = 0;
-    for (; i < 36 && marker + i < _eos; i++)
-    {
-      if (uuid_pattern[i] == 'x')
-      {
-        if (! unicodeHexDigit (_text[marker + i]))
-          break;
-      }
-      else if (uuid_pattern[i] != _text[marker + i])
-        break;
-    }
-
-    if (i >= uuid_min_length                   &&
-        (! endBoundary                         ||
-         ! _text[marker + i]                   ||
-         unicodeWhitespace (_text[marker + i]) ||
-         isSingleCharOperator (_text[marker + i])))
-    {
-      token = _text.substr (_cursor, i);
-      type = Lexer::Type::uuid;
-      _cursor += i;
-      return true;
-    }
-
-  }
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::hex
-//   0xX+
-bool Lexer::isHexNumber (std::string& token, Lexer::Type& type)
-{
-  if (_enableHexNumber)
-  {
-    std::size_t marker = _cursor;
-
-    if (_eos - marker >= 3 &&
-        _text[marker + 0] == '0' &&
-        _text[marker + 1] == 'x')
-    {
-      marker += 2;
-
-      while (unicodeHexDigit (_text[marker]))
-        ++marker;
-
-      if (marker - _cursor > 2)
-      {
-        token = _text.substr (_cursor, marker - _cursor);
-        type = Lexer::Type::hex;
-        _cursor = marker;
-        return true;
-      }
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::word
-//   [^\s]+
-bool Lexer::isWord (std::string& token, Lexer::Type& type)
-{
-  if (_enableWord)
-  {
-    std::size_t marker = _cursor;
-
-    while (_text[marker] &&
-           ! unicodeWhitespace (_text[marker]) &&
-           (! _enableOperator || ! isSingleCharOperator (_text[marker])))
-      utf8_next_char (_text, marker);
-
-    if (marker > _cursor)
-    {
-      token = _text.substr (_cursor, marker - _cursor);
-      type = Lexer::Type::word;
-      _cursor = marker;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::url
-//   http [s] :// ...
-bool Lexer::isURL (std::string& token, Lexer::Type& type)
-{
-  if (_enableURL)
-  {
-    std::size_t marker = _cursor;
-
-    if (_eos - _cursor > 9 &&    // length 'https://*'
-        (_text[marker + 0] == 'h' || _text[marker + 0] == 'H') &&
-        (_text[marker + 1] == 't' || _text[marker + 1] == 'T') &&
-        (_text[marker + 2] == 't' || _text[marker + 2] == 'T') &&
-        (_text[marker + 3] == 'p' || _text[marker + 3] == 'P'))
-    {
-      marker += 4;
-      if (_text[marker + 0] == 's' || _text[marker + 0] == 'S')
-        ++marker;
-
-      if (_text[marker + 0] == ':' &&
-          _text[marker + 1] == '/' &&
-          _text[marker + 2] == '/')
-      {
-        marker += 3;
-
-        while (marker < _eos &&
-               ! unicodeWhitespace (_text[marker]))
-          utf8_next_char (_text, marker);
-
-        token = _text.substr (_cursor, marker - _cursor);
-        type = Lexer::Type::url;
-        _cursor = marker;
-        return true;
-      }
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::path
-//   ( / <non-slash, non-whitespace> )+
-bool Lexer::isPath (std::string& token, Lexer::Type& type)
-{
-  if (_enablePath)
-  {
-    std::size_t marker = _cursor;
-    int slashCount = 0;
-
-    while (1)
-    {
-      if (_text[marker] == '/')
-      {
-        ++marker;
-        ++slashCount;
-      }
-      else
-        break;
-
-      if (_text[marker] &&
-          ! unicodeWhitespace (_text[marker]) &&
-          _text[marker] != '/')
-      {
-        utf8_next_char (_text, marker);
-        while (_text[marker] &&
-               ! unicodeWhitespace (_text[marker]) &&
-               _text[marker] != '/')
-          utf8_next_char (_text, marker);
-      }
-      else
-        break;
-    }
-
-    if (marker > _cursor &&
-        slashCount > 3)
-    {
-      type = Lexer::Type::path;
-      token = _text.substr (_cursor, marker - _cursor);
-      _cursor = marker;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::pattern
-//   / <unquoted-string> /  <EOS> | <unicodeWhitespace>
-bool Lexer::isPattern (std::string& token, Lexer::Type& type)
-{
-  if (_enablePattern)
-  {
-    std::size_t marker = _cursor;
-
-    std::string word;
-    if (readWord (_text, "/", _cursor, word) &&
-        (isEOS () ||
-         unicodeWhitespace (_text[_cursor])))
-    {
-      token = _text.substr (marker, _cursor - marker);
-      type = Lexer::Type::pattern;
-      return true;
-    }
-
-    _cursor = marker;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Lexer::Type::op
-//   _hastag_ | _notag | _neg_ | _pos_ |
-//   <isTripleCharOperator> |
-//   <isDoubleCharOperator> |
-//   <isSingleCharOperator> |
-bool Lexer::isOperator (std::string& token, Lexer::Type& type)
-{
-  if (_enableOperator)
-  {
-    std::size_t marker = _cursor;
-
-    if (_eos - marker >= 8 && _text.substr (marker, 8) == "_hastag_")
-    {
-      marker += 8;
-      type = Lexer::Type::op;
-      token = _text.substr (_cursor, marker - _cursor);
-      _cursor = marker;
-      return true;
-    }
-
-    else if (_eos - marker >= 7 && _text.substr (marker, 7) == "_notag_")
-    {
-      marker += 7;
-      type = Lexer::Type::op;
-      token = _text.substr (_cursor, marker - _cursor);
-      _cursor = marker;
-      return true;
-    }
-
-    else if (_eos - marker >= 5 && _text.substr (marker, 5) == "_neg_")
-    {
-      marker += 5;
-      type = Lexer::Type::op;
-      token = _text.substr (_cursor, marker - _cursor);
-      _cursor = marker;
-      return true;
-    }
-
-    else if (_eos - marker >= 5 && _text.substr (marker, 5) == "_pos_")
-    {
-      marker += 5;
-      type = Lexer::Type::op;
-      token = _text.substr (_cursor, marker - _cursor);
-      _cursor = marker;
-      return true;
-    }
-
-    else if (_eos - marker >= 3 &&
-        isTripleCharOperator (_text[marker], _text[marker + 1], _text[marker + 2], _text[marker + 3]))
-    {
-      marker += 3;
-      type = Lexer::Type::op;
-      token = _text.substr (_cursor, marker - _cursor);
-      _cursor = marker;
-      return true;
-    }
-
-    else if (_eos - marker >= 2 &&
-        isDoubleCharOperator (_text[marker], _text[marker + 1], _text[marker + 2]))
-    {
-      marker += 2;
-      type = Lexer::Type::op;
-      token = _text.substr (_cursor, marker - _cursor);
-      _cursor = marker;
-      return true;
-    }
-
-    else if (isSingleCharOperator (_text[marker]))
-    {
-      token = _text[marker];
-      type = Lexer::Type::op;
-      _cursor = ++marker;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Static
-std::string Lexer::typeToString (Lexer::Type type)
-{
-       if (type == Lexer::Type::string)       return std::string ("\033[38;5;7m\033[48;5;3m")    + "string"       + "\033[0m";
-  else if (type == Lexer::Type::uuid)         return std::string ("\033[38;5;7m\033[48;5;10m")   + "uuid"         + "\033[0m";
-  else if (type == Lexer::Type::hex)          return std::string ("\033[38;5;7m\033[48;5;14m")   + "hex"          + "\033[0m";
-  else if (type == Lexer::Type::number)       return std::string ("\033[38;5;7m\033[48;5;6m")    + "number"       + "\033[0m";
-  else if (type == Lexer::Type::url)          return std::string ("\033[38;5;7m\033[48;5;4m")    + "url"          + "\033[0m";
-  else if (type == Lexer::Type::path)         return std::string ("\033[37;102m")                + "path"         + "\033[0m";
-  else if (type == Lexer::Type::pattern)      return std::string ("\033[37;42m")                 + "pattern"      + "\033[0m";
-  else if (type == Lexer::Type::op)           return std::string ("\033[38;5;7m\033[48;5;203m")  + "op"           + "\033[0m";
-  else if (type == Lexer::Type::word)         return std::string ("\033[38;5;15m\033[48;5;236m") + "word"         + "\033[0m";
-  else if (type == Lexer::Type::date)         return std::string ("\033[38;5;15m\033[48;5;34m")  + "date"         + "\033[0m";
-  else if (type == Lexer::Type::duration)     return std::string ("\033[38;5;15m\033[48;5;34m")  + "duration"     + "\033[0m";
-  else                                        return std::string ("\033[37;41m")                 + "unknown"      + "\033[0m";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Full implementation of a quoted word.  Includes:
-//   '\''
-//   '"'
-//   "'"
-//   "\""
-//   'one two'
-// Result includes the quotes.
-bool Lexer::readWord (
-  const std::string& text,
-  const std::string& quotes,
-  std::string::size_type& cursor,
-  std::string& word)
-{
-  if (quotes.find (text[cursor]) == std::string::npos)
-    return false;
-
-  std::string::size_type eos = text.length ();
-  int quote = text[cursor++];
-  word = quote;
-
-  int c;
-  while ((c = text[cursor]))
-  {
-    // Quoted word ends on a quote.
-    if (quote && quote == c)
-    {
-      word += utf8_character (utf8_next_char (text, cursor));
-      break;
-    }
-
-    // Unicode U+XXXX or \uXXXX codepoint.
-    else if (eos - cursor >= 6 &&
-             ((text[cursor + 0] == 'U'  && text[cursor + 1] == '+') ||
-              (text[cursor + 0] == '\\' && text[cursor + 1] == 'u')) &&
-             unicodeHexDigit (text[cursor + 2]) &&
-             unicodeHexDigit (text[cursor + 3]) &&
-             unicodeHexDigit (text[cursor + 4]) &&
-             unicodeHexDigit (text[cursor + 5]))
-    {
-      word += utf8_character (
-                hexToInt (
-                  text[cursor + 2],
-                  text[cursor + 3],
-                  text[cursor + 4],
-                  text[cursor + 5]));
-      cursor += 6;
-    }
-
-    // An escaped thing.
-    else if (c == '\\')
-    {
-      c = text[++cursor];
-
-      switch (c)
-      {
-      case '"':  word += (char) 0x22; ++cursor; break;
-      case '\'': word += (char) 0x27; ++cursor; break;
-      case '\\': word += (char) 0x5C; ++cursor; break;
-      case 'b':  word += (char) 0x08; ++cursor; break;
-      case 'f':  word += (char) 0x0C; ++cursor; break;
-      case 'n':  word += (char) 0x0A; ++cursor; break;
-      case 'r':  word += (char) 0x0D; ++cursor; break;
-      case 't':  word += (char) 0x09; ++cursor; break;
-      case 'v':  word += (char) 0x0B; ++cursor; break;
-
-      // This pass-through default case means that anything can be escaped
-      // harmlessly. In particular 'quote' is included, if it not one of the
-      // above characters.
-      default:   word += (char) c;    ++cursor; break;
-      }
-    }
-
-    // Ordinary character.
-    else
-      word += utf8_character (utf8_next_char (text, cursor));
-  }
-
-  // Verify termination.
-  return word[0]                  == quote &&
-         word[word.length () - 1] == quote &&
-         word.length () >= 2;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Full implementation of an unquoted word.  Includes:
-//   one\ two
-//   abcU+0020def
-//   abc\u0020def
-//   a\tb
-//
-// Ends at:
-//   Lexer::isEOS
-//   unicodeWhitespace
-//   Lexer::isHardBoundary
-bool Lexer::readWord (
-  const std::string& text,
-  std::string::size_type& cursor,
-  std::string& word)
-{
-  std::string::size_type eos = text.length ();
-
-  word = "";
-  int c;
-  int prev = 0;
-  while ((c = text[cursor]))  // Handles EOS.
-  {
-    // Unquoted word ends on white space.
-    if (unicodeWhitespace (c))
-      break;
-
-    // Parentheses mostly.
-    if (prev && Lexer::isHardBoundary (prev, c))
-      break;
-
-    // Unicode U+XXXX or \uXXXX codepoint.
-    else if (eos - cursor >= 6 &&
-             ((text[cursor + 0] == 'U'  && text[cursor + 1] == '+') ||
-              (text[cursor + 0] == '\\' && text[cursor + 1] == 'u')) &&
-             unicodeHexDigit (text[cursor + 2]) &&
-             unicodeHexDigit (text[cursor + 3]) &&
-             unicodeHexDigit (text[cursor + 4]) &&
-             unicodeHexDigit (text[cursor + 5]))
-    {
-      word += utf8_character (
-                hexToInt (
-                  text[cursor + 2],
-                  text[cursor + 3],
-                  text[cursor + 4],
-                  text[cursor + 5]));
-      cursor += 6;
-    }
-
-    // An escaped thing.
-    else if (c == '\\')
-    {
-      c = text[++cursor];
-
-      switch (c)
-      {
-      case '"':  word += (char) 0x22; ++cursor; break;
-      case '\'': word += (char) 0x27; ++cursor; break;
-      case '\\': word += (char) 0x5C; ++cursor; break;
-      case 'b':  word += (char) 0x08; ++cursor; break;
-      case 'f':  word += (char) 0x0C; ++cursor; break;
-      case 'n':  word += (char) 0x0A; ++cursor; break;
-      case 'r':  word += (char) 0x0D; ++cursor; break;
-      case 't':  word += (char) 0x09; ++cursor; break;
-      case 'v':  word += (char) 0x0B; ++cursor; break;
-
-      // This pass-through default case means that anything can be escaped
-      // harmlessly. In particular 'quote' is included, if it not one of the
-      // above characters.
-      default:   word += (char) c;    ++cursor; break;
-      }
-    }
-
-    // Ordinary character.
-    else
-      word += utf8_character (utf8_next_char (text, cursor));
-
-    prev = c;
-  }
-
-  return word.length () > 0 ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Lexer.h b/src/libshared/src/Lexer.h
deleted file mode 100644 (file)
index 03b5166..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2013 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_LEXER
-#define INCLUDED_LEXER
-
-#include <string>
-#include <map>
-#include <vector>
-#include <tuple>
-#include <cstddef>
-
-class Lexer
-{
-public:
-  // These are overridable.
-  static std::string dateFormat;
-
-  enum class Type { uuid, number, hex,
-                    string,
-                    url,
-                    path,
-                    pattern,
-                    op,
-                    word,
-                    date, duration };
-
-  explicit Lexer (const std::string&);
-  bool token (std::string&, Lexer::Type&);
-  static std::string typeToString (Lexer::Type);
-
-  // Static helpers.
-  static std::vector <std::tuple <std::string, Lexer::Type>> tokenize (const std::string&);
-  static const std::string typeName          (const Lexer::Type&);
-  static bool isSingleCharOperator           (int);
-  static bool isDoubleCharOperator           (int, int, int);
-  static bool isTripleCharOperator           (int, int, int, int);
-  static bool isBoundary                     (int, int);
-  static bool isHardBoundary                 (int, int);
-  static bool isPunctuation                  (int);
-  static bool wasQuoted                      (const std::string&);
-  static bool readWord                       (const std::string&, const std::string&, std::string::size_type&, std::string&);
-  static bool readWord                       (const std::string&, std::string::size_type&, std::string&);
-  static int hexToInt                        (int);
-  static int hexToInt                        (int, int);
-  static int hexToInt                        (int, int, int, int);
-  static std::string trimLeft                (const std::string& in, const std::string& t = " ");
-  static std::string trimRight               (const std::string& in, const std::string& t = " ");
-  static std::string trim                    (const std::string& in, const std::string& t = " ");
-  static std::string dequote                 (const std::string&, const std::string& quotes = "'\"");
-
-  // Stream Classifiers.
-  bool isEOS          () const;
-  bool isString       (std::string&, Lexer::Type&, const std::string&);
-  bool isDate         (std::string&, Lexer::Type&);
-  bool isDuration     (std::string&, Lexer::Type&);
-  bool isUUID         (std::string&, Lexer::Type&, bool);
-  bool isNumber       (std::string&, Lexer::Type&);
-  bool isInteger      (std::string&, Lexer::Type&);
-  bool isHexNumber    (std::string&, Lexer::Type&);
-  bool isURL          (std::string&, Lexer::Type&);
-  bool isPath         (std::string&, Lexer::Type&);
-  bool isPattern      (std::string&, Lexer::Type&);
-  bool isOperator     (std::string&, Lexer::Type&);
-  bool isWord         (std::string&, Lexer::Type&);
-
-  // Disabling features.
-  void noString ()    { _enableString    = false; }
-  void noDate ()      { _enableDate      = false; }
-  void noDuration ()  { _enableDuration  = false; }
-  void noUUID ()      { _enableUUID      = false; }
-  void noHexNumber () { _enableHexNumber = false; }
-  void noWord ()      { _enableWord      = false; }
-  void noURL ()       { _enableURL       = false; }
-  void noPath ()      { _enablePath      = false; }
-  void noPattern ()   { _enablePattern   = false; }
-  void noOperator ()  { _enableOperator  = false; }
-
-private:
-  std::string _text          {};
-  std::size_t _cursor        {0};
-  std::size_t _eos           {0};
-
-  bool        _enableString    {true};
-  bool        _enableDate      {true};
-  bool        _enableDuration  {true};
-  bool        _enableUUID      {true};
-  bool        _enableHexNumber {true};
-  bool        _enableWord      {true};
-  bool        _enableURL       {true};
-  bool        _enablePath      {true};
-  bool        _enablePattern   {true};
-  bool        _enableOperator  {true};
-};
-
-#endif
diff --git a/src/libshared/src/Log.cpp b/src/libshared/src/Log.cpp
deleted file mode 100644 (file)
index a77d600..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Log.h>
-#include <shared.h>
-#include <format.h>
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Log::file () const
-{
-  return _name;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Log::file (const std::string& name)
-{
-  _name = name;
-  _file = File (_name);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Log::ignore (const std::string& category)
-{
-  _ignore.insert (category);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Log::write (const std::string& line)
-{
-  write ("info", line);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Log::write (const std::string& category, const std::string& line)
-{
-  // Determine if this category is in the ignore list.
-  if (_ignore.find (category) != _ignore.end ())
-    return;
-
-  if (line != "")
-  {
-    // If line contains newlines, split it into separate lines and log each one.
-    if (line.find ('\n') != std::string::npos)
-    {
-      for (const auto& single : split (line, '\n'))
-        write (category, single);
-
-      return;
-    }
-
-    // Single line.
-    if (line == _prior)
-    {
-      ++_repetition;
-    }
-    else
-    {
-      _prior = line;
-
-      // Catch up by writing out the backlog.
-      if (_name != "" && _backlog.size ())
-      {
-        for (const auto& line : _backlog)
-          _file.append (line); 
-
-        _backlog.clear ();
-      }
-
-      if (_repetition)
-      {
-        std::string message = Datetime ().toISO ()
-                            + ' ' + PACKAGE_VERSION
-                            + ' ' + category
-                            + ' ' + format ("(Repeated {1} times)", _repetition)
-                            + '\n';
-
-        if (_name != "")
-          _file.append (message);
-        else
-          _backlog.push_back (message);
-
-        _repetition = 0;
-      }
-
-      std::string message = Datetime ().toISO ()
-                          + ' ' + PACKAGE_VERSION
-                          + ' ' + category
-                          + ' ' + line
-                          + '\n';
-
-      if (_name != "")
-        _file.append (message);
-      else
-        _backlog.push_back (message);
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Log.h b/src/libshared/src/Log.h
deleted file mode 100644 (file)
index 06981ed..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_LOG
-#define INCLUDED_LOG
-
-#include <FS.h>
-#include <Datetime.h>
-#include <vector>
-#include <set>
-#include <string>
-#include <stdio.h>
-
-class Log
-{
-public:
-  std::string file () const;
-  void file (const std::string&);
-  void ignore (const std::string&);
-  void write (const std::string&);
-  void write (const std::string&, const std::string&);
-
-private:
-  std::string               _name       {};
-  std::vector <std::string> _backlog    {};
-  File                      _file       {};
-  std::string               _prior      {"none"};
-  int                       _repetition {0};
-  std::set <std::string>    _ignore     {};
-};
-
-#endif
-
diff --git a/src/libshared/src/Msg.cpp b/src/libshared/src/Msg.cpp
deleted file mode 100644 (file)
index 99664b9..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Msg.h>
-#include <shared.h>
-#include <format.h>
-
-////////////////////////////////////////////////////////////////////////////////
-void Msg::set (const std::string& name, int value)
-{
-  _header[name] = format (value);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Msg::set (const std::string& name, const std::string& value)
-{
-  _header[name] = value;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Msg::get (const std::string& name) const
-{
-  auto i = _header.find (name);
-  if (i != _header.end ())
-    return i->second;
-
-  return "";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Msg::setPayload (const std::string& payload)
-{
-  _payload = payload;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Msg::getPayload () const
-{
-  return _payload;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::vector <std::string> Msg::all () const
-{
-  std::vector <std::string> names;
-  for (auto& i : _header)
-    names.push_back (i.first);
-
-  return names;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Msg::serialize () const
-{
-  std::string output;
-  for (auto& i : _header)
-    output += i.first + ": " + i.second + '\n';
-
-  output += '\n' + _payload + '\n';
-
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Msg::parse (const std::string& input)
-{
-  _header.clear ();
-  _payload = "";
-
-  auto separator = input.find ("\n\n");
-  if (separator == std::string::npos)
-    throw std::string ("Malformed message");
-
-  // Parse header.
-  auto lines = split (input.substr (0, separator), '\n');
-  for (auto& i : lines)
-  {
-    auto delimiter = i.find (':');
-    if (delimiter == std::string::npos)
-        throw std::string ("Malformed message header '") + i + '\'';
-
-    _header[trim (i.substr (0, delimiter))] = trim (i.substr (delimiter + 1));
-  }
-
-  // Parse payload.
-  _payload = input.substr (separator + 2);
-
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Msg.h b/src/libshared/src/Msg.h
deleted file mode 100644 (file)
index 69ed2da..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_MSG
-#define INCLUDED_MSG
-
-#include <map>
-#include <vector>
-#include <string>
-
-class Msg
-{
-public:
-  void set (const std::string&, int);
-  void set (const std::string&, const std::string&);
-  std::string get (const std::string&) const;
-
-  void setPayload (const std::string&);
-  std::string getPayload () const;
-
-  std::vector <std::string> all () const;
-  std::string serialize () const;
-  bool parse (const std::string&);
-
-private:
-  std::map <std::string, std::string> _header {};
-  std::string _payload                        {""};
-};
-
-#endif
-
diff --git a/src/libshared/src/PEG.cpp b/src/libshared/src/PEG.cpp
deleted file mode 100644 (file)
index efa5f61..0000000
+++ /dev/null
@@ -1,436 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <PEG.h>
-#include <Lexer.h>
-#include <shared.h>
-#include <format.h>
-#include <iostream>
-
-////////////////////////////////////////////////////////////////////////////////
-std::string PEG::Token::dump () const
-{
-  std::stringstream out;
-  out << (_lookahead == Token::Lookahead::positive ? "\e[34m&\e[0m" :
-          _lookahead == Token::Lookahead::negative ? "\e[34m!\e[0m" : "")
-      << _token
-      << (_quantifier == Token::Quantifier::zero_or_one  ? "\e[34m?\e[0m" :
-          _quantifier == Token::Quantifier::one_or_more  ? "\e[34m+\e[0m" :
-          _quantifier == Token::Quantifier::zero_or_more ? "\e[34m*\e[0m" : "");
-
-  for (const auto& tag : _tags)
-    out << " \e[34m" << tag << "\e[0m";
-
-  return out.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void PEG::loadFromFile (File& file)
-{
-  if (! file.exists ())
-    throw format ("PEG file '{1}' not found.", file._data);
-
-  std::string contents;
-  file.read (contents);
-
-  // TODO Instead of simply reading a file, read a file and allow lines that
-  //      match /^include <path>$/ to represent nested files.
-
-  loadFromString (contents);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Load and parse PEG.
-//
-// Syntax:
-//   rule-name:  alternate1-token1 alternate1-token2
-//               alternate2-token1
-//
-// - Rules are aligned at left margin only, followed by colon.
-// - Productions are indented and never at left margin.
-// - Blank lines delineate rules.
-//
-// Details:
-// - String literals are always double-quoted.
-// - Character literals are alをays single-quoted.
-// - "*", "+" and "?" suffixes have POSIX wildcard semantics.
-//
-void PEG::loadFromString (const std::string& input)
-{
-  // This is a state machine.  Read each line.
-  std::string rule_name = "";
-  for (auto& line : loadImports (split (input, '\n')))
-  {
-    line = trim (line);
-
-    // Eliminate inline comments.
-    auto hash = line.find ('#');
-    if (hash != std::string::npos)
-    {
-      line.resize (hash);
-      line = trim (line);
-
-      if (line == "")
-        continue;
-    }
-    else
-    {
-      line = trim (line);
-    }
-
-    // Skip blank lines with no semantics.
-    if (line == "" and rule_name == "")
-      continue;
-
-    if (line != "")
-    {
-      int token_count = 0;
-
-      // Instantiate and configure the Lexer.
-      Lexer l (line);
-      l.noDate ();
-      l.noDuration ();
-      l.noUUID ();
-      l.noHexNumber ();
-      l.noURL ();
-      l.noPath ();
-      l.noPattern ();
-      l.noOperator ();
-
-      Lexer::Type type;
-      std::string token;
-      while (l.token (token, type))
-      {
-        ++token_count;
-
-        // Rule definitions end in a colon.
-        if (token.back () == ':')
-        {
-          // Capture the Rule_name.
-          rule_name = token.substr (0, token.size () - 1);
-
-          // If this is the first Rule, capture it as a starting point.
-          if (_start == "")
-            _start = rule_name;
-
-          _rules[rule_name] = PEG::Rule ();
-          token_count = 0;
-        }
-        // Production definition.
-        else
-        {
-          // If no Production was added yet, add one.
-          if (token_count <= 1)
-            _rules[rule_name].push_back (PEG::Production ());
-
-          // Decorate the token, if necessary.
-          std::string::size_type start = 0;
-          std::string::size_type end = token.length ();
-
-          auto q = Token::Quantifier::one;
-          auto l = Token::Lookahead::none;
-
-          if (token.back () == '?')
-          {
-            q = Token::Quantifier::zero_or_one;
-            --end;
-          }
-          else if (token.back () == '+')
-          {
-            q = Token::Quantifier::one_or_more;
-            --end;
-          }
-          else if (token.back () == '*')
-          {
-            q = Token::Quantifier::zero_or_more;
-            --end;
-          }
-
-          if (token.front () == '&')
-          {
-            l = Token::Lookahead::positive;
-            ++start;
-          }
-          else if (token.front () == '!')
-          {
-            l = Token::Lookahead::negative;
-            ++start;
-          }
-
-          PEG::Token t (token.substr (start, end - start));
-          t._quantifier = q;
-          t._lookahead = l;
-
-          if (type == Lexer::Type::string)
-          {
-            t.tag ("literal");
-            t.tag (token[0] == '\'' ? "character" : "string");
-          }
-          else if (t._token.front () == '<' and
-                   t._token.back ()  == '>')
-          {
-            t.tag ("intrinsic");
-
-            if (t._token.substr (0, 8) == "<entity:")
-              t.tag ("entity");
-
-            if (t._token.substr (0, 10) == "<external:")
-              t.tag ("external");
-          }
-
-          // Add the new Token to the most recent Production, of the current
-          // Rule.
-          _rules[rule_name].back ().push_back (t);
-        }
-      }
-    }
-
-    // A blank line in the input ends the current rule definition.
-    else
-      rule_name = "";
-  }
-
-  if (_debug)
-    std::cout << dump ();
-
-  // Validate the parsed grammar.
-  validate ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::map <std::string, PEG::Rule> PEG::syntax () const
-{
-  return _rules;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string PEG::firstRule () const
-{
-  return _start;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void PEG::debug ()
-{
-  ++_debug;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void PEG::strict (bool value)
-{
-  _strict = value;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string PEG::dump () const
-{
-  std::stringstream out;
-  out << "PEG\n";
-
-  // Show the import files, if any.
-  if (_imports.size ())
-  {
-    for (const auto& import : _imports)
-      out << "  import " << import << '\n';
-    out << '\n';
-  }
-
-  // Determine longest rule name, for display alignment.
-  size_t longest = 0;
-  for (const auto& rule : _rules)
-    if (rule.first.length () > longest)
-      longest = rule.first.length ();
-
-  for (const auto& rule : _rules)
-  {
-    // Indicate the start Rule.
-    out << "  "
-        << (rule.first == _start ? "▶" : " ")
-        << ' '
-        << rule.first
-        << ':'
-        << std::string (1 + longest - rule.first.length (), ' ');
-
-    int count = 0;
-    for (const auto& production : rule.second)
-    {
-      if (count)
-        out << std::string (6 + longest, ' ');
-
-      for (const auto& token : production)
-        out << token.dump () << ' ';
-
-      out << "\n";
-      ++count;
-    }
-
-    out << "\n";
-  }
-
-  return out.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::vector <std::string> PEG::loadImports (const std::vector <std::string>& lines)
-{
-  std::vector <std::string> resolved;
-
-  for (auto& line : lines)
-  {
-    auto copy = trim (line);
-
-    auto hash = copy.find ('#');
-    if (hash != std::string::npos)
-    {
-      copy.resize (hash);
-      copy = trim (copy);
-    }
-
-    if (copy.find ("import ") == 0)
-    {
-      File file (trim (copy.substr (7)));
-      if (file.exists () &&
-          file.readable ())
-      {
-        // Only import files that are not already imported.
-        if (std::find (_imports.begin (), _imports.end (), file._data) == _imports.end ())
-        {
-          _imports.push_back (file._data);
-
-          std::vector <std::string> imported;
-          file.read (imported);
-          imported = loadImports (imported);
-
-          resolved.insert(std::end(resolved), std::begin(imported), std::end(imported));
-        }
-      }
-      else
-        throw format ("Cannot import '{1}'", file._data);
-    }
-    else
-    {
-      // Store original line.
-      resolved.push_back (line);
-    }
-  }
-
-  return resolved;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void PEG::validate () const
-{
-  if (_start == "")
-    throw std::string ("There are no rules defined.");
-
-  std::vector <std::string> allRules;
-  std::vector <std::string> allTokens;
-  std::vector <std::string> allLeftRecursive;
-  std::vector <std::string> intrinsics;
-  std::vector <std::string> externals;
-
-  for (const auto& rule : _rules)
-  {
-    allRules.push_back (rule.first);
-
-    for (const auto& production : rule.second)
-    {
-      for (const auto& token : production)
-      {
-        if (token.hasTag ("intrinsic"))
-          intrinsics.push_back (token._token);
-
-        else if (token.hasTag ("external"))
-          externals.push_back (token._token);
-
-        else if (! token.hasTag ("literal"))
-          allTokens.push_back (token._token);
-
-        if (token._token == production[0]._token and
-            rule.first == production[0]._token   and
-            production.size () == 1)
-          allLeftRecursive.push_back (token._token);
-      }
-    }
-  }
-
-  std::vector <std::string> notUsed;
-  std::vector <std::string> notDefined;
-  listDiff (allRules, allTokens, notUsed, notDefined);
-
-  // Undefined value - these are definitions that appear in token, but are
-  // not in _rules.
-  for (const auto& nd : notDefined)
-    if (std::find (externals.begin (), externals.end (), nd) == externals.end ())
-      throw format ("Definition '{1}' referenced, but not defined.", nd);
-
-  // Circular definitions - these are names in _rules that also appear as
-  // the only token in any of the alternates for that definition.
-  for (const auto& lr : allLeftRecursive)
-    throw format ("Definition '{1}' is left recursive.", lr);
-
-  for (const auto& r : allRules)
-    if (r[0] == '<')
-      throw format ("Definition '{1}' may not redefine an intrinsic.");
-
-  for (const auto& r : allRules)
-    if (r[0] == '"' or
-        r[0] == '\'')
-      throw format ("Definition '{1}' may not be a literal.");
-
-  // Unused definitions - these are names in _rules that are never
-  // referenced as token.
-  for (const auto& nu : notUsed)
-  {
-    if (std::find (externals.begin (), externals.end (), nu) == externals.end () &&
-        nu != _start)
-    {
-      if (_strict)
-        throw format ("Definition '{1}' is defined, but not referenced.", nu);
-      else
-        std::cout << "Warning: Definition '" << nu << "' is defined, but not referenced.\n";
-    }
-  }
-
-  // Intrinsics must be recognized.
-  for (auto& intrinsic : intrinsics)
-    if (intrinsic != "<digit>"                 &&
-        intrinsic != "<hex>"                   &&
-        intrinsic != "<punct>"                 &&
-        intrinsic != "<eol>"                   &&
-        intrinsic != "<sep>"                   &&
-        intrinsic != "<ws>"                    &&
-        intrinsic != "<alpha>"                 &&
-        intrinsic != "<character>"             &&
-        intrinsic != "<word>"                  &&
-        intrinsic != "<token>"                 &&
-        intrinsic.substr (0, 8)  != "<entity:" &&
-        intrinsic.substr (0, 10) != "<external:")
-      throw format ("Specified intrinsic '{1}' is not supported.", intrinsic);
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/PEG.h b/src/libshared/src/PEG.h
deleted file mode 100644 (file)
index bf99b34..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_PEG
-#define INCLUDED_PEG
-
-#include <FS.h>
-#include <string>
-#include <vector>
-#include <map>
-#include <set>
-
-class PEG
-{
-public:
-  class Token
-  {
-  public:
-    Token (const std::string& value)           { _token = value; }
-    void tag (const std::string& tag)          { _tags.insert (tag); }
-    bool hasTag (const std::string& tag) const { return _tags.find (tag) != _tags.end (); };
-    std::string dump () const;
-
-    enum class Quantifier                      { one, zero_or_one, one_or_more, zero_or_more };
-    enum class Lookahead                       { none, positive, negative };
-
-    std::string _token                         {};
-    std::set <std::string> _tags               {};
-    Quantifier  _quantifier                    {Quantifier::one};
-    Lookahead   _lookahead                     {Lookahead::none};
-    // TODO Added Lexer::Type support, which allows the PEG to specify
-    //      "<Lexer::Type>" as a built-in type.
-  };
-
-  class Production : public std::vector <Token>
-  {
-  };
-
-  class Rule : public std::vector <Production>
-  {
-  };
-
-public:
-  void loadFromFile (File&);
-  void loadFromString (const std::string&);
-  std::map <std::string, PEG::Rule> syntax () const;
-  std::string firstRule () const;
-  void debug ();
-  void strict (bool);
-  std::string dump () const;
-
-private:
-  std::vector <std::string> loadImports (const std::vector <std::string>&);
-  void validate () const;
-
-private:
-  //        rule name    rule
-  //        |            |
-  std::map <std::string, PEG::Rule> _rules     {};
-  std::string                       _start     {};
-  int                               _debug     {0};
-  bool                              _strict    {false};
-  std::vector <std::string>         _imports   {};
-};
-
-#endif
diff --git a/src/libshared/src/Packrat.cpp b/src/libshared/src/Packrat.cpp
deleted file mode 100644 (file)
index 2d1d358..0000000
+++ /dev/null
@@ -1,770 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Packrat.h>
-#include <shared.h>
-#include <format.h>
-#include <unicode.h>
-#include <utf8.h>
-#include <iostream>
-
-int Packrat::minimumMatchLength = 3;
-
-////////////////////////////////////////////////////////////////////////////////
-void Packrat::debug ()
-{
-  ++_debug;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Walk the grammar tree to parse the input text, resulting in a parse tree.
-void Packrat::parse (const PEG& peg, const std::string& input)
-{
-  // Used to walk the grammar tree.
-  // Note there is only one rule at the top of the syntax tree, which was the
-  // first one defined.
-  _syntax = peg.syntax ();
-  _tree->_name = peg.firstRule ();
-
-  // The pig that will be sent down the pipe.
-  Pig pig (input);
-  if (_debug)
-    std::cout << "trace " << pig.dump () << "\n";
-
-  // Match the first rule.  Recursion does the rest.
-  if (! matchRule (_tree->_name, pig, _tree, 0))
-    throw std::string ("Parse failed.");
-
-  if (! pig.eos ())
-    throw format ("Parse failed - extra character at position {1}.", pig.cursor ());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Packrat::entity (const std::string& category, const std::string& name)
-{
-  // Walk the list of entities for category.
-  auto c = _entities.equal_range (category);
-  for (auto e = c.first; e != c.second; ++e)
-    if (e->second == name)
-      return;
-
-  // The category/name pair was not found, therefore add it.
-  _entities.insert (std::pair <std::string, std::string> (category, name));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Packrat::external (
-  const std::string& rule,
-  bool (*fn)(Pig&, std::shared_ptr <Tree>))
-{
-  if (_externals.find (rule) != _externals.end ())
-    throw format ("There is already an external parser defined for rule '{1}'.", rule);
-
-  _externals[rule] = fn;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// If there is a match, pig advances further down the pipe.
-bool Packrat::matchRule (
-  const std::string& rule,
-  Pig& pig,
-  std::shared_ptr <Tree> parseTree,
-  int indent)
-{
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "matchRule " << rule << "\n";
-  auto checkpoint = pig.cursor ();
-
-  for (const auto& production : _syntax.find (rule)->second)
-    if (matchProduction (production, pig, parseTree, indent + 1))
-      return true;
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Packrat::matchProduction (
-  const PEG::Production& production,
-  Pig& pig,
-  std::shared_ptr <Tree> parseTree,
-  int indent)
-{
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "matchProduction\n";
-  auto checkpoint = pig.cursor ();
-
-  auto collector = std::make_shared <Tree> ();
-  for (const auto& token : production)
-  {
-    auto b = std::make_shared <Tree> ();
-    if (! matchTokenQuant (token, pig, b, indent + 1))
-    {
-      pig.restoreTo (checkpoint);
-      return false;
-    }
-
-    // Accumulate branches.
-    collector->addBranch (b);
-  }
-
-  // On success transfer all sub-branches.
-  for (auto& b : collector->_branches)
-    for (auto sub : b->_branches)
-      parseTree->addBranch (sub);
-
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Wraps calls to matchTokenLookahead, while properly handling the quantifier.
-bool Packrat::matchTokenQuant (
-  const PEG::Token& token,
-  Pig& pig,
-  std::shared_ptr <Tree> parseTree,
-  int indent)
-{
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "matchTokenQuant " << token.dump () << "\n";
-
-  // Must match exactly once, so run once and return the result.
-  if (token._quantifier == PEG::Token::Quantifier::one)
-  {
-    return matchTokenLookahead (token, pig, parseTree, indent + 1);
-  }
-
-  // May match zero or one time.  If it matches, the cursor will be advanced.
-  // If it fails, the cursor will not be advanced, but this is still considered
-  // successful.  Return true either way, but backtrack the cursor on failure.
-  else if (token._quantifier == PEG::Token::Quantifier::zero_or_one)
-  {
-    // Check for a single match, succeed anyway.
-    matchTokenLookahead (token, pig, parseTree, indent + 1);
-    if (_debug > 1)
-      std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch ?\e[0m " << token.dump () << "\n";
-    if (_debug)
-      std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-    return true;
-  }
-
-  // May match 1 or more times.  If it matches on the first attempt, continue
-  // to greedily match until it fails.  If it fails on the first attempt, then
-  // the rule fails.
-  else if (token._quantifier == PEG::Token::Quantifier::one_or_more)
-  {
-    if (! matchTokenLookahead (token, pig, parseTree, indent + 1))
-      return false;
-
-    while (matchTokenLookahead (token, pig, parseTree, indent + 1))
-    {
-      // "Forget it, he's rolling."
-    }
-
-    if (_debug > 1)
-      std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch +\e[0m " << token.dump () << "\n";
-    if (_debug)
-      std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-    return true;
-  }
-
-  // May match zero or more times.  Keep calling while there are matches, and
-  // return true always.  Backtrack the cursor on failure.
-  else if (token._quantifier == PEG::Token::Quantifier::zero_or_more)
-  {
-    while (matchTokenLookahead (token, pig, parseTree, indent + 1))
-    {
-      // Let it go.
-    }
-
-    if (_debug > 1)
-      std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch *\e[0m " << token.dump () << "\n";
-    if (_debug)
-      std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-    return true;
-  }
-
-  throw std::string ("This should never happen.");
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Wraps calls to matchToken, while properly handling lookahead.
-bool Packrat::matchTokenLookahead (
-  const PEG::Token& token,
-  Pig& pig,
-  std::shared_ptr <Tree> parseTree,
-  int indent)
-{
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "matchTokenLookahead " << token.dump () << "\n";
-
-  if (token._lookahead == PEG::Token::Lookahead::none)
-  {
-    return matchToken (token, pig, parseTree, indent + 1);
-  }
-  else if (token._lookahead == PEG::Token::Lookahead::positive)
-  {
-    auto checkpoint = pig.cursor ();
-    auto b = std::make_shared <Tree> ();
-    if (matchToken (token, pig, b, indent + 1))
-    {
-      pig.restoreTo (checkpoint);
-      return true;
-    }
-  }
-  else if (token._lookahead == PEG::Token::Lookahead::negative)
-  {
-    auto checkpoint = pig.cursor ();
-    auto b = std::make_shared <Tree> ();
-    if (! matchToken (token, pig, b, indent + 1))
-    {
-      return true;
-    }
-
-    pig.restoreTo (checkpoint);
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Packrat::matchToken (
-  const PEG::Token& token,
-  Pig& pig,
-  std::shared_ptr <Tree> parseTree,
-  int indent)
-{
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "matchToken " << token.dump () << "\n";
-
-  auto checkpoint = pig.cursor ();
-  auto b = std::make_shared <Tree> ();
-
-  if (token.hasTag ("intrinsic") &&
-      matchIntrinsic (token, pig, parseTree, indent + 1))
-  {
-    return true;
-  }
-
-  else if (_syntax.find (token._token) != _syntax.end () &&
-           matchRule (token._token, pig, b, indent + 1))
-  {
-    // This is the only case that adds a sub-branch.
-    b->_name = token._token;
-    parseTree->addBranch (b);
-    return true;
-  }
-
-  else if (token.hasTag ("literal") &&
-           token.hasTag ("character") &&
-           matchCharLiteral (token, pig, parseTree, indent + 1))
-  {
-   return true;
-  }
-
-  else if (token.hasTag ("literal") &&
-           token.hasTag ("string") &&
-           matchStringLiteral (token, pig, parseTree, indent + 1))
-  {
-    return true;
-  }
-
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Supports the following:
-//   <digit>      --> unicodeLatinDigit
-//   <hex>        --> unicodeHexDigit
-//   <character>  --> anything
-//   <alpha>      --> unicodeAlpha
-//   <punct>      --> unicodePunctuation
-//   <ws>         --> unicodeWhitespace
-//   <sep>        --> unicodeHorizontalWhitespace
-//   <eol>        --> unicodeVerticalWhitespace
-//   <word>       --> <alpha>
-//   <token>      --> consecutive non <ws>
-//   <entity:e>   --> Any category 'e' token
-//   <external:x> --> Delegate to external function
-bool Packrat::matchIntrinsic (
-  const PEG::Token& token,
-  Pig& pig,
-  std::shared_ptr <Tree> parseTree,
-  int indent)
-{
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "matchIntrinsic " << token.dump () << "\n";
-  auto checkpoint = pig.cursor ();
-
-  // There are only 10 digits.
-  if (token._token == "<digit>")
-  {
-    int digit;
-    if (pig.getDigit (digit))
-    {
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", format ("{1}", digit));
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << digit << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // Upper or lower case hex digit.
-  if (token._token == "<hex>")
-  {
-    int digit;
-    if (pig.getHexDigit (digit))
-    {
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", format ("{1}", digit));
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << digit << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // Character means anything.
-  else if (token._token == "<character>")
-  {
-    int character;
-    if (pig.getCharacter (character))
-    {
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", format ("{1}", character));
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << character << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // <punct> ::ispunct
-  else if (token._token == "<punct>")
-  {
-    int character = pig.peek ();
-    if (unicodePunctuation (character))
-    {
-      pig.skip (character);
-
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", format ("{1}", character));
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << character << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // <alpha>
-  else if (token._token == "<alpha>")
-  {
-    int character = pig.peek ();
-    if (unicodeAlpha (character))
-    {
-      pig.skip (character);
-
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", format ("{1}", character));
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << character << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // <ws>
-  else if (token._token == "<ws>")
-  {
-    int character = pig.peek ();
-    if (unicodeWhitespace (character))
-    {
-      pig.skip (character);
-
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", format ("{1}", character));
-      parseTree->addBranch (b);
-
-      if (_debug > 10)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << character << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // <sep>
-  else if (token._token == "<sep>")
-  {
-    int character = pig.peek ();
-    if (unicodeHorizontalWhitespace (character))
-    {
-      pig.skip (character);
-
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", format ("{1}", character));
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << character << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // <eol>
-  else if (token._token == "<eol>")
-  {
-    int character = pig.peek ();
-    if (unicodeVerticalWhitespace (character))
-    {
-      pig.skip (character);
-
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", format ("{1}", character));
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << character << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // <word> consecutive non-<ws>, non-<punct>.
-  else if (token._token == "<word>")
-  {
-    while (auto character = pig.peek ())
-    {
-      if (! character ||
-          unicodeWhitespace (character) ||
-          unicodePunctuation (character))
-        break;
-
-      pig.skip (character);
-    }
-
-    if (pig.cursor () > checkpoint)
-    {
-      auto word = pig.substr (checkpoint, pig.cursor () - checkpoint + 1);
-
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", word);
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << word << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // <token> consecutive non-<ws>.
-  else if (token._token == "<token>")
-  {
-    while (auto character = pig.peek ())
-    {
-      if (! character ||
-          unicodeWhitespace (character))
-        break;
-
-      pig.skip (character);
-    }
-
-    if (pig.cursor () > checkpoint)
-    {
-      auto word = pig.substr (checkpoint, pig.cursor () - checkpoint);
-
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "intrinsic";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", word);
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << word << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  // <entity:category>.
-  else if (token._token.find ("<entity:") == 0)
-  {
-    // Extract entity category
-    auto category = token._token.substr (8, token._token.length () - 9);
-
-    // Match against any one of the entity values in this category.
-    auto values = _entities.equal_range (category);
-    for (auto value = values.first; value != values.second; ++value)
-    {
-      if (pig.skipLiteral (value->second))
-      {
-        // Create a populated branch.
-        auto b = std::make_shared <Tree> ();
-        b->_name = "intrinsic";
-        b->tag ("entity");
-        b->attribute ("expected", token._token);
-        b->attribute ("value", value->second);
-        parseTree->addBranch (b);
-
-        if (_debug > 1)
-          std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << value->second << "\n";
-        if (_debug)
-          std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-
-        return true;
-      }
-    }
-  }
-
-  // <external:rule>
-  else if (token._token.find ("<external:") == 0)
-  {
-    // Extract entity category
-    auto rule = token._token.substr (10, token._token.length () - 11);
-
-    // Any rule can be overridden by an external parser.
-    if (_externals.find (rule) != _externals.end ())
-    {
-      // Create a pre-populated branch, which is attached on success only.
-      auto newBranch = std::make_shared <Tree> ();
-      newBranch->_name = "intrinsic";
-      newBranch->tag ("external");
-      newBranch->attribute ("expected", token._token);
-
-      if (_externals[rule] (pig, newBranch))
-      {
-        // Determine what was parsed.
-        auto word = pig.substr (checkpoint, pig.cursor () - checkpoint);
-
-        // Attach the new branch.
-        newBranch->attribute ("value", word);
-        parseTree->addBranch (newBranch);
-
-        if (_debug > 1)
-          std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << word << "\n";
-        if (_debug)
-          std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-
-        return true;
-      }
-
-      // Note: Branch 'newBranch' goes out of scope here if parsing fails.
-    }
-  }
-
-  if (_debug > 1)
-     std::cout << "trace " << std::string (indent, ' ') << "\e[31mfail\e[0m " << token._token << "\n";
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Packrat::matchCharLiteral (
-  const PEG::Token& token,
-  Pig& pig,
-  std::shared_ptr <Tree> parseTree,
-  int indent)
-{
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "matchCharLiteral " << token.dump () << "\n";
-  auto checkpoint = pig.cursor ();
-
-  if (token._token.length () >= 3 &&
-      token._token[0] == '\'' &&
-      token._token[2] == '\'')
-  {
-    int literal = token._token[1];
-    if (pig.skip (literal))
-    {
-      // Create a populated branch.
-      auto b = std::make_shared <Tree> ();
-      b->_name = "charLiteral";
-      b->attribute ("expected", token._token);
-      b->attribute ("value", utf8_character (literal));
-      parseTree->addBranch (b);
-
-      if (_debug > 1)
-        std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << token._token << "\n";
-      if (_debug)
-        std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-      return true;
-    }
-  }
-
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "\e[31mfail\e[0m " << token._token << "\n";
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Packrat::matchStringLiteral (
-  const PEG::Token& token,
-  Pig& pig,
-  std::shared_ptr <Tree> parseTree,
-  int indent)
-{
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "matchStringLiteral " << token.dump () << "\n";
-  auto checkpoint = pig.cursor ();
-
-  std::string literal = token._token.substr (1, token._token.length () - 2);
-  if (pig.skipLiteral (literal))
-  {
-    // Create a populated branch.
-    auto b = std::make_shared <Tree> ();
-    b->_name = "stringLiteral";
-    b->attribute ("expected", token._token);
-    b->attribute ("value", literal);
-    parseTree->addBranch (b);
-
-    if (_debug > 1)
-      std::cout << "trace " << std::string (indent, ' ') << "\e[32mmatch\e[0m " << literal << "\n";
-    if (_debug)
-      std::cout << "trace " << pig.dump () << ' ' << token.dump () << "\n";
-    return true;
-  }
-
-  if (_debug > 1)
-    std::cout << "trace " << std::string (indent, ' ') << "\e[31mfail\e[0m " << token._token << "\n";
-  pig.restoreTo (checkpoint);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Search for 'value' in _entities category, return canonicalized value.
-bool Packrat::canonicalize (
-  std::string& canonicalized,
-  const std::string& category,
-  const std::string& value) const
-{
-  // Extract a list of entities for category.
-  std::vector <std::string> options;
-  auto c = _entities.equal_range (category);
-  for (auto e = c.first; e != c.second; ++e)
-  {
-    // Shortcut: if an exact match is found, success.
-    if (value == e->second)
-    {
-      canonicalized = value;
-      return true;
-    }
-
-    options.push_back (e->second);
-  }
-
-  // Match against the options, throw away results.
-  std::vector <std::string> matches;
-  if (autoComplete (value, options, matches, minimumMatchLength) == 1)
-  {
-    canonicalized = matches[0];
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Packrat::dump () const
-{
-  std::stringstream out;
-  if (_debug)
-    out << '\n';
-
-  out << "Packrat Parse "
-      << _tree->dump ();
-
-  if (_entities.size ())
-  {
-    out << "  Entities\n";
-    for (const auto& entity : _entities)
-      out << "    " << entity.first << ':' << entity.second << '\n';
-  }
-
-  if (_externals.size ())
-  {
-    out << "  Externals\n";
-    for (const auto& external : _externals)
-      out << "    " << external.first << "\n";
-  }
-
-  return out.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Packrat.h b/src/libshared/src/Packrat.h
deleted file mode 100644 (file)
index 0585077..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_PACKRAT
-#define INCLUDED_PACKRAT
-
-#include <PEG.h>
-#include <Tree.h>
-#include <Pig.h>
-#include <string>
-
-class Packrat
-{
-public:
-  void parse (const PEG&, const std::string&);
-  void entity (const std::string&, const std::string&);
-  void external (const std::string&, bool (*)(Pig&, std::shared_ptr <Tree>));
-
-  void debug ();
-  std::string dump () const;
-
-private:
-  bool matchRule           (const std::string&,     Pig&, std::shared_ptr <Tree>, int);
-  bool matchProduction     (const PEG::Production&, Pig&, std::shared_ptr <Tree>, int);
-  bool matchTokenQuant     (const PEG::Token&,      Pig&, std::shared_ptr <Tree>, int);
-  bool matchTokenLookahead (const PEG::Token&,      Pig&, std::shared_ptr <Tree>, int);
-  bool matchToken          (const PEG::Token&,      Pig&, std::shared_ptr <Tree>, int);
-  bool matchIntrinsic      (const PEG::Token&,      Pig&, std::shared_ptr <Tree>, int);
-  bool matchCharLiteral    (const PEG::Token&,      Pig&, std::shared_ptr <Tree>, int);
-  bool matchStringLiteral  (const PEG::Token&,      Pig&, std::shared_ptr <Tree>, int);
-
-  bool canonicalize (std::string&, const std::string&, const std::string&) const;
-
-public:
-  static int minimumMatchLength;
-
-private:
-  int                                                            _debug    {0};
-  std::map <std::string, PEG::Rule>                              _syntax   {};
-  std::shared_ptr <Tree>                                         _tree     {std::make_shared <Tree> ()};
-  std::multimap <std::string, std::string>                       _entities {};
-  std::map <std::string, bool (*)(Pig&, std::shared_ptr <Tree>)> _externals {};
-};
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Palette.cpp b/src/libshared/src/Palette.cpp
deleted file mode 100644 (file)
index 62fb08f..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Palette.h>
-
-////////////////////////////////////////////////////////////////////////////////
-// Use a default palette, which is overwritten in ::initialize.
-Palette::Palette ()
-{
-  _colors = {
-    Color ("white on red"),
-    Color ("white on blue"),
-    Color ("black on green"),
-    Color ("black on magenta"),
-    Color ("black on cyan"),
-    Color ("black on yellow"),
-    Color ("black on white"),
-    Color ("white on bright red"),
-    Color ("white on bright blue"),
-    Color ("black on bright green"),
-    Color ("black on bright magenta"),
-    Color ("black on bright cyan"),
-    Color ("black on bright yellow"),
-  };
-
-  _current = 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Palette::add (Color c)
-{
-  _colors.push_back (c);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Return the next color in the list.  Cycle to the beginning if necessary.
-Color Palette::next ()
-{
-  if (enabled)
-    return _colors[_current++ % _colors.size ()];
-
-  return Color ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Palette::size () const
-{
-  return static_cast <int> (_colors.size ());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Palette::clear ()
-{
-  _colors.clear ();
-  _current = 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Palette.h b/src/libshared/src/Palette.h
deleted file mode 100644 (file)
index 771b285..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_PALETTE
-#define INCLUDED_PALETTE
-
-#include <Color.h>
-#include <vector>
-#include <string>
-
-class Palette
-{
-public:
-  Palette ();
-  void add (Color);
-  Color next ();
-  int size () const;
-  void clear ();
-
-public:
-  bool enabled {true};
-
-private:
-  std::vector <Color> _colors  {};
-  int                 _current {0};
-};
-
-#endif
diff --git a/src/libshared/src/Pig.cpp b/src/libshared/src/Pig.cpp
deleted file mode 100644 (file)
index fd8d23c..0000000
+++ /dev/null
@@ -1,668 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Pig.h>
-#include <shared.h>
-#include <unicode.h>
-#include <utf8.h>
-#include <algorithm>
-#include <sstream>
-#include <cinttypes>
-#include <cstdlib>
-
-////////////////////////////////////////////////////////////////////////////////
-Pig::Pig (const std::string& text)
-: _text {std::make_shared <std::string> (text)}
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::skip (int c)
-{
-  if ((*_text)[_cursor] == c)
-  {
-    ++_cursor;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::skipN (const int quantity)
-{
-  auto save = _cursor;
-
-  auto count = 0;
-  while (count++ < quantity)
-  {
-    if (! utf8_next_char (*_text, _cursor))
-    {
-      _cursor = save;
-      return false;
-    }
-  }
-
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::skipWS ()
-{
-  auto save = _cursor;
-
-  int c;
-  auto prev = _cursor;
-  while ((c = utf8_next_char (*_text, _cursor)))
-  {
-    if (! unicodeWhitespace (c))
-    {
-      _cursor = prev;
-      break;
-    }
-    prev = _cursor;
-  }
-
-  return _cursor > save;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::skipLiteral (const std::string& literal)
-{
-  if (_text->find (literal, _cursor) == _cursor)
-  {
-    _cursor += literal.length ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::skipPartial (const std::string& reference, std::string& result)
-{
-  // Walk the common substring.
-  auto pos = 0;
-  while (reference[pos] &&
-         (*_text)[_cursor + pos] &&
-         reference[pos] == (*_text)[_cursor + pos])
-    ++pos;
-
-  if (pos > 0)
-  {
-    result = _text->substr (_cursor, pos);
-    _cursor += pos;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getUntil (int end, std::string& result)
-{
-  auto save = _cursor;
-
-  int c;
-  auto prev = _cursor;
-  while ((c = utf8_next_char (*_text, _cursor)))
-  {
-    if (c == end)
-    {
-      _cursor = prev;
-      result = _text->substr (save, _cursor - save);
-      return true;
-    }
-
-    else if (eos ())
-    {
-      result = _text->substr (save, _cursor - save);
-      return true;
-    }
-
-    prev = _cursor;
-  }
-
-  return _cursor > save;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getUntilWS (std::string& result)
-{
-  auto save = _cursor;
-
-  int c;
-  auto prev = _cursor;
-  while ((c = utf8_next_char (*_text, _cursor)))
-  {
-    if (unicodeWhitespace (c))
-    {
-      _cursor = prev;
-      result = _text->substr (save, _cursor - save);
-      return true;
-    }
-
-    // Note: This test must follow the above unicodeWhitespace(c) test because
-    //       it is testing the value of 'c', and eos() is testing _cursor,
-    //       which has already been advanced.
-    else if (eos ())
-    {
-      result = _text->substr (save, _cursor - save);
-      return true;
-    }
-
-    prev = _cursor;
-  }
-
-  return _cursor > save;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getCharacter (int& result)
-{
-  int c = (*_text)[_cursor];
-  if (c)
-  {
-    result = c;
-    ++_cursor;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getDigit (int& result)
-{
-  int c = (*_text)[_cursor];
-  if (c &&
-      unicodeLatinDigit (c))
-  {
-    result = c - '0';
-    ++_cursor;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getDigit2 (int& result)
-{
-  if (unicodeLatinDigit ((*_text)[_cursor + 0]))
-  {
-    if (unicodeLatinDigit ((*_text)[_cursor + 1]))
-    {
-      result = strtoimax (_text->substr (_cursor, 2).c_str (), NULL, 10);
-      _cursor += 2;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getDigit3 (int& result)
-{
-  if (unicodeLatinDigit ((*_text)[_cursor + 0]))
-  {
-    if (unicodeLatinDigit ((*_text)[_cursor + 1]))
-    {
-      if (unicodeLatinDigit ((*_text)[_cursor + 2]))
-      {
-        result = strtoimax (_text->substr (_cursor, 3).c_str (), NULL, 10);
-        _cursor += 3;
-        return true;
-      }
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getDigit4 (int& result)
-{
-  if (unicodeLatinDigit ((*_text)[_cursor + 0]))
-  {
-    if (unicodeLatinDigit ((*_text)[_cursor + 1]))
-    {
-      if (unicodeLatinDigit ((*_text)[_cursor + 2]))
-      {
-        if (unicodeLatinDigit ((*_text)[_cursor + 3]))
-        {
-          result = strtoimax (_text->substr (_cursor, 4).c_str (), NULL, 10);
-          _cursor += 4;
-          return true;
-        }
-      }
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getDigits (int& result)
-{
-  auto save = _cursor;
-
-  int c;
-  auto prev = _cursor;
-  while ((c = utf8_next_char (*_text, _cursor)))
-  {
-    if (! unicodeLatinDigit (c))
-    {
-      _cursor = prev;
-      break;
-    }
-
-    prev = _cursor;
-  }
-
-  if (_cursor > save)
-  {
-    result = strtoimax (_text->substr (save, _cursor - save).c_str (), NULL, 10);
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getHexDigit (int& result)
-{
-  int c = (*_text)[_cursor];
-  if (c &&
-      unicodeHexDigit (c))
-  {
-    if (c >= '0' && c <= '9')
-    {
-      result = c - '0';
-      ++_cursor;
-      return true;
-    }
-    else if (c >= 'A' && c <= 'F')
-    {
-      result = c - 'A' + 10;
-      ++_cursor;
-      return true;
-    }
-    else if (c >= 'a' && c <= 'f')
-    {
-      result = c - 'a' + 10;
-      ++_cursor;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// number:
-//   int frac? exp?
-//
-// int:
-//   (-|+)? digit+
-//
-// frac:
-//   . digit+
-//
-// exp:
-//   e digit+
-//
-// e:
-//   e|E (+|-)?
-//
-bool Pig::getNumber (std::string& result)
-{
-  auto i = _cursor;
-
-  // [+-]?
-  if ((*_text)[i] &&
-      ((*_text)[i] == '-' ||
-       (*_text)[i] == '+'))
-    ++i;
-
-  // digit+
-  if ((*_text)[i] &&
-      unicodeLatinDigit ((*_text)[i]))
-  {
-    ++i;
-
-    while ((*_text)[i] && unicodeLatinDigit ((*_text)[i]))
-      ++i;
-
-    // ( . digit+ )?
-    if ((*_text)[i] && (*_text)[i] == '.')
-    {
-      ++i;
-
-      while ((*_text)[i] && unicodeLatinDigit ((*_text)[i]))
-        ++i;
-    }
-
-    // ( [eE] [+-]? digit+ )?
-    if ((*_text)[i] &&
-        ((*_text)[i] == 'e' ||
-         (*_text)[i] == 'E'))
-    {
-      ++i;
-
-      if ((*_text)[i] &&
-          ((*_text)[i] == '+' ||
-           (*_text)[i] == '-'))
-        ++i;
-
-      if ((*_text)[i] && unicodeLatinDigit ((*_text)[i]))
-      {
-        ++i;
-
-        while ((*_text)[i] && unicodeLatinDigit ((*_text)[i]))
-          ++i;
-
-        result = _text->substr (_cursor, i - _cursor);
-        _cursor = i;
-        return true;
-      }
-
-      return false;
-    }
-
-    result = _text->substr (_cursor, i - _cursor);
-    _cursor = i;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getNumber (double& result)
-{
-  std::string s;
-  if (getNumber (s))
-  {
-    result = std::strtod (s.c_str (), NULL);
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// [ + | - ] \d+ [ . [ \d+ ]]
-bool Pig::getDecimal (std::string& result)
-{
-  auto i = _cursor;
-
-  // [+-]?
-  if ((*_text)[i] &&
-      ((*_text)[i] == '-' ||
-       (*_text)[i] == '+'))
-    ++i;
-
-  // digit+
-  if ((*_text)[i] && unicodeLatinDigit ((*_text)[i]))
-  {
-    ++i;
-
-    while ((*_text)[i] && unicodeLatinDigit ((*_text)[i]))
-      ++i;
-
-    // ( . digit+ )?
-    if ((*_text)[i] && (*_text)[i] == '.')
-    {
-      ++i;
-
-      while ((*_text)[i] && unicodeLatinDigit ((*_text)[i]))
-        ++i;
-    }
-
-    result = _text->substr (_cursor, i - _cursor);
-    _cursor = i;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getDecimal (double& result)
-{
-  std::string s;
-  if (getDecimal (s))
-  {
-    result = std::strtod (s.c_str (), NULL);
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Gets quote content:      "foobar" -> foobar      (for c = '"')
-// Handles escaped quotes:  "foo\"bar" -> foo\"bar  (for c = '"')
-// Returns false if first character is not c, or if there is no closing c.
-// Does not modify content between quotes.
-bool Pig::getQuoted (int quote, std::string& result)
-{
-  if (! (*_text)[_cursor] ||
-      (*_text)[_cursor] != quote)
-    return false;
-
-  auto start = _cursor + utf8_sequence (quote);
-  auto i = start;
-
-  while ((*_text)[i])
-  {
-    i = _text->find (quote, i);
-    if (i == std::string::npos)
-      return false;  // Unclosed quote.  Short cut, not definitive.
-
-    if (i == start)
-    {
-      // Empty quote
-      _cursor += 2 * utf8_sequence (quote);  // Skip both quote chars
-      result = "";
-      return true;
-    }
-
-    if ((*_text)[i - 1] == '\\')
-    {
-      // Check for escaped backslashes.  Backtracking like this is not very
-      // efficient, but is only done in extreme corner cases.
-
-      auto j = i - 2;  // Start one character further left
-      bool is_escaped_quote = true;
-      while (j >= start && (*_text)[j] == '\\')
-      {
-        // Toggle flag for each further backslash encountered.
-        is_escaped_quote = is_escaped_quote ? false : true;
-        --j;
-      }
-
-      if (is_escaped_quote)
-      {
-        // Keep searching
-        ++i;
-        continue;
-      }
-    }
-
-    // None of the above applied, we must have found the closing quote char.
-    result.assign (*_text, start, i - start);
-    _cursor = i + utf8_sequence (quote);  // Skip closing quote char
-    return true;
-  }
-
-  // This should never be reached.  We could throw here instead.
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Assumes that the options are sorted by decreasing length, so that if the
-// options contain 'fourteen' and 'four', the stream is first matched against
-// the longer entry.
-bool Pig::getOneOf (
-  const std::vector <std::string>& options,
-  std::string& found)
-{
-  for (const auto& option : options)
-  {
-    if (skipLiteral (option))
-    {
-      found = option;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getHMS (int& hours, int& minutes, int& seconds)
-{
-  auto save = _cursor;
-
-  if ((getDigit2 (hours) || getDigit (hours)) &&
-      skip (':')                              &&
-      getDigit2 (minutes))
-  {
-    seconds = 0;
-    if (skip (':') &&
-        ! getDigit2 (seconds))
-      return false;
-
-    return true;
-  }
-
-  _cursor = save;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::getRemainder (std::string& result)
-{
-  if ((*_text)[_cursor])
-  {
-    result = _text->substr (_cursor);
-    _cursor += result.length ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Pig::eos () const
-{
-  return (*_text)[_cursor] == '\0';
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Peeks ahead - does not move cursor.
-int Pig::peek () const
-{
-  return (*_text)[_cursor];
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Peeks ahead - does not move cursor.
-std::string Pig::peek (const int quantity) const
-{
-  std::string::size_type adjusted = std::min (static_cast <std::string::size_type> (quantity), _text->length () - _cursor);
-  if ((*_text)[_cursor])
-    return _text->substr (_cursor, adjusted);
-
-  return "";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string::size_type Pig::cursor () const
-{
-  return _cursor;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Note: never called internally, otherwise the client cannot rely on iṫ.
-std::string::size_type Pig::save ()
-{
-  return _saved = _cursor;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Note: never called internally, otherwise the client cannot rely on iṫ.
-std::string::size_type Pig::restore ()
-{
-  return _cursor = _saved;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string::size_type Pig::restoreTo (std::string::size_type previous)
-{
-  return _cursor = previous;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Pig::substr (
-  std::string::size_type start,
-  std::string::size_type end) const
-{
-  return _text->substr (start, end - start);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Pig::str () const
-{
-  return _text->substr (_cursor);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Show the text, with the matched part in white on green, and the unmatched
-// part white on red, followed by the index equivalent.
-std::string Pig::dump () const
-{
-  std::stringstream out;
-  if (_cursor)
-    out << "\e[37;42m"
-        << _text->substr (0, _cursor)
-        << "\e[0m";
-
-  out << "\e[37;41m"
-      << _text->substr (_cursor)
-      << "\e[0m "
-      << _cursor
-      << '/'
-      << _text->length ();
-
-  return str_replace (out.str (), "\n", "\\n");
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Pig.h b/src/libshared/src/Pig.h
deleted file mode 100644 (file)
index 3485e43..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_PIG
-#define INCLUDED_PIG
-
-#include <string>
-#include <vector>
-#include <memory>
-
-class Pig
-{
-public:
-  explicit Pig (const std::string&);
-
-  bool skip (int);
-  bool skipN (const int quantity = 1);
-  bool skipWS ();
-  bool skipLiteral (const std::string&);
-  bool skipPartial (const std::string&, std::string&);
-
-  bool getUntil (int, std::string&);
-  bool getUntilWS (std::string&);
-  bool getCharacter (int&);
-  bool getDigit (int&);
-  bool getDigit2 (int&);
-  bool getDigit3 (int&);
-  bool getDigit4 (int&);
-  bool getDigits (int&);
-  bool getHexDigit (int&);
-  bool getNumber (std::string&);
-  bool getNumber (double&);
-  bool getDecimal (std::string&);
-  bool getDecimal (double&);
-  bool getQuoted (int, std::string&);
-  bool getOneOf (const std::vector <std::string>&, std::string&);
-  bool getHMS (int&, int&, int&);
-  bool getRemainder (std::string&);
-
-  bool eos () const;
-  int peek () const;
-  std::string peek (const int) const;
-  std::string::size_type cursor () const;
-  std::string::size_type save ();
-  std::string::size_type restore ();
-  std::string::size_type restoreTo (std::string::size_type);
-
-  std::string substr (std::string::size_type, std::string::size_type) const;
-  std::string str () const;
-  std::string dump () const;
-
-private:
-  std::shared_ptr<std::string> _text;
-  std::string::size_type       _cursor {0};
-  std::string::size_type       _saved  {0};
-};
-
-#endif
diff --git a/src/libshared/src/README b/src/libshared/src/README
deleted file mode 100644 (file)
index dc654da..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Shared
-======
-
-The 'shared' library is a set of reusable objects to be shared as-is between
-various programs, including Taskwarrior, Taskserver, Tasksh and Timewarrior.
-
-In order to be reusable, and therefore a member of libshared, conditions must
-be met:
-
-  - Shared objects may only make use of other shared objects, or external
-    dependencies (libuuid, gettext, readline etc), but no objects from the
-    project directories.
-
-  - Shared objects may assume only one external 'cmake.h' that defines
-    platform/portability constants.
-
diff --git a/src/libshared/src/RX.cpp b/src/libshared/src/RX.cpp
deleted file mode 100644 (file)
index 59a683f..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <RX.h>
-#include <cstdlib>
-#include <cstring>
-
-////////////////////////////////////////////////////////////////////////////////
-RX::RX ()
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-RX::RX (
-  const std::string& pattern,
-  bool case_sensitive /* = true */)
-: _compiled (false)
-, _pattern (pattern)
-, _case_sensitive (case_sensitive)
-{
-  compile ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-RX::RX (const RX& other)
-{
-  _compiled       = false;
-  _pattern        = other._pattern;
-  _case_sensitive = other._case_sensitive;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-RX::~RX ()
-{
-  if (_compiled)
-    regfree (&_regex);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-RX& RX::operator= (const RX& other)
-{
-  _compiled       = false;
-  _pattern        = other._pattern;
-  _case_sensitive = other._case_sensitive;
-
-  return *this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void RX::compile ()
-{
-  if (! _compiled)
-  {
-    memset (&_regex, 0, sizeof (regex_t));
-
-    int result;
-    if ((result = regcomp (&_regex, _pattern.c_str (),
-#if defined REG_ENHANCED
-                           REG_ENHANCED | REG_EXTENDED | REG_NEWLINE |
-#else
-                           REG_EXTENDED | REG_NEWLINE |
-#endif
-                           (_case_sensitive ? 0 : REG_ICASE))) != 0)
-    {
-      char message[256];
-      regerror (result, &_regex, message, 256);
-      throw std::string (message);
-    }
-
-    _compiled = true;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool RX::match (const std::string& in)
-{
-  if (! _compiled)
-    compile ();
-
-  return regexec (&_regex, in.c_str (), 0, nullptr, 0) == 0 ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool RX::match (
-  std::vector<std::string>& matches,
-  const std::string& in)
-{
-  if (! _compiled)
-    compile ();
-
-  regmatch_t rm[2];
-  int offset = 0;
-  int length = in.length ();
-  while (regexec (&_regex, in.c_str () + offset, 2, &rm[0], 0) == 0 &&
-         offset < length)
-  {
-    matches.push_back (in.substr (rm[0].rm_so + offset, rm[0].rm_eo - rm[0].rm_so));
-    offset += rm[0].rm_eo;
-
-    // Protection against zero-width patterns causing infinite loops.
-    if (rm[0].rm_so == rm[0].rm_eo)
-      ++offset;
-  }
-
-  return matches.size () ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool RX::match (
-  std::vector <int>& start,
-  std::vector <int>& end,
-  const std::string& in)
-{
-  if (! _compiled)
-    compile ();
-
-  regmatch_t rm[2];
-  int offset = 0;
-  int length = in.length ();
-  while (regexec (&_regex, in.c_str () + offset, 2, &rm[0], 0) == 0 &&
-         offset < length)
-  {
-    start.push_back (rm[0].rm_so + offset);
-    end.push_back   (rm[0].rm_eo + offset);
-    offset += rm[0].rm_eo;
-
-    // Protection against zero-width patterns causing infinite loops.
-    if (rm[0].rm_so == rm[0].rm_eo)
-      ++offset;
-  }
-
-  return start.size () ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/RX.h b/src/libshared/src/RX.h
deleted file mode 100644 (file)
index 1626582..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_RX
-#define INCLUDED_RX
-
-#include <string>
-#include <vector>
-#include <regex.h>
-
-class RX
-{
-public:
-  RX ();
-  RX (const std::string&, bool caseSensitive = true);
-  RX (const RX&);
-  ~RX ();
-  RX& operator= (const RX&);
-
-  bool match (const std::string&);
-  bool match (std::vector<std::string>&, const std::string&);
-  bool match (std::vector <int>&, std::vector <int>&, const std::string&);
-
-private:
-  void compile ();
-
-private:
-  bool _compiled       {false};
-  std::string _pattern {};
-  bool _case_sensitive {false};
-  regex_t _regex;
-};
-
-#endif
-
diff --git a/src/libshared/src/SAX.cpp b/src/libshared/src/SAX.cpp
deleted file mode 100644 (file)
index 5503593..0000000
+++ /dev/null
@@ -1,579 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <JSON.h>
-#include <utf8.h>
-#include <sstream>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <errno.h>
-
-////////////////////////////////////////////////////////////////////////////////
-bool json::SAX::parse (const std::string& input, SAX::Sink& sink)
-{
-  sink.eventDocStart ();
-  std::string::size_type cursor = 0;
-  ignoreWhitespace (input, cursor);
-  if (isObject (input, cursor, sink) ||
-      isArray  (input, cursor, sink))
-  {
-    ignoreWhitespace (input, cursor);
-    if (cursor < input.length ())
-      error ("Error: extra characters found at position ", cursor);
-
-    sink.eventDocEnd ();
-    return true;
-  }
-
-  error ("Error: Missing '{' or '[' at position ", cursor);
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Complete Unicode whitespace list.
-//
-// http://en.wikipedia.org/wiki/Whitespace_character
-// Updated 2015-09-13
-void json::SAX::ignoreWhitespace (const std::string& input, std::string::size_type& cursor)
-{
-  int c = input[cursor];
-  while (c == 0x0020 ||   // space Common  Separator, space
-         c == 0x0009 ||   // Common  Other, control  HT, Horizontal Tab
-         c == 0x000A ||   // Common  Other, control  LF, Line feed
-         c == 0x000B ||   // Common  Other, control  VT, Vertical Tab
-         c == 0x000C ||   // Common  Other, control  FF, Form feed
-         c == 0x000D ||   // Common  Other, control  CR, Carriage return
-         c == 0x0085 ||   // Common  Other, control  NEL, Next line
-         c == 0x00A0 ||   // no-break space  Common  Separator, space
-         c == 0x1680 ||   // ogham space mark  Ogham Separator, space
-         c == 0x180E ||   // mongolian vowel separator Mongolian Separator, space
-         c == 0x2000 ||   // en quad Common  Separator, space
-         c == 0x2001 ||   // em quad Common  Separator, space
-         c == 0x2002 ||   // en space  Common  Separator, space
-         c == 0x2003 ||   // em space  Common  Separator, space
-         c == 0x2004 ||   // three-per-em space  Common  Separator, space
-         c == 0x2005 ||   // four-per-em space Common  Separator, space
-         c == 0x2006 ||   // six-per-em space  Common  Separator, space
-         c == 0x2007 ||   // figure space  Common  Separator, space
-         c == 0x2008 ||   // punctuation space Common  Separator, space
-         c == 0x2009 ||   // thin space  Common  Separator, space
-         c == 0x200A ||   // hair space  Common  Separator, space
-         c == 0x200B ||   // zero width space
-         c == 0x200C ||   // zero width non-joiner
-         c == 0x200D ||   // zero width joiner
-         c == 0x2028 ||   // line separator  Common  Separator, line
-         c == 0x2029 ||   // paragraph separator Common  Separator, paragraph
-         c == 0x202F ||   // narrow no-break space Common  Separator, space
-         c == 0x205F ||   // medium mathematical space Common  Separator, space
-         c == 0x2060 ||   // word joiner
-         c == 0x3000)     // ideographic space Common  Separator, space
-  {
-    c = input[++cursor];
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// object := '{' [<pair> [, <pair> ...]] '}'
-bool json::SAX::isObject (const std::string& input, std::string::size_type& cursor, SAX::Sink& sink)
-{
-  ignoreWhitespace (input, cursor);
-  auto backup = cursor;
-
-  if (isLiteral (input, '{', cursor))
-  {
-    sink.eventObjectStart ();
-    int counter = 0;
-
-    if (isPair (input, cursor, sink))
-    {
-      ++counter;
-      while (isLiteral (input, ',', cursor) &&
-             isPair    (input, cursor, sink))
-      {
-        ++counter;
-      }
-    }
-
-    ignoreWhitespace (input, cursor);
-    if (isLiteral (input, '}', cursor))
-    {
-      sink.eventObjectEnd (counter);
-      return true;
-    }
-    else
-      error ("Error: Missing '}' at position ", cursor);
-  }
-
-  cursor = backup;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// array := '[' [<value> [, <value> ...]] ']'
-bool json::SAX::isArray (const std::string& input, std::string::size_type& cursor, SAX::Sink& sink)
-{
-  ignoreWhitespace (input, cursor);
-  auto backup = cursor;
-
-  if (isLiteral (input, '[', cursor))
-  {
-    sink.eventArrayStart ();
-    int counter = 0;
-
-    if (isValue (input, cursor, sink))
-    {
-      ++counter;
-      while (isLiteral (input, ',', cursor) &&
-             isValue   (input,      cursor, sink))
-      {
-        ++counter;
-      }
-    }
-
-    ignoreWhitespace (input, cursor);
-    if (isLiteral (input, ']', cursor))
-    {
-      sink.eventArrayEnd (counter);
-      return true;
-    }
-    else
-      error ("Error: Missing ']' at position ", cursor);
-  }
-
-  cursor = backup;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// pair := <string> ':' <value>
-bool json::SAX::isPair (const std::string& input, std::string::size_type& cursor, SAX::Sink& sink)
-{
-  ignoreWhitespace (input, cursor);
-  auto backup = cursor;
-
-  if (isKey (input, cursor, sink))
-  {
-    if (isLiteral (input, ':', cursor))
-    {
-      if (isValue (input, cursor, sink))
-        return true;
-
-      error ("Error: Missing value at position ", cursor);
-    }
-    else
-      error ("Error: Missing ':' at position ", cursor);
-  }
-
-  cursor = backup;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// value  := <string>
-//         | <number>
-//         | <object>
-//         | <array>
-//         | 'true'
-//         | 'false'
-//         | 'null'
-bool json::SAX::isValue (const std::string& input, std::string::size_type& cursor, SAX::Sink& sink)
-{
-  ignoreWhitespace (input, cursor);
-
-  return isString (input, cursor, sink) ||
-         isNumber (input, cursor, sink) ||
-         isObject (input, cursor, sink) ||
-         isArray  (input, cursor, sink) ||
-         isBool   (input, cursor, sink) ||
-         isNull   (input, cursor, sink);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool json::SAX::isKey (const std::string& input, std::string::size_type& cursor, SAX::Sink& sink)
-{
-  ignoreWhitespace (input, cursor);
-
-  std::string value;
-  if (isStringValue (input, cursor, value))
-  {
-    sink.eventName (value);
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool json::SAX::isString (const std::string& input, std::string::size_type& cursor, SAX::Sink& sink)
-{
-  ignoreWhitespace (input, cursor);
-
-  std::string value;
-  if (isStringValue (input, cursor, value))
-  {
-    sink.eventValueString (value);
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// string := '"' [<chars> ...] '"'
-// chars  := <unicode>
-//         | '\"'
-//         | '\\'
-//         | '\/'
-//         | '\b'
-//         | '\f'
-//         | '\n'
-//         | '\r'
-//         | '\t'
-//         | \uXXXX
-bool json::SAX::isStringValue (const std::string& input, std::string::size_type& cursor, std::string& value)
-{
-  auto backup = cursor;
-
-  if (isLiteral (input, '"', cursor))
-  {
-    std::string word;
-    int c;
-    while ((c = input[cursor]))
-    {
-      // EOS.
-      if (c == '"')
-      {
-        ++cursor;
-        value = word;
-        return true;
-      }
-
-      // Unicode \uXXXX codepoint.
-      else if (input[cursor + 0] == '\\'  &&
-               input[cursor + 1] == 'u'   &&
-               isHexDigit (input[cursor + 2]) &&
-               isHexDigit (input[cursor + 3]) &&
-               isHexDigit (input[cursor + 4]) &&
-               isHexDigit (input[cursor + 5]))
-      {
-        word += utf8_character (
-                  hexToInt (
-                    input[cursor + 2],
-                    input[cursor + 3],
-                    input[cursor + 4],
-                    input[cursor + 5]));
-        cursor += 6;
-      }
-
-      // An escaped thing.
-      else if (c == '\\')
-      {
-        c = input[++cursor];
-        switch (c)
-        {
-        case '"':  word += (char) 0x22; ++cursor; break;
-        case '\'': word += (char) 0x27; ++cursor; break;
-        case '\\': word += (char) 0x5C; ++cursor; break;
-        case 'b':  word += (char) 0x08; ++cursor; break;
-        case 'f':  word += (char) 0x0C; ++cursor; break;
-        case 'n':  word += (char) 0x0A; ++cursor; break;
-        case 'r':  word += (char) 0x0D; ++cursor; break;
-        case 't':  word += (char) 0x09; ++cursor; break;
-        case 'v':  word += (char) 0x0B; ++cursor; break;
-
-        // This pass-through default case means that anything can be escaped
-        // harmlessly. In particular 'quote' is included, if it not one of the
-        // above characters.
-        default:   word += (char) c;    ++cursor; break;
-        }
-      }
-
-      // Ordinary character.
-      else
-      {
-        word += (char) c;
-        ++cursor;
-      }
-    }
-
-    error ("Error: Missing '\"' at position ", cursor);
-  }
-
-  cursor = backup;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// number := <int> [<frac>] [<exp>]
-bool json::SAX::isNumber (const std::string& input, std::string::size_type& cursor, SAX::Sink& sink)
-{
-  ignoreWhitespace (input, cursor);
-  auto backup = cursor;
-
-  std::string integerPart;
-  if (isInt (input, cursor, integerPart))
-  {
-    std::string fractionalPart;
-    isFrac (input, cursor, fractionalPart);
-
-    std::string exponentPart;
-    isExp (input, cursor, exponentPart);
-
-    // Does it fit in a long?
-    std::string combined = integerPart + fractionalPart + exponentPart;
-    char* end;
-    long longValue = strtol (combined.c_str (), &end, 10);
-    if (! *end && errno != ERANGE)
-    {
-      sink.eventValueInt (longValue);
-      return true;
-    }
-
-    // Does it fit in an unsigned long?
-    unsigned long ulongValue = strtoul (combined.c_str (), &end, 10);
-    if (! *end && errno != ERANGE)
-    {
-      sink.eventValueUint (ulongValue);
-      return true;
-    }
-
-    // If the above fail, allow this one to be capped at imax.
-    double doubleValue = strtod (combined.c_str (), &end);
-    if (! *end)
-    {
-      sink.eventValueDouble (doubleValue);
-      return true;
-    }
-  }
-
-  cursor = backup;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// int := ['-'] <digits>
-bool json::SAX::isInt (const std::string& input, std::string::size_type& cursor, std::string& value)
-{
-  auto backup = cursor;
-
-  isLiteral (input, '-', cursor);
-  if (isDigits (input, cursor))
-  {
-    value = input.substr (backup, cursor - backup);
-    return true;
-  }
-
-  // No restore necessary.
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// frac := '.' <digits>
-bool json::SAX::isFrac (const std::string& input, std::string::size_type& cursor, std::string& value)
-{
-  auto backup = cursor;
-
-  if (isLiteral (input, '.', cursor) &&
-      isDigits  (input,      cursor))
-  {
-    value = input.substr (backup, cursor - backup);
-    return true;
-  }
-
-  cursor = backup;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// digits := <digit> [<digit> ...]
-bool json::SAX::isDigits (const std::string& input, std::string::size_type& cursor)
-{
-  int c = input[cursor];
-  if (isDecDigit (c))
-  {
-    c = input[++cursor];
-
-    while (isDecDigit (c))
-      c = input[++cursor];
-
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// digit := 0x30 ('0') .. 0x39 ('9')
-bool json::SAX::isDecDigit (int c)
-{
-  return c >= 0x30 && c <= 0x39;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// hex := 0x30 ('0') .. 0x39 ('9')
-bool json::SAX::isHexDigit (int c)
-{
-  return (c >= 0x30 && c <= 0x39) ||
-         (c >= 0x61 && c <= 0x66) ||
-         (c >= 0x41 && c <= 0x46);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// exp := <e> <digits>
-bool json::SAX::isExp (const std::string& input, std::string::size_type& cursor, std::string& value)
-{
-  auto backup = cursor;
-
-  if (isE      (input, cursor) &&
-      isDigits (input, cursor))
-  {
-    value = input.substr (backup, cursor - backup);
-    return true;
-  }
-
-  cursor = backup;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// e := e
-//    | e+
-//    | e-
-//    | E
-//    | E+
-//    | E-
-bool json::SAX::isE (const std::string& input, std::string::size_type& cursor)
-{
-  int c = input[cursor];
-  if (c == 'e' ||
-      c == 'E')
-  {
-    c = input[++cursor];
-
-    if (c == '+' ||
-        c == '-')
-    {
-      ++cursor;
-    }
-
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool json::SAX::isBool (const std::string& input, std::string::size_type& cursor, SAX::Sink& sink)
-{
-  ignoreWhitespace (input, cursor);
-
-  if (input[cursor + 0] == 't' &&
-      input[cursor + 1] == 'r' &&
-      input[cursor + 2] == 'u' &&
-      input[cursor + 3] == 'e')
-  {
-    cursor += 4;
-    sink.eventValueBool (true);
-    return true;
-  }
-  else if (input[cursor + 0] == 'f' &&
-           input[cursor + 1] == 'a' &&
-           input[cursor + 2] == 'l' &&
-           input[cursor + 3] == 's' &&
-           input[cursor + 4] == 'e')
-  {
-    cursor += 5;
-    sink.eventValueBool (false);
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool json::SAX::isNull (const std::string& input, std::string::size_type& cursor, SAX::Sink& sink)
-{
-  ignoreWhitespace (input, cursor);
-
-  if (input[cursor + 0] == 'n' &&
-      input[cursor + 1] == 'u' &&
-      input[cursor + 2] == 'l' &&
-      input[cursor + 3] == 'l')
-  {
-    cursor += 4;
-    sink.eventValueNull ();
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool json::SAX::isLiteral (const std::string& input, char literal, std::string::size_type& cursor)
-{
-  ignoreWhitespace (input, cursor);
-
-  if (input[cursor] == literal)
-  {
-    ++cursor;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Converts '0'     -> 0
-//          '9'     -> 9
-//          'a'/'A' -> 10
-//          'f'/'F' -> 15
-int json::SAX::hexToInt (int c)
-{
-       if (c >= 0x30 && c <= 0x39) return (c - 0x30);
-  else if (c >= 0x41 && c <= 0x46) return (c - 0x41 + 10);
-  else                             return (c - 0x61 + 10);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int json::SAX::hexToInt (int c0, int c1, int c2, int c3)
-{
-  return (hexToInt (c0) << 12) +
-         (hexToInt (c1) << 8)  +
-         (hexToInt (c2) << 4)  +
-          hexToInt (c3);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void json::SAX::error (const std::string& message, std::string::size_type cursor)
-{
-  std::stringstream error;
-  error << message << cursor;
-  throw error.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
diff --git a/src/libshared/src/Table.cpp b/src/libshared/src/Table.cpp
deleted file mode 100644 (file)
index d1e63bf..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Table.h>
-#include <shared.h>
-#include <format.h>
-#include <utf8.h>
-#include <unistd.h>
-
-////////////////////////////////////////////////////////////////////////////////
-void Table::add (const std::string& col, bool alignLeft, bool wrap)
-{
-  _columns.push_back (col);
-  _align.push_back (alignLeft);
-  _wrap.push_back (wrap);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Table::addRow ()
-{
-  _data.push_back (std::vector <std::string> (_columns.size (), ""));
-  _color.push_back (std::vector <Color> (_columns.size (), Color::nocolor));
-  _oddness.push_back (_data.size () % 2 ? true : false);
-  return _data.size () - 1;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Table::addRowOdd ()
-{
-  _data.push_back (std::vector <std::string> (_columns.size (), ""));
-  _color.push_back (std::vector <Color> (_columns.size (), Color::nocolor));
-  _oddness.push_back (true);
-  return _data.size () - 1;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Table::addRowEven ()
-{
-  _data.push_back (std::vector <std::string> (_columns.size (), ""));
-  _color.push_back (std::vector <Color> (_columns.size (), Color::nocolor));
-  _oddness.push_back (false);
-  return _data.size () - 1;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Table::set (int row, int col, const std::string& value, const Color color)
-{
-  _data[row][col] = value;
-
-  if (color.nontrivial ())
-    _color[row][col] = color;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Table::set (int row, int col, int value, const Color color)
-{
-  std::string string_value = format (value);
-  _data[row][col] = string_value;
-
-  if (color.nontrivial ())
-    _color[row][col] = color;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Table::set (int row, int col, const Color color)
-{
-  if (color.nontrivial ())
-    _color[row][col] = color;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Table::render ()
-{
-  // Piped output disables color, unless overridden.
-  if (! _forceColor &&
-      ! isatty (STDOUT_FILENO))
-  {
-    _header     = Color ("");
-    _odd        = Color ("");
-    _even       = Color ("");
-    _intra_odd  = Color ("");
-    _intra_even = Color ("");
-    _extra_odd  = Color ("");
-    _extra_even = Color ("");
-
-    for (auto& row : _color)
-      for (auto& col : row)
-        col = Color ("");
-
-    _underline_headers = true;
-  }
-
-  // Determine minimal, ideal column widths.
-  std::vector <int> minimal;
-  std::vector <int> ideal;
-  for (unsigned int col = 0; col < _columns.size (); ++col)
-  {
-    // Headers factor in to width calculations.
-    unsigned int global_min = utf8_text_width (_columns[col]);
-    unsigned int global_ideal = global_min;
-
-    for (unsigned int row = 0; row < _data.size (); ++row)
-    {
-      // Determine minimum and ideal width for this column.
-      unsigned int min = 0;
-      unsigned int ideal = 0;
-      measureCell (_data[row][col], min, ideal);
-
-      if (min   > global_min)   global_min = min;
-      if (ideal > global_ideal) global_ideal = ideal;
-    }
-
-    minimal.push_back (global_min);
-    ideal.push_back (global_ideal);
-  }
-
-  // Sum the minimal widths.
-  int sum_minimal = 0;
-  for (const auto& c : minimal)
-    sum_minimal += c;
-
-  // Sum the ideal widths.
-  int sum_ideal = 0;
-  for (const auto& c : ideal)
-    sum_ideal += c;
-
-  // Calculate final column widths.
-  int overage = _width
-              - _left_margin
-              - (2 * _extra_padding)
-              - ((_columns.size () - 1) * _intra_padding);
-
-  std::vector <int> widths;
-  if (sum_ideal <= overage)
-    widths = ideal;
-  else if (sum_minimal > overage || overage < 0)
-    widths = minimal;
-  else if (overage > 0)
-  {
-    widths = minimal;
-    overage -= sum_minimal;
-
-    // Spread 'overage' among columns where width[i] < ideal[i]
-    while (overage)
-    {
-      for (unsigned int i = 0; i < _columns.size () && overage; ++i)
-      {
-        if (widths[i] < ideal[i])
-        {
-          ++widths[i];
-          --overage;
-        }
-      }
-    }
-  }
-
-  // Compose column headers.
-  unsigned int max_lines = 0;
-  std::vector <std::vector <std::string>> headers;
-  for (unsigned int c = 0; c < _columns.size (); ++c)
-  {
-    headers.push_back ({});
-    renderCell (headers[c], _columns[c], widths[c], _align[c], _wrap[c], _header);
-
-    if (headers[c].size () > max_lines)
-      max_lines = headers[c].size ();
-  }
-
-  // Output string.
-  std::string out;
-  _lines = 0;
-
-  // Render column headers.
-  std::string left_margin = std::string (_left_margin, ' ');
-  std::string extra       = std::string (_extra_padding, ' ');
-  std::string intra       = std::string (_intra_padding, ' ');
-
-  std::string extra_odd   = _extra_odd.colorize  (extra);
-  std::string extra_even  = _extra_even.colorize (extra);
-  std::string intra_odd   = _intra_odd.colorize  (intra);
-  std::string intra_even  = _intra_even.colorize (intra);
-
-  for (unsigned int i = 0; i < max_lines; ++i)
-  {
-    out += left_margin + extra;
-
-    for (unsigned int c = 0; c < _columns.size (); ++c)
-    {
-      if (c)
-        out += intra;
-
-      if (headers[c].size () < max_lines - i)
-        out += _header.colorize (std::string (widths[c], ' '));
-      else
-        out += headers[c][i];
-    }
-
-    out += extra;
-
-    // Trim right.
-    out.erase (out.find_last_not_of (" ") + 1);
-    out += '\n';
-
-    // Stop if the line limit is exceeded.
-    if (++_lines >= _truncate_lines && _truncate_lines != 0)
-      return out;
-  }
-
-  // Underline headers with ------ if necessary.
-  if (_underline_headers)
-  {
-    out += left_margin + extra;
-    for (unsigned int c = 0; c < _columns.size (); ++c)
-    {
-      if (c)
-        out += intra;
-
-      out += _header.colorize (std::string (widths[c], '-'));
-    }
-
-    out += '\n';
-  }
-
-  // Compose, render columns, in sequence.
-  _rows = 0;
-  std::vector <std::vector <std::string>> cells;
-  for (unsigned int row = 0; row < _data.size (); ++row)
-  {
-    max_lines = 0;
-
-    // Alternate rows based on |s % 2|
-    auto oddness = _oddness[row];
-    Color row_color = oddness ? _odd : _even;
-
-    // TODO row_color.blend (provided color);
-    // TODO Problem: colors for columns are specified, not rows,
-    //      therefore there are only cell colors, not intra colors.
-
-    Color cell_color;
-    for (unsigned int col = 0; col < _columns.size (); ++col)
-    {
-      cell_color = row_color;
-      cell_color.blend (_color[row][col]);
-
-      cells.push_back (std::vector <std::string> ());
-      renderCell (cells[col], _data[row][col], widths[col], _align[col], _wrap[col], cell_color);
-
-      if (cells[col].size () > max_lines)
-        max_lines = cells[col].size ();
-
-      if (_obfuscate)
-        for (auto& value : cells[col])
-          value = obfuscateText (value);
-    }
-
-    for (unsigned int i = 0; i < max_lines; ++i)
-    {
-      out += left_margin + (oddness ? extra_odd : extra_even);
-
-      for (unsigned int col = 0; col < _columns.size (); ++col)
-      {
-        if (col)
-        {
-          if (row_color.nontrivial ())
-            out += row_color.colorize (intra);
-          else
-            out += (oddness ? intra_odd : intra_even);
-        }
-
-        if (i < cells[col].size ())
-          out += cells[col][i];
-        else
-        {
-          cell_color = row_color;
-          cell_color.blend (_color[row][col]);
-          out += cell_color.colorize (std::string (widths[col], ' '));
-        }
-      }
-
-      out += (oddness ? extra_odd : extra_even);
-
-      // Trim right.
-      out.erase (out.find_last_not_of (" ") + 1);
-      out += '\n';
-
-      // Stop if the line limit is exceeded.
-      if (++_lines >= _truncate_lines && _truncate_lines != 0)
-        return out;
-    }
-
-    cells.clear ();
-
-    // Stop if the row limit is exceeded.
-    if (++_rows >= _truncate_rows && _truncate_rows != 0)
-      return out;
-  }
-
-  return out;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Table::measureCell (
-  const std::string& data,
-  unsigned int& minimum,
-  unsigned int& maximum) const
-{
-  std::string stripped = Color::strip (data);
-  maximum = longestLine (stripped);
-  minimum = longestWord (stripped);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Table::renderCell (
-  std::vector <std::string>& lines,
-  const std::string& value,
-  int width,
-  bool alignLeft,
-  bool wrap,
-  const Color& color) const
-{
-  if (wrap)
-  {
-    std::vector <std::string> raw;
-    wrapText (raw, value, width, false);
-
-    for (const auto& line : raw)
-      if (alignLeft)
-        lines.push_back (
-          color.colorize (
-            leftJustify (line, width)));
-      else
-        lines.push_back (
-          color.colorize (
-            rightJustify (line, width)));
-  }
-  else
-  {
-    if (alignLeft)
-      lines.push_back (
-        color.colorize (
-          leftJustify (value, width)));
-    else
-      lines.push_back (
-        color.colorize (
-          rightJustify (value, width)));
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
diff --git a/src/libshared/src/Table.h b/src/libshared/src/Table.h
deleted file mode 100644 (file)
index 977fa99..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_TABLE
-#define INCLUDED_TABLE
-
-#include <string>
-#include <vector>
-#include <Color.h>
-
-class Table
-{
-public:
-  // View specifications.
-  void add (const std::string& col, bool alignLeft = true, bool wrap = true);
-  void width (int width)               { _width = width;             }
-  void leftMargin (int margin)         { _left_margin = margin;      }
-  void colorHeader (const Color& c)    { _header = c;                }
-  void colorOdd (const Color& c)       { _odd = c;                   }
-  void colorEven (const Color& c)      { _even = c;                  }
-  void intraPadding (int padding)      { _intra_padding = padding;   }
-  void intraColorOdd (const Color& c)  { _intra_odd = c;             }
-  void intraColorEven (const Color& c) { _intra_even = c;            }
-  void extraPadding (int padding)      { _extra_padding = padding;   }
-  void extraColorOdd (const Color& c)  { _extra_odd = c;             }
-  void extraColorEven (const Color& c) { _extra_even = c;            }
-  void truncateLines (int n)           { _truncate_lines = n;        }
-  void truncateRows (int n)            { _truncate_rows = n;         }
-  void forceColor ()                   { _forceColor = true;         }
-  void obfuscate ()                    { _obfuscate = true;          }
-  void underlineHeaders ()             { _underline_headers = true;  }
-  int lines ()                         { return _lines;              }
-  int rows ()                          { return (int) _data.size (); }
-
-  // Data provision.
-  int addRow ();
-  int addRowOdd ();
-  int addRowEven ();
-  void set (int, int, const std::string&, const Color color = Color::nocolor);
-  void set (int, int, int, const Color color = Color::nocolor);
-  void set (int, int, const Color);
-
-  // View rendering.
-  std::string render ();
-
-private:
-  void measureCell (const std::string&, unsigned int&, unsigned int&) const;
-  void renderCell (std::vector <std::string>&, const std::string&, int, bool, bool, const Color&) const;
-
-private:
-  std::vector <std::vector <std::string>> _data;
-  std::vector <std::vector <Color>>       _color;
-  std::vector <std::string>               _columns;
-  std::vector <bool>                      _align;
-  std::vector <bool>                      _wrap;
-  std::vector <bool>                      _oddness;
-  int                                     _width             {0};
-  int                                     _left_margin       {0};
-  Color                                   _header            {0};
-  Color                                   _odd               {0};
-  Color                                   _even              {0};
-  int                                     _intra_padding     {1};
-  Color                                   _intra_odd         {0};
-  Color                                   _intra_even        {0};
-  int                                     _extra_padding     {0};
-  Color                                   _extra_odd         {0};
-  Color                                   _extra_even        {0};
-  int                                     _truncate_lines    {0};
-  int                                     _truncate_rows     {0};
-  bool                                    _forceColor        {false};
-  bool                                    _obfuscate         {false};
-  bool                                    _underline_headers {false};
-  int                                     _lines             {0};
-  int                                     _rows              {0};
-};
-
-#endif
diff --git a/src/libshared/src/Timer.cpp b/src/libshared/src/Timer.cpp
deleted file mode 100644 (file)
index a60e7f2..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Timer.h>
-
-////////////////////////////////////////////////////////////////////////////////
-Timer::Timer ()
-{
-  start ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Timer::start ()
-{
-  _start = std::chrono::high_resolution_clock::now ();
-  _end = {};
-  _running = true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Timer::stop ()
-{
-  if (_running)
-  {
-    _end = std::chrono::high_resolution_clock::now ();
-    _running = false;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-double Timer::total_s () const
-{
-  auto endpoint = _end;
-  if (_running)
-    endpoint = std::chrono::high_resolution_clock::now ();
-
-  return std::chrono::duration_cast<std::chrono::seconds>(endpoint - _start).count();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-double Timer::total_ms () const
-{
-  auto endpoint = _end;
-  if (_running)
-    endpoint = std::chrono::high_resolution_clock::now ();
-
-  return std::chrono::duration_cast<std::chrono::milliseconds>(endpoint - _start).count();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-double Timer::total_us () const
-{
-  auto endpoint = _end;
-  if (_running)
-    endpoint = std::chrono::high_resolution_clock::now ();
-
-  return std::chrono::duration_cast<std::chrono::microseconds>(endpoint - _start).count();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-double Timer::total_ns () const
-{
-  auto endpoint = _end;
-  if (_running)
-    endpoint = std::chrono::high_resolution_clock::now ();
-
-  return std::chrono::duration_cast<std::chrono::nanoseconds>(endpoint - _start).count();
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/Timer.h b/src/libshared/src/Timer.h
deleted file mode 100644 (file)
index 0c3b7dc..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_TIMER
-#define INCLUDED_TIMER
-
-#include <string>
-#include <chrono>
-
-class Timer
-{
-public:
-  Timer ();
-  ~Timer () = default;
-
-  void start ();
-  void stop ();
-
-  double total_s () const;
-  double total_ms () const;
-  double total_us () const;
-  double total_ns () const;
-
-private:
-  std::chrono::time_point<std::chrono::high_resolution_clock> _start   {};
-  std::chrono::time_point<std::chrono::high_resolution_clock> _end     {};
-  bool                                                        _running {false};
-};
-
-#endif
diff --git a/src/libshared/src/Tree.cpp b/src/libshared/src/Tree.cpp
deleted file mode 100644 (file)
index 91fd82b..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2010 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <Tree.h>
-#include <algorithm>
-#include <iostream>
-#include <sstream>
-#include <shared.h>
-#include <format.h>
-
-////////////////////////////////////////////////////////////////////////////////
-//  - Tree, Branch and Node are synonymous.
-//  - A Tree may contain any number of branches.
-//  - A Branch may contain any number of name/value pairs, unique by name.
-//  - The destructor will delete all branches recursively.
-//  - Tree::enumerate is a snapshot, and is invalidated by modification.
-//  - Branch sequence is preserved.
-void Tree::addBranch (std::shared_ptr <Tree> branch)
-{
-  if (! branch)
-    throw "Failed to allocate memory for parse tree.";
-
-  _branches.push_back (branch);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Tree::removeBranch (std::shared_ptr <Tree> branch)
-{
-  for (auto i = _branches.begin (); i != _branches.end (); ++i)
-  {
-    if (branch == *i)
-    {
-      _branches.erase (i);
-      return;
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Tree::removeAllBranches ()
-{
-  _branches.erase (_branches.begin (), _branches.end ());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Tree::replaceBranch (std::shared_ptr <Tree> from, std::shared_ptr <Tree> to)
-{
-  for (unsigned int i = 0; i < _branches.size (); ++i)
-  {
-    if (_branches[i] == from)
-    {
-      _branches[i] = to;
-      return;
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Accessor for attributes.
-void Tree::attribute (const std::string& name, const std::string& value)
-{
-  _attributes[name] = value;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Accessor for attributes.
-void Tree::attribute (const std::string& name, const int value)
-{
-  _attributes[name] = format (value);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Accessor for attributes.
-void Tree::attribute (const std::string& name, const double value)
-{
-  _attributes[name] = format (value, 1, 8);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Accessor for attributes.
-std::string Tree::attribute (const std::string& name)
-{
-  // Prevent autovivification.
-  auto i = _attributes.find (name);
-  if (i != _attributes.end ())
-    return i->second;
-
-  return "";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Tree::removeAttribute (const std::string& name)
-{
-  _attributes.erase (name);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Recursively builds a list of std::shared_ptr <Tree> objects, left to right,
-// depth first. The reason for the depth-first enumeration is that a client may
-// wish to traverse the tree and delete nodes.  With a depth-first iteration,
-// this is a safe mechanism, and a node pointer will never be dereferenced after
-// it has been deleted.
-void Tree::enumerate (std::vector <std::shared_ptr <Tree>>& all) const
-{
-  for (auto& i : _branches)
-  {
-    i->enumerate (all);
-    all.push_back (i);
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool Tree::hasTag (const std::string& tag) const
-{
-  return std::find (_tags.begin (), _tags.end (), tag) != _tags.end ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Tree::tag (const std::string& tag)
-{
-  if (! hasTag (tag))
-    _tags.push_back (tag);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void Tree::unTag (const std::string& tag)
-{
-  auto i = std::find (_tags.begin (), _tags.end (), tag);
-  if (i != _tags.end ())
-    _tags.erase (i);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Tree::countTags () const
-{
-  return _tags.size ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int Tree::count () const
-{
-  // This branch.
-  int total = 1;
-
-  // Recurse and count the branches.
-  for (auto& i : _branches)
-    total += i->count ();
-
-  return total;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::shared_ptr <Tree> Tree::find (const std::string& path)
-{
-  std::vector <std::string> elements = split (path, '/');
-
-  // Must start at the trunk.
-  auto cursor = std::make_shared <Tree> (*this);
-  auto it = elements.begin ();
-  if (cursor->_name != *it)
-    return nullptr;
-
-  // Perhaps the trunk is what is needed?
-  if (elements.size () == 1)
-    return cursor;
-
-  // Now look for the next branch.
-  for (++it; it != elements.end (); ++it)
-  {
-    bool found = false;
-
-    // If the cursor has a branch that matches *it, proceed.
-    for (auto i = cursor->_branches.begin (); i != cursor->_branches.end (); ++i)
-    {
-      if ((*i)->_name == *it)
-      {
-        cursor = *i;
-        found = true;
-        break;
-      }
-    }
-
-    if (! found)
-      return nullptr;
-  }
-
-  return cursor;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Tree::dumpNode (
-  const std::shared_ptr <Tree> t,
-  int depth) const
-{
-  std::stringstream out;
-
-  // Dump node
-  for (int i = 0; i < depth; ++i)
-    out << "  ";
-
-  out
-      // Useful for debugging tree node new/delete errors.
-      // << std::hex << t << " "
-      << "\033[1m" << t->_name << "\033[0m";
-
-  // Dump attributes.
-  std::string atts;
-  for (auto& a : t->_attributes)
-  {
-    if (atts != "")
-      atts += ' ';
-
-    atts += a.first + "='\033[33m" + a.second + "\033[0m'";
-  }
-
-  if (atts.length ())
-    out << ' ' << atts;
-
-  // Dump tags.
-  std::string tags;
-  for (auto& tag : t->_tags)
-  {
-    if (tags.length ())
-      tags += ' ';
-
-    tags += "\033[32m" + tag + "\033[0m";
-  }
-
-  if (tags.length ())
-    out << ' ' << tags;
-  out << '\n';
-
-  // Recurse for branches.
-  for (auto& b : t->_branches)
-    out << dumpNode (b, depth + 1);
-
-  return out.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string Tree::dump () const
-{
-  std::stringstream out;
-  out << "Tree (" << count () << " nodes)\n"
-      << dumpNode (std::make_shared <Tree> (*this), 1);
-
-  return out.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
diff --git a/src/libshared/src/Tree.h b/src/libshared/src/Tree.h
deleted file mode 100644 (file)
index 4444d75..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2010 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_TREE
-#define INCLUDED_TREE
-
-#include <map>
-#include <vector>
-#include <string>
-#include <memory>
-
-class Tree;
-
-class Tree
-{
-public:
-  void addBranch (std::shared_ptr <Tree>);
-  void removeBranch (std::shared_ptr <Tree>);
-  void removeAllBranches ();
-  void replaceBranch (std::shared_ptr <Tree>, std::shared_ptr <Tree>);
-
-  void attribute (const std::string&, const std::string&);
-  void attribute (const std::string&, const int);
-  void attribute (const std::string&, const double);
-  std::string attribute (const std::string&);
-  void removeAttribute (const std::string&);
-
-  void enumerate (std::vector <std::shared_ptr <Tree>>& all) const;
-
-  bool hasTag (const std::string&) const;
-  void tag (const std::string&);
-  void unTag (const std::string&);
-  int countTags () const;
-
-  int count () const;
-
-  std::shared_ptr <Tree> find (const std::string&);
-
-  std::string dump () const;
-
-private:
-  std::string dumpNode (const std::shared_ptr <Tree>, int) const;
-
-public:
-  std::string                          _name       {"Unknown"};  // Name.
-  std::vector <std::shared_ptr <Tree>> _branches   {};           // Children.
-  std::map <std::string, std::string>  _attributes {};           // Attributes (name->value).
-  std::vector <std::string>            _tags       {};           // Tags (tag, tag ...).
-};
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/format.cpp b/src/libshared/src/format.cpp
deleted file mode 100644 (file)
index 82e67a7..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <format.h>
-#include <utf8.h>
-#include <algorithm>
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-#include <cctype>
-#include <strings.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/select.h>
-#include <time.h>
-#include <csignal>
-#include <cmath>
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string format (std::string& value)
-{
-  return value;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string format (const char* value)
-{
-  std::string s (value);
-  return s;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string formatHex (int value)
-{
-  std::stringstream s;
-  s.setf (std::ios::hex, std::ios::basefield);
-  s << value;
-  return s.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string format (float value, int width, int precision)
-{
-  std::stringstream s;
-  s.width (width);
-  s.precision (precision);
-  if (0 < value && value < 1)
-  {
-    // For value close to zero, width - 2 (2 accounts for the first zero and
-    // the dot) is the number of digits after zero that are significant
-    double factor = 1;
-    for (int i = 2; i < width; i++)
-      factor *= 10;
-    value = roundf (value * factor) / factor;
-  }
-  s << value;
-  return s.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string format (double value, int width, int precision)
-{
-  std::stringstream s;
-  s.width (width);
-  s.precision (precision);
-  if (0 < value && value < 1)
-  {
-    // For value close to zero, width - 2 (2 accounts for the first zero and
-    // the dot) is the number of digits after zero that are significant
-    double factor = 1;
-    for (int i = 2; i < width; i++)
-      factor *= 10;
-    value = round (value * factor) / factor;
-  }
-  s << value;
-  return s.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string format (double value)
-{
-  std::stringstream s;
-  s << std::fixed << value;
-  return s.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void replace_positional (
-  std::string& fmt,
-  const std::string& from,
-  const std::string& to)
-{
-  std::string::size_type pos = 0;
-  while ((pos = fmt.find (from, pos)) != std::string::npos)
-  {
-    fmt.replace (pos, from.length (), to);
-    pos += to.length ();
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string leftJustify (const int input, const int width)
-{
-  std::stringstream s;
-  s << input;
-  std::string output = s.str ();
-  return output + std::string (width - output.length (), ' ');
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string leftJustify (const std::string& input, const int width)
-{
-  return input + std::string (width - utf8_text_width (input), ' ');
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string rightJustifyZero (const int input, const int width)
-{
-  std::stringstream s;
-  s << std::setw (width) << std::setfill ('0') << input;
-  return s.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string rightJustify (const int input, const int width)
-{
-  std::stringstream s;
-  s << std::setw (width) << std::setfill (' ') << input;
-  return s.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string rightJustify (const std::string& input, const int width)
-{
-  unsigned int len = utf8_text_width (input);
-  return (((unsigned int) width > len)
-           ? std::string (width - len, ' ')
-           : "")
-         + input;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string commify (const std::string& data)
-{
-  // First scan for decimal point and end of digits.
-  int decimalPoint = -1;
-  int end          = -1;
-
-  int i;
-  for (int i = 0; i < (int) data.length (); ++i)
-  {
-    if (isdigit (data[i]))
-      end = i;
-
-    if (data[i] == '.')
-      decimalPoint = i;
-  }
-
-  std::string result;
-  if (decimalPoint != -1)
-  {
-    // In reverse order, transfer all digits up to, and including the decimal
-    // point.
-    for (i = (int) data.length () - 1; i >= decimalPoint; --i)
-      result += data[i];
-
-    int consecutiveDigits = 0;
-    for (; i >= 0; --i)
-    {
-      if (isdigit (data[i]))
-      {
-        result += data[i];
-
-        if (++consecutiveDigits == 3 && i && isdigit (data[i - 1]))
-        {
-          result += ',';
-          consecutiveDigits = 0;
-        }
-      }
-      else
-        result += data[i];
-    }
-  }
-  else
-  {
-    // In reverse order, transfer all digits up to, but not including the last
-    // digit.
-    for (i = (int) data.length () - 1; i > end; --i)
-      result += data[i];
-
-    int consecutiveDigits = 0;
-    for (; i >= 0; --i)
-    {
-      if (isdigit (data[i]))
-      {
-        result += data[i];
-
-        if (++consecutiveDigits == 3 && i && isdigit (data[i - 1]))
-        {
-          result += ',';
-          consecutiveDigits = 0;
-        }
-      }
-      else
-        result += data[i];
-    }
-  }
-
-  // reverse result into data.
-  std::string done;
-  for (int i = (int) result.length () - 1; i >= 0; --i)
-    done += result[i];
-
-  return done;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Convert a quantity in bytes to a more readable format.
-std::string formatBytes (size_t bytes)
-{
-  char formatted[24];
-
-       if (bytes >=  995000000) sprintf (formatted, "%.1f GiB", bytes / 1000000000.0);
-  else if (bytes >=     995000) sprintf (formatted, "%.1f MiB", bytes /    1000000.0);
-  else if (bytes >=        995) sprintf (formatted, "%.1f KiB", bytes /       1000.0);
-  else                          sprintf (formatted, "%d B",     (int)bytes);
-
-  return commify (formatted);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Convert a quantity in seconds to a more readable format.
-std::string formatTime (time_t seconds)
-{
-  char formatted[24];
-  float days = (float) seconds / 86400.0;
-
-       if (seconds >= 86400 * 365) sprintf (formatted, "%.1f y", (days / 365.0));
-  else if (seconds >= 86400 * 84)  sprintf (formatted, "%1d mo", (int) (days / 30));
-  else if (seconds >= 86400 * 13)  sprintf (formatted, "%d wk",  (int) (float) (days / 7.0));
-  else if (seconds >= 86400)       sprintf (formatted, "%d d",   (int) days);
-  else if (seconds >= 3600)        sprintf (formatted, "%d h",   (int) (seconds / 3600));
-  else if (seconds >= 60)          sprintf (formatted, "%d m",   (int) (seconds / 60));
-  else if (seconds >= 1)           sprintf (formatted, "%d s",   (int) seconds);
-  else                             strcpy (formatted, "-");
-
-  return std::string (formatted);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string printable (const std::string& input)
-{
-  // Sanitize 'message'.
-  std::string sanitized = input;
-  std::string::size_type bad;
-  while ((bad = sanitized.find ("\r")) != std::string::npos)
-    sanitized.replace (bad, 1, "\\r");
-
-  while ((bad = sanitized.find ("\n")) != std::string::npos)
-    sanitized.replace (bad, 1, "\\n");
-
-  while ((bad = sanitized.find ("\f")) != std::string::npos)
-    sanitized.replace (bad, 1, "\\f");
-
-  while ((bad = sanitized.find ("\t")) != std::string::npos)
-    sanitized.replace (bad, 1, "\\t");
-
-  while ((bad = sanitized.find ("\v")) != std::string::npos)
-    sanitized.replace (bad, 1, "\\v");
-
-  return sanitized;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string printable (char input)
-{
-  // Sanitize 'message'.
-  char stringized[2] = {0};
-  stringized[0] = input;
-
-  std::string sanitized = stringized;
-  switch (input)
-  {
-  case '\r': sanitized = "\\r"; break;
-  case '\n': sanitized = "\\n"; break;
-  case '\f': sanitized = "\\f"; break;
-  case '\t': sanitized = "\\t"; break;
-  case '\v': sanitized = "\\v"; break;
-  default:   sanitized = input; break;
-  }
-
-  return sanitized;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Iterate over the input, converting text to 'x'.
-// Does not modify color codes.
-std::string obfuscateText (const std::string& input)
-{
-  std::stringstream output;
-  std::string::size_type i = 0;
-  int character;
-  bool inside = false;
-
-  while ((character = utf8_next_char (input, i)))
-  {
-    if (inside)
-    {
-      output << (char) character;
-
-      if (character == 'm')
-        inside = false;
-    }
-    else
-    {
-      if (character == 033)
-        inside = true;
-
-      if (inside || character == ' ')
-        output << (char) character;
-      else
-        output << 'x';
-    }
-  }
-
-  return output.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/format.h b/src/libshared/src/format.h
deleted file mode 100644 (file)
index 57f6236..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_FORMAT
-#define INCLUDED_FORMAT
-
-#include <sstream>
-#include <algorithm>
-#include <string>
-#include <vector>
-
-const std::string format (std::string&);
-const std::string format (const char*);
-const std::string formatHex (int);
-const std::string format (float, int, int);
-const std::string format (double, int, int);
-const std::string format (double);
-
-void replace_positional (std::string&, const std::string&, const std::string&);
-
-template<typename T>
-const std::string format (T value)
-{
-    std::stringstream s;
-    s << value;
-    return s.str ();
-}
-
-template<typename T>
-const std::string format (int fmt_num, const std::string& fmt, T arg)
-{
-    std::string output = fmt;
-    replace_positional (output, '{' + format (fmt_num) + '}', format (arg));
-    return output;
-}
-
-template<typename T, typename... Args>
-const std::string format (int fmt_num, const std::string& fmt, T arg, Args... args)
-{
-    const std::string fmt_replaced (format (fmt_num, fmt, arg));
-    return format (fmt_num+1, fmt_replaced, args...);
-}
-
-template<typename... Args>
-const std::string format (const std::string& fmt, Args... args)
-{
-    return format (1, fmt, args...);
-}
-
-std::string leftJustify (const int, const int);
-std::string leftJustify (const std::string&, const int);
-std::string rightJustifyZero (const int, const int);
-std::string rightJustify (const int, const int);
-std::string rightJustify (const std::string&, const int);
-
-std::string commify (const std::string&);
-std::string formatBytes (size_t);
-std::string formatTime (time_t);
-std::string printable (const std::string&);
-std::string printable (char);
-
-std::string obfuscateText (const std::string&);
-
-#endif
diff --git a/src/libshared/src/ip.cpp b/src/libshared/src/ip.cpp
deleted file mode 100644 (file)
index 511e6f4..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <shared.h>
-#include <cctype>
-
-static bool isPort (const std::string&, unsigned int&);
-static bool isChar (const std::string&, char, unsigned int&);
-static bool isEOS (const std::string&, unsigned int&);
-static bool isIPv4Block (const std::string&, unsigned int&);
-static bool isIPv4BlockSet (const std::string&, unsigned int&);
-static bool isIPv6Block (const std::string&, unsigned int&);
-static bool isIPv6BlockSet (const std::string&, unsigned int&);
-
-////////////////////////////////////////////////////////////////////////////////
-static bool isPort (const std::string& input, unsigned int& c)
-{
-  auto start = c;
-  while (std::isdigit (input[c]))
-    ++c;
-
-  return c - start > 0 &&
-         c - start < 6;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-static bool isChar (const std::string& input, char character, unsigned int& c)
-{
-  if (input[c] == character)
-  {
-    ++c;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-static bool isEOS (const std::string& input, unsigned int& c)
-{
-  return c >= input.length ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-static bool isIPv4Block (const std::string& input, unsigned int& c)
-{
-  auto start = c;
-  while (std::isdigit (input[c]))
-    ++c;
-
-  if (c - start > 0 &&
-      c - start < 4)
-  {
-    auto byte = std::stoi (input.substr (start, c - start));
-    if (byte < 256)
-      return true;
-  }
-
-  c = start;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-static bool isIPv4BlockSet (const std::string& input, unsigned int& c)
-{
-  auto start = c;
-
-  if (isIPv4Block (input,      c) &&
-      isChar      (input, '.', c) &&
-      isIPv4Block (input,      c) &&
-      isChar      (input, '.', c) &&
-      isIPv4Block (input,      c) &&
-      isChar      (input, '.', c) &&
-      isIPv4Block (input,      c))
-  {
-
-    return true;
-  }
-
-  c = start;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-static bool isIPv6Block (const std::string& input, unsigned int& c)
-{
-  auto start = c;
-  while (std::isxdigit (input[c]))
-    ++c;
-
-  if (c - start > 0 &&
-      c - start < 5)
-  {
-    return true;
-  }
-
-  c = start;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// at least one non-empty block, or '::'
-// at least two colons
-// 8 or less blocks
-static bool isIPv6BlockSet (const std::string& input, unsigned int& c)
-{
-  auto start = c;
-  int count_colons {0};
-  int count_blocks {0};
-
-  while (1)
-  {
-    if (isEOS (input, c))
-    {
-      if (c == start)
-        return false;
-
-      break;
-    }
-
-    else if (isChar (input, ':', c))
-      ++count_colons;
-
-    else if (isIPv4BlockSet (input, c))
-      ++count_blocks;
-
-    else if (isIPv6Block (input, c))
-      ++count_blocks;
-
-    else if (isChar (input, '.', c) ||
-             isChar (input, ']', c))
-    {
-      --c;
-      break;
-    }
-
-    else
-      break;
-  }
-
-  if (count_colons >= 2 &&
-      count_colons <= 7 &&
-      ((count_blocks == 0 && input.substr (start, c) == "::") || count_blocks >= 1) &&
-      count_blocks <= 8)
-  {
-    return true;
-  }
-
-  c = start;
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// <address>:<port>
-// <address>
-bool isIPv4Address (const std::string& input, std::string& address, int& port)
-{
-  unsigned int c = 0;
-  if (isIPv4BlockSet (input, c))
-  {
-    auto colon = c;
-    if (isChar (input, ':', c))
-      if (! isPort (input, c))
-        return false;
-
-    if (isEOS (input, c))
-    {
-      address = input.substr (0, std::min (c, colon));
-      if (! isEOS (input, colon))
-        port = std::stoi (input.substr (colon + 1));
-
-      return true;
-    }
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//  [<address>]:<port>
-//  <address>
-bool isIPv6Address (const std::string& input, std::string& address, int& port)
-{
-  unsigned int c = 0;
-
-  if (isChar         (input, '[', c) &&
-      isIPv6BlockSet (input,      c) &&
-      isChar         (input, ']', c))
-  {
-    auto colon = c;
-    if (isChar         (input, ':', c) &&
-        isPort         (input,      c) &&
-        isEOS          (input,      c))
-    {
-      address = input.substr (1, colon - 2);
-      port = std::stoi (input.substr (colon + 1));
-      return true;
-    }
-  }
-
-  c = 0;
-  if (isIPv6BlockSet (input, c) &&
-      isEOS          (input, c))
-  {
-    address = input;
-    port = 0;
-    return true;
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/lex.cpp b/src/libshared/src/lex.cpp
deleted file mode 100644 (file)
index 2a96862..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-
-#include <iostream>
-#include <Lexer.h>
-
-int main (int argc, char** argv)
-{
-  for (auto i = 1; i < argc; i++)
-  {
-    std::cout << "argument '" << argv[i] << "'\n";
-
-    Lexer l (argv[i]);
-    std::string token;
-    Lexer::Type type;
-    while (l.token (token, type))
-      std::cout << "  token '" << token << "' " << Lexer::typeToString (type) << "\n";
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/shared.cpp b/src/libshared/src/shared.cpp
deleted file mode 100644 (file)
index 14f4c2c..0000000
+++ /dev/null
@@ -1,861 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <shared.h>
-#include <utf8.h>
-#include <algorithm>
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-#include <cctype>
-#include <strings.h>
-#include <unistd.h>
-#include <sys/select.h>
-#include <cerrno>
-#include <csignal>
-#include <cmath>
-#include <cstring>
-#include <sys/wait.h>
-#include <format.h>
-
-///////////////////////////////////////////////////////////////////////////////
-void wrapText (
-  std::vector <std::string>& lines,
-  const std::string& text,
-  const int width,
-  bool hyphenate)
-{
-  std::string line;
-  unsigned int offset = 0;
-  while (extractLine (line, text, width, hyphenate, offset))
-    lines.push_back (line);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Split in a separator. Two adjacent separators means empty token.
-std::vector <std::string> split (const std::string& input, const char delimiter)
-{
-  std::vector <std::string> results;
-  std::string::size_type start = 0;
-  std::string::size_type i;
-  while ((i = input.find (delimiter, start)) != std::string::npos)
-  {
-    results.push_back (input.substr (start, i - start));
-    start = i + 1;
-  }
-
-  if (input.length ())
-    results.push_back (input.substr (start));
-
-  return results;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Split on words. Adjacent separators collapsed.
-std::vector <std::string> split (const std::string& input)
-{
-  static std::string delims = " \t\n\f\r";
-  std::vector <std::string> results;
-
-  std::string::size_type start = 0;
-  std::string::size_type end;
-  while ((start = input.find_first_not_of (delims, start)) != std::string::npos)
-  {
-    if ((end = input.find_first_of (delims, start)) != std::string::npos)
-    {
-      results.push_back (input.substr (start, end - start));
-      start = end;
-    }
-    else
-    {
-      results.push_back (input.substr (start));
-      start = std::string::npos;
-    }
-  }
-
-  return results;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string join (
-  const std::string& separator,
-  const std::vector<int>& items)
-{
-  std::stringstream s;
-  auto size = items.size ();
-  for (unsigned int i = 0; i < size; ++i)
-  {
-    if (i)
-      s << separator;
-
-    s << items[i];
-  }
-
-  return s.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string join (
-  const std::string& separator,
-  const std::vector<std::string>& items)
-{
-  std::stringstream s;
-  auto size = items.size ();
-  for (unsigned int i = 0; i < size; ++i)
-  {
-    if (i)
-      s << separator;
-
-    s << items[i];
-  }
-
-  return s.str ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string str_replace (
-  const std::string &str,
-  const std::string& search,
-  const std::string& replacement)
-{
-  std::string modified {str};
-  std::string::size_type pos = 0;
-  while ((pos = modified.find (search, pos)) != std::string::npos)
-  {
-    modified.replace (pos, search.length (), replacement);
-    pos += replacement.length ();
-  }
-
-  return modified;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string trim (const std::string& input, const std::string& edible)
-{
-  auto start = input.find_first_not_of (edible);
-  auto end   = input.find_last_not_of  (edible);
-
-  if (start == std::string::npos)
-    return "";
-
-  if (end == std::string::npos)
-    return input.substr (start);
-
-  return input.substr (start, end - start + 1);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string ltrim (const std::string& input, const std::string& edible)
-{
-  auto start = input.find_first_not_of (edible);
-  if (start == std::string::npos)
-    return "";
-
-  return input.substr (start);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string rtrim (const std::string& input, const std::string& edible)
-{
-  if (input.find_first_not_of (edible) == std::string::npos)
-    return "";
-
-  auto end = input.find_last_not_of (edible);
-  if (end == std::string::npos)
-    return input;
-
-  return input.substr (0, end + 1);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int longestWord (const std::string& input)
-{
-  int longest = 0;
-  int length = 0;
-  std::string::size_type i = 0;
-  int character;
-
-  while ((character = utf8_next_char (input, i)))
-  {
-    if (character == ' ')
-    {
-      if (length > longest)
-        longest = length;
-
-      length = 0;
-    }
-    else
-      length += mk_wcwidth (character);
-  }
-
-  if (length > longest)
-    longest = length;
-
-  return longest;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int longestLine (const std::string& input)
-{
-  int longest = 0;
-  int length = 0;
-  std::string::size_type i = 0;
-  int character;
-
-  while ((character = utf8_next_char (input, i)))
-  {
-    if (character == '\n')
-    {
-      if (length > longest)
-        longest = length;
-
-      length = 0;
-    }
-    else
-      length += mk_wcwidth (character);
-  }
-
-  if (length > longest)
-    longest = length;
-
-  return longest;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Walk the input text looking for a break point.  A break point is one of:
-//   - EOS
-//   - \n
-//   - last space before 'length' characters
-//   - last punctuation (, ; . :) before 'length' characters, even if not
-//     followed by a space
-//   - first 'length' characters
-//
-// text       "one two three\n  four"
-// bytes       0123456789012 3456789
-// characters  1234567890a23 4567890
-//
-// leading_ws
-// ws             ^   ^       ^^
-// punct
-// break                     ^
-bool extractLine (
-  std::string& line,
-  const std::string& text,
-  int width,
-  bool hyphenate,
-  unsigned int& offset)
-{
-  // Terminate processing.
-  // Note: bytes vs bytes.
-  if (offset >= text.length ())
-    return false;
-
-  std::string::size_type last_last_bytes = offset;
-  std::string::size_type last_bytes = offset;
-  std::string::size_type bytes = offset;
-  unsigned int last_ws = 0;
-  int character;
-  int char_width = 0;
-  int line_width = 0;
-  while (1)
-  {
-    last_last_bytes = last_bytes;
-    last_bytes = bytes;
-    character = utf8_next_char (text, bytes);
-
-    if (character == 0 ||
-        character == '\n')
-    {
-      line = text.substr (offset, last_bytes - offset);
-      offset = bytes;
-      break;
-    }
-    else if (character == ' ')
-      last_ws = last_bytes;
-
-    char_width = mk_wcwidth (character);
-    if (line_width + char_width > width)
-    {
-      int last_last_character = text[last_last_bytes];
-      int last_character = text[last_bytes];
-
-      // [case 1] one| two --> last_last != 32, last == 32, ws == 0
-      if (last_last_character != ' ' &&
-          last_character      == ' ')
-      {
-        line = text.substr (offset, last_bytes - offset);
-        offset = last_bytes + 1;
-        break;
-      }
-
-      // [case 2] one |two --> last_last == 32, last != 32, ws != 0
-      else if (last_last_character == ' ' &&
-               last_character      != ' ' &&
-               last_ws             != 0)
-      {
-        line = text.substr (offset, last_bytes - offset - 1);
-        offset = last_bytes;
-        break;
-      }
-
-      else if (last_last_character != ' ' &&
-               last_character      != ' ')
-      {
-        // [case 3] one t|wo --> last_last != 32, last != 32, ws != 0
-        if (last_ws != 0)
-        {
-          line = text.substr (offset, last_ws - offset);
-          offset = last_ws + 1;
-          break;
-        }
-        // [case 4] on|e two --> last_last != 32, last != 32, ws == 0
-        else
-        {
-          if (hyphenate)
-          {
-            line = text.substr (offset, last_bytes - offset - 1) + '-';
-            offset = last_last_bytes;
-          }
-          else
-          {
-            line = text.substr (offset, last_bytes - offset);
-            offset = last_bytes;
-          }
-        }
-
-        break;
-      }
-    }
-
-    line_width += char_width;
-  }
-
-  return true;
-}
-/*
-
-TODO Resolve above against below, which is from Taskwarrior 2.6.0, and known to
-     be wrong.
-////////////////////////////////////////////////////////////////////////////////
-// Break UTF8 text into chunks no more than width characters.
-bool extractLine (
-  std::string& line,
-  const std::string& text,
-  int width,
-  bool hyphenate,
-  unsigned int& offset)
-{
-  // Terminate processing.
-  if (offset >= text.length ())
-    return false;
-
-  int line_length                     {0};
-  int character                       {0};
-  std::string::size_type lastWordEnd  {std::string::npos};
-  bool something                      {false};
-  std::string::size_type cursor       {offset};
-  std::string::size_type prior_cursor {offset};
-  while ((character = utf8_next_char (text, cursor)))
-  {
-    // Premature EOL.
-    if (character == '\n')
-    {
-      line = text.substr (offset, line_length);
-      offset = cursor;
-      return true;
-    }
-
-    if (! Lexer::isWhitespace (character))
-    {
-      something = true;
-      if (! text[cursor] || Lexer::isWhitespace (text[cursor]))
-        lastWordEnd = prior_cursor;
-    }
-
-    line_length += mk_wcwidth (character);
-
-    if (line_length >= width)
-    {
-      // Backtrack to previous word end.
-      if (lastWordEnd != std::string::npos)
-      {
-        // Eat one WS after lastWordEnd.
-        std::string::size_type lastBreak = lastWordEnd;
-        utf8_next_char (text, lastBreak);
-
-        // Position offset at following char.
-        std::string::size_type nextStart = lastBreak;
-        utf8_next_char (text, nextStart);
-
-        line = text.substr (offset, lastBreak - offset);
-        offset = nextStart;
-        return true;
-      }
-
-      // No backtrack, possible hyphenation.
-      else if (hyphenate)
-      {
-        line = text.substr (offset, prior_cursor - offset) + '-';
-        offset = prior_cursor;
-        return true;
-      }
-
-      // No hyphenation, just truncation.
-      else
-      {
-        line = text.substr (offset, cursor - offset);
-        offset = cursor;
-        return true;
-      }
-    }
-
-    // Hindsight.
-    prior_cursor = cursor;
-  }
-
-  // Residual text.
-  if (something)
-  {
-    line = text.substr (offset, cursor - offset);
-     offset = cursor;
-    return true;
-  }
-
-  return false;
-}
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-bool compare (
-  const std::string& left,
-  const std::string& right,
-  bool sensitive /*= true*/)
-{
-  // Use strcasecmp if required.
-  if (! sensitive)
-    return strcasecmp (left.c_str (), right.c_str ()) == 0 ? true : false;
-
-  // Otherwise, just use std::string::operator==.
-  return left == right;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool closeEnough (
-  const std::string& reference,
-  const std::string& attempt,
-  unsigned int minLength /* = 0 */)
-{
-  // An exact match is accepted first.
-  if (compare (reference, attempt, false))
-    return true;
-
-  // A partial match will suffice.
-  if (attempt.length () < reference.length () &&
-      attempt.length () >= minLength)
-    return compare (reference.substr (0, attempt.length ()), attempt, false);
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int matchLength (
-  const std::string& left,
-  const std::string& right)
-{
-  int pos = 0;
-  while (left[pos] &&
-         right[pos] &&
-         left[pos] == right[pos])
-    ++pos;
-
-  return pos;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string::size_type find (
-  const std::string& text,
-  const std::string& pattern,
-  bool sensitive)
-{
-  return find (text, pattern, 0, sensitive);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string::size_type find (
-  const std::string& text,
-  const std::string& pattern,
-  std::string::size_type begin,
-  bool sensitive)
-{
-  // Implement a sensitive find, which is really just a loop withing a loop,
-  // comparing lower-case versions of each character in turn.
-  if (!sensitive)
-  {
-    // Handle empty pattern.
-    const char* p = pattern.c_str ();
-    size_t len = pattern.length ();
-    if (len == 0)
-      return 0;
-
-    // Handle bad begin.
-    if (begin >= text.length ())
-      return std::string::npos;
-
-    // Evaluate these once, for performance reasons.
-    const char* start = text.c_str ();
-    const char* t = start + begin;
-    const char* end = start + text.size ();
-
-    for (; t <= end - len; ++t)
-    {
-      int diff = 0;
-      for (size_t i = 0; i < len; ++i)
-        if ((diff = tolower (t[i]) - tolower (p[i])))
-          break;
-
-      // diff == 0 means there was no break from the loop, which only occurs
-      // when a difference is detected.  Therefore, the loop terminated, and
-      // diff is zero.
-      if (diff == 0)
-        return t - start;
-    }
-
-    return std::string::npos;
-  }
-
-  // Otherwise, just use std::string::find.
-  return text.find (pattern, begin);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string lowerCase (const std::string& input)
-{
-  std::string output {input};
-  std::transform (output.begin (), output.end (), output.begin (), tolower);
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string upperCase (const std::string& input)
-{
-  std::string output {input};
-  std::transform (output.begin (), output.end (), output.begin (), toupper);
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string upperCaseFirst (const std::string& input)
-{
-  std::string output {input};
-  output[0] = toupper (output[0]);
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int autoComplete (
-  const std::string& partial,
-  const std::vector<std::string>& list,
-  std::vector<std::string>& matches,
-  int minimum/* = 1*/)
-{
-  matches.clear ();
-
-  // Handle trivial case.
-  unsigned int length = partial.length ();
-  if (length)
-  {
-    for (auto& item : list)
-    {
-      // An exact match is a special case.  Assume there is only one exact match
-      // and return immediately.
-      if (partial == item)
-      {
-        matches.clear ();
-        matches.push_back (item);
-        return 1;
-      }
-
-      // Maintain a list of partial matches.
-      else if (length >= (unsigned) minimum &&
-               length <= item.length ()     &&
-               partial == item.substr (0, length))
-        matches.push_back (item);
-    }
-  }
-
-  return matches.size ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Uses std::getline, because std::cin eats leading whitespace, and that means
-// that if a newline is entered, std::cin eats it and never returns from the
-// "std::cin >> answer;" line, but it does display the newline.  This way, with
-// std::getline, the newline can be detected, and the prompt re-written.
-static void signal_handler (int s)
-{
-  if (s == SIGINT)
-  {
-    std::cout << "\n\nInterrupted: No changes made.\n";
-    exit (1);
-  }
-}
-
-bool confirm (const std::string& question)
-{
-  std::vector <std::string> options {"yes", "no"};
-  std::vector <std::string> matches;
-
-  signal (SIGINT, signal_handler);
-
-  do
-  {
-    std::cout << question
-              << " (yes/no) ";
-
-    std::string answer {""};
-    std::getline (std::cin, answer);
-    answer = std::cin.eof () ? "no" : lowerCase (trim (answer));
-
-    autoComplete (answer, options, matches, 1); // Hard-coded 1.
-  }
-  while (! std::cin.eof () && matches.size () != 1);
-
-  signal (SIGINT, SIG_DFL);
-  return matches.size () == 1 && matches[0] == "yes" ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Run a binary with args, capturing output.
-int execute (
-  const std::string& executable,
-  const std::vector <std::string>& args,
-  const std::string& input,
-  std::string& output)
-{
-  pid_t pid;
-  int pin[2], pout[2];
-  fd_set rfds, wfds;
-  struct timeval tv;
-  int select_retval, read_retval, write_retval;
-  char buf[16384];
-  unsigned int written;
-  const char* input_cstr = input.c_str ();
-
-  if (signal (SIGPIPE, SIG_IGN) == SIG_ERR) // Handled locally with EPIPE.
-    throw std::string (std::strerror (errno));
-
-  if (pipe (pin) == -1)
-    throw std::string (std::strerror (errno));
-
-  if (pipe (pout) == -1)
-    throw std::string (std::strerror (errno));
-
-  if ((pid = fork ()) == -1)
-    throw std::string (std::strerror (errno));
-
-  if (pid == 0)
-  {
-    // This is only reached in the child
-    close (pin[1]);   // Close the write end of the input pipe.
-    close (pout[0]);  // Close the read end of the output pipe.
-
-    // Parent writes to pin[1]. Set read end pin[0] as STDIN for child.
-    if (dup2 (pin[0], STDIN_FILENO) == -1)
-      throw std::string (std::strerror (errno));
-    close (pin[0]);
-
-    // Parent reads from pout[0]. Set write end pout[1] as STDOUT for child.
-    if (dup2 (pout[1], STDOUT_FILENO) == -1)
-      throw std::string (std::strerror (errno));
-    close (pout[1]);
-
-    // Add executable as argv[0] and NULL-terminate the array for execvp().
-    char** argv = new char* [args.size () + 2];
-    argv[0] = (char*) executable.c_str ();
-    for (unsigned int i = 0; i < args.size (); ++i)
-      argv[i+1] = (char*) args[i].c_str ();
-
-    argv[args.size () + 1] = NULL;
-    _exit (execvp (executable.c_str (), argv));
-  }
-
-  // This is only reached in the parent
-  close (pin[0]);   // Close the read end of the input pipe.
-  close (pout[1]);  // Close the write end of the output pipe.
-
-  if (input.size () == 0)
-  {
-    // Nothing to send to the child, close the pipe early.
-    close (pin[1]);
-  }
-
-  output = "";
-  read_retval = -1;
-  written = 0;
-  while (read_retval != 0 || input.size () != written)
-  {
-    FD_ZERO (&rfds);
-    if (read_retval != 0)
-      FD_SET (pout[0], &rfds);
-
-    FD_ZERO (&wfds);
-    if (input.size () != written)
-      FD_SET (pin[1], &wfds);
-
-    // On Linux, tv may be overwritten by select().  Reset it each time.
-    // NOTE: Timeout chosen arbitrarily - we don't time out execute() calls.
-    // select() is run over and over again unless the child exits or closes
-    // its pipes.
-    tv.tv_sec = 5;
-    tv.tv_usec = 0;
-
-    select_retval = select (std::max (pout[0], pin[1]) + 1, &rfds, &wfds, NULL, &tv);
-
-    if (select_retval == -1)
-      throw std::string (std::strerror (errno));
-
-    // Write data to child's STDIN
-    if (FD_ISSET (pin[1], &wfds))
-    {
-      write_retval = write (pin[1], input_cstr + written, input.size () - written);
-      if (write_retval == -1)
-      {
-        if (errno == EPIPE)
-        {
-          // Child died (or closed the pipe) before reading all input.
-          // We don't really care; pretend we wrote it all.
-          write_retval = input.size () - written;
-        }
-        else
-        {
-          throw std::string (std::strerror (errno));
-        }
-      }
-      written += write_retval;
-
-      if (written == input.size ())
-      {
-        // Let the child know that no more input is coming by closing the pipe.
-        close (pin[1]);
-      }
-    }
-
-    // Read data from child's STDOUT
-    if (FD_ISSET (pout[0], &rfds))
-    {
-      read_retval = read (pout[0], &buf, sizeof (buf) - 1);
-      if (read_retval == -1)
-        throw std::string (std::strerror (errno));
-
-      buf[read_retval] = '\0';
-      output += buf;
-    }
-  }
-
-  close (pout[0]);  // Close the read end of the output pipe.
-
-  int status = -1;
-  if (wait (&status) == -1)
-    throw std::string (std::strerror (errno));
-
-  if (WIFEXITED (status))
-  {
-    status = WEXITSTATUS (status);
-  }
-  else
-  {
-    throw std::string ("Error: Could not get Hook exit status!");
-  }
-
-  if (signal (SIGPIPE, SIG_DFL) == SIG_ERR)  // We're done, return to default.
-    throw std::string (std::strerror (errno));
-
-  return status;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-std::string osName ()
-{
-#if defined (DARWIN)
-  return "Darwin";
-#elif defined (SOLARIS)
-  return "Solaris";
-#elif defined (CYGWIN)
-  return "Cygwin";
-#elif defined (HAIKU)
-  return "Haiku";
-#elif defined (OPENBSD)
-  return "OpenBSD";
-#elif defined (FREEBSD)
-  return "FreeBSD";
-#elif defined (NETBSD)
-  return "NetBSD";
-#elif defined (LINUX)
-  return "Linux";
-#elif defined (KFREEBSD)
-  return "GNU/kFreeBSD";
-#elif defined (GNUHURD)
-  return "GNU/Hurd";
-#else
-  return "<unknown>";
-#endif
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 16.8 Predefined macro names [cpp.predefined]
-//
-// The following macro names shall be defined by the implementation:
-//
-// __cplusplus
-//   The name __cplusplus is defined to the value 201402L when compiling a C++
-//   translation unit.156
-//
-// ---
-//   156) It is intended that future versions of this standard will replace the
-//   value of this macro with a greater value. Non-conforming compilers should
-//   use a value with at most five decimal digits.
-std::string cppCompliance ()
-{
-#ifdef __cplusplus
-  auto level = __cplusplus;
-
-       if (level == 199711) return "C++98/03";
-  else if (level == 201103) return "C++11";
-  else if (level == 201402) return "C++14";
-
-  // This is a hack.  Replace with correct value on standard publication.
-  else if (level >  201700) return "C++17";
-
-  // Unknown, just show the value.
-  else if (level >   99999) return format (__cplusplus);
-#endif
-
-  // No C++.
-  return "non-compliant";
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/shared.h b/src/libshared/src/shared.h
deleted file mode 100644 (file)
index d8a56bb..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_SHARED
-#define INCLUDED_SHARED
-
-#include <sstream>
-#include <algorithm>
-#include <string>
-#include <vector>
-
-// shared.cpp, Non-UTF-8 aware.
-void wrapText (std::vector <std::string>&, const std::string&, const int, bool);
-int longestWord (const std::string&);
-int longestLine (const std::string&);
-bool extractLine (std::string&, const std::string&, int, bool, unsigned int&);
-std::vector <std::string> split (const std::string&, const char);
-std::vector <std::string> split (const std::string&);
-std::string join (const std::string&, const std::vector<int>&);
-std::string join (const std::string&, const std::vector<std::string>&);
-std::string str_replace (const std::string&, const std::string&, const std::string&);
-std::string trim (const std::string&, const std::string& edible = " \t\n\f\r");
-std::string ltrim (const std::string&, const std::string& edible = " \t\n\f\r");
-std::string rtrim (const std::string&, const std::string& edible = " \t\n\f\r");
-bool compare (const std::string&, const std::string&, bool sensitive = true);
-bool closeEnough (const std::string&, const std::string&, unsigned int minLength = 0);
-int matchLength (const std::string&, const std::string&);
-std::string::size_type find (const std::string&, const std::string&, bool sensitive = true);
-std::string::size_type find (const std::string&, const std::string&, std::string::size_type, bool sensitive = true);
-
-// List operations.
-template <class T> void listDiff (
-  const T& left, const T& right, T& leftOnly, T& rightOnly)
-{
-  leftOnly.clear ();
-  for (auto& l : left)
-    if (std::find (right.begin (), right.end (), l) == right.end ())
-      leftOnly.push_back (l);
-
-  rightOnly.clear ();
-  for (auto& r : right)
-    if (std::find (left.begin (), left.end (), r) == left.end ())
-      rightOnly.push_back (r);
-}
-
-template <class T> T listIntersect (
-  const T& left, const T& right)
-{
-  T intersection;
-  for (auto& l : left)
-    if (std::find (right.begin (), right.end (), l) != right.end ())
-      intersection.push_back (l);
-
-  return intersection;
-}
-
-std::string lowerCase (const std::string&);
-std::string upperCase (const std::string&);
-std::string upperCaseFirst (const std::string&);
-
-int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&, int minimum = 1);
-bool confirm (const std::string&);
-
-int execute (const std::string&, const std::vector <std::string>&, const std::string&, std::string&);
-std::string osName ();
-std::string cppCompliance ();
-
-// ip.cpp
-bool isIPv4Address (const std::string&, std::string&, int&);
-bool isIPv6Address (const std::string&, std::string&, int&);
-
-#endif
diff --git a/src/libshared/src/unicode.cpp b/src/libshared/src/unicode.cpp
deleted file mode 100644 (file)
index fa5a164..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <unicode.h>
-#include <cwctype>
-
-////////////////////////////////////////////////////////////////////////////////
-// Complete Unicode whitespace list.
-bool unicodeWhitespace (unsigned int c)
-{
-  return unicodeHorizontalWhitespace (c) ||
-         unicodeVerticalWhitespace   (c);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Complete Unicode whitespace list.
-//
-// http://en.wikipedia.org/wiki/Whitespace_character
-// Updated 2015-09-13
-// Static
-//
-// TODO This list should be derived from the Unicode database.
-bool unicodeHorizontalWhitespace (unsigned int c)
-{
-  return (c == 0x0020 ||   // space Common  Separator, space
-          c == 0x0009 ||   // Common  Other, control  HT, Horizontal Tab
-          c == 0x00A0 ||   // no-break space  Common  Separator, space
-          c == 0x1680 ||   // ogham space mark  Ogham Separator, space
-          c == 0x180E ||   // mongolian vowel separator Mongolian Separator, space
-          c == 0x2000 ||   // en quad Common  Separator, space
-          c == 0x2001 ||   // em quad Common  Separator, space
-          c == 0x2002 ||   // en space  Common  Separator, space
-          c == 0x2003 ||   // em space  Common  Separator, space
-          c == 0x2004 ||   // three-per-em space  Common  Separator, space
-          c == 0x2005 ||   // four-per-em space Common  Separator, space
-          c == 0x2006 ||   // six-per-em space  Common  Separator, space
-          c == 0x2007 ||   // figure space  Common  Separator, space
-          c == 0x2008 ||   // punctuation space Common  Separator, space
-          c == 0x2009 ||   // thin space  Common  Separator, space
-          c == 0x200A ||   // hair space  Common  Separator, space
-          c == 0x200B ||   // zero width space
-          c == 0x200C ||   // zero width non-joiner
-          c == 0x200D ||   // zero width joiner
-          c == 0x202F ||   // narrow no-break space Common  Separator, space
-          c == 0x205F ||   // medium mathematical space Common  Separator, space
-          c == 0x2060 ||   // word joiner
-          c == 0x3000);    // ideographic space Common  Separator, space
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Complete Unicode whitespace list.
-//
-// http://en.wikipedia.org/wiki/Whitespace_character
-// Updated 2015-09-13
-// Static
-//
-// TODO This list should be derived from the Unicode database.
-bool unicodeVerticalWhitespace (unsigned int c)
-{
-  return (c == 0x000A ||   // Common  Other, control  LF, Line feed
-          c == 0x000B ||   // Common  Other, control  VT, Vertical Tab
-          c == 0x000C ||   // Common  Other, control  FF, Form feed
-          c == 0x000D ||   // Common  Other, control  CR, Carriage return
-          c == 0x0085 ||   // Common  Other, control  NEL, Next line
-          c == 0x2028 ||   // line separator  Common  Separator, line
-          c == 0x2029);    // paragraph separator Common  Separator, paragraph
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool unicodePunctuation (unsigned int c)
-{
-  return iswpunct (c) ? true : false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool unicodeAlpha (unsigned int c)
-{
-  return iswprint (c)             &&
-         ! iswpunct (c)           &&
-         ! unicodeWhitespace (c);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TODO Needs better definition.
-bool unicodeLatinAlpha (unsigned int c)
-{
-  return (c >= 'A' && c <= 'Z') ||
-         (c >= 'a' && c <= 'z');
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Digits 0-9.
-//
-// TODO This list should be derived from the Unicode database.
-bool unicodeLatinDigit (unsigned int c)
-{
-  return c >= 0x30 && c <= 0x39;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Digits 0-9 a-f A-F.
-bool unicodeHexDigit (unsigned int c)
-{
-  return (c >= '0' && c <= '9') ||
-         (c >= 'a' && c <= 'f') ||
-         (c >= 'A' && c <= 'F');
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/unicode.h b/src/libshared/src/unicode.h
deleted file mode 100644 (file)
index b28017b..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_UNICODE
-#define INCLUDED_UNICODE
-
-bool unicodeWhitespace           (unsigned int);
-bool unicodeHorizontalWhitespace (unsigned int);
-bool unicodeVerticalWhitespace   (unsigned int);
-bool unicodePunctuation          (unsigned int);
-bool unicodeAlpha                (unsigned int);
-bool unicodeLatinAlpha           (unsigned int);
-bool unicodeLatinDigit           (unsigned int);
-bool unicodeHexDigit             (unsigned int);
-
-#endif
diff --git a/src/libshared/src/utf8.cpp b/src/libshared/src/utf8.cpp
deleted file mode 100644 (file)
index 580d9ec..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2013 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <utf8.h>
-
-////////////////////////////////////////////////////////////////////////////////
-// Converts '0'     -> 0
-//          '9'     -> 9
-//          'a'/'A' -> 10
-//          'f'/'F' -> 15
-#define XDIGIT(x) ((x) >= '0' && (x) <= '9' ? ((x) - '0') : \
-                   (x) >= 'a' && (x) <= 'f' ? ((x) + 10 - 'a') : \
-                   (x) >= 'A' && (x) <= 'F' ? ((x) + 10 - 'A') : 0)
-
-////////////////////////////////////////////////////////////////////////////////
-// Note: Assumes 4-digit hex codepoints:
-//         xxxx
-//         \uxxxx
-//         U+xxxx
-unsigned int utf8_codepoint (const std::string& input)
-{
-  unsigned int codepoint = 0;
-  int length = input.length ();
-
-  // U+xxxx, \uxxxx
-  if (length >= 6 &&
-      ((input[0] == 'U'  && input[1] == '+') ||
-       (input[0] == '\\' && input[1] == 'u')))
-  {
-    codepoint = XDIGIT (input[2]) << 12 |
-                XDIGIT (input[3]) <<  8 |
-                XDIGIT (input[4]) <<  4 |
-                XDIGIT (input[5]);
-  }
-  else if (length >= 4)
-  {
-    codepoint = XDIGIT (input[0]) << 12 |
-                XDIGIT (input[1]) <<  8 |
-                XDIGIT (input[2]) <<  4 |
-                XDIGIT (input[3]);
-  }
-
-  return codepoint;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Iterates along a UTF8 string.
-//   - argument i counts bytes advanced through the string
-//   - returns the next character
-unsigned int utf8_next_char (const std::string& input, std::string::size_type& i)
-{
-  if (input[i] == '\0')
-    return 0;
-
-  // How many bytes in the sequence?
-  int length = utf8_sequence (input[i]);
-  i += length;
-
-  // 0xxxxxxx -> 0xxxxxxx
-  if (length == 1)
-    return input[i - 1];
-
-  // 110yyyyy 10xxxxxx -> 00000yyy yyxxxxxx
-  if (length == 2)
-    return ((input[i - 2] & 0x1F) << 6) +
-            (input[i - 1] & 0x3F);
-
-  // 1110zzzz 10yyyyyy 10xxxxxx -> zzzzyyyy yyxxxxxx
-  if (length == 3)
-    return ((input[i - 3] & 0xF)  << 12) +
-           ((input[i - 2] & 0x3F) <<  6) +
-            (input[i - 1] & 0x3F);
-
-  // 11110www 10zzzzzz 10yyyyyy 10xxxxxx -> 000wwwzz zzzzyyyy yyxxxxxx
-  if (length == 4)
-    return ((input[i - 4] & 0x7)  << 18) +
-           ((input[i - 3] & 0x3F) << 12) +
-           ((input[i - 2] & 0x3F) <<  6) +
-            (input[i - 1] & 0x3F);
-
-  // Default: pretend as though it's a single character.
-  // TODO Or should this throw?
-  return input[i - 1];
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// http://en.wikipedia.org/wiki/UTF-8
-std::string utf8_character (unsigned int codepoint)
-{
-  char sequence[5] {};
-
-  // 0xxxxxxx -> 0xxxxxxx
-  if (codepoint < 0x80)
-  {
-    sequence[0] = codepoint;
-  }
-
-  // 00000yyy yyxxxxxx -> 110yyyyy 10xxxxxx
-  else if (codepoint < 0x800)
-  {
-    sequence[0] = 0xC0 | (codepoint & 0x7C0) >> 6;
-    sequence[1] = 0x80 | (codepoint & 0x3F);
-  }
-
-  // zzzzyyyy yyxxxxxx -> 1110zzzz 10yyyyyy 10xxxxxx
-  else if (codepoint < 0x10000)
-  {
-    sequence[0] = 0xE0 | (codepoint & 0xF000) >> 12;
-    sequence[1] = 0x80 | (codepoint & 0xFC0)  >> 6;
-    sequence[2] = 0x80 | (codepoint & 0x3F);
-  }
-
-  // 000wwwzz zzzzyyyy yyxxxxxx -> 11110www 10zzzzzz 10yyyyyy 10xxxxxx
-  else if (codepoint < 0x110000)
-  {
-    sequence[0] = 0xF0 | (codepoint & 0x1C0000) >> 18;
-    sequence[1] = 0x80 | (codepoint & 0x03F000) >> 12;
-    sequence[2] = 0x80 | (codepoint & 0x0FC0)   >> 6;
-    sequence[3] = 0x80 | (codepoint & 0x3F);
-  }
-
-  return std::string (sequence);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-int utf8_sequence (unsigned int character)
-{
-  if ((character & 0xE0) == 0xC0)
-    return 2;
-
-  if ((character & 0xF0) == 0xE0)
-    return 3;
-
-  if ((character & 0xF8) == 0xF0)
-    return 4;
-
-  return 1;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Length of a string in characters.
-unsigned int utf8_length (const std::string& str)
-{
-  int byteLength = str.length ();
-  int charLength = byteLength;
-  const char* data = str.data ();
-
-  // Decrement the number of bytes for each byte that matches 0b10??????
-  // this way only the first byte of any utf8 sequence is counted.
-  for (int i = 0; i < byteLength; i++)
-  {
-    // Extract the first two bits and check whether they are 10
-    if ((data[i] & 0xC0) == 0x80)
-      charLength--;
-  }
-
-  return charLength;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Width of a string in character cells.
-unsigned int utf8_width (const std::string& str)
-{
-  unsigned int length = 0;
-  std::string::size_type i = 0;
-  unsigned int c;
-  while ((c = utf8_next_char (str, i)))
-  {
-    // Control characters, and more especially newline characters, make
-    // mk_wcwidth() return -1.  Ignore that, thereby "adding zero" to length.
-    // Since control characters are not displayed in reports, this is a valid
-    // choice.
-    int l = mk_wcwidth (c);
-    if (l != -1)
-      length += l;
-  }
-
-  return length;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-unsigned int utf8_text_length (const std::string& str)
-{
-  int byteLength = str.length ();
-  int charLength = byteLength;
-  const char* data = str.data ();
-  bool in_color = false;
-
-  // Decrement the number of bytes for each byte that matches 0b10??????
-  // this way only the first byte of any utf8 sequence is counted.
-  for (int i = 0; i < byteLength; i++)
-  {
-    if (in_color)
-    {
-      if (data[i] == 'm')
-        in_color = false;
-
-      --charLength;
-    }
-    else
-    {
-      if (data[i] == 033)
-      {
-        in_color = true;
-        --charLength;
-      }
-      else
-      {
-        // Extract the first two bits and check whether they are 10
-        if ((data[i] & 0xC0) == 0x80)
-          --charLength;
-      }
-    }
-  }
-
-  return charLength;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-unsigned int utf8_text_width (const std::string& str)
-{
-  bool in_color = false;
-
-  unsigned int length = 0;
-  std::string::size_type i = 0;
-  unsigned int c;
-  while ((c = utf8_next_char (str, i)))
-  {
-    if (in_color)
-    {
-      if (c == 'm')
-        in_color = false;
-    }
-    else if (c == 033)
-    {
-      in_color = true;
-    }
-    else
-      length += mk_wcwidth (c);
-  }
-
-  return length;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-const std::string utf8_substr (
-  const std::string& input,
-  unsigned int start,
-  unsigned int length /* = 0 */)
-{
-  // Find the starting index.
-  std::string::size_type index_start = 0;
-  for (unsigned int i = 0; i < start; i++)
-    utf8_next_char (input, index_start);
-
-  std::string result;
-  if (length)
-  {
-    std::string::size_type index_end = index_start;
-    for (unsigned int i = 0; i < length; i++)
-      utf8_next_char (input, index_end);
-
-    result = input.substr (index_start, index_end - index_start);
-  }
-  else
-    result = input.substr (index_start);
-
-  return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libshared/src/utf8.h b/src/libshared/src/utf8.h
deleted file mode 100644 (file)
index 0edc3d8..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2013 - 2017, Paul Beckingham, Federico Hernandez.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifndef INCLUDED_UTF8
-#define INCLUDED_UTF8
-
-#include <string>
-
-unsigned int utf8_codepoint (const std::string&);
-unsigned int utf8_next_char (const std::string&, std::string::size_type&);
-std::string utf8_character (unsigned int);
-int utf8_sequence (unsigned int);
-unsigned int utf8_length (const std::string&);
-unsigned int utf8_text_length (const std::string&);
-unsigned int utf8_width (const std::string& str);
-unsigned int utf8_text_width (const std::string&);
-const std::string utf8_substr (const std::string&, unsigned int, unsigned int length = 0);
-
-int mk_wcwidth (wchar_t);
-
-#endif
diff --git a/src/libshared/src/wcwidth6.cpp b/src/libshared/src/wcwidth6.cpp
deleted file mode 100644 (file)
index b26aa8f..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * This is an implementation of wcwidth() and wcswidth() (defined in
- * IEEE Std 1002.1-2001) for Unicode.
- *
- * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
- * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
- *
- * In fixed-width output devices, Latin characters all occupy a single
- * "cell" position of equal width, whereas ideographic CJK characters
- * occupy two such cells. Interoperability between terminal-line
- * applications and (teletype-style) character terminals using the
- * UTF-8 encoding requires agreement on which character should advance
- * the cursor by how many cell positions. No established formal
- * standards exist at present on which Unicode character shall occupy
- * how many cell positions on character terminals. These routines are
- * a first attempt of defining such behavior based on simple rules
- * applied to data provided by the Unicode Consortium.
- *
- * For some graphical characters, the Unicode standard explicitly
- * defines a character-cell width via the definition of the East Asian
- * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
- * In all these cases, there is no ambiguity about which width a
- * terminal shall use. For characters in the East Asian Ambiguous (A)
- * class, the width choice depends purely on a preference of backward
- * compatibility with either historic CJK or Western practice.
- * Choosing single-width for these characters is easy to justify as
- * the appropriate long-term solution, as the CJK practice of
- * displaying these characters as double-width comes from historic
- * implementation simplicity (8-bit encoded characters were displayed
- * single-width and 16-bit ones double-width, even for Greek,
- * Cyrillic, etc.) and not any typographic considerations.
- *
- * Much less clear is the choice of width for the Not East Asian
- * (Neutral) class. Existing practice does not dictate a width for any
- * of these characters. It would nevertheless make sense
- * typographically to allocate two character cells to characters such
- * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
- * represented adequately with a single-width glyph. The following
- * routines at present merely assign a single-cell width to all
- * neutral characters, in the interest of simplicity. This is not
- * entirely satisfactory and should be reconsidered before
- * establishing a formal standard in this area. At the moment, the
- * decision which Not East Asian (Neutral) characters should be
- * represented by double-width glyphs cannot yet be answered by
- * applying a simple rule from the Unicode database content. Setting
- * up a proper standard for the behavior of UTF-8 character terminals
- * will require a careful analysis not only of each Unicode character,
- * but also of each presentation form, something the author of these
- * routines has avoided to do so far.
- *
- * http://www.unicode.org/unicode/reports/tr11/
- *
- * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
- *
- * Permission to use, copy, modify, and distribute this software
- * for any purpose and without fee is hereby granted. The author
- * disclaims all warranties with regard to this software.
- *
- * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
- */
-
-#include <cmake.h>
-#include <wchar.h>
-
-struct interval {
-    int first;
-    int last;
-};
-
-/* auxiliary function for binary search in interval table */
-static int bisearch(wchar_t ucs, const struct interval *table, int max) {
-    int min = 0;
-    int mid;
-
-    if (ucs < table[0].first || ucs > table[max].last)
-        return 0;
-    while (max >= min) {
-        mid = (min + max) / 2;
-        if (ucs > table[mid].last)
-            min = mid + 1;
-        else if (ucs < table[mid].first)
-            max = mid - 1;
-        else
-            return 1;
-    }
-
-    return 0;
-}
-
-
-/* The following two functions define the column width of an ISO 10646
- * character as follows:
- *
- *    - The null character (U+0000) has a column width of 0.
- *
- *    - Other C0/C1 control characters and DEL will lead to a return
- *      value of -1.
- *
- *    - Non-spacing and enclosing combining characters (general
- *      category code Mn or Me in the Unicode database) have a
- *      column width of 0.
- *
- *    - SOFT HYPHEN (U+00AD) has a column width of 1.
- *
- *    - Other format characters (general category code Cf in the Unicode
- *      database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
- *
- *    - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
- *      have a column width of 0.
- *
- *    - Spacing characters in the East Asian Wide (W) or East Asian
- *      Full-width (F) category as defined in Unicode Technical
- *      Report #11 have a column width of 2.
- *
- *    - All remaining characters (including all printable
- *      ISO 8859-1 and WGL4 characters, Unicode control characters,
- *      etc.) have a column width of 1.
- *
- * This implementation assumes that wchar_t characters are encoded
- * in ISO 10646.
- */
-
-int mk_wcwidth(wchar_t ucs)
-{
-  /* sorted list of non-overlapping intervals of non-spacing characters */
-  /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
-  static const struct interval combining[] = {
-    { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
-    { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
-    { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
-    { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
-    { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
-    { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
-    { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
-    { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
-    { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
-    { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
-    { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
-    { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
-    { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
-    { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
-    { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
-    { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
-    { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
-    { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
-    { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
-    { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
-    { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
-    { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
-    { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
-    { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
-    { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
-    { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
-    { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
-    { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
-    { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
-    { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
-    { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
-    { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
-    { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
-    { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
-    { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
-    { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
-    { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
-    { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
-    { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
-    { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
-    { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
-    { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
-    { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
-    { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
-    { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
-    { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
-    { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
-    { 0xE0100, 0xE01EF }
-  };
-
-  /* test for 8-bit control characters */
-  if (ucs == 0)
-    return 0;
-  if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
-    return -1;
-
-  /* binary search in table of non-spacing characters */
-  if (bisearch(ucs, combining,
-         sizeof(combining) / sizeof(struct interval) - 1))
-    return 0;
-
-  /* if we arrive here, ucs is not a combining or C0/C1 control character */
-
-  return 1 +
-    (ucs >= 0x1100 &&
-     (ucs <= 0x115f ||                    /* Hangul Jamo init. consonants */
-      ucs == 0x2329 || ucs == 0x232a ||
-      (ucs >= 0x2e80 && ucs <= 0xa4cf &&
-       ucs != 0x303f) ||                  /* CJK ... Yi */
-      (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
-      (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
-      (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
-      (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
-      (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
-      (ucs >= 0xffe0 && ucs <= 0xffe6)
-#ifndef CYGWIN
-                                       ||
-      (ucs >= 0x20000 && ucs <= 0x2fffd) ||
-      (ucs >= 0x30000 && ucs <= 0x3fffd)
-#endif
-     )
-    );
-}
-
index cae64a1099b868b3759211f6609249d2b7cd57e0..8c7683315cf41af527a7e36505a70ffbc8e9380f 100644 (file)
@@ -32,7 +32,6 @@
 #include <cstdio>
 #include <stdlib.h>
 #include <unistd.h>
-#include <shared.h>
 
 #ifdef HAVE_READLINE
 #include <readline/readline.h>
@@ -95,12 +94,8 @@ static int commandLoop (bool autoClear)
   }
   else if (command != "")
   {
-    auto args = split (command, ' ');
-
     // Dispatch command.
-         if (args[0] == "<EOF>")                      status = -1;
-    else if (closeEnough ("exit",        args[0], 3)) status = -1;
-    else if (closeEnough ("quit",        args[0], 3)) status = -1;
+    if (command == "<EOF>")                      status = -1;
     else if (command != "")
     {
       command = command;
@@ -126,12 +121,9 @@ int main (int argc, const char** argv)
   {
     try
     {
-      // Get the Taskwarrior rc.tasksh.autoclear Boolean setting.
       bool autoClear = false;
       std::string input;
       std::string output;
-      execute ("task", {"_get", "rc.tasksh.autoclear"}, input, output);
-      output = lowerCase (output);
       autoClear = (output == "true\n" ||
                    output == "1\n"    ||
                    output == "y\n"    ||
index 6c98b7cf2749474acabc2946ceb0e13090f0faf7..5b594983ade912ae5068b4ab2ddfd83386305559 100644 (file)
@@ -27,7 +27,6 @@
 #include <cmake.h>
 #include <vector>
 #include <string>
-#include <Color.h>
 
 static std::vector <std::string> contextColors = {
   "bold white on red",
@@ -74,7 +73,6 @@ std::string composeContexts (bool pretty /* = false */)
     if (pretty)
       combined += (combined != "" ? " " : "")
                 + std::string ("\001")
-                + Color::colorize ("\002 " + contexts[i] + " \001", contextColors[i % contextColors.size ()])
                 + "\002";
     else
       combined += (combined != "" ? " " : "") + contexts[i];
@@ -88,10 +86,6 @@ std::string composeContexts (bool pretty /* = false */)
 ////////////////////////////////////////////////////////////////////////////////
 std::string promptCompose ()
 {
-/*   auto decoration = composeContexts (true); */
-  // if (decoration.length ())
-    // return "task " + decoration + "> ";
-
   return ">>>";
 }
 
diff --git a/src/shell.cpp b/src/shell.cpp
deleted file mode 100644 (file)
index 04900a5..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-// http://www.opensource.org/licenses/mit-license.php
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cmake.h>
-#include <vector>
-#include <string>
-#include <stdlib.h>
-#include <shared.h>
-
-////////////////////////////////////////////////////////////////////////////////
-int cmdShell (const std::vector <std::string>& args)
-{
-  auto combined = join (" ", args);
-
-  // Support '!ls' as well as '! ls'.
-  if (combined[0] == '!')
-    combined = combined.substr (1);
-
-  system (combined.c_str ());
-  return 0; // Ignore system return code.
-}
-
-////////////////////////////////////////////////////////////////////////////////