Program.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. //===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements the operating system Program concept.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/Support/Program.h"
  13. #include "llvm/ADT/StringRef.h"
  14. #include "llvm/Config/llvm-config.h"
  15. #include "llvm/Support/raw_ostream.h"
  16. #include <system_error>
  17. using namespace llvm;
  18. using namespace sys;
  19. //===----------------------------------------------------------------------===//
  20. //=== WARNING: Implementation here must contain only TRULY operating system
  21. //=== independent code.
  22. //===----------------------------------------------------------------------===//
  23. static bool Execute(ProcessInfo &PI, StringRef Program,
  24. ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
  25. ArrayRef<Optional<StringRef>> Redirects,
  26. unsigned MemoryLimit, std::string *ErrMsg,
  27. BitVector *AffinityMask);
  28. int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args,
  29. Optional<ArrayRef<StringRef>> Env,
  30. ArrayRef<Optional<StringRef>> Redirects,
  31. unsigned SecondsToWait, unsigned MemoryLimit,
  32. std::string *ErrMsg, bool *ExecutionFailed,
  33. Optional<ProcessStatistics> *ProcStat,
  34. BitVector *AffinityMask) {
  35. assert(Redirects.empty() || Redirects.size() == 3);
  36. ProcessInfo PI;
  37. if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg,
  38. AffinityMask)) {
  39. if (ExecutionFailed)
  40. *ExecutionFailed = false;
  41. ProcessInfo Result =
  42. Wait(PI, SecondsToWait, /*WaitUntilTerminates=*/SecondsToWait == 0,
  43. ErrMsg, ProcStat);
  44. return Result.ReturnCode;
  45. }
  46. if (ExecutionFailed)
  47. *ExecutionFailed = true;
  48. return -1;
  49. }
  50. ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
  51. Optional<ArrayRef<StringRef>> Env,
  52. ArrayRef<Optional<StringRef>> Redirects,
  53. unsigned MemoryLimit, std::string *ErrMsg,
  54. bool *ExecutionFailed, BitVector *AffinityMask) {
  55. assert(Redirects.empty() || Redirects.size() == 3);
  56. ProcessInfo PI;
  57. if (ExecutionFailed)
  58. *ExecutionFailed = false;
  59. if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg,
  60. AffinityMask))
  61. if (ExecutionFailed)
  62. *ExecutionFailed = true;
  63. return PI;
  64. }
  65. bool sys::commandLineFitsWithinSystemLimits(StringRef Program,
  66. ArrayRef<const char *> Args) {
  67. SmallVector<StringRef, 8> StringRefArgs;
  68. StringRefArgs.reserve(Args.size());
  69. for (const char *A : Args)
  70. StringRefArgs.emplace_back(A);
  71. return commandLineFitsWithinSystemLimits(Program, StringRefArgs);
  72. }
  73. void sys::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
  74. const bool Escape = Arg.find_first_of(" \"\\$") != StringRef::npos;
  75. if (!Quote && !Escape) {
  76. OS << Arg;
  77. return;
  78. }
  79. // Quote and escape. This isn't really complete, but good enough.
  80. OS << '"';
  81. for (const auto c : Arg) {
  82. if (c == '"' || c == '\\' || c == '$')
  83. OS << '\\';
  84. OS << c;
  85. }
  86. OS << '"';
  87. }
  88. // Include the platform-specific parts of this class.
  89. #ifdef LLVM_ON_UNIX
  90. #include "Unix/Program.inc"
  91. #endif
  92. #ifdef _WIN32
  93. #include "Windows/Program.inc"
  94. #endif