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