#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "revng/Storage/Path.h" namespace revng { /// This enum is used to allow specifying via cl::init if the path should have /// stdin/stdout as the default value. enum class PathInit { None, Dash }; namespace detail { /// Utility class similar to std::optional, to be used as a llvm::cl::opt. /// The DashGenerator template parameter dictates the Path that will be used /// when the path '-' or cl::init(PathInit::Dash) are used template struct PathImpl { private: std::optional Path; public: PathImpl() = default; void setDash() { Path = DashGenerator(); } void parse(llvm::StringRef Value) { if (Value == "-") Path = DashGenerator(); else Path = FilePath::fromLocalStorage(Value); } llvm::Expected> get() const { if (not Path.has_value()) return std::nullopt; if (llvm::Error Error = Path->check()) return Error; return *Path; } }; /// cl::parser specialization to be used in conjunction with PathImpl, will call /// PathImpl::parse given the input string from the command-line. template class PathImplParser : public llvm::cl::parser> { public: using llvm::cl::parser>::parser; bool parse(llvm::cl::Option &Option, llvm::StringRef ArgName, const llvm::StringRef ArgValue, PathImpl &Val) { Val.parse(ArgValue); return false; } }; template using PathImplOpt = llvm::cl::opt, false, PathImplParser>; } // namespace detail // cl::opts for input and output revng::FilePaths using InputPathOpt = detail::PathImplOpt; using OutputPathOpt = detail::PathImplOpt; } // namespace revng namespace llvm::cl { // These 'apply' specializations are needed to allow using cl::init(PathInit) // with the {Input,Output}PathOpt. template<> inline void apply>(revng::InputPathOpt *O, const initializer &M) { if (M.Init == revng::PathInit::Dash) O->setDash(); } template<> inline void apply>(revng::OutputPathOpt *O, const initializer &M) { if (M.Init == revng::PathInit::Dash) O->setDash(); } } // namespace llvm::cl