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, ...);
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);
assert(arrp);
}
void push_back(const char *cstr);
void push_back(const std::string &str) { push_back(str.c_str()); }
};
}
|