diff --git a/llvm/include/llvm/System/Program.h b/llvm/include/llvm/System/Program.h index 01a5ec5b0151..e37ef491e62a 100644 --- a/llvm/include/llvm/System/Program.h +++ b/llvm/include/llvm/System/Program.h @@ -21,14 +21,13 @@ namespace llvm { namespace sys { /// This class provides an abstraction for programs that are executable by the - /// operating system. It derives from Path because every executable on all - /// known operating systems has a pathname that is needed in order to execute - /// the program. This class provides an operating system agnostic interface - /// for the procedure of finding and executing programs in a variety of ways. + /// operating system. It provides a platform generic way to find executable + /// programs from the path and to execute them. The sys::Path class is used to + /// locate the Program. /// @since 1.4 - /// @brief An abstraction for operating system programs. - class Program : public Path { - /// @name Constructors + /// @brief An abstraction for finding and executing programs. + class Program { + /// @name Methods /// @{ public: /// This static constructor (factory) will attempt to locate a program in @@ -38,20 +37,8 @@ namespace sys { /// Path object that is empty (invalid) if the program could not be found. /// @throws nothing /// @brief Construct a Program by finding it by name. - static Program FindProgramByName(const std::string& name); + static Path FindProgramByName(const std::string& name); - /// This static constructor (factory) constructs a Program object that - /// refers to the currently executing program. - /// @brief Constructs a Program object for the currently executing - /// program. - // static Program This(); - /// FIXME: Not sure if this is currently doable. - - - /// @} - /// @name Methods - /// @{ - public: /// This function executes the program using the \p arguments provided and /// waits for the program to exit. This function will block the current /// program until the invoked program exits. The invoked program will @@ -60,13 +47,18 @@ namespace sys { /// If Path::executable() does not return true when this function is /// called then a std::string is thrown. /// Path::executable() returns true. - /// @param arguments A vector of strings that are passed to the program. + /// @param path A sys::Path object providing the path of the program to be + /// executed. It is presumed this is the result of the FindProgramByName + /// method. + /// @param args A vector of strings that are passed to the program. /// The first element should *not* be the name of the program. /// @returns an integer result code indicating the status of the program. /// @throws std::string on a variety of error conditions or if the invoked /// program aborted abnormally. + /// @see FindProgrambyName /// @brief Executes the program with the given set of \p arguments. - int ExecuteAndWait(const std::vector& arguments) const; + static int ExecuteAndWait(const Path& path, + const std::vector& args); /// @} }; } diff --git a/llvm/lib/System/Unix/Program.cpp b/llvm/lib/System/Unix/Program.cpp index b8ef55925d63..27f39dfd54dd 100644 --- a/llvm/lib/System/Unix/Program.cpp +++ b/llvm/lib/System/Unix/Program.cpp @@ -30,15 +30,15 @@ namespace llvm { using namespace sys; // This function just uses the PATH environment variable to find the program. -Program +Path Program::FindProgramByName(const std::string& progName) { // Check some degenerate cases if (progName.length() == 0) // no program - return Program(); - Program temp; + return Path(); + Path temp; if (!temp.set_file(progName)) // invalid name - return Program(); + return Path(); if (temp.executable()) // already executable as is return temp; @@ -47,7 +47,7 @@ Program::FindProgramByName(const std::string& progName) { // Get the path. If its empty, we can't do anything to find it. const char *PathStr = getenv("PATH"); if (PathStr == 0) - return Program(); + return Path(); // Now we have a colon separated list of directories to search; try them. unsigned PathLen = strlen(PathStr); @@ -56,7 +56,7 @@ Program::FindProgramByName(const std::string& progName) { const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); // Check to see if this first directory contains the executable... - Program FilePath; + Path FilePath; if (FilePath.set_directory(std::string(PathStr,Colon))) { FilePath.append_file(progName); if (FilePath.executable()) @@ -73,21 +73,22 @@ Program::FindProgramByName(const std::string& progName) { PathLen--; } } - return Program(); + return Path(); } // int -Program::ExecuteAndWait(const std::vector& args) const { - if (!executable()) - throw get() + " is not executable"; +Program::ExecuteAndWait(const Path& path, + const std::vector& args) { + if (!path.executable()) + throw path.get() + " 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()); + std::string progname(path.getLast()); argv[index++] = progname.c_str(); for (unsigned i = 0; i < args.size(); i++) argv[index++] = args[i].c_str(); @@ -97,12 +98,12 @@ Program::ExecuteAndWait(const std::vector& args) const { switch (fork()) { // An error occured: Return to the caller. case -1: - ThrowErrno(std::string("Couldn't execute program '") + get() + "'"); + ThrowErrno(std::string("Couldn't execute program '") + path.get() + "'"); break; // Child process: Execute the program. case 0: - execve (get().c_str(), (char** const)argv, environ); + execve (path.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); @@ -115,13 +116,13 @@ Program::ExecuteAndWait(const std::vector& args) const { // Parent process: Wait for the child process to terminate. int status; if ((::wait (&status)) == -1) - ThrowErrno(std::string("Failed waiting for program '") + get() + "'"); + ThrowErrno(std::string("Failed waiting for program '") + path.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."; + throw std::string("Program '") + path.get() + "' received terminating signal."; else return 0;