.. _program_listing_file_src_common_cli_helper.h: Program Listing for File cli_helper.h ===================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/common/cli_helper.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include #include "3rd_party/yaml-cpp/yaml.h" #include "common/logging.h" namespace marian { namespace cli { // helper to replace environment-variable expressions of the form ${VARNAME} in // a string static inline std::string interpolateEnvVars(std::string str) { // temporary workaround for MS-internal PhillyOnAzure cluster: warm storage // presently has the form /hdfs/VC instead of /{gfs,hdfs}/CLUSTER/VC // Catch stdin/stdout and do not process if(str == "stdin" || str == "stdout") { return str; } #if 1 if(getenv("PHILLY_JOB_ID")) { const char* cluster = getenv("PHILLY_CLUSTER"); const char* vc = getenv("PHILLY_VC"); // this environment variable exists when running on the cluster if(cluster && vc) { static const std::string s_gfsPrefix = std::string("/gfs/") + cluster + "/" + vc + "/"; static const std::string s_hdfsPrefix = std::string("/hdfs/") + cluster + "/" + vc + "/"; if(str.find(s_gfsPrefix) == 0) str = std::string("/hdfs/") + vc + "/" + str.substr(s_gfsPrefix.size()); else if(str.find(s_hdfsPrefix) == 0) str = std::string("/hdfs/") + vc + "/" + str.substr(s_hdfsPrefix.size()); } } #endif for(;;) { const auto pos = str.find("${"); if(pos == std::string::npos) return str; const auto epos = str.find("}", pos + 2); ABORT_IF(epos == std::string::npos, "interpolate-env-vars option: ${{ without matching }} in '{}'", str.c_str()); // isolate the variable name const auto var = str.substr(pos + 2, epos - (pos + 2)); const auto val = getenv(var.c_str()); ABORT_IF(!val, "interpolate-env-vars option: environment variable '{}' not " "defined in '{}'", var.c_str(), str.c_str()); // replace it; then try again for further replacements str = str.substr(0, pos) + val + str.substr(epos + 1); } } // Helper to implement interpolate-env-vars and relative-paths options static inline void processPaths( YAML::Node& node, const std::function& TransformPath, const std::set& PATHS, bool isPath = false, const std::string parentKey = "") { // For a scalar node (leaves in the config), just transform the path if(isPath && node.IsScalar()) { std::string nodePath = node.as(); if(!nodePath.empty()) node = TransformPath(nodePath); } // For a sequence node, recursively iterate each value else if(node.IsSequence()) { for(auto&& sub : node) { processPaths(sub, TransformPath, PATHS, isPath); // Exception for the shortlist option, which keeps a path and three numbers; // we want to process the path only and keep the rest untouched if(isPath && parentKey == "shortlist") break; } } // For a map node that is not a path, recursively iterate each value else if(!isPath && node.IsMap()) { for(auto&& sub : node) { std::string key = sub.first.as(); // Exception for the sqlite option, which has a special value of 'temporary' if(key == "sqlite" && sub.second.as() == "temporary") continue; processPaths(sub.second, TransformPath, PATHS, PATHS.count(key) > 0, key); } } } // helper to convert a YAML node recursively into a string // // TODO: create a helper function that converts a YAML node into a string // without an emitter; consider extracting YAML-related helper functions to a // separate file // TODO: Look for Frank's function that does that. static void OutputYaml(const YAML::Node node, YAML::Emitter& out) { std::set sorter; switch(node.Type()) { case YAML::NodeType::Null: out << node; break; case YAML::NodeType::Scalar: out << node; break; case YAML::NodeType::Sequence: out << YAML::BeginSeq; for(auto&& n : node) OutputYaml(n, out); out << YAML::EndSeq; break; case YAML::NodeType::Map: for(auto& n : node) sorter.insert(n.first.as()); out << YAML::BeginMap; for(auto& key : sorter) { out << YAML::Key; out << key; out << YAML::Value; OutputYaml(node[key], out); } out << YAML::EndMap; break; case YAML::NodeType::Undefined: out << node; break; } } // Change relative paths to absolute paths relative to the config file's // directory void makeAbsolutePaths(YAML::Node& config, const std::string& configPath, const std::set& PATHS); } // namespace cli } // namespace marian