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