LLVM 19.0.0git
Utils.cpp
Go to the documentation of this file.
1//===- Utils.cpp ----------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Implements utility functions for TextAPI Darwin operations.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/TextAPI/Utils.h"
14
15using namespace llvm;
16using namespace llvm::MachO;
17
19 const Twine &Extension) {
20 StringRef P(Path.begin(), Path.size());
21 auto ParentPath = sys::path::parent_path(P);
22 auto Filename = sys::path::filename(P);
23
24 if (!ParentPath.ends_with(Filename.str() + ".framework")) {
25 sys::path::replace_extension(Path, Extension);
26 return;
27 }
28 // Framework dylibs do not have a file extension, in those cases the new
29 // extension is appended. e.g. given Path: "Foo.framework/Foo" and Extension:
30 // "tbd", the result is "Foo.framework/Foo.tbd".
31 SmallString<8> Storage;
32 StringRef Ext = Extension.toStringRef(Storage);
33
34 // Append '.' if needed.
35 if (!Ext.empty() && Ext[0] != '.')
36 Path.push_back('.');
37
38 // Append extension.
39 Path.append(Ext.begin(), Ext.end());
40}
41
42std::error_code llvm::MachO::shouldSkipSymLink(const Twine &Path,
43 bool &Result) {
44 Result = false;
46 auto P = Path.toNullTerminatedStringRef(Storage);
48 auto EC = sys::fs::status(P.data(), Stat1);
49 if (EC == std::errc::too_many_symbolic_link_levels) {
50 Result = true;
51 return {};
52 }
53
54 if (EC)
55 return EC;
56
58 while (!Parent.empty()) {
60 if (auto ec = sys::fs::status(Parent, Stat2))
61 return ec;
62
63 if (sys::fs::equivalent(Stat1, Stat2)) {
64 Result = true;
65 return {};
66 }
67
68 Parent = sys::path::parent_path(Parent);
69 }
70 return {};
71}
72
73std::error_code
75 SmallVectorImpl<char> &RelativePath) {
77 SmallString<PATH_MAX> Dst = To;
78 if (auto EC = sys::fs::make_absolute(Src))
79 return EC;
80
81 if (auto EC = sys::fs::make_absolute(Dst))
82 return EC;
83
86 auto IT1 = sys::path::begin(Src), IT2 = sys::path::begin(Dst),
87 IE1 = sys::path::end(Src), IE2 = sys::path::end(Dst);
88 // Ignore the common part.
89 for (; IT1 != IE1 && IT2 != IE2; ++IT1, ++IT2) {
90 if (*IT1 != *IT2)
91 break;
92 }
93
94 for (; IT1 != IE1; ++IT1)
95 sys::path::append(Result, "../");
96
97 for (; IT2 != IE2; ++IT2)
98 sys::path::append(Result, *IT2);
99
100 if (Result.empty())
101 Result = ".";
102
103 RelativePath.swap(Result);
104
105 return {};
106}
107
108bool llvm::MachO::isPrivateLibrary(StringRef Path, bool IsSymLink) {
109 // Remove the iOSSupport and DriverKit prefix to identify public locations.
110 Path.consume_front(MACCATALYST_PREFIX_PATH);
111 Path.consume_front(DRIVERKIT_PREFIX_PATH);
112 // Also /Library/Apple prefix for ROSP.
113 Path.consume_front("/Library/Apple");
114
115 if (Path.starts_with("/usr/local/lib"))
116 return true;
117
118 if (Path.starts_with("/System/Library/PrivateFrameworks"))
119 return true;
120
121 // Everything in /usr/lib/swift (including sub-directories) are considered
122 // public.
123 if (Path.consume_front("/usr/lib/swift/"))
124 return false;
125
126 // Only libraries directly in /usr/lib are public. All other libraries in
127 // sub-directories are private.
128 if (Path.consume_front("/usr/lib/"))
129 return Path.contains('/');
130
131 // "/System/Library/Frameworks/" is a public location.
132 if (Path.starts_with("/System/Library/Frameworks/")) {
133 StringRef Name, Rest;
134 std::tie(Name, Rest) =
135 Path.drop_front(sizeof("/System/Library/Frameworks")).split('.');
136
137 // Allow symlinks to top-level frameworks.
138 if (IsSymLink && Rest == "framework")
139 return false;
140
141 // Only top level framework are public.
142 // /System/Library/Frameworks/Foo.framework/Foo ==> true
143 // /System/Library/Frameworks/Foo.framework/Versions/A/Foo ==> true
144 // /System/Library/Frameworks/Foo.framework/Resources/libBar.dylib ==> false
145 // /System/Library/Frameworks/Foo.framework/Frameworks/Bar.framework/Bar
146 // ==> false
147 // /System/Library/Frameworks/Foo.framework/Frameworks/Xfoo.framework/XFoo
148 // ==> false
149 return !(Rest.starts_with("framework/") &&
150 (Rest.ends_with(Name) || Rest.ends_with((Name + ".tbd").str()) ||
151 (IsSymLink && Rest.ends_with("Current"))));
152 }
153 return false;
154}
155
156static StringLiteral RegexMetachars = "()^$|+.[]\\{}";
157
159 SmallString<128> RegexString("^");
160 unsigned NumWildcards = 0;
161 for (unsigned i = 0; i < Glob.size(); ++i) {
162 char C = Glob[i];
163 switch (C) {
164 case '?':
165 RegexString += '.';
166 break;
167 case '*': {
168 const char *PrevChar = i > 0 ? Glob.data() + i - 1 : nullptr;
169 NumWildcards = 1;
170 ++i;
171 while (i < Glob.size() && Glob[i] == '*') {
172 ++NumWildcards;
173 ++i;
174 }
175 const char *NextChar = i < Glob.size() ? Glob.data() + i : nullptr;
176
177 if ((NumWildcards > 1) && (PrevChar == nullptr || *PrevChar == '/') &&
178 (NextChar == nullptr || *NextChar == '/')) {
179 RegexString += "(([^/]*(/|$))*)";
180 } else
181 RegexString += "([^/]*)";
182 break;
183 }
184 default:
186 RegexString.push_back('\\');
187 RegexString.push_back(C);
188 }
189 }
190 RegexString.push_back('$');
191 if (NumWildcards == 0)
192 return make_error<StringError>("not a glob", inconvertibleErrorCode());
193
194 llvm::Regex Rule = Regex(RegexString);
195 std::string Error;
196 if (!Rule.isValid(Error))
197 return make_error<StringError>(Error, inconvertibleErrorCode());
198
199 return std::move(Rule);
200}
BlockVerifier::State From
std::string Name
#define P(N)
static StringLiteral RegexMetachars
Definition: Utils.cpp:156
#define DRIVERKIT_PREFIX_PATH
Definition: Utils.h:27
#define MACCATALYST_PREFIX_PATH
Definition: Utils.h:26
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Tagged union holding either a T or a Error.
Definition: Error.h:474
bool isValid(std::string &Error) const
isValid - returns the error encountered during regex compilation, if any.
Definition: Regex.cpp:69
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void swap(SmallVectorImpl &RHS)
Definition: SmallVector.h:981
void push_back(const T &Elt)
Definition: SmallVector.h:426
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition: StringRef.h:849
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:257
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:293
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:271
static constexpr size_t npos
Definition: StringRef.h:52
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:226
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
std::error_code make_relative(StringRef From, StringRef To, SmallVectorImpl< char > &RelativePath)
Turn absolute symlink into relative.
Definition: Utils.cpp:74
void replace_extension(SmallVectorImpl< char > &Path, const Twine &Extension)
Replace extension considering frameworks.
Definition: Utils.cpp:18
bool isPrivateLibrary(StringRef Path, bool IsSymLink=false)
Determine if library is private by parsing file path.
Definition: Utils.cpp:108
llvm::Expected< llvm::Regex > createRegexFromGlob(llvm::StringRef Glob)
Create a regex rule from provided glob string.
Definition: Utils.cpp:158
std::error_code shouldSkipSymLink(const Twine &Path, bool &Result)
Determine whether to skip over symlink due to either too many symlink levels or is cyclic.
Definition: Utils.cpp:42
bool equivalent(file_status A, file_status B)
Do file_status's represent the same thing?
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:907
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:227
void replace_extension(SmallVectorImpl< char > &path, const Twine &extension, Style style=Style::native)
Replace the file extension of path with extension.
Definition: Path.cpp:481
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:236
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:578
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:468
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:457
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:90