yang-cli: Allow loading module by name

Linking with filesystem is back!

Change-Id: I355f0991848df1dd72aceff5a57559ddc20a6082
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4b2f0bc..4fd1b0d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -154,6 +154,12 @@
 target_compile_definitions(yang-cli PRIVATE YANG_CLI)
 cli_link_required(yang-cli)
 target_link_libraries(yang-cli yangaccess)
+if(CMAKE_CXX_FLAGS MATCHES "-stdlib=libc\\+\\+" AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
+    target_link_libraries(yang-cli c++experimental)
+elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.1)
+    target_link_libraries(yang-cli stdc++fs)
+endif()
+
 
 
 include(CTest)
diff --git a/src/cli.cpp b/src/cli.cpp
index 46650b2..53670d0 100644
--- a/src/cli.cpp
+++ b/src/cli.cpp
@@ -26,12 +26,17 @@
   -d <datastore>   can be "running" or "startup" [default: running])";
 #elif defined(YANG_CLI)
 #include <boost/spirit/home/x3.hpp>
+#include <filesystem>
 #include "yang_access.hpp"
 #define PROGRAM_NAME "yang-cli"
 static const auto usage = R"(CLI interface for creating local YANG data instances
 
+  The <schema_file_or_module_name> argument is treated as a file name if a file
+  with such a path exists, otherwise it's treated as a module name. Search dirs
+  will be used to find a schema for that module.
+
 Usage:
-  yang-cli [-s <search_dir>] [-e enable_features]... [-i data_file]... <schema_file>...
+  yang-cli [-s <search_dir>] [-e enable_features]... [-i data_file]... <schema_file_or_module_name>...
   yang-cli (-h | --help)
   yang-cli --version
 
@@ -72,8 +77,14 @@
     if (const auto& search_dir = args["-s"]) {
         datastore.addSchemaDir(search_dir.asString());
     }
-    for (const auto& schemaFile : args["<schema_file>"].asStringList()) {
-        datastore.addSchemaFile(schemaFile);
+    for (const auto& schemaFile : args["<schema_file_or_module_name>"].asStringList()) {
+        if (std::filesystem::exists(schemaFile)) {
+            datastore.addSchemaFile(schemaFile);
+        } else if (schemaFile.find('/') == std::string::npos) { // Module names cannot have a slash
+            datastore.loadModule(schemaFile);
+        } else {
+            std::cerr << "Cannot load YANG module " << schemaFile << "\n";
+        }
     }
     if (const auto& enableFeatures = args["-e"]) {
         namespace x3 = boost::spirit::x3;
diff --git a/src/yang_access.cpp b/src/yang_access.cpp
index 8eccef4..d5c0ade 100644
--- a/src/yang_access.cpp
+++ b/src/yang_access.cpp
@@ -279,6 +279,11 @@
     return "";
 }
 
+void YangAccess::loadModule(const std::string& name)
+{
+    m_schema->loadModule(name);
+}
+
 void YangAccess::addSchemaFile(const std::string& path)
 {
     m_schema->addSchemaFile(path.c_str());
diff --git a/src/yang_access.hpp b/src/yang_access.hpp
index acbcc08..aaabd4b 100644
--- a/src/yang_access.hpp
+++ b/src/yang_access.hpp
@@ -37,6 +37,7 @@
     void enableFeature(const std::string& module, const std::string& feature);
     std::string dump(const DataFormat format) const override;
 
+    void loadModule(const std::string& name);
     void addSchemaFile(const std::string& path);
     void addSchemaDir(const std::string& path);
     void addDataFile(const std::string& path);