Index: Program.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/System/Win32/Program.cpp,v
retrieving revision 1.1
diff -u -r1.1 Program.cpp
--- Program.cpp	29 Aug 2004 19:20:41 -0000	1.1
+++ Program.cpp	13 Sep 2004 23:01:29 -0000
@@ -4,6 +4,8 @@
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+// Modified by Henrik Bach to comply with at least MinGW.
//
//===----------------------------------------------------------------------===//
//
@@ -16,4 +18,120 @@
//===          is guaranteed to work on *all* Win32 variants.
//===----------------------------------------------------------------------===//

+#include <llvm/Config/config.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+extern char** environ;
+
+namespace llvm {
+using namespace sys;
+
+// This function just uses the PATH environment variable to find the 
program.
+Program
+Program::FindProgramByName(const std::string& progName) {
+
+  // Check some degenerate cases
+  if (progName.length() == 0) // no program
+    return Program();
+  Program temp;
+  if (!temp.set_file(progName)) // invalid name
+    return Program();
+  if (temp.executable()) // already executable as is
+    return temp;
+
+  // At this point, the file name is valid and its not executable
+
+  // Get the path. If its empty, we can't do anything to find it.
+  const char *PathStr = getenv("PATH");
+  if (PathStr == 0)
+    return Program();
+
+  // Now we have a colon separated list of directories to search; try them.
+  unsigned PathLen = strlen(PathStr);
+  while (PathLen) {
+    // Find the first colon...
+    const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
+
+    // Check to see if this first directory contains the executable...
+    Program FilePath;
+    if (FilePath.set_directory(std::string(PathStr,Colon))) {
+      FilePath.append_file(progName);
+      if (FilePath.executable())
+        return FilePath;                    // Found the executable!
+    }
+
+    // Nope it wasn't in this directory, check the next path in the list!
+    PathLen -= Colon-PathStr;
+    PathStr = Colon;
+
+    // Advance past duplicate colons
+    while (*PathStr == ':') {
+      PathStr++;
+      PathLen--;
+    }
+  }
+  return Program();
+}
+
+//
+int
+Program::ExecuteAndWait(const std::vector<std::string>& args) const {
+  if (!executable())
+    throw std::string(get()) + std::string(" is not executable");
+
+#ifdef HAVE_SYS_WAIT_H
+  // Create local versions of the parameters that can be passed into 
execve()
+  // without creating const problems.
+  const char* argv[ args.size() + 2 ];
+  unsigned index = 0;
+  std::string progname(this->getLast());
+  argv[index++] = progname.c_str();
+  for (unsigned i = 0; i < args.size(); i++)
+    argv[index++] = args[i].c_str();
+  argv[index] = 0;
+
+  // Create a child process.
+  switch (fork()) {
+    // An error occured:  Return to the caller.
+    case -1:
+      ThrowErrno(std::string("Couldn't execute program '") + get() + "'");
+      break;
+
+    // Child process: Execute the program.
+    case 0:
+      execve (get().c_str(), (char** const)argv, environ);
+      // If the execve() failed, we should exit and let the parent pick up
+      // our non-zero exit status.
+      exit (errno);
+
+    // Parent process: Break out of the switch to do our processing.
+    default:
+      break;
+  }
+
+  // Parent process: Wait for the child process to terminate.
+  int status;
+  if ((::wait (&status)) == -1)
+    ThrowErrno(std::string("Failed waiting for program '") + get() + "'");
+
+  // If the program exited normally with a zero exit status, return 
success!
+  if (WIFEXITED (status))
+    return WEXITSTATUS(status);
+  else if (WIFSIGNALED(status))
+    throw std::string("Program '") + get() + "' received terminating 
signal.";
+  else
+    return 0;
+
+#else
+  throw std::string("Program::ExecuteAndWait not implemented on this 
platform!\n");
+#endif
+
+}
+
+} //namespace llvm
+
// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab

