[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