diff options
author | Reid Spencer <rspencer@reidspencer.com> | 2004-09-15 05:49:50 +0000 |
---|---|---|
committer | Reid Spencer <rspencer@reidspencer.com> | 2004-09-15 05:49:50 +0000 |
commit | b016a376abc0d35ab4e77ea32a5b0421d980482b (patch) | |
tree | bb0e4e7ab7fecf084e5f24e08dedd8cef564104c /lib/System/Win32/Program.cpp | |
parent | 90418436c039dbc281e356b049310f1912a85b4c (diff) |
Patches to make this file actually compile under windows.
Patches submitted by Jeff Cohen. Thanks Jeff!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16362 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/System/Win32/Program.cpp')
-rw-r--r-- | lib/System/Win32/Program.cpp | 142 |
1 files changed, 138 insertions, 4 deletions
diff --git a/lib/System/Win32/Program.cpp b/lib/System/Win32/Program.cpp index 7a6b124d2d..a83f0e84f8 100644 --- a/lib/System/Win32/Program.cpp +++ b/lib/System/Win32/Program.cpp @@ -1,8 +1,8 @@ -//===- Win32/Program.cpp - Win32 Program Implelementation ----- -*- C++ -*-===// +//===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===// // // The LLVM Compiler Infrastructure // -// This file was developed by Reid Spencer and is distributed under the +// This file was developed by Jeff Cohen and is distributed under the // University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// @@ -11,9 +11,143 @@ // //===----------------------------------------------------------------------===// +// Include the generic Unix implementation +#include "Win32.h" +#include "llvm/System/Program.h" +#include <malloc.h> + //===----------------------------------------------------------------------===// -//=== WARNING: Implementation here must contain only generic Win32 code that -//=== is guaranteed to work on *all* Win32 variants. +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code //===----------------------------------------------------------------------===// +namespace llvm { +using namespace sys; + +// This function just uses the PATH environment variable to find the program. +Path +Program::FindProgramByName(const std::string& progName) { + + // Check some degenerate cases + if (progName.length() == 0) // no program + return Path(); + Path temp; + if (!temp.set_file(progName)) // invalid name + return Path(); + if (temp.executable()) // already executable as is + return temp; + + // At this point, the file name is valid and its not executable. + // Let Windows search for it. + char buffer[MAX_PATH]; + char *dummy = NULL; + DWORD len = SearchPath(NULL, progName.c_str(), ".exe", MAX_PATH, + buffer, &dummy); + + // See if it wasn't found. + if (len == 0) + return Path(); + + // See if we got the entire path. + if (len < MAX_PATH) + return Path(buffer); + + // Buffer was too small; grow and retry. + while (true) { + char *b = reinterpret_cast<char *>(_alloca(len+1)); + DWORD len2 = SearchPath(NULL, progName.c_str(), ".exe", len+1, b, &dummy); + + // It is unlikely the search failed, but it's always possible some file + // was added or removed since the last search, so be paranoid... + if (len2 == 0) + return Path(); + else if (len2 <= len) + return Path(b); + + len = len2; + } +} + +// +int +Program::ExecuteAndWait(const Path& path, + const std::vector<std::string>& args) { + if (!path.executable()) + throw path.get() + " is not executable"; + + // Windows wants a command line, not an array of args, to pass to the new + // process. We have to concatenate them all, while quoting the args that + // have embedded spaces. + + // First, determine the length of the command line. + std::string progname(path.getLast()); + unsigned len = progname.length() + 1; + if (progname.find(' ') != std::string::npos) + len += 2; + + for (unsigned i = 0; i < args.size(); i++) { + len += args[i].length() + 1; + if (args[i].find(' ') != std::string::npos) + len += 2; + } + + // Now build the command line. + char *command = reinterpret_cast<char *>(_alloca(len)); + char *p = command; + + bool needsQuoting = progname.find(' ') != std::string::npos; + if (needsQuoting) + *p++ = '"'; + memcpy(p, progname.c_str(), progname.length()); + p += progname.length(); + if (needsQuoting) + *p++ = '"'; + *p++ = ' '; + + for (unsigned i = 0; i < args.size(); i++) { + const std::string& arg = args[i]; + needsQuoting = arg.find(' ') != std::string::npos; + if (needsQuoting) + *p++ = '"'; + memcpy(p, arg.c_str(), arg.length()); + p += arg.length(); + if (needsQuoting) + *p++ = '"'; + *p++ = ' '; + } + + *p = 0; + + // Create a child process. + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + + if (!CreateProcess(path.get().c_str(), command, NULL, NULL, FALSE, 0, + NULL, NULL, &si, &pi)) + { + ThrowError(std::string("Couldn't execute program '") + path.get() + "'"); + } + + // Wait for it to terminate. + WaitForSingleObject(pi.hProcess, INFINITE); + + // Get its exit status. + DWORD status; + BOOL rc = GetExitCodeProcess(pi.hProcess, &status); + + // Done with the handles; go close them. + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + if (!rc) + ThrowError(std::string("Failed getting status for program '") + path.get() + "'"); + + return status; +} + +} // vim: sw=2 smartindent smarttab tw=80 autoindent expandtab |