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