aboutsummaryrefslogtreecommitdiff
path: root/lib/System/Win32/Program.cpp
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2004-09-15 05:49:50 +0000
committerReid Spencer <rspencer@reidspencer.com>2004-09-15 05:49:50 +0000
commitb016a376abc0d35ab4e77ea32a5b0421d980482b (patch)
treebb0e4e7ab7fecf084e5f24e08dedd8cef564104c /lib/System/Win32/Program.cpp
parent90418436c039dbc281e356b049310f1912a85b4c (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.cpp142
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