[llvm] r221220 - [Support][Program] Add findProgramByName(Name, OptionalPaths)
Reid Kleckner
rnk at google.com
Thu Nov 13 14:11:32 PST 2014
I tweaked this in r221932 to go back to wchar_t / wstring because of some
STL difficulties with MSVC "14".
On Mon, Nov 3, 2014 at 5:29 PM, Michael J. Spencer <bigcheesegs at gmail.com>
wrote:
> 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) {
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141113/62afa9ba/attachment.html>
More information about the llvm-commits
mailing list