[llvm] r213114 - Perform wildcard expansion in Process::GetArgumentVector on Windows (PR17098)

Timur Iskhodzhanov timurrrr at google.com
Wed Jul 16 06:16:13 PDT 2014


2014-07-16 4:52 GMT+04:00 Hans Wennborg <hans at hanshq.net>:
> Author: hans
> Date: Tue Jul 15 19:52:11 2014
> New Revision: 213114
>
> URL: http://llvm.org/viewvc/llvm-project?rev=213114&view=rev
> Log:
> Perform wildcard expansion in Process::GetArgumentVector on Windows (PR17098)
>
> On Windows, wildcard expansion isn't performed by the shell, but left to the
> program itself. The common way to do this is to link with setargv.obj, which
> performs the expansion on argc/argv before main is entered. However, we don't
> use argv in Clang on Windows, but instead call GetCommandLineW so we can handle
> unicode arguments.

Why don't we use wmain?

> This means we have to do wildcard expansion ourselves.
>
> A test case will be added on the Clang side.
>
> Differential Revision: http://reviews.llvm.org/D4529
>
> Modified:
>     llvm/trunk/lib/Support/Windows/Process.inc
>
> Modified: llvm/trunk/lib/Support/Windows/Process.inc
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Process.inc?rev=213114&r1=213113&r2=213114&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Support/Windows/Process.inc (original)
> +++ llvm/trunk/lib/Support/Windows/Process.inc Tue Jul 15 19:52:11 2014
> @@ -183,37 +183,89 @@ static std::error_code windows_error(DWO
>    return mapWindowsError(E);
>  }
>
> +static void AllocateAndPush(const SmallVectorImpl<char> &S,
> +                            SmallVectorImpl<const char *> &Vector,
> +                            SpecificBumpPtrAllocator<char> &Allocator) {
> +  char *Buffer = Allocator.Allocate(S.size() + 1);
> +  ::memcpy(Buffer, S.data(), S.size());
> +  Buffer[S.size()] = '\0';
> +  Vector.push_back(Buffer);
> +}
> +
> +/// Convert Arg from UTF-16 to UTF-8 and push it onto Args.
> +static std::error_code
> +ConvertAndPushArg(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
> +                  SpecificBumpPtrAllocator<char> &Allocator) {
> +  SmallVector<char, MAX_PATH> ArgString;
> +  if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), ArgString))
> +    return ec;
> +  AllocateAndPush(ArgString, Args, Allocator);
> +  return std::error_code();
> +}
> +
> +/// \brief Perform wildcard expansion of Arg, or just push it into Args if it
> +/// doesn't have wildcards or doesn't match any files.
> +static std::error_code
> +WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
> +               SpecificBumpPtrAllocator<char> &Allocator) {
> +  if (!wcspbrk(Arg, L"*?")) {
> +    // Arg does not contain any wildcard characters. This is the common case.
> +    return ConvertAndPushArg(Arg, Args, Allocator);
> +  }
> +
> +  // Extract any directory part of the argument.
> +  SmallVector<char, MAX_PATH> Dir;
> +  if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), Dir))
> +    return ec;
> +  sys::path::remove_filename(Dir);
> +  const int DirSize = Dir.size();
> +
> +  // Search for matching files.
> +  WIN32_FIND_DATAW FileData;
> +  HANDLE FindHandle = FindFirstFileW(Arg, &FileData);
> +  if (FindHandle == INVALID_HANDLE_VALUE) {
> +    return ConvertAndPushArg(Arg, Args, Allocator);
> +  }
> +
> +  std::error_code ec;
> +  do {
> +    SmallVector<char, MAX_PATH> FileName;
> +    ec = windows::UTF16ToUTF8(FileData.cFileName, wcslen(FileData.cFileName),
> +                              FileName);
> +    if (ec)
> +      break;
> +
> +    // Push the filename onto Dir, and remove it afterwards.
> +    llvm::sys::path::append(Dir, StringRef(FileName.data(), FileName.size()));
> +    AllocateAndPush(Dir, Args, Allocator);
> +    Dir.resize(DirSize);
> +  } while (FindNextFileW(FindHandle, &FileData));
> +
> +  FindClose(FindHandle);
> +  return ec;
> +}
> +
>  std::error_code
>  Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
>                             ArrayRef<const char *>,
>                             SpecificBumpPtrAllocator<char> &ArgAllocator) {
> -  int NewArgCount;
> -  std::error_code ec;
> -
> -  wchar_t **UnicodeCommandLine = CommandLineToArgvW(GetCommandLineW(),
> -                                                    &NewArgCount);
> +  int ArgCount;
> +  wchar_t **UnicodeCommandLine =
> +      CommandLineToArgvW(GetCommandLineW(), &ArgCount);
>    if (!UnicodeCommandLine)
>      return windows_error(::GetLastError());
>
> -  Args.reserve(NewArgCount);
> +  Args.reserve(ArgCount);
> +  std::error_code ec;
>
> -  for (int i = 0; i < NewArgCount; ++i) {
> -    SmallVector<char, MAX_PATH> NewArgString;
> -    ec = windows::UTF16ToUTF8(UnicodeCommandLine[i],
> -                              wcslen(UnicodeCommandLine[i]),
> -                              NewArgString);
> +  for (int i = 0; i < ArgCount; ++i) {
> +    ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator);
>      if (ec)
>        break;
> -
> -    char *Buffer = ArgAllocator.Allocate(NewArgString.size() + 1);
> -    ::memcpy(Buffer, NewArgString.data(), NewArgString.size() + 1);
> -    Args.push_back(Buffer);
>    }
> -  LocalFree(UnicodeCommandLine);
> -  if (ec)
> -    return ec;
>
> -  return std::error_code();
> +  LocalFree(UnicodeCommandLine);
> +  return ec;
>  }
>
>  bool Process::StandardInIsUserInput() {
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list