mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
79272adc9d
Add checks that return an `llvm::Error` in case a provided path is a directory in the case a `FilePath` was requested.
102 lines
2.6 KiB
C++
102 lines
2.6 KiB
C++
#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<FilePath (*DashGenerator)()>
|
|
struct PathImpl {
|
|
private:
|
|
std::optional<revng::FilePath> Path;
|
|
|
|
public:
|
|
PathImpl() = default;
|
|
|
|
void setDash() { Path = DashGenerator(); }
|
|
|
|
void parse(llvm::StringRef Value) {
|
|
if (Value == "-")
|
|
Path = DashGenerator();
|
|
else
|
|
Path = FilePath::fromLocalStorage(Value);
|
|
}
|
|
|
|
llvm::Expected<std::optional<const revng::FilePath>> 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<FilePath (*DashGenerator)()>
|
|
class PathImplParser : public llvm::cl::parser<PathImpl<DashGenerator>> {
|
|
public:
|
|
using llvm::cl::parser<PathImpl<DashGenerator>>::parser;
|
|
|
|
bool parse(llvm::cl::Option &Option,
|
|
llvm::StringRef ArgName,
|
|
const llvm::StringRef ArgValue,
|
|
PathImpl<DashGenerator> &Val) {
|
|
Val.parse(ArgValue);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
template<FilePath (*DG)()>
|
|
using PathImplOpt = llvm::cl::opt<PathImpl<DG>, false, PathImplParser<DG>>;
|
|
|
|
} // namespace detail
|
|
|
|
// cl::opts for input and output revng::FilePaths
|
|
using InputPathOpt = detail::PathImplOpt<FilePath::stdin>;
|
|
using OutputPathOpt = detail::PathImplOpt<FilePath::stdout>;
|
|
|
|
} // 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,
|
|
initializer<revng::PathInit>>(revng::InputPathOpt *O,
|
|
const initializer<revng::PathInit> &M) {
|
|
if (M.Init == revng::PathInit::Dash)
|
|
O->setDash();
|
|
}
|
|
|
|
template<>
|
|
inline void
|
|
apply<revng::OutputPathOpt,
|
|
initializer<revng::PathInit>>(revng::OutputPathOpt *O,
|
|
const initializer<revng::PathInit> &M) {
|
|
if (M.Init == revng::PathInit::Dash)
|
|
O->setDash();
|
|
}
|
|
|
|
} // namespace llvm::cl
|