-
-
Notifications
You must be signed in to change notification settings - Fork 267
/
Copy pathcl_helpers.h
182 lines (152 loc) · 5.48 KB
/
cl_helpers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//===-- gen/cl_helpers.h - Command line processing helpers ------*- C++ -*-===//
//
// LDC – the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
//
// Helpers to augment the LLVM command line parsing library with some extra
// functionality.
//
//===----------------------------------------------------------------------===//
#pragma once
#include "dmd/globals.h" // for CHECKENABLE enum
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
template <typename TYPE> struct Array;
typedef Array<const char *> Strings;
namespace opts {
namespace cl = llvm::cl;
/// Duplicate the string (incl. null-termination) and replace '/' with '\' on
/// Windows.
DString dupPathString(llvm::StringRef src);
/// Helper function to handle -of, -od, etc.
DString fromPathString(const cl::opt<std::string> &src);
/// Helper class to determine values
template <class DT> struct FlagParserDataType {};
template <> struct FlagParserDataType<bool> {
static bool true_val() { return true; }
static bool false_val() { return false; }
};
template <> struct FlagParserDataType<cl::boolOrDefault> {
static cl::boolOrDefault true_val() { return cl::BOU_TRUE; }
static cl::boolOrDefault false_val() { return cl::BOU_FALSE; }
};
inline bool getFlagOrDefault(cl::boolOrDefault value, bool defaultValue) {
return value == cl::BOU_UNSET ? defaultValue : value == cl::BOU_TRUE;
}
template <> struct FlagParserDataType<CHECKENABLE> {
static CHECKENABLE true_val() { return CHECKENABLEon; }
static CHECKENABLE false_val() { return CHECKENABLEoff; }
};
template <class DataType> class FlagParser : public cl::generic_parser_base {
protected:
llvm::SmallVector<std::pair<std::string, DataType>, 2> switches;
cl::Option &owner() const { return Owner; }
public:
FlagParser(cl::Option &O) : generic_parser_base(O) {}
typedef DataType parser_data_type;
void initialize() {
std::string Name(owner().ArgStr);
switches.push_back(
make_pair("enable-" + Name, FlagParserDataType<DataType>::true_val()));
switches.push_back(make_pair("disable-" + Name,
FlagParserDataType<DataType>::false_val()));
// Replace <foo> with -enable-<foo> and register -disable-<foo>.
// A literal option can only registered if the argstr is empty -
// just do this first.
owner().setArgStr("");
AddLiteralOption(Owner, strdup(switches[1].first.data()));
owner().setArgStr(switches[0].first.data());
}
enum cl::ValueExpected getValueExpectedFlagDefault() const {
return cl::ValueOptional;
}
// Implement virtual functions needed by generic_parser_base
unsigned getNumOptions() const override { return 0; }
llvm::StringRef getOption(unsigned N) const override {
llvm_unreachable("Unexpected call");
return "";
}
llvm::StringRef getDescription(unsigned N) const override {
llvm_unreachable("Unexpected call");
return "";
}
private:
struct OptionValue : cl::OptionValueBase<DataType, false> {
OptionValue(){};
};
const OptionValue EmptyOptionValue;
public:
// getOptionValue - Return the value of option name N.
const cl::GenericOptionValue &getOptionValue(unsigned N) const override {
return EmptyOptionValue;
}
// parse - Return true on error.
bool parse(cl::Option &O, llvm::StringRef ArgName, llvm::StringRef Arg,
DataType &Val) {
for (const auto &pair : switches) {
const auto &name = pair.first;
if (name == ArgName || (name.size() < ArgName.size() &&
ArgName.substr(0, name.size()) == name &&
ArgName[name.size()] == '=')) {
if (!parse(owner(), Arg, Val)) {
Val = (Val == pair.second)
? FlagParserDataType<DataType>::true_val()
: FlagParserDataType<DataType>::false_val();
return false;
}
// Invalid option value
break;
}
}
return true;
}
void getExtraOptionNames(llvm::SmallVectorImpl<llvm::StringRef> &Names) {
for (auto I = switches.begin() + 1, E = switches.end(); I != E; ++I) {
Names.push_back(I->first.data());
}
}
private:
static bool parse(cl::Option &O, llvm::StringRef Arg, DataType &Val) {
if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
Arg == "1") {
Val = FlagParserDataType<DataType>::true_val();
return false;
}
if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
Val = FlagParserDataType<DataType>::false_val();
return false;
}
return O.error("'" + Arg +
"' is invalid value for boolean argument! Try 0 or 1");
}
};
/// Helper class for options that set multiple flags
class MultiSetter {
std::vector<CHECKENABLE *> locations;
bool invert;
explicit MultiSetter(bool); // not implemented, disable auto-conversion
public:
// end with a nullptr
MultiSetter(bool invert, CHECKENABLE *p, ...);
MultiSetter() = default;
void operator=(bool val);
};
/// Helper class to fill Strings with char* when given strings
/// (Errors on empty strings)
class StringsAdapter {
const char *name;
Strings *arrp;
public:
StringsAdapter(const char *name_, Strings &arr) {
name = name_;
arrp = &arr;
assert(name);
}
void push_back(const char *cstr);
void push_back(const std::string &str) { push_back(str.c_str()); }
};
}