10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/SmallVector.h"
12#include "llvm/Support/CommandLine.h"
13#include "llvm/Support/DynamicLibrary.h"
14#include "llvm/Support/Error.h"
15#include "llvm/Support/FileSystem.h"
16#include "llvm/Support/FormatVariadic.h"
17#include "llvm/Support/Path.h"
18#include "llvm/Support/Process.h"
19#include "llvm/Support/WithColor.h"
20#include "llvm/Support/raw_ostream.h"
27namespace fs = llvm::sys::fs;
28namespace path = llvm::sys::path;
36namespace ErrorMessages {
38constexpr const char *CannotValidatePath =
"failed to validate path '{0}': {1}";
40constexpr const char *ExtensionNotSupplied =
"Extension not supplied";
42constexpr const char *NoFormatForExtension =
43 "No format registered for extension '{0}'";
45constexpr const char *PathDoesNotExist =
"Path does not exist";
47constexpr const char *PathIsNotAFile =
"Path is not a file";
49constexpr const char *OutputDirectoryMissing =
50 "Parent directory does not exist";
52constexpr const char *OutputDirectoryNotWritable =
53 "Parent directory is not writable";
55constexpr const char *FileAlreadyExists =
"File already exists";
57constexpr const char *FailedToLoadPlugin =
"failed to load plugin '{0}': {1}";
61llvm::StringRef ToolName;
62llvm::StringRef ToolVersion;
64void printVersion(llvm::raw_ostream &OS) {
65 OS << ToolName <<
" " << ToolVersion <<
"\n";
72SerializationFormat *getFormatForExtension(llvm::StringRef Extension) {
78 static llvm::SmallVector<
79 std::pair<std::string, std::unique_ptr<SerializationFormat>>, 4>
83 auto ReversedList = llvm::reverse(ExtensionFormatList);
84 auto It = llvm::find_if(ReversedList, [&](
const auto &Entry) {
87 if (It != ReversedList.end()) {
88 return It->second.get();
96 SerializationFormat *
Result = Format.get();
98 "makeFormat must return non-null for a registered extension");
100 ExtensionFormatList.emplace_back(Extension, std::move(Format));
105FormatFile fromPath(llvm::StringRef Path) {
106 llvm::StringRef
Extension = path::extension(Path);
108 fail(ErrorMessages::CannotValidatePath, Path,
109 ErrorMessages::ExtensionNotSupplied);
113 SerializationFormat *Format = getFormatForExtension(Extension);
115 std::string BadExtension =
116 llvm::formatv(ErrorMessages::NoFormatForExtension, Extension);
117 fail(ErrorMessages::CannotValidatePath, Path, BadExtension);
120 return {Path.str(), Format};
128 llvm::WithColor::error(llvm::errs(), ToolName) << Msg <<
"\n";
129 llvm::sys::Process::Exit(1);
133 std::string Message = llvm::toString(std::move(Err));
138 for (
const std::string &PluginPath : Paths) {
140 if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(PluginPath.c_str(),
142 fail(ErrorMessages::FailedToLoadPlugin, PluginPath, ErrMsg);
148 llvm::cl::OptionCategory &Category,
149 llvm::StringRef ToolHeading) {
151 ToolName = path::stem(argv[0]);
154 ToolVersion = Version;
157 llvm::cl::HideUnrelatedOptions(Category);
160 llvm::cl::SetVersionPrinter(printVersion);
163 std::string Overview = (ToolHeading +
"\n").str();
164 llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
169 if (!fs::exists(
Path)) {
170 fail(ErrorMessages::CannotValidatePath,
Path,
171 ErrorMessages::PathDoesNotExist);
174 if (!fs::is_regular_file(
Path)) {
175 fail(ErrorMessages::CannotValidatePath,
Path,
176 ErrorMessages::PathIsNotAFile);
179 return fromPath(
Path);
184 if (fs::exists(
Path)) {
185 fail(ErrorMessages::CannotValidatePath,
Path,
186 ErrorMessages::FileAlreadyExists);
189 llvm::StringRef ParentDir = path::parent_path(
Path);
190 llvm::StringRef DirToCheck = ParentDir.empty() ?
"." : ParentDir;
192 if (!fs::exists(DirToCheck)) {
193 fail(ErrorMessages::CannotValidatePath,
Path,
194 ErrorMessages::OutputDirectoryMissing);
197 if (fs::access(DirToCheck, fs::AccessMode::Write)) {
198 fail(ErrorMessages::CannotValidatePath,
Path,
199 ErrorMessages::OutputDirectoryNotWritable);
202 return fromPath(
Path);
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
llvm::StringRef getToolName()
Returns the name of the running tool, as set by initTool().
std::unique_ptr< SerializationFormat > makeFormat(llvm::StringRef FormatName)
Try to instantiate a SerializationFormat with a given name.
void fail(const char *Msg)
void initTool(int argc, const char **argv, llvm::StringRef Version, llvm::cl::OptionCategory &Category, llvm::StringRef ToolHeading)
Sets ToolName, ToolVersion, and the version printer, hides unrelated command-line options,...
bool isFormatRegistered(llvm::StringRef FormatName)
Check if a SerializationFormat was registered with a given name.
void loadPlugins(llvm::ArrayRef< std::string > Paths)
@ Result
The result type of a method or function.