1 //===- Reproduce.cpp - Utilities for creating reproducers -----------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lld/Common/Reproduce.h"
11 #include "llvm/Option/Arg.h"
12 #include "llvm/Support/Error.h"
13 #include "llvm/Support/FileSystem.h"
14 #include "llvm/Support/Path.h"
15 
16 using namespace lld;
17 using namespace llvm;
18 using namespace llvm::sys;
19 
20 // Makes a given pathname an absolute path first, and then remove
21 // beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
22 // assuming that the current directory is "/home/john/bar".
23 // Returned string is a forward slash separated path even on Windows to avoid
24 // a mess with backslash-as-escape and backslash-as-path-separator.
relativeToRoot(StringRef Path)25 std::string lld::relativeToRoot(StringRef Path) {
26   SmallString<128> Abs = Path;
27   if (fs::make_absolute(Abs))
28     return Path;
29   path::remove_dots(Abs, /*remove_dot_dot=*/true);
30 
31   // This is Windows specific. root_name() returns a drive letter
32   // (e.g. "c:") or a UNC name (//net). We want to keep it as part
33   // of the result.
34   SmallString<128> Res;
35   StringRef Root = path::root_name(Abs);
36   if (Root.endswith(":"))
37     Res = Root.drop_back();
38   else if (Root.startswith("//"))
39     Res = Root.substr(2);
40 
41   path::append(Res, path::relative_path(Abs));
42   return path::convert_to_slash(Res);
43 }
44 
45 // Quote a given string if it contains a space character.
quote(StringRef S)46 std::string lld::quote(StringRef S) {
47   if (S.contains(' '))
48     return ("\"" + S + "\"").str();
49   return S;
50 }
51 
rewritePath(StringRef S)52 std::string lld::rewritePath(StringRef S) {
53   if (fs::exists(S))
54     return relativeToRoot(S);
55   return S;
56 }
57 
toString(const opt::Arg & Arg)58 std::string lld::toString(const opt::Arg &Arg) {
59   std::string K = Arg.getSpelling();
60   if (Arg.getNumValues() == 0)
61     return K;
62   std::string V = quote(Arg.getValue());
63   if (Arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle)
64     return K + V;
65   return K + " " + V;
66 }
67