/// \brief Simple utility function that appends a \p New string to the given /// \p Old string, using the \p Buffer for storage. /// /// \param Old The string to which we are appending. This parameter will be /// updated to reflect the complete string. /// /// /// \param New The string to append to \p Old. /// /// \param Buffer A buffer that stores the actual, concatenated string. It will /// be used if the old string is already-non-empty. static void AppendToString(StringRef &Old, StringRef New, llvm::SmallString<256> &Buffer) { if (Old.empty()) { Old = New; return; } if (Buffer.empty()) Buffer.append(Old.begin(), Old.end()); Buffer.append(New.begin(), New.end()); Old = Buffer.str(); }
static bool identStr(llvm::SmallString<16> &x) { char c; if (!identChar1(c)) return false; x.clear(); x.push_back(c); while (true) { const char *p = save(); if (!identChar2(c)) { restore(p); break; } x.push_back(c); } return true; }
/// \brief Compute the relative path that names the given file relative to /// the given directory. static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir, const FileEntry *File, llvm::SmallString<128> &Result) { Result.clear(); StringRef FilePath = File->getDir()->getName(); StringRef Path = FilePath; while (!Path.empty()) { if (const DirectoryEntry *CurDir = FM.getDirectory(Path)) { if (CurDir == Dir) { Result = FilePath.substr(Path.size()); llvm::sys::path::append(Result, llvm::sys::path::filename(File->getName())); return; } } Path = llvm::sys::path::parent_path(Path); } Result = File->getName(); }
static std::unique_ptr<llvm::tool_output_file> GetTemporaryObjectStream(char const *ProgramName, llvm::SmallString<256> &Path) { // TODO: If we ever support Win32 then extension should be ".obj". int FD; auto const Err = llvm::sys::fs::createUniqueFile("seec-instr-%%%%%%%%%%.o", FD, Path); if (Err) { llvm::errs() << ProgramName << ": couldn't create temporary file.\n" << Err.message() << "\n"; exit(EXIT_FAILURE); } auto Out = seec::makeUnique<llvm::tool_output_file>(Path.c_str(), FD); if (!Out) { llvm::errs() << ProgramName << ": couldn't create temporary file.\n"; exit(EXIT_FAILURE); } return Out; }
bool ConfigFile::locate(llvm::SmallString<128> &p, const char* argv0, void* mainAddr, const char* filename) { // temporary configuration // try the current working dir if (!sys::fs::current_path(p)) { sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; } // try next to the executable p = getMainExecutable(argv0, mainAddr); sys::path::remove_filename(p); sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; // user configuration // try ~/.ldc p = getUserHomeDirectory(); sys::path::append(p, ".ldc"); sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; #if _WIN32 // try home dir p = getUserHomeDirectory(); sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; #endif // system configuration // try in etc relative to the executable: exe\..\etc // do not use .. in path because of security risks p = getMainExecutable(argv0, mainAddr); sys::path::remove_filename(p); sys::path::remove_filename(p); if (!p.empty()) { sys::path::append(p, "etc"); sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; } #if _WIN32 // Try reading path from registry if (ReadPathFromRegistry(p)) { sys::path::append(p, "etc"); sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; } #else // try the install-prefix/etc p = LDC_INSTALL_PREFIX; sys::path::append(p, "etc"); sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; // try the install-prefix/etc/ldc p = LDC_INSTALL_PREFIX; sys::path::append(p, "etc"); sys::path::append(p, "ldc"); sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; // try /etc (absolute path) p = "/etc"; sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; // try /etc/ldc (absolute path) p = "/etc/ldc"; sys::path::append(p, filename); if (sys::fs::exists(p.str())) return true; #endif return false; }
HexState operator() (const char*& Ptr, llvm::raw_ostream& Stream, bool ForceHex) { // Block allocate the next chunk if (!(m_Buf.size() % kBufSize)) m_Buf.reserve(m_Buf.size() + kBufSize); HexState State = kText; const char* const Start = Ptr; char32_t Char; if (m_Utf8) { Char = utf8::next(Ptr); if (Ptr > m_End) { // Invalid/bad encoding: dump the remaining as hex Ptr = Start; while (Ptr < m_End) Stream << "\\x" << llvm::format_hex_no_prefix(uint8_t(*Ptr++), 2); m_HexRun = true; return kHex; } } else Char = (*Ptr++ & 0xff); // Assume more often than not -regular- strings are printed if (LLVM_UNLIKELY(!isPrintable(Char, m_Loc))) { m_HexRun = false; if (LLVM_UNLIKELY(ForceHex || !std::isspace(wchar_t(Char), m_Loc))) { if (Char > 0xffff) Stream << "\\U" << llvm::format_hex_no_prefix(uint32_t(Char), 8); else if (Char > 0xff) Stream << "\\u" << llvm::format_hex_no_prefix(uint16_t(Char), 4); else if (Char) { Stream << "\\x" << llvm::format_hex_no_prefix(uint8_t(Char), 2); m_HexRun = true; return kHex; } else Stream << "\\0"; return kText; } switch (Char) { case '\b': Stream << "\\b"; return kEsc; // \r isn't so great on Unix, what about Windows? case '\r': Stream << "\\r"; return kEsc; default: break; } State = kEsc; } if (m_HexRun) { // If the last print was a hex code, and this is now a char that could // be interpreted as a continuation of that hex-sequence, close out // the string and use concatenation. {'\xea', 'B'} -> "\xea" "B" m_HexRun = false; if (std::isxdigit(wchar_t(Char), m_Loc)) Stream << "\" \""; } if (m_Utf8) Stream << llvm::StringRef(Start, Ptr-Start); else Stream << char(Char); return State; }