* Implement support for folding multiple single letter arguments together like
[oota-llvm.git] / lib / Support / CommandLine.cpp
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 correctly before its first use.
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     // Add argument to the argument map!
34     getOpts().insert(make_pair(ArgName, Opt));
35   }
36 }
37
38 static const char *ProgramName = 0;
39 static const char *ProgramOverview = 0;
40
41 static inline bool ProvideOption(Option *Handler, const char *ArgName,
42                                  const char *Value, int argc, char **argv,
43                                  int &i) {
44   // Enforce value requirements
45   switch (Handler->getValueExpectedFlag()) {
46   case ValueRequired:
47     if (Value == 0 || *Value == 0) {  // No value specified?
48       if (i+1 < argc) {     // Steal the next argument, like for '-o filename'
49         Value = argv[++i];
50       } else {
51         return Handler->error(" requires a value!");
52       }
53     }
54     break;
55   case ValueDisallowed:
56     if (*Value != 0)
57       return Handler->error(" does not allow a value! '" + 
58                             string(Value) + "' specified.");
59     break;
60   case ValueOptional: break;
61   default: cerr << "Bad ValueMask flag! CommandLine usage error:" 
62                 << Handler->getValueExpectedFlag() << endl; abort();
63   }
64
65   // Run the handler now!
66   return Handler->addOccurance(ArgName, Value);
67 }
68
69 // ValueGroupedArgs - Return true if the specified string is valid as a group
70 // of single letter arguments stuck together like the 'ls -la' case.
71 //
72 static inline bool ValidGroupedArgs(string Args) {
73   for (unsigned i = 0; i < Args.size(); ++i) {
74     map<string, Option*>::iterator I = getOpts().find(string(1, Args[i]));
75     if (I == getOpts().end()) return false;   // Make sure option exists
76
77     // Grouped arguments have no value specified, make sure that if this option
78     // exists that it can accept no argument.
79     //
80     switch (I->second->getValueExpectedFlag()) {
81     case ValueDisallowed:
82     case ValueOptional: break;
83     default: return false;
84     }
85   }
86
87   return true;
88 }
89
90 void cl::ParseCommandLineOptions(int &argc, char **argv,
91                                  const char *Overview = 0, int Flags = 0) {
92   ProgramName = argv[0];  // Save this away safe and snug
93   ProgramOverview = Overview;
94   bool ErrorParsing = false;
95
96   // Loop over all of the arguments... processing them.
97   for (int i = 1; i < argc; ++i) {
98     Option *Handler = 0;
99     const char *Value = "";
100     const char *ArgName = "";
101     if (argv[i][0] != '-') {   // Unnamed argument?
102       map<string, Option*>::iterator I = getOpts().find("");
103       Handler = I != getOpts().end() ? I->second : 0;
104       Value = argv[i];
105     } else {               // We start with a - or --, eat dashes
106       ArgName = argv[i]+1;
107       while (*ArgName == '-') ++ArgName;  // Eat leading dashes
108
109       const char *ArgNameEnd = ArgName;
110       while (*ArgNameEnd && *ArgNameEnd != '=')
111         ++ArgNameEnd; // Scan till end of argument name...
112
113       Value = ArgNameEnd;
114       if (*Value)           // If we have an equals sign...
115         ++Value;            // Advance to value...
116
117       if (*ArgName != 0) {
118         string RealName(ArgName, ArgNameEnd);
119         // Extract arg name part
120         map<string, Option*>::iterator I = getOpts().find(RealName);
121
122         if (I == getOpts().end() && !*Value && RealName.size() > 1) {
123           // If grouping of single letter arguments is enabled, see if this is a
124           // legal grouping...
125           //
126           if (!(Flags & DisableSingleLetterArgGrouping) &&
127               ValidGroupedArgs(RealName)) {
128
129             for (unsigned i = 0; i < RealName.size(); ++i) {
130               char ArgName[2] = { 0, 0 }; int Dummy;
131               ArgName[0] = RealName[i];
132               I = getOpts().find(ArgName);
133               assert(I != getOpts().end() && "ValidGroupedArgs failed!");
134
135               // Because ValueRequired is an invalid flag for grouped arguments,
136               // we don't need to pass argc/argv in...
137               //
138               ErrorParsing |= ProvideOption(I->second, ArgName, "",
139                                             0, 0, Dummy);
140             }
141             continue;
142           } else if (Flags & EnableSingleLetterArgValue) {
143             // Check to see if the first letter is a single letter argument that
144             // have a value that is equal to the rest of the string.  If this
145             // is the case, recognize it now.  (Example:  -lfoo for a linker)
146             //
147             I = getOpts().find(string(1, RealName[0]));
148             if (I != getOpts().end()) {
149               // If we are successful, fall through to later processing, by
150               // setting up the argument name flags and value fields.
151               //
152               ArgNameEnd = ArgName+1;
153               Value = ArgNameEnd;
154             }
155           }
156         }
157
158
159         Handler = I != getOpts().end() ? I->second : 0;
160       }
161     }
162
163     if (Handler == 0) {
164       cerr << "Unknown command line argument '" << argv[i] << "'.  Try: "
165            << argv[0] << " --help'\n";
166       ErrorParsing = true;
167       continue;
168     }
169
170     ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i);
171
172     // If this option should consume all arguments that come after it...
173     if (Handler->getNumOccurancesFlag() == ConsumeAfter) {
174       for (++i; i < argc; ++i)
175         ErrorParsing |= ProvideOption(Handler, ArgName, argv[i], argc, argv, i);
176     }
177   }
178
179   // Loop over args and make sure all required args are specified!
180   for (map<string, Option*>::iterator I = getOpts().begin(), 
181          E = getOpts().end(); I != E; ++I) {
182     switch (I->second->getNumOccurancesFlag()) {
183     case Required:
184     case OneOrMore:
185       if (I->second->getNumOccurances() == 0) {
186         I->second->error(" must be specified at least once!");
187         ErrorParsing = true;
188       }
189       // Fall through
190     default:
191       break;
192     }
193   }
194
195   // Free all of the memory allocated to the vector.  Command line options may
196   // only be processed once!
197   getOpts().clear();
198
199   // If we had an error processing our arguments, don't let the program execute
200   if (ErrorParsing) exit(1);
201 }
202
203 //===----------------------------------------------------------------------===//
204 // Option Base class implementation
205 //
206 Option::Option(const char *argStr, const char *helpStr, int flags)
207   : NumOccurances(0), Flags(flags), ArgStr(argStr), HelpStr(helpStr) {
208   AddArgument(ArgStr, this);
209 }
210
211 bool Option::error(string Message, const char *ArgName = 0) {
212   if (ArgName == 0) ArgName = ArgStr;
213   cerr << "-" << ArgName << " option" << Message << endl;
214   return true;
215 }
216
217 bool Option::addOccurance(const char *ArgName, const string &Value) {
218   NumOccurances++;   // Increment the number of times we have been seen
219
220   switch (getNumOccurancesFlag()) {
221   case Optional:
222     if (NumOccurances > 1)
223       return error(": may only occur zero or one times!", ArgName);
224     break;
225   case Required:
226     if (NumOccurances > 1)
227       return error(": must occur exactly one time!", ArgName);
228     // Fall through
229   case OneOrMore:
230   case ZeroOrMore:
231   case ConsumeAfter: break;
232   default: return error(": bad num occurances flag value!");
233   }
234
235   return handleOccurance(ArgName, Value);
236 }
237
238 // Return the width of the option tag for printing...
239 unsigned Option::getOptionWidth() const {
240   return std::strlen(ArgStr)+6;
241 }
242
243 void Option::printOptionInfo(unsigned GlobalWidth) const {
244   unsigned L = std::strlen(ArgStr);
245   if (L == 0) return;  // Don't print the empty arg like this!
246   cerr << "  -" << ArgStr << string(GlobalWidth-L-6, ' ') << " - "
247        << HelpStr << endl;
248 }
249
250
251 //===----------------------------------------------------------------------===//
252 // Boolean/flag command line option implementation
253 //
254
255 bool Flag::handleOccurance(const char *ArgName, const string &Arg) {
256   if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || 
257       Arg == "1") {
258     Value = true;
259   } else if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
260     Value = false;
261   } else {
262     return error(": '" + Arg +
263                  "' is invalid value for boolean argument! Try 0 or 1");
264   }
265
266   return false;
267 }
268
269 //===----------------------------------------------------------------------===//
270 // Integer valued command line option implementation
271 //
272 bool Int::handleOccurance(const char *ArgName, const string &Arg) {
273   const char *ArgStart = Arg.c_str();
274   char *End;
275   Value = (int)strtol(ArgStart, &End, 0);
276   if (*End != 0) 
277     return error(": '" + Arg + "' value invalid for integer argument!");
278   return false;  
279 }
280
281 //===----------------------------------------------------------------------===//
282 // String valued command line option implementation
283 //
284 bool String::handleOccurance(const char *ArgName, const string &Arg) {
285   *this = Arg;
286   return false;
287 }
288
289 //===----------------------------------------------------------------------===//
290 // StringList valued command line option implementation
291 //
292 bool StringList::handleOccurance(const char *ArgName, const string &Arg) {
293   push_back(Arg);
294   return false;
295 }
296
297 //===----------------------------------------------------------------------===//
298 // Enum valued command line option implementation
299 //
300 void EnumBase::processValues(va_list Vals) {
301   while (const char *EnumName = va_arg(Vals, const char *)) {
302     int EnumVal = va_arg(Vals, int);
303     const char *EnumDesc = va_arg(Vals, const char *);
304     ValueMap.push_back(make_pair(EnumName,           // Add value to value map
305                                  make_pair(EnumVal, EnumDesc)));
306   }
307 }
308
309 // registerArgs - notify the system about these new arguments
310 void EnumBase::registerArgs() {
311   for (unsigned i = 0; i < ValueMap.size(); ++i)
312     AddArgument(ValueMap[i].first, this);
313 }
314
315 const char *EnumBase::getArgName(int ID) const {
316   for (unsigned i = 0; i < ValueMap.size(); ++i)
317     if (ID == ValueMap[i].second.first) return ValueMap[i].first;
318   return "";
319 }
320 const char *EnumBase::getArgDescription(int ID) const {
321   for (unsigned i = 0; i < ValueMap.size(); ++i)
322     if (ID == ValueMap[i].second.first) return ValueMap[i].second.second;
323   return "";
324 }
325
326
327
328 bool EnumValueBase::handleOccurance(const char *ArgName, const string &Arg) {
329   unsigned i;
330   for (i = 0; i < ValueMap.size(); ++i)
331     if (ValueMap[i].first == Arg) break;
332   if (i == ValueMap.size())
333     return error(": unrecognized alternative '"+Arg+"'!");
334   Value = ValueMap[i].second.first;
335   return false;
336 }
337
338 // Return the width of the option tag for printing...
339 unsigned EnumValueBase::getOptionWidth() const {
340   unsigned BaseSize = Option::getOptionWidth();
341   for (unsigned i = 0; i < ValueMap.size(); ++i)
342     BaseSize = max(BaseSize, std::strlen(ValueMap[i].first)+8);
343   return BaseSize;
344 }
345
346 // printOptionInfo - Print out information about this option.  The 
347 // to-be-maintained width is specified.
348 //
349 void EnumValueBase::printOptionInfo(unsigned GlobalWidth) const {
350   Option::printOptionInfo(GlobalWidth);
351   for (unsigned i = 0; i < ValueMap.size(); ++i) {
352     unsigned NumSpaces = GlobalWidth-strlen(ValueMap[i].first)-8;
353     cerr << "    =" << ValueMap[i].first << string(NumSpaces, ' ') << " - "
354          << ValueMap[i].second.second;
355
356     if (i == 0) cerr << " (default)";
357     cerr << endl;
358   }
359 }
360
361 //===----------------------------------------------------------------------===//
362 // Enum flags command line option implementation
363 //
364
365 bool EnumFlagsBase::handleOccurance(const char *ArgName, const string &Arg) {
366   return EnumValueBase::handleOccurance("", ArgName);
367 }
368
369 unsigned EnumFlagsBase::getOptionWidth() const {
370   unsigned BaseSize = 0;
371   for (unsigned i = 0; i < ValueMap.size(); ++i)
372     BaseSize = max(BaseSize, std::strlen(ValueMap[i].first)+6);
373   return BaseSize;
374 }
375
376 void EnumFlagsBase::printOptionInfo(unsigned GlobalWidth) const {
377   for (unsigned i = 0; i < ValueMap.size(); ++i) {
378     unsigned L = std::strlen(ValueMap[i].first);
379     cerr << "  -" << ValueMap[i].first << string(GlobalWidth-L-6, ' ') << " - "
380          << ValueMap[i].second.second;
381     if (i == 0) cerr << " (default)";
382     cerr << endl;
383   }
384 }
385
386
387 //===----------------------------------------------------------------------===//
388 // Enum list command line option implementation
389 //
390
391 bool EnumListBase::handleOccurance(const char *ArgName, const string &Arg) {
392   unsigned i;
393   for (i = 0; i < ValueMap.size(); ++i)
394     if (ValueMap[i].first == string(ArgName)) break;
395   if (i == ValueMap.size())
396     return error(": CommandLine INTERNAL ERROR", ArgName);
397   Values.push_back(ValueMap[i].second.first);
398   return false;
399 }
400
401 // Return the width of the option tag for printing...
402 unsigned EnumListBase::getOptionWidth() const {
403   unsigned BaseSize = 0;
404   for (unsigned i = 0; i < ValueMap.size(); ++i)
405     BaseSize = max(BaseSize, std::strlen(ValueMap[i].first)+6);
406   return BaseSize;
407 }
408
409
410 // printOptionInfo - Print out information about this option.  The 
411 // to-be-maintained width is specified.
412 //
413 void EnumListBase::printOptionInfo(unsigned GlobalWidth) const {
414   for (unsigned i = 0; i < ValueMap.size(); ++i) {
415     unsigned L = std::strlen(ValueMap[i].first);
416     cerr << "  -" << ValueMap[i].first << string(GlobalWidth-L-6, ' ') << " - "
417          << ValueMap[i].second.second << endl;
418   }
419 }
420
421
422 //===----------------------------------------------------------------------===//
423 // Help option... always automatically provided.
424 //
425 namespace {
426
427 // isHidden/isReallyHidden - Predicates to be used to filter down arg lists.
428 inline bool isHidden(pair<string, Option *> &OptPair) {
429   return OptPair.second->getOptionHiddenFlag() >= Hidden;
430 }
431 inline bool isReallyHidden(pair<string, Option *> &OptPair) {
432   return OptPair.second->getOptionHiddenFlag() == ReallyHidden;
433 }
434
435 class Help : public Option {
436   unsigned MaxArgLen;
437   const Option *EmptyArg;
438   const bool ShowHidden;
439
440   virtual bool handleOccurance(const char *ArgName, const string &Arg) {
441     // Copy Options into a vector so we can sort them as we like...
442     vector<pair<string, Option*> > Options;
443     copy(getOpts().begin(), getOpts().end(), back_inserter(Options));
444
445     // Eliminate Hidden or ReallyHidden arguments, depending on ShowHidden
446     Options.erase(remove_if(Options.begin(), Options.end(), 
447                             ptr_fun(ShowHidden ? isReallyHidden : isHidden)),
448                   Options.end());
449
450     // Eliminate duplicate entries in table (from enum flags options, f.e.)
451     set<Option*> OptionSet;
452     for (unsigned i = 0; i < Options.size(); )
453       if (OptionSet.count(Options[i].second) == 0)
454         OptionSet.insert(Options[i++].second); // Add to set
455       else
456         Options.erase(Options.begin()+i);      // Erase duplicate
457
458
459     if (ProgramOverview)
460       cerr << "OVERVIEW:" << ProgramOverview << endl;
461     // TODO: Sort options by some criteria
462
463     cerr << "USAGE: " << ProgramName << " [options]\n\n";
464     // TODO: print usage nicer
465
466     // Compute the maximum argument length...
467     MaxArgLen = 0;
468     for_each(Options.begin(), Options.end(),
469              bind_obj(this, &Help::getMaxArgLen));
470
471     cerr << "OPTIONS:\n";
472     for_each(Options.begin(), Options.end(), 
473              bind_obj(this, &Help::printOption));
474
475     return true;  // Displaying help is cause to terminate the program
476   }
477
478   void getMaxArgLen(pair<string, Option *> OptPair) {
479     const Option *Opt = OptPair.second;
480     if (Opt->ArgStr[0] == 0) EmptyArg = Opt; // Capture the empty arg if exists
481     MaxArgLen = max(MaxArgLen, Opt->getOptionWidth());
482   }
483
484   void printOption(pair<string, Option *> OptPair) {
485     const Option *Opt = OptPair.second;
486     Opt->printOptionInfo(MaxArgLen);
487   }
488
489 public:
490   inline Help(const char *ArgVal, const char *HelpVal, bool showHidden)
491     : Option(ArgVal, HelpVal, showHidden ? Hidden : 0), ShowHidden(showHidden) {
492     EmptyArg = 0;
493   }
494 };
495
496 Help HelpOp("help", "display available options"
497             " (--help-hidden for more)", false);
498 Help HelpHiddenOpt("help-hidden", "display all available options", true);
499
500 } // End anonymous namespace