[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