1ece8a530Spatrick //===- Reproduce.cpp - Utilities for creating reproducers -----------------===// 2ece8a530Spatrick // 3ece8a530Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ece8a530Spatrick // See https://llvm.org/LICENSE.txt for license information. 5ece8a530Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ece8a530Spatrick // 7ece8a530Spatrick //===----------------------------------------------------------------------===// 8ece8a530Spatrick 9ece8a530Spatrick #include "lld/Common/Reproduce.h" 10ece8a530Spatrick #include "llvm/Option/Arg.h" 11ece8a530Spatrick #include "llvm/Support/Error.h" 12ece8a530Spatrick #include "llvm/Support/FileSystem.h" 13ece8a530Spatrick #include "llvm/Support/Path.h" 14ece8a530Spatrick 15ece8a530Spatrick using namespace lld; 16ece8a530Spatrick using namespace llvm; 17ece8a530Spatrick using namespace llvm::sys; 18ece8a530Spatrick 19ece8a530Spatrick // Makes a given pathname an absolute path first, and then remove 20ece8a530Spatrick // beginning /. For example, "../foo.o" is converted to "home/john/foo.o", 21ece8a530Spatrick // assuming that the current directory is "/home/john/bar". 22ece8a530Spatrick // Returned string is a forward slash separated path even on Windows to avoid 23ece8a530Spatrick // a mess with backslash-as-escape and backslash-as-path-separator. relativeToRoot(StringRef path)24ece8a530Spatrickstd::string lld::relativeToRoot(StringRef path) { 25ece8a530Spatrick SmallString<128> abs = path; 26ece8a530Spatrick if (fs::make_absolute(abs)) 27bb684c34Spatrick return std::string(path); 28ece8a530Spatrick path::remove_dots(abs, /*remove_dot_dot=*/true); 29ece8a530Spatrick 30ece8a530Spatrick // This is Windows specific. root_name() returns a drive letter 31ece8a530Spatrick // (e.g. "c:") or a UNC name (//net). We want to keep it as part 32ece8a530Spatrick // of the result. 33ece8a530Spatrick SmallString<128> res; 34ece8a530Spatrick StringRef root = path::root_name(abs); 35ece8a530Spatrick if (root.endswith(":")) 36ece8a530Spatrick res = root.drop_back(); 37ece8a530Spatrick else if (root.startswith("//")) 38ece8a530Spatrick res = root.substr(2); 39ece8a530Spatrick 40ece8a530Spatrick path::append(res, path::relative_path(abs)); 41ece8a530Spatrick return path::convert_to_slash(res); 42ece8a530Spatrick } 43ece8a530Spatrick 44ece8a530Spatrick // Quote a given string if it contains a space character. quote(StringRef s)45ece8a530Spatrickstd::string lld::quote(StringRef s) { 46ece8a530Spatrick if (s.contains(' ')) 47ece8a530Spatrick return ("\"" + s + "\"").str(); 48bb684c34Spatrick return std::string(s); 49ece8a530Spatrick } 50ece8a530Spatrick 51ece8a530Spatrick // Converts an Arg to a string representation suitable for a response file. 52ece8a530Spatrick // To show an Arg in a diagnostic, use Arg::getAsString() instead. toString(const opt::Arg & arg)53ece8a530Spatrickstd::string lld::toString(const opt::Arg &arg) { 54bb684c34Spatrick std::string k = std::string(arg.getSpelling()); 55ece8a530Spatrick if (arg.getNumValues() == 0) 56ece8a530Spatrick return k; 57*1cf9926bSpatrick std::string v; 58*1cf9926bSpatrick for (size_t i = 0; i < arg.getNumValues(); ++i) { 59*1cf9926bSpatrick if (i > 0) 60*1cf9926bSpatrick v.push_back(' '); 61*1cf9926bSpatrick v += quote(arg.getValue(i)); 62*1cf9926bSpatrick } 63ece8a530Spatrick if (arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle) 64ece8a530Spatrick return k + v; 65ece8a530Spatrick return k + " " + v; 66ece8a530Spatrick } 67