[DominatorTree] Add support for mixed pre/post CFG views.
[llvm-project.git] / compiler-rt / lib / fuzzer / FuzzerCommand.h
blob87308864af5314a0321b3328616258b25c666605
1 //===- FuzzerCommand.h - Interface representing a process -------*- 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 // FuzzerCommand represents a command to run in a subprocess. It allows callers
9 // to manage command line arguments and output and error streams.
10 //===----------------------------------------------------------------------===//
12 #ifndef LLVM_FUZZER_COMMAND_H
13 #define LLVM_FUZZER_COMMAND_H
15 #include "FuzzerDefs.h"
16 #include "FuzzerIO.h"
18 #include <algorithm>
19 #include <sstream>
20 #include <string>
21 #include <vector>
23 namespace fuzzer {
25 class Command final {
26 public:
27 // This command line flag is used to indicate that the remaining command line
28 // is immutable, meaning this flag effectively marks the end of the mutable
29 // argument list.
30 static inline const char *ignoreRemainingArgs() {
31 return "-ignore_remaining_args=1";
34 Command() : CombinedOutAndErr(false) {}
36 explicit Command(const Vector<std::string> &ArgsToAdd)
37 : Args(ArgsToAdd), CombinedOutAndErr(false) {}
39 explicit Command(const Command &Other)
40 : Args(Other.Args), CombinedOutAndErr(Other.CombinedOutAndErr),
41 OutputFile(Other.OutputFile) {}
43 Command &operator=(const Command &Other) {
44 Args = Other.Args;
45 CombinedOutAndErr = Other.CombinedOutAndErr;
46 OutputFile = Other.OutputFile;
47 return *this;
50 ~Command() {}
52 // Returns true if the given Arg is present in Args. Only checks up to
53 // "-ignore_remaining_args=1".
54 bool hasArgument(const std::string &Arg) const {
55 auto i = endMutableArgs();
56 return std::find(Args.begin(), i, Arg) != i;
59 // Gets all of the current command line arguments, **including** those after
60 // "-ignore-remaining-args=1".
61 const Vector<std::string> &getArguments() const { return Args; }
63 // Adds the given argument before "-ignore_remaining_args=1", or at the end
64 // if that flag isn't present.
65 void addArgument(const std::string &Arg) {
66 Args.insert(endMutableArgs(), Arg);
69 // Adds all given arguments before "-ignore_remaining_args=1", or at the end
70 // if that flag isn't present.
71 void addArguments(const Vector<std::string> &ArgsToAdd) {
72 Args.insert(endMutableArgs(), ArgsToAdd.begin(), ArgsToAdd.end());
75 // Removes the given argument from the command argument list. Ignores any
76 // occurrences after "-ignore_remaining_args=1", if present.
77 void removeArgument(const std::string &Arg) {
78 auto i = endMutableArgs();
79 Args.erase(std::remove(Args.begin(), i, Arg), i);
82 // Like hasArgument, but checks for "-[Flag]=...".
83 bool hasFlag(const std::string &Flag) const {
84 std::string Arg("-" + Flag + "=");
85 auto IsMatch = [&](const std::string &Other) {
86 return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
88 return std::any_of(Args.begin(), endMutableArgs(), IsMatch);
91 // Returns the value of the first instance of a given flag, or an empty string
92 // if the flag isn't present. Ignores any occurrences after
93 // "-ignore_remaining_args=1", if present.
94 std::string getFlagValue(const std::string &Flag) const {
95 std::string Arg("-" + Flag + "=");
96 auto IsMatch = [&](const std::string &Other) {
97 return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
99 auto i = endMutableArgs();
100 auto j = std::find_if(Args.begin(), i, IsMatch);
101 std::string result;
102 if (j != i) {
103 result = j->substr(Arg.length());
105 return result;
108 // Like AddArgument, but adds "-[Flag]=[Value]".
109 void addFlag(const std::string &Flag, const std::string &Value) {
110 addArgument("-" + Flag + "=" + Value);
113 // Like RemoveArgument, but removes "-[Flag]=...".
114 void removeFlag(const std::string &Flag) {
115 std::string Arg("-" + Flag + "=");
116 auto IsMatch = [&](const std::string &Other) {
117 return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
119 auto i = endMutableArgs();
120 Args.erase(std::remove_if(Args.begin(), i, IsMatch), i);
123 // Returns whether the command's stdout is being written to an output file.
124 bool hasOutputFile() const { return !OutputFile.empty(); }
126 // Returns the currently set output file.
127 const std::string &getOutputFile() const { return OutputFile; }
129 // Configures the command to redirect its output to the name file.
130 void setOutputFile(const std::string &FileName) { OutputFile = FileName; }
132 // Returns whether the command's stderr is redirected to stdout.
133 bool isOutAndErrCombined() const { return CombinedOutAndErr; }
135 // Sets whether to redirect the command's stderr to its stdout.
136 void combineOutAndErr(bool combine = true) { CombinedOutAndErr = combine; }
138 // Returns a string representation of the command. On many systems this will
139 // be the equivalent command line.
140 std::string toString() const {
141 std::stringstream SS;
142 for (auto arg : getArguments())
143 SS << arg << " ";
144 if (hasOutputFile())
145 SS << ">" << getOutputFile() << " ";
146 if (isOutAndErrCombined())
147 SS << "2>&1 ";
148 std::string result = SS.str();
149 if (!result.empty())
150 result = result.substr(0, result.length() - 1);
151 return result;
154 private:
155 Command(Command &&Other) = delete;
156 Command &operator=(Command &&Other) = delete;
158 Vector<std::string>::iterator endMutableArgs() {
159 return std::find(Args.begin(), Args.end(), ignoreRemainingArgs());
162 Vector<std::string>::const_iterator endMutableArgs() const {
163 return std::find(Args.begin(), Args.end(), ignoreRemainingArgs());
166 // The command arguments. Args[0] is the command name.
167 Vector<std::string> Args;
169 // True indicates stderr is redirected to stdout.
170 bool CombinedOutAndErr;
172 // If not empty, stdout is redirected to the named file.
173 std::string OutputFile;
176 } // namespace fuzzer
178 #endif // LLVM_FUZZER_COMMAND_H