ErrorOr<StringRef> MachOLinkingContext::searchDirForLibrary(StringRef path, StringRef libName) const { SmallString<256> fullPath; if (libName.endswith(".o")) { // A request ending in .o is special: just search for the file directly. fullPath.assign(path); llvm::sys::path::append(fullPath, libName); if (fileExists(fullPath)) return fullPath.str().copy(_allocator); return make_error_code(llvm::errc::no_such_file_or_directory); } // Search for dynamic library fullPath.assign(path); llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib"); if (fileExists(fullPath)) return fullPath.str().copy(_allocator); // If not, try for a static library fullPath.assign(path); llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a"); if (fileExists(fullPath)) return fullPath.str().copy(_allocator); return make_error_code(llvm::errc::no_such_file_or_directory); }
static void buildSearchPath(SmallString<128> &path, StringRef dir, StringRef sysRoot) { if (dir.startswith("=/")) { // If a search directory begins with "=", "=" is replaced // with the sysroot path. path.assign(sysRoot); path.append(dir.substr(1)); } else { path.assign(dir); } }
MachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) { // See if already loaded. auto pos = _pathToDylibMap.find(path); if (pos != _pathToDylibMap.end()) return pos->second; // Search -L paths if of the form "libXXX.dylib" std::pair<StringRef, StringRef> split = path.rsplit('/'); StringRef leafName = split.second; if (leafName.startswith("lib") && leafName.endswith(".dylib")) { // FIXME: Need to enhance searchLibrary() to only look for .dylib auto libPath = searchLibrary(leafName); if (!libPath.getError()) { return loadIndirectDylib(libPath.get()); } } // Try full path with sysroot. for (StringRef sysPath : _syslibRoots) { SmallString<256> fullPath; fullPath.assign(sysPath); llvm::sys::path::append(fullPath, path); if (pathExists(fullPath)) return loadIndirectDylib(fullPath); } // Try full path. if (pathExists(path)) { return loadIndirectDylib(path); } return nullptr; }
ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const { bool foundFile = false; StringRef pathref; SmallString<128> path; for (StringRef dir : _inputSearchPaths) { // Search for dynamic library if (!_isStaticExecutable) { path.clear(); if (dir.startswith("=/")) { path.assign(_sysrootPath); path.append(dir.substr(1)); } else { path.assign(dir); } llvm::sys::path::append(path, Twine("lib") + libName + ".so"); pathref = path.str(); if (llvm::sys::fs::exists(pathref)) { foundFile = true; } } // Search for static libraries too if (!foundFile) { path.clear(); if (dir.startswith("=/")) { path.assign(_sysrootPath); path.append(dir.substr(1)); } else { path.assign(dir); } llvm::sys::path::append(path, Twine("lib") + libName + ".a"); pathref = path.str(); if (llvm::sys::fs::exists(pathref)) { foundFile = true; } } if (foundFile) return StringRef(*new (_allocator) std::string(pathref)); } if (!llvm::sys::fs::exists(libName)) return llvm::make_error_code(llvm::errc::no_such_file_or_directory); return libName; }
ErrorOr<StringRef> MachOLinkingContext::findPathForFramework(StringRef fwName) const { SmallString<256> fullPath; for (StringRef dir : frameworkDirs()) { fullPath.assign(dir); llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName); if (fileExists(fullPath)) return fullPath.str().copy(_allocator); } return make_error_code(llvm::errc::no_such_file_or_directory); }
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, const ArgList &Args) : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)), CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) { SmallString<128> P; P.assign(D.ResourceDir); llvm::sys::path::append(P, D.getTargetTriple(), "lib"); if (getVFS().exists(P)) getLibraryPaths().push_back(P.str()); P.assign(D.ResourceDir); llvm::sys::path::append(P, Triple.str(), "lib"); if (getVFS().exists(P)) getLibraryPaths().push_back(P.str()); std::string CandidateLibPath = getArchSpecificLibPath(); if (getVFS().exists(CandidateLibPath)) getFilePaths().push_back(CandidateLibPath); }
/// \brief Print the given string to a stream, word-wrapping it to /// some number of columns in the process. /// /// \param OS the stream to which the word-wrapping string will be /// emitted. /// \param Str the string to word-wrap and output. /// \param Columns the number of columns to word-wrap to. /// \param Column the column number at which the first character of \p /// Str will be printed. This will be non-zero when part of the first /// line has already been printed. /// \param Bold if the current text should be bold /// \param Indentation the number of spaces to indent any lines beyond /// the first line. /// \returns true if word-wrapping was required, or false if the /// string fit on the first line. static bool printWordWrapped(raw_ostream &OS, StringRef Str, unsigned Columns, unsigned Column = 0, bool Bold = false, unsigned Indentation = WordWrapIndentation) { const unsigned Length = std::min(Str.find('\n'), Str.size()); bool TextNormal = true; // The string used to indent each line. SmallString<16> IndentStr; IndentStr.assign(Indentation, ' '); bool Wrapped = false; for (unsigned WordStart = 0, WordEnd; WordStart < Length; WordStart = WordEnd) { // Find the beginning of the next word. WordStart = skipWhitespace(WordStart, Str, Length); if (WordStart == Length) break; // Find the end of this word. WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns); // Does this word fit on the current line? unsigned WordLength = WordEnd - WordStart; if (Column + WordLength < Columns) { // This word fits on the current line; print it there. if (WordStart) { OS << ' '; Column += 1; } applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength), TextNormal, Bold); Column += WordLength; continue; } // This word does not fit on the current line, so wrap to the next // line. OS << '\n'; OS.write(&IndentStr[0], Indentation); applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength), TextNormal, Bold); Column = Indentation + WordLength; Wrapped = true; } // Append any remaning text from the message with its existing formatting. applyTemplateHighlighting(OS, Str.substr(Length), TextNormal, Bold); assert(TextNormal && "Text highlighted at end of diagnostic message."); return Wrapped; }
/// Determine if the given invocation should run as a subcommand. /// /// \param ExecName The name of the argv[0] we were invoked as. /// \param SubcommandName On success, the full name of the subcommand to invoke. /// \param Args On return, the adjusted program arguments to use. /// \returns True if running as a subcommand. static bool shouldRunAsSubcommand(StringRef ExecName, SmallString<256> &SubcommandName, const ArrayRef<const char *> Args, bool &isRepl) { assert(!Args.empty()); // If we are not run as 'swift', don't do anything special. This doesn't work // with symlinks with alternate names, but we can't detect 'swift' vs 'swiftc' // if we try and resolve using the actual executable path. if (ExecName != "swift") return false; // If there are no program arguments, always invoke as normal. if (Args.size() == 1) return false; // Otherwise, we have a program argument. If it looks like an option or a // path, then invoke in interactive mode with the arguments as given. StringRef FirstArg(Args[1]); if (FirstArg.startswith("-") || FirstArg.find('.') != StringRef::npos || FirstArg.find('/') != StringRef::npos) return false; // Otherwise, we should have some sort of subcommand. Get the subcommand name // and remove it from the program arguments. StringRef Subcommand = Args[1]; // If the subcommand is the "built-in" 'repl', then use the // normal driver. if (Subcommand == "repl") { isRepl = true; return false; } // Form the subcommand name. SubcommandName.assign("swift-"); SubcommandName.append(Subcommand); return true; }
ErrorOr<StringRef> ELFLinkingContext::searchFile(StringRef fileName, bool isSysRooted) const { SmallString<128> path; if (is_absolute(fileName) && isSysRooted) { path.assign(_sysrootPath); path.append(fileName); if (exists(path.str())) return path.str().copy(_allocator); } else if (exists(fileName)) { return fileName; } if (is_absolute(fileName)) return make_error_code(llvm::errc::no_such_file_or_directory); for (StringRef dir : _inputSearchPaths) { buildSearchPath(path, dir, _sysrootPath); llvm::sys::path::append(path, fileName); if (exists(path.str())) return path.str().copy(_allocator); } return make_error_code(llvm::errc::no_such_file_or_directory); }
/// \brief returns a printable representation of first item from input range /// /// This function returns a printable representation of the next item in a line /// of source. If the next byte begins a valid and printable character, that /// character is returned along with 'true'. /// /// Otherwise, if the next byte begins a valid, but unprintable character, a /// printable, escaped representation of the character is returned, along with /// 'false'. Otherwise a printable, escaped representation of the next byte /// is returned along with 'false'. /// /// \note The index is updated to be used with a subsequent call to /// printableTextForNextCharacter. /// /// \param SourceLine The line of source /// \param i Pointer to byte index, /// \param TabStop used to expand tabs /// \return pair(printable text, 'true' iff original text was printable) /// static std::pair<SmallString<16>, bool> printableTextForNextCharacter(StringRef SourceLine, size_t *i, unsigned TabStop) { assert(i && "i must not be null"); assert(*i<SourceLine.size() && "must point to a valid index"); if (SourceLine[*i]=='\t') { assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop && "Invalid -ftabstop value"); unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i); unsigned NumSpaces = TabStop - col%TabStop; assert(0 < NumSpaces && NumSpaces <= TabStop && "Invalid computation of space amt"); ++(*i); SmallString<16> expandedTab; expandedTab.assign(NumSpaces, ' '); return std::make_pair(expandedTab, true); } unsigned char const *begin, *end; begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i)); end = begin + (SourceLine.size() - *i); if (isLegalUTF8Sequence(begin, end)) { UTF32 c; UTF32 *cptr = &c; unsigned char const *original_begin = begin; unsigned char const *cp_end = begin+getNumBytesForUTF8(SourceLine[*i]); ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1, strictConversion); (void)res; assert(conversionOK==res); assert(0 < begin-original_begin && "we must be further along in the string now"); *i += begin-original_begin; if (!llvm::sys::locale::isPrint(c)) { // If next character is valid UTF-8, but not printable SmallString<16> expandedCP("<U+>"); while (c) { expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16)); c/=16; } while (expandedCP.size() < 8) expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0)); return std::make_pair(expandedCP, false); } // If next character is valid UTF-8, and printable return std::make_pair(SmallString<16>(original_begin, cp_end), true); } // If next byte is not valid UTF-8 (and therefore not printable) SmallString<16> expandedByte("<XX>"); unsigned char byte = SourceLine[*i]; expandedByte[1] = llvm::hexdigit(byte / 16); expandedByte[2] = llvm::hexdigit(byte % 16); ++(*i); return std::make_pair(expandedByte, false); }
static StringRef input(StringRef Scalar, void *, SmallString<U> &Value) { Value.assign(Scalar.begin(), Scalar.end()); return StringRef(); }