blob: fec7bd4e1f2a410c43103215cd10f2196ce86919 [file] [log] [blame]
Rui Ueyama93c9af42016-06-29 08:01:32 +00001//===- Strings.cpp -------------------------------------------------------===//
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 "Strings.h"
11#include "Error.h"
George Rimarc91930a2016-09-02 21:17:20 +000012#include "llvm/ADT/ArrayRef.h"
Rui Ueyama93c9af42016-06-29 08:01:32 +000013#include "llvm/ADT/StringRef.h"
14#include "llvm/ADT/Twine.h"
Rui Ueyamaf4d93382016-07-07 23:04:15 +000015#include "llvm/Config/config.h"
Rafael Espindolad1942132016-09-06 19:17:14 +000016#include "llvm/Demangle/Demangle.h"
Rui Ueyamafbbde542016-06-29 09:08:02 +000017#include <algorithm>
Rui Ueyama93c9af42016-06-29 08:01:32 +000018
19using namespace llvm;
20using namespace lld;
21using namespace lld::elf;
22
George Rimarc91930a2016-09-02 21:17:20 +000023bool elf::hasWildcard(StringRef S) {
George Rimar51da9c72016-09-07 10:19:44 +000024 return S.find_first_of("?*[") != StringRef::npos;
George Rimarc91930a2016-09-02 21:17:20 +000025}
26
Rui Ueyamadad2b882016-09-02 22:15:08 +000027// Converts a glob pattern to a regular expression.
George Rimarc91930a2016-09-02 21:17:20 +000028static std::string toRegex(StringRef S) {
George Rimarc91930a2016-09-02 21:17:20 +000029 std::string T;
George Rimar51da9c72016-09-07 10:19:44 +000030 bool InBracket = false;
George Rimarc91930a2016-09-02 21:17:20 +000031 while (!S.empty()) {
32 char C = S.front();
George Rimar51da9c72016-09-07 10:19:44 +000033 if (InBracket) {
34 InBracket = C != ']';
35 T += C;
36 S = S.drop_front();
37 continue;
38 }
39
George Rimarc91930a2016-09-02 21:17:20 +000040 if (C == '*')
41 T += ".*";
42 else if (C == '?')
43 T += '.';
George Rimar51da9c72016-09-07 10:19:44 +000044 else if (StringRef(".+^${}()|/\\").find_first_of(C) != StringRef::npos)
George Rimarc91930a2016-09-02 21:17:20 +000045 T += std::string("\\") + C;
46 else
47 T += C;
George Rimar51da9c72016-09-07 10:19:44 +000048
49 InBracket = C == '[';
Rui Ueyama93c9af42016-06-29 08:01:32 +000050 S = S.substr(1);
Rui Ueyama93c9af42016-06-29 08:01:32 +000051 }
George Rimarc91930a2016-09-02 21:17:20 +000052 return T;
53}
54
Rui Ueyamadad2b882016-09-02 22:15:08 +000055// Converts multiple glob patterns to a regular expression.
George Rimarc91930a2016-09-02 21:17:20 +000056Regex elf::compileGlobPatterns(ArrayRef<StringRef> V) {
57 std::string T = "^(" + toRegex(V[0]);
58 for (StringRef S : V.slice(1))
59 T += "|" + toRegex(S);
60 return Regex(T + ")$");
Rui Ueyama93c9af42016-06-29 08:01:32 +000061}
62
63// Converts a hex string (e.g. "deadbeef") to a vector.
64std::vector<uint8_t> elf::parseHex(StringRef S) {
65 std::vector<uint8_t> Hex;
66 while (!S.empty()) {
67 StringRef B = S.substr(0, 2);
68 S = S.substr(2);
69 uint8_t H;
70 if (B.getAsInteger(16, H)) {
71 error("not a hexadecimal value: " + B);
72 return {};
73 }
74 Hex.push_back(H);
75 }
76 return Hex;
77}
Rui Ueyamafbbde542016-06-29 09:08:02 +000078
79static bool isAlpha(char C) {
80 return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
81}
82
83static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
84
85// Returns true if S is valid as a C language identifier.
86bool elf::isValidCIdentifier(StringRef S) {
87 return !S.empty() && isAlpha(S[0]) &&
88 std::all_of(S.begin() + 1, S.end(), isAlnum);
89}
Rui Ueyamaf4d93382016-07-07 23:04:15 +000090
91// Returns the demangled C++ symbol name for Name.
92std::string elf::demangle(StringRef Name) {
Rui Ueyamaf4d93382016-07-07 23:04:15 +000093 // __cxa_demangle can be used to demangle strings other than symbol
94 // names which do not necessarily start with "_Z". Name can be
95 // either a C or C++ symbol. Don't call __cxa_demangle if the name
96 // does not look like a C++ symbol name to avoid getting unexpected
97 // result for a C symbol that happens to match a mangled type name.
98 if (!Name.startswith("_Z"))
99 return Name;
100
Rafael Espindolad1942132016-09-06 19:17:14 +0000101 char *Buf = itaniumDemangle(Name.str().c_str(), nullptr, nullptr, nullptr);
Rui Ueyamaf4d93382016-07-07 23:04:15 +0000102 if (!Buf)
103 return Name;
104 std::string S(Buf);
105 free(Buf);
106 return S;
Rui Ueyamaf4d93382016-07-07 23:04:15 +0000107}