1 //===-- CommandLine.cpp - Command line parser implementation --------------===// 2 // 3 // This class implements a command line argument processor that is useful when 4 // creating a tool. It provides a simple, minimalistic interface that is easily 5 // extensible and supports nonlocal (library) command line options. 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Support/CommandLine.h" 10 #include "llvm/Support/STLExtras.h" 11 #include <vector> 12 #include <algorithm> 13 #include <map> 14 #include <set> 15 using namespace cl; 16 17 // Return the global command line option vector. Making it a function scoped 18 // static ensures that it will be initialized before its first use correctly. 19 // 20 static map<string, Option*> &getOpts() { 21 static map<string,Option*> CommandLineOptions; 22 return CommandLineOptions; 23 } 24 25 static void AddArgument(const string &ArgName, Option *Opt) { 26 if (getOpts().find(ArgName) != getOpts().end()) { 27 cerr << "CommandLine Error: Argument '" << ArgName 28 << "' specified more than once!\n"; 29 } else { 30 getOpts()[ArgName] = Opt; // Add argument to the argument map! 31 } 32 } 33 34 static const char *ProgramName = 0; 35 static const char *ProgramOverview = 0; 36 37 void cl::ParseCommandLineOptions(int &argc, char **argv, 38 const char *Overview = 0) { 39 ProgramName = argv[0]; // Save this away safe and snug 40 ProgramOverview = Overview; 41 bool ErrorParsing = false; 42 43 // Loop over all of the arguments... processing them. 44 for (int i = 1; i < argc; ++i) { 45 Option *Handler = 0; 46 const char *Value = ""; 47 const char *ArgName = ""; 48 if (argv[i][0] != '-') { // Unnamed argument? 49 Handler = getOpts()[""]; 50 Value = argv[i]; 51 } else { // We start with a - or --, eat dashes 52 ArgName = argv[i]+1; 53 while (*ArgName == '-') ++ArgName; // Eat leading dashes 54 55 const char *ArgNameEnd = ArgName; 56 while (*ArgNameEnd && *ArgNameEnd != '=') ++ArgNameEnd; // Scan till end 57 58 Value = ArgNameEnd; 59 if (*Value) // If we have an equals sign... 60 ++Value; // Advance to value... 61 62 if (*ArgName != 0) { 63 string ArgNameStr(ArgName, ArgNameEnd); // Extract arg name part 64 Handler = getOpts()[ArgNameStr]; 65 } 66 } 67 68 if (Handler == 0) { 69 cerr << "Unknown command line argument '" << argv[i] << "'. Try: " 70 << argv[0] << " --help\n'"; 71 ErrorParsing = true; 72 continue; 73 } 74 75 // Enforce value requirements 76 switch (Handler->Flags & ValueMask) { 77 case ValueRequired: 78 if (Value == 0 || *Value == 0) { // No value specified? 79 if (i+1 < argc) { // Steal the next argument, like for '-o filename' 80 Value = argv[++i]; 81 } else { 82 ErrorParsing = Handler->error(" requires a value!"); 83 continue; 84 } 85 } 86 break; 87 case ValueDisallowed: 88 if (*Value != 0) { 89 ErrorParsing = Handler->error(" does not allow a value! '" + 90 string(Value) + "' specified."); 91 continue; 92 } 93 break; 94 case Optional: break; 95 default: cerr << "Bad ValueMask flag! CommandLine usage error!\n"; abort(); 96 } 97 98 // Run the handler now! 99 ErrorParsing |= Handler->addOccurance(ArgName, Value); 100 } 101 102 // TODO: loop over args and make sure all required args are specified! 103 104 // Free all of the memory allocated to the vector. Command line options may 105 // only be processed once! 106 getOpts().clear(); 107 108 // If we had an error processing our arguments, don't let the program execute 109 if (ErrorParsing) exit(1); 110 } 111 112 //===----------------------------------------------------------------------===// 113 // Option Base class implementation 114 // 115 Option::Option(const char *argStr, const char *helpStr, int flags) 116 : NumOccurances(0), ArgStr(argStr), HelpStr(helpStr), Flags(flags) { 117 AddArgument(ArgStr, this); 118 } 119 120 bool Option::error(string Message, const char *ArgName = 0) { 121 if (ArgName == 0) ArgName = ArgStr; 122 cerr << "-" << ArgName << " option" << Message << endl; 123 return true; 124 } 125 126 bool Option::addOccurance(const char *ArgName, const string &Value) { 127 NumOccurances++; // Increment the number of times we have been seen 128 129 switch (Flags & OccurancesMask) { 130 case Optional: 131 if (NumOccurances > 1) 132 return error(": may only occur zero or one times!", ArgName); 133 break; 134 case Required: 135 if (NumOccurances > 1) 136 return error(": must occur exactly one time!", ArgName); 137 // Fall through 138 case OneOrMore: 139 case ZeroOrMore: break; 140 default: return error(": bad num occurances flag value!"); 141 } 142 143 return handleOccurance(ArgName, Value); 144 } 145 146 // Return the width of the option tag for printing... 147 unsigned Option::getOptionWidth() const { 148 return std::strlen(ArgStr)+6; 149 } 150 151 void Option::printOptionInfo(unsigned GlobalWidth) const { 152 unsigned L = std::strlen(ArgStr); 153 if (L == 0) return; // Don't print the empty arg like this! 154 cerr << " -" << ArgStr << string(GlobalWidth-L-6, ' ') << " - " 155 << HelpStr << endl; 156 } 157 158 159 //===----------------------------------------------------------------------===// 160 // Boolean/flag command line option implementation 161 // 162 163 bool Flag::handleOccurance(const char *ArgName, const string &Arg) { 164 if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || 165 Arg == "1") { 166 Value = true; 167 } else if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { 168 Value = false; 169 } else { 170 return error(": '" + Arg + "' is invalid value for boolean argument! Try 0 or 1"); 171 } 172 173 return false; 174 } 175 176 //===----------------------------------------------------------------------===// 177 // Integer valued command line option implementation 178 // 179 bool Int::handleOccurance(const char *ArgName, const string &Arg) { 180 const char *ArgStart = Arg.c_str(); 181 char *End; 182 Value = (int)strtol(ArgStart, &End, 0); 183 if (*End != 0) 184 return error(": '" + Arg + "' value invalid for integer argument!"); 185 return false; 186 } 187 188 //===----------------------------------------------------------------------===// 189 // String valued command line option implementation 190 // 191 bool String::handleOccurance(const char *ArgName, const string &Arg) { 192 *this = Arg; 193 return false; 194 } 195 196 //===----------------------------------------------------------------------===// 197 // Enum valued command line option implementation 198 // 199 void EnumBase::processValues(va_list Vals) { 200 while (const char *EnumName = va_arg(Vals, const char *)) { 201 int EnumVal = va_arg(Vals, int); 202 const char *EnumDesc = va_arg(Vals, const char *); 203 ValueMap.push_back(make_pair(EnumName, // Add value to value map 204 make_pair(EnumVal, EnumDesc))); 205 } 206 } 207 208 // registerArgs - notify the system about these new arguments 209 void EnumBase::registerArgs() { 210 for (unsigned i = 0; i < ValueMap.size(); ++i) 211 AddArgument(ValueMap[i].first, this); 212 } 213 214 const char *EnumBase::getArgName(int ID) const { 215 for (unsigned i = 0; i < ValueMap.size(); ++i) 216 if (ID == ValueMap[i].second.first) return ValueMap[i].first; 217 return ""; 218 } 219 const char *EnumBase::getArgDescription(int ID) const { 220 for (unsigned i = 0; i < ValueMap.size(); ++i) 221 if (ID == ValueMap[i].second.first) return ValueMap[i].second.second; 222 return ""; 223 } 224 225 226 227 bool EnumValueBase::handleOccurance(const char *ArgName, const string &Arg) { 228 unsigned i; 229 for (i = 0; i < ValueMap.size(); ++i) 230 if (ValueMap[i].first == Arg) break; 231 if (i == ValueMap.size()) 232 return error(": unrecognized alternative '"+Arg+"'!"); 233 Value = ValueMap[i].second.first; 234 return false; 235 } 236 237 // Return the width of the option tag for printing... 238 unsigned EnumValueBase::getOptionWidth() const { 239 unsigned BaseSize = Option::getOptionWidth(); 240 for (unsigned i = 0; i < ValueMap.size(); ++i) 241 BaseSize = max(BaseSize, std::strlen(ValueMap[i].first)+8); 242 return BaseSize; 243 } 244 245 // printOptionInfo - Print out information about this option. The 246 // to-be-maintained width is specified. 247 // 248 void EnumValueBase::printOptionInfo(unsigned GlobalWidth) const { 249 Option::printOptionInfo(GlobalWidth); 250 for (unsigned i = 0; i < ValueMap.size(); ++i) { 251 unsigned NumSpaces = GlobalWidth-strlen(ValueMap[i].first)-8; 252 cerr << " =" << ValueMap[i].first << string(NumSpaces, ' ') << " - " 253 << ValueMap[i].second.second; 254 255 if (i == 0) cerr << " (default)"; 256 cerr << endl; 257 } 258 } 259 260 //===----------------------------------------------------------------------===// 261 // Enum flags command line option implementation 262 // 263 264 bool EnumFlagsBase::handleOccurance(const char *ArgName, const string &Arg) { 265 return EnumValueBase::handleOccurance("", ArgName); 266 } 267 268 unsigned EnumFlagsBase::getOptionWidth() const { 269 unsigned BaseSize = 0; 270 for (unsigned i = 0; i < ValueMap.size(); ++i) 271 BaseSize = max(BaseSize, std::strlen(ValueMap[i].first)+6); 272 return BaseSize; 273 } 274 275 void EnumFlagsBase::printOptionInfo(unsigned GlobalWidth) const { 276 for (unsigned i = 0; i < ValueMap.size(); ++i) { 277 unsigned L = std::strlen(ValueMap[i].first); 278 cerr << " -" << ValueMap[i].first << string(GlobalWidth-L-6, ' ') << " - " 279 << ValueMap[i].second.second; 280 if (i == 0) cerr << " (default)"; 281 cerr << endl; 282 } 283 } 284 285 286 //===----------------------------------------------------------------------===// 287 // Enum list command line option implementation 288 // 289 290 bool EnumListBase::handleOccurance(const char *ArgName, const string &Arg) { 291 unsigned i; 292 for (i = 0; i < ValueMap.size(); ++i) 293 if (ValueMap[i].first == string(ArgName)) break; 294 if (i == ValueMap.size()) 295 return error(": CommandLine INTERNAL ERROR", ArgName); 296 Values.push_back(ValueMap[i].second.first); 297 return false; 298 } 299 300 // Return the width of the option tag for printing... 301 unsigned EnumListBase::getOptionWidth() const { 302 unsigned BaseSize = 0; 303 for (unsigned i = 0; i < ValueMap.size(); ++i) 304 BaseSize = max(BaseSize, std::strlen(ValueMap[i].first)+6); 305 return BaseSize; 306 } 307 308 309 // printOptionInfo - Print out information about this option. The 310 // to-be-maintained width is specified. 311 // 312 void EnumListBase::printOptionInfo(unsigned GlobalWidth) const { 313 for (unsigned i = 0; i < ValueMap.size(); ++i) { 314 unsigned L = std::strlen(ValueMap[i].first); 315 cerr << " -" << ValueMap[i].first << string(GlobalWidth-L-6, ' ') << " - " 316 << ValueMap[i].second.second << endl; 317 } 318 } 319 320 321 //===----------------------------------------------------------------------===// 322 // Help option... always automatically provided. 323 // 324 namespace { 325 326 // isHidden/isReallyHidden - Predicates to be used to filter down arg lists. 327 inline bool isHidden(pair<string, Option *> &OptPair) { 328 return (OptPair.second->Flags & HiddenMask) == Hidden; 329 } 330 inline bool isReallyHidden(pair<string, Option *> &OptPair) { 331 return (OptPair.second->Flags & HiddenMask) == ReallyHidden; 332 } 333 334 class Help : public Option { 335 unsigned MaxArgLen; 336 const Option *EmptyArg; 337 const bool ShowHidden; 338 339 virtual bool handleOccurance(const char *ArgName, const string &Arg) { 340 // Copy Options into a vector so we can sort them as we like... 341 vector<pair<string, Option*> > Options; 342 copy(getOpts().begin(), getOpts().end(), back_inserter(Options)); 343 344 // Eliminate Hidden or ReallyHidden arguments, depending on ShowHidden 345 Options.erase(remove_if(Options.begin(), Options.end(), 346 ptr_fun(ShowHidden ? isReallyHidden : isHidden)), 347 Options.end()); 348 349 // Eliminate duplicate entries in table (from enum flags options, f.e.) 350 set<Option*> OptionSet; 351 for (unsigned i = 0; i < Options.size(); ) 352 if (OptionSet.count(Options[i].second) == 0) 353 OptionSet.insert(Options[i++].second); // Add to set 354 else 355 Options.erase(Options.begin()+i); // Erase duplicate 356 357 358 if (ProgramOverview) 359 cerr << "OVERVIEW:" << ProgramOverview << endl; 360 // TODO: Sort options by some criteria 361 362 cerr << "USAGE: " << ProgramName << " [options]\n\n"; 363 // TODO: print usage nicer 364 365 // Compute the maximum argument length... 366 MaxArgLen = 0; 367 for_each(Options.begin(), Options.end(), 368 bind_obj(this, &Help::getMaxArgLen)); 369 370 cerr << "OPTIONS:\n"; 371 for_each(Options.begin(), Options.end(), 372 bind_obj(this, &Help::printOption)); 373 374 return true; // Displaying help is cause to terminate the program 375 } 376 377 void getMaxArgLen(pair<string, Option *> OptPair) { 378 const Option *Opt = OptPair.second; 379 if (Opt->ArgStr[0] == 0) EmptyArg = Opt; // Capture the empty arg if exists 380 MaxArgLen = max(MaxArgLen, Opt->getOptionWidth()); 381 } 382 383 void printOption(pair<string, Option *> OptPair) { 384 const Option *Opt = OptPair.second; 385 Opt->printOptionInfo(MaxArgLen); 386 } 387 388 public: 389 inline Help(const char *ArgVal, const char *HelpVal, bool showHidden) 390 : Option(ArgVal, HelpVal, showHidden ? Hidden : 0), ShowHidden(showHidden) { 391 EmptyArg = 0; 392 } 393 }; 394 395 Help HelpOp("help", "display available options" 396 " (-help-hidden for more)", false); 397 Help HelpHiddenOpt("help-hidden", "display all available options", true); 398 399 } // End anonymous namespace 400