<br><br>On Wednesday, July 16, 2014, Timur Iskhodzhanov <<a href="mailto:timurrrr@google.com">timurrrr@google.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
2014-07-16 4:52 GMT+04:00 Hans Wennborg <<a href="javascript:;" onclick="_e(event, 'cvml', 'hans@hanshq.net')">hans@hanshq.net</a>>:<br>
> Author: hans<br>
> Date: Tue Jul 15 19:52:11 2014<br>
> New Revision: 213114<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=213114&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=213114&view=rev</a><br>
> Log:<br>
> Perform wildcard expansion in Process::GetArgumentVector on Windows (PR17098)<br>
><br>
> On Windows, wildcard expansion isn't performed by the shell, but left to the<br>
> program itself. The common way to do this is to link with setargv.obj, which<br>
> performs the expansion on argc/argv before main is entered. However, we don't<br>
> use argv in Clang on Windows, but instead call GetCommandLineW so we can handle<br>
> unicode arguments.<br>
<br>
Why don't we use wmain?</blockquote><div><br></div><div>Because using it with MinGW is non trivial.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
> This means we have to do wildcard expansion ourselves.<br>
><br>
> A test case will be added on the Clang side.<br>
><br>
> Differential Revision: <a href="http://reviews.llvm.org/D4529" target="_blank">http://reviews.llvm.org/D4529</a><br>
><br>
> Modified:<br>
>     llvm/trunk/lib/Support/Windows/Process.inc<br>
><br>
> Modified: llvm/trunk/lib/Support/Windows/Process.inc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Process.inc?rev=213114&r1=213113&r2=213114&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Process.inc?rev=213114&r1=213113&r2=213114&view=diff</a><br>

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