[llvm] r221220 - [Support][Program] Add findProgramByName(Name, OptionalPaths)
Michael J. Spencer
bigcheesegs at gmail.com
Mon Nov 3 17:29:29 PST 2014
Author: mspencer
Date: Mon Nov 3 19:29:29 2014
New Revision: 221220
URL: http://llvm.org/viewvc/llvm-project?rev=221220&view=rev
Log:
[Support][Program] Add findProgramByName(Name, OptionalPaths)
Modified:
llvm/trunk/include/llvm/Support/Program.h
llvm/trunk/lib/Support/Unix/Program.inc
llvm/trunk/lib/Support/Windows/Program.inc
Modified: llvm/trunk/include/llvm/Support/Program.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Program.h?rev=221220&r1=221219&r2=221220&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Program.h (original)
+++ llvm/trunk/include/llvm/Support/Program.h Mon Nov 3 19:29:29 2014
@@ -15,6 +15,7 @@
#define LLVM_SUPPORT_PROGRAM_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Path.h"
#include <system_error>
@@ -63,6 +64,23 @@ struct ProcessInfo {
/// the program could not be found.
std::string FindProgramByName(const std::string& name);
+ /// \brief Find the first executable file \p Name in \p Paths.
+ ///
+ /// This does not perform hashing as a shell would but instead stats each PATH
+ /// entry individually so should generally be avoided. Core LLVM library
+ /// functions and options should instead require fully specified paths.
+ ///
+ /// \param Name name of the executable to find. If it contains any system
+ /// slashes, it will be returned as is.
+ /// \param Paths optional list of paths to search for \p Name. If empty it
+ /// will use the system PATH environment instead.
+ ///
+ /// \returns The fully qualified path to the first \p Name in \p Paths if it
+ /// exists. \p Name if \p Name has slashes in it. Otherwise an error.
+ ErrorOr<std::string>
+ findProgramByName(StringRef Name,
+ ArrayRef<StringRef> Paths = ArrayRef<StringRef>());
+
// These functions change the specified standard stream (stdin or stdout) to
// binary mode. They return errc::success if the specified stream
// was changed. Otherwise a platform dependent error is returned.
Modified: llvm/trunk/lib/Support/Unix/Program.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Program.inc?rev=221220&r1=221219&r2=221220&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Unix/Program.inc (original)
+++ llvm/trunk/lib/Support/Unix/Program.inc Mon Nov 3 19:29:29 2014
@@ -17,6 +17,7 @@
//===----------------------------------------------------------------------===//
#include "Unix.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
@@ -100,6 +101,33 @@ sys::FindProgramByName(const std::string
return "";
}
+ErrorOr<std::string> sys::findProgramByName(StringRef Name,
+ ArrayRef<StringRef> Paths) {
+ assert(!Name.empty() && "Must have a name!");
+ // Use the given path verbatim if it contains any slashes; this matches
+ // the behavior of sh(1) and friends.
+ if (Name.find('/') != StringRef::npos)
+ return std::string(Name);
+
+ if (Paths.empty()) {
+ SmallVector<StringRef, 16> SearchPaths;
+ SplitString(std::getenv("PATH"), SearchPaths, ":");
+ return findProgramByName(Name, SearchPaths);
+ }
+
+ for (auto Path : Paths) {
+ if (Path.empty())
+ continue;
+
+ // Check to see if this first directory contains the executable...
+ SmallString<128> FilePath(Path);
+ sys::path::append(FilePath, Name);
+ if (sys::fs::can_execute(FilePath.c_str()))
+ return std::string(FilePath.str()); // Found the executable!
+ }
+ return std::errc::no_such_file_or_directory;
+}
+
static bool RedirectIO(const StringRef *Path, int FD, std::string* ErrMsg) {
if (!Path) // Noop
return false;
Modified: llvm/trunk/lib/Support/Windows/Program.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Program.inc?rev=221220&r1=221219&r2=221220&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Windows/Program.inc (original)
+++ llvm/trunk/lib/Support/Windows/Program.inc Mon Nov 3 19:29:29 2014
@@ -12,9 +12,11 @@
//===----------------------------------------------------------------------===//
#include "WindowsSupport.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/WindowsError.h"
#include <cstdio>
#include <fcntl.h>
#include <io.h>
@@ -69,6 +71,68 @@ std::string sys::FindProgramByName(const
return std::string(result.data(), result.size());
}
+ErrorOr<std::string> sys::findProgramByName(StringRef Name,
+ ArrayRef<StringRef> Paths) {
+ assert(!Name.empty() && "Must have a name!");
+
+ if (Name.find_first_of("/\\") != StringRef::npos)
+ return std::string(Name);
+
+ const char16_t *Path = nullptr;
+ std::u16string PathStorage;
+ if (!Paths.empty()) {
+ PathStorage.reserve(Paths.size() * MAX_PATH);
+ for (int i = 0; i < Paths.size(); ++i) {
+ if (i)
+ PathStorage.push_back(';');
+ StringRef P = Paths[i];
+ SmallVector<wchar_t, MAX_PATH> TmpPath;
+ if (std::error_code EC = windows::UTF8ToUTF16(P, TmpPath))
+ return EC;
+ PathStorage.append(TmpPath.begin(), TmpPath.end());
+ }
+ Path = PathStorage.c_str();
+ }
+
+ SmallVector<wchar_t, MAX_PATH> U16Name;
+ if (std::error_code EC = windows::UTF8ToUTF16(Name, U16Name))
+ return EC;
+
+ SmallVector<StringRef, 12> PathExts;
+ PathExts.push_back("");
+ SplitString(std::getenv("PATHEXT"), PathExts, ";");
+
+ SmallVector<wchar_t, MAX_PATH> U16Result;
+ DWORD Len = MAX_PATH;
+ for (StringRef Ext : PathExts) {
+ SmallVector<wchar_t, MAX_PATH> U16Ext;
+ if (std::error_code EC = windows::UTF8ToUTF16(Ext, U16Ext))
+ return EC;
+
+ do {
+ U16Result.reserve(Len);
+ Len = ::SearchPathW((const wchar_t *)Path, c_str(U16Name),
+ U16Ext.empty() ? nullptr : c_str(U16Ext),
+ U16Result.capacity(), U16Result.data(), nullptr);
+ } while (Len > U16Result.capacity());
+
+ if (Len != 0)
+ break; // Found it.
+ }
+
+ if (Len == 0)
+ return mapWindowsError(::GetLastError());
+
+ U16Result.set_size(Len);
+
+ SmallVector<char, MAX_PATH> U8Result;
+ if (std::error_code EC =
+ windows::UTF16ToUTF8(U16Result.data(), U16Result.size(), U8Result))
+ return EC;
+
+ return std::string(U8Result.begin(), U8Result.end());
+}
+
static HANDLE RedirectIO(const StringRef *path, int fd, std::string* ErrMsg) {
HANDLE h;
if (path == 0) {
More information about the llvm-commits
mailing list