| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 1 | //===-- CommandLine.cpp - Command line parser implementation --------------===// | 
| John Criswell | b576c94 | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 2 | //  | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
 | 5 | // This file was developed by the LLVM research group and is distributed under | 
 | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
 | 7 | //  | 
 | 8 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 9 | // | 
 | 10 | // This class implements a command line argument processor that is useful when | 
 | 11 | // creating a tool.  It provides a simple, minimalistic interface that is easily | 
 | 12 | // extensible and supports nonlocal (library) command line options. | 
 | 13 | // | 
| Chris Lattner | 03fe1bd | 2001-07-23 23:04:07 +0000 | [diff] [blame] | 14 | // Note that rather than trying to figure out what this code does, you could try | 
 | 15 | // reading the library documentation located in docs/CommandLine.html | 
 | 16 | // | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 17 | //===----------------------------------------------------------------------===// | 
 | 18 |  | 
| Reid Spencer | 69105f3 | 2004-08-04 00:36:06 +0000 | [diff] [blame] | 19 | #include "Config/config.h" | 
| Chris Lattner | cee8f9a | 2001-11-27 00:03:19 +0000 | [diff] [blame] | 20 | #include "Support/CommandLine.h" | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 21 | #include <algorithm> | 
 | 22 | #include <map> | 
 | 23 | #include <set> | 
| Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 24 | #include <iostream> | 
| Brian Gaeke | 2d6a236 | 2003-10-10 17:01:36 +0000 | [diff] [blame] | 25 | #include <cstdlib> | 
 | 26 | #include <cerrno> | 
| Chris Lattner | 5114004 | 2004-07-03 01:21:05 +0000 | [diff] [blame] | 27 | #include <cstring> | 
| Chris Lattner | 2cdd21c | 2003-12-14 21:35:53 +0000 | [diff] [blame] | 28 | using namespace llvm; | 
| Brian Gaeke | d0fde30 | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 29 |  | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 30 | using namespace cl; | 
 | 31 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 32 | //===----------------------------------------------------------------------===// | 
 | 33 | // Basic, shared command line option processing machinery... | 
 | 34 | // | 
 | 35 |  | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 36 | // Return the global command line option vector.  Making it a function scoped | 
| Chris Lattner | f78032f | 2001-11-26 18:58:34 +0000 | [diff] [blame] | 37 | // static ensures that it will be initialized correctly before its first use. | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 38 | // | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 39 | static std::map<std::string, Option*> *CommandLineOptions = 0; | 
 | 40 | static std::map<std::string, Option*> &getOpts() { | 
 | 41 |   if (CommandLineOptions == 0) | 
 | 42 |     CommandLineOptions = new std::map<std::string,Option*>(); | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 43 |   return *CommandLineOptions; | 
 | 44 | } | 
 | 45 |  | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 46 | static Option *getOption(const std::string &Str) { | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 47 |   if (CommandLineOptions == 0) return 0; | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 48 |   std::map<std::string,Option*>::iterator I = CommandLineOptions->find(Str); | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 49 |   return I != CommandLineOptions->end() ? I->second : 0; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 50 | } | 
 | 51 |  | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 52 | static std::vector<Option*> &getPositionalOpts() { | 
| Alkis Evlogimenos | 5f65add | 2004-03-04 17:50:44 +0000 | [diff] [blame] | 53 |   static std::vector<Option*> *Positional = 0; | 
 | 54 |   if (!Positional) Positional = new std::vector<Option*>(); | 
 | 55 |   return *Positional; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 56 | } | 
 | 57 |  | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 58 | static void AddArgument(const char *ArgName, Option *Opt) { | 
 | 59 |   if (getOption(ArgName)) { | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 60 |     std::cerr << "CommandLine Error: Argument '" << ArgName | 
 | 61 |               << "' defined more than once!\n"; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 62 |   } else { | 
| Chris Lattner | f78032f | 2001-11-26 18:58:34 +0000 | [diff] [blame] | 63 |     // Add argument to the argument map! | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 64 |     getOpts()[ArgName] = Opt; | 
 | 65 |   } | 
 | 66 | } | 
 | 67 |  | 
 | 68 | // RemoveArgument - It's possible that the argument is no longer in the map if | 
 | 69 | // options have already been processed and the map has been deleted! | 
 | 70 | //  | 
 | 71 | static void RemoveArgument(const char *ArgName, Option *Opt) { | 
 | 72 |   if (CommandLineOptions == 0) return; | 
| Chris Lattner | f98cfc7 | 2004-07-18 21:56:20 +0000 | [diff] [blame] | 73 | #ifndef NDEBUG | 
 | 74 |   // This disgusting HACK is brought to you courtesy of GCC 3.3.2, which ICE's | 
 | 75 |   // If we pass ArgName directly into getOption here. | 
 | 76 |   std::string Tmp = ArgName; | 
 | 77 |   assert(getOption(Tmp) == Opt && "Arg not in map!"); | 
 | 78 | #endif | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 79 |   CommandLineOptions->erase(ArgName); | 
 | 80 |   if (CommandLineOptions->empty()) { | 
 | 81 |     delete CommandLineOptions; | 
 | 82 |     CommandLineOptions = 0; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 83 |   } | 
 | 84 | } | 
 | 85 |  | 
 | 86 | static const char *ProgramName = 0; | 
 | 87 | static const char *ProgramOverview = 0; | 
 | 88 |  | 
| Chris Lattner | caccd76 | 2001-10-27 05:54:17 +0000 | [diff] [blame] | 89 | static inline bool ProvideOption(Option *Handler, const char *ArgName, | 
 | 90 |                                  const char *Value, int argc, char **argv, | 
 | 91 |                                  int &i) { | 
 | 92 |   // Enforce value requirements | 
 | 93 |   switch (Handler->getValueExpectedFlag()) { | 
 | 94 |   case ValueRequired: | 
 | 95 |     if (Value == 0 || *Value == 0) {  // No value specified? | 
 | 96 |       if (i+1 < argc) {     // Steal the next argument, like for '-o filename' | 
 | 97 |         Value = argv[++i]; | 
 | 98 |       } else { | 
 | 99 |         return Handler->error(" requires a value!"); | 
 | 100 |       } | 
 | 101 |     } | 
 | 102 |     break; | 
 | 103 |   case ValueDisallowed: | 
 | 104 |     if (*Value != 0) | 
 | 105 |       return Handler->error(" does not allow a value! '" +  | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 106 |                             std::string(Value) + "' specified."); | 
| Chris Lattner | caccd76 | 2001-10-27 05:54:17 +0000 | [diff] [blame] | 107 |     break; | 
 | 108 |   case ValueOptional: break; | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 109 |   default: std::cerr << "Bad ValueMask flag! CommandLine usage error:"  | 
 | 110 |                      << Handler->getValueExpectedFlag() << "\n"; abort(); | 
| Chris Lattner | caccd76 | 2001-10-27 05:54:17 +0000 | [diff] [blame] | 111 |   } | 
 | 112 |  | 
 | 113 |   // Run the handler now! | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 114 |   return Handler->addOccurrence(i, ArgName, Value); | 
| Chris Lattner | caccd76 | 2001-10-27 05:54:17 +0000 | [diff] [blame] | 115 | } | 
 | 116 |  | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 117 | static bool ProvidePositionalOption(Option *Handler, const std::string &Arg,  | 
 | 118 |                                     int i) { | 
 | 119 |   int Dummy = i; | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 120 |   return ProvideOption(Handler, Handler->ArgStr, Arg.c_str(), 0, 0, Dummy); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 121 | } | 
| Chris Lattner | f78032f | 2001-11-26 18:58:34 +0000 | [diff] [blame] | 122 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 123 |  | 
 | 124 | // Option predicates... | 
 | 125 | static inline bool isGrouping(const Option *O) { | 
 | 126 |   return O->getFormattingFlag() == cl::Grouping; | 
 | 127 | } | 
 | 128 | static inline bool isPrefixedOrGrouping(const Option *O) { | 
 | 129 |   return isGrouping(O) || O->getFormattingFlag() == cl::Prefix; | 
 | 130 | } | 
 | 131 |  | 
 | 132 | // getOptionPred - Check to see if there are any options that satisfy the | 
 | 133 | // specified predicate with names that are the prefixes in Name.  This is | 
 | 134 | // checked by progressively stripping characters off of the name, checking to | 
 | 135 | // see if there options that satisfy the predicate.  If we find one, return it, | 
 | 136 | // otherwise return null. | 
 | 137 | // | 
 | 138 | static Option *getOptionPred(std::string Name, unsigned &Length, | 
 | 139 |                              bool (*Pred)(const Option*)) { | 
 | 140 |    | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 141 |   Option *Op = getOption(Name); | 
 | 142 |   if (Op && Pred(Op)) { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 143 |     Length = Name.length(); | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 144 |     return Op; | 
| Chris Lattner | f78032f | 2001-11-26 18:58:34 +0000 | [diff] [blame] | 145 |   } | 
 | 146 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 147 |   if (Name.size() == 1) return 0; | 
 | 148 |   do { | 
 | 149 |     Name.erase(Name.end()-1, Name.end());   // Chop off the last character... | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 150 |     Op = getOption(Name); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 151 |  | 
 | 152 |     // Loop while we haven't found an option and Name still has at least two | 
 | 153 |     // characters in it (so that the next iteration will not be the empty | 
 | 154 |     // string... | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 155 |   } while ((Op == 0 || !Pred(Op)) && Name.size() > 1); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 156 |  | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 157 |   if (Op && Pred(Op)) { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 158 |     Length = Name.length(); | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 159 |     return Op;             // Found one! | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 160 |   } | 
 | 161 |   return 0;                // No option found! | 
 | 162 | } | 
 | 163 |  | 
 | 164 | static bool RequiresValue(const Option *O) { | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 165 |   return O->getNumOccurrencesFlag() == cl::Required || | 
 | 166 |          O->getNumOccurrencesFlag() == cl::OneOrMore; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 167 | } | 
 | 168 |  | 
 | 169 | static bool EatsUnboundedNumberOfValues(const Option *O) { | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 170 |   return O->getNumOccurrencesFlag() == cl::ZeroOrMore || | 
 | 171 |          O->getNumOccurrencesFlag() == cl::OneOrMore; | 
| Chris Lattner | f78032f | 2001-11-26 18:58:34 +0000 | [diff] [blame] | 172 | } | 
| Chris Lattner | caccd76 | 2001-10-27 05:54:17 +0000 | [diff] [blame] | 173 |  | 
| Brian Gaeke | c48ef2a | 2003-08-15 21:05:57 +0000 | [diff] [blame] | 174 | /// ParseCStringVector - Break INPUT up wherever one or more | 
 | 175 | /// whitespace characters are found, and store the resulting tokens in | 
 | 176 | /// OUTPUT. The tokens stored in OUTPUT are dynamically allocated | 
 | 177 | /// using strdup (), so it is the caller's responsibility to free () | 
 | 178 | /// them later. | 
| Brian Gaeke | 06b06c5 | 2003-08-14 22:00:59 +0000 | [diff] [blame] | 179 | /// | 
 | 180 | static void ParseCStringVector (std::vector<char *> &output, | 
| Reid Spencer | 69105f3 | 2004-08-04 00:36:06 +0000 | [diff] [blame] | 181 |                                 const char *input) { | 
| Brian Gaeke | c48ef2a | 2003-08-15 21:05:57 +0000 | [diff] [blame] | 182 |   // Characters which will be treated as token separators: | 
 | 183 |   static const char *delims = " \v\f\t\r\n"; | 
 | 184 |  | 
 | 185 |   std::string work (input); | 
 | 186 |   // Skip past any delims at head of input string. | 
 | 187 |   size_t pos = work.find_first_not_of (delims); | 
 | 188 |   // If the string consists entirely of delims, then exit early. | 
 | 189 |   if (pos == std::string::npos) return; | 
 | 190 |   // Otherwise, jump forward to beginning of first word. | 
 | 191 |   work = work.substr (pos); | 
 | 192 |   // Find position of first delimiter. | 
 | 193 |   pos = work.find_first_of (delims); | 
 | 194 |  | 
 | 195 |   while (!work.empty() && pos != std::string::npos) { | 
 | 196 |     // Everything from 0 to POS is the next word to copy. | 
 | 197 |     output.push_back (strdup (work.substr (0,pos).c_str ())); | 
 | 198 |     // Is there another word in the string? | 
 | 199 |     size_t nextpos = work.find_first_not_of (delims, pos + 1); | 
 | 200 |     if (nextpos != std::string::npos) { | 
 | 201 |       // Yes? Then remove delims from beginning ... | 
 | 202 |       work = work.substr (work.find_first_not_of (delims, pos + 1)); | 
 | 203 |       // and find the end of the word. | 
 | 204 |       pos = work.find_first_of (delims); | 
 | 205 |     } else { | 
 | 206 |       // No? (Remainder of string is delims.) End the loop. | 
 | 207 |       work = ""; | 
 | 208 |       pos = std::string::npos; | 
 | 209 |     } | 
 | 210 |   } | 
 | 211 |  | 
 | 212 |   // If `input' ended with non-delim char, then we'll get here with | 
 | 213 |   // the last word of `input' in `work'; copy it now. | 
 | 214 |   if (!work.empty ()) { | 
 | 215 |     output.push_back (strdup (work.c_str ())); | 
| Brian Gaeke | 06b06c5 | 2003-08-14 22:00:59 +0000 | [diff] [blame] | 216 |   } | 
 | 217 | } | 
 | 218 |  | 
 | 219 | /// ParseEnvironmentOptions - An alternative entry point to the | 
 | 220 | /// CommandLine library, which allows you to read the program's name | 
 | 221 | /// from the caller (as PROGNAME) and its command-line arguments from | 
 | 222 | /// an environment variable (whose name is given in ENVVAR). | 
 | 223 | /// | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 224 | void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, | 
 | 225 |                                  const char *Overview) { | 
| Brian Gaeke | c48ef2a | 2003-08-15 21:05:57 +0000 | [diff] [blame] | 226 |   // Check args. | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 227 |   assert(progName && "Program name not specified"); | 
 | 228 |   assert(envVar && "Environment variable name missing"); | 
| Brian Gaeke | c48ef2a | 2003-08-15 21:05:57 +0000 | [diff] [blame] | 229 |    | 
 | 230 |   // Get the environment variable they want us to parse options out of. | 
 | 231 |   const char *envValue = getenv (envVar); | 
 | 232 |   if (!envValue) | 
 | 233 |     return; | 
 | 234 |  | 
| Brian Gaeke | 06b06c5 | 2003-08-14 22:00:59 +0000 | [diff] [blame] | 235 |   // Get program's "name", which we wouldn't know without the caller | 
 | 236 |   // telling us. | 
| Brian Gaeke | c48ef2a | 2003-08-15 21:05:57 +0000 | [diff] [blame] | 237 |   std::vector<char *> newArgv; | 
 | 238 |   newArgv.push_back (strdup (progName)); | 
| Brian Gaeke | 06b06c5 | 2003-08-14 22:00:59 +0000 | [diff] [blame] | 239 |  | 
 | 240 |   // Parse the value of the environment variable into a "command line" | 
 | 241 |   // and hand it off to ParseCommandLineOptions(). | 
| Brian Gaeke | c48ef2a | 2003-08-15 21:05:57 +0000 | [diff] [blame] | 242 |   ParseCStringVector (newArgv, envValue); | 
 | 243 |   int newArgc = newArgv.size (); | 
 | 244 |   ParseCommandLineOptions (newArgc, &newArgv[0], Overview); | 
 | 245 |  | 
 | 246 |   // Free all the strdup()ed strings. | 
 | 247 |   for (std::vector<char *>::iterator i = newArgv.begin (), e = newArgv.end (); | 
 | 248 |        i != e; ++i) { | 
 | 249 |     free (*i); | 
 | 250 |   } | 
| Brian Gaeke | 06b06c5 | 2003-08-14 22:00:59 +0000 | [diff] [blame] | 251 | } | 
 | 252 |  | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 253 | /// LookupOption - Lookup the option specified by the specified option on the | 
 | 254 | /// command line.  If there is a value specified (after an equal sign) return | 
 | 255 | /// that as well. | 
 | 256 | static Option *LookupOption(const char *&Arg, const char *&Value) { | 
 | 257 |   while (*Arg == '-') ++Arg;  // Eat leading dashes | 
 | 258 |    | 
 | 259 |   const char *ArgEnd = Arg; | 
 | 260 |   while (*ArgEnd && *ArgEnd != '=') | 
 | 261 |     ++ArgEnd; // Scan till end of argument name... | 
 | 262 |  | 
 | 263 |   Value = ArgEnd; | 
 | 264 |   if (*Value)           // If we have an equals sign... | 
 | 265 |     ++Value;            // Advance to value... | 
 | 266 |    | 
 | 267 |   if (*Arg == 0) return 0; | 
 | 268 |  | 
 | 269 |   // Look up the option. | 
 | 270 |   std::map<std::string, Option*> &Opts = getOpts(); | 
 | 271 |   std::map<std::string, Option*>::iterator I = | 
 | 272 |     Opts.find(std::string(Arg, ArgEnd)); | 
 | 273 |   return (I != Opts.end()) ? I->second : 0; | 
 | 274 | } | 
 | 275 |  | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 276 | void cl::ParseCommandLineOptions(int &argc, char **argv, | 
| Chris Lattner | 0c0edf8 | 2002-07-25 06:17:51 +0000 | [diff] [blame] | 277 |                                  const char *Overview) { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 278 |   assert((!getOpts().empty() || !getPositionalOpts().empty()) && | 
 | 279 |          "No options specified, or ParseCommandLineOptions called more" | 
 | 280 |          " than once!"); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 281 |   ProgramName = argv[0];  // Save this away safe and snug | 
 | 282 |   ProgramOverview = Overview; | 
 | 283 |   bool ErrorParsing = false; | 
 | 284 |  | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 285 |   std::map<std::string, Option*> &Opts = getOpts(); | 
 | 286 |   std::vector<Option*> &PositionalOpts = getPositionalOpts(); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 287 |  | 
 | 288 |   // Check out the positional arguments to collect information about them. | 
 | 289 |   unsigned NumPositionalRequired = 0; | 
 | 290 |   Option *ConsumeAfterOpt = 0; | 
 | 291 |   if (!PositionalOpts.empty()) { | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 292 |     if (PositionalOpts[0]->getNumOccurrencesFlag() == cl::ConsumeAfter) { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 293 |       assert(PositionalOpts.size() > 1 && | 
 | 294 |              "Cannot specify cl::ConsumeAfter without a positional argument!"); | 
 | 295 |       ConsumeAfterOpt = PositionalOpts[0]; | 
 | 296 |     } | 
 | 297 |  | 
 | 298 |     // Calculate how many positional values are _required_. | 
 | 299 |     bool UnboundedFound = false; | 
 | 300 |     for (unsigned i = ConsumeAfterOpt != 0, e = PositionalOpts.size(); | 
 | 301 |          i != e; ++i) { | 
 | 302 |       Option *Opt = PositionalOpts[i]; | 
 | 303 |       if (RequiresValue(Opt)) | 
 | 304 |         ++NumPositionalRequired; | 
 | 305 |       else if (ConsumeAfterOpt) { | 
 | 306 |         // ConsumeAfter cannot be combined with "optional" positional options | 
| Chris Lattner | 54ec7ae | 2002-07-22 02:21:57 +0000 | [diff] [blame] | 307 |         // unless there is only one positional argument... | 
 | 308 |         if (PositionalOpts.size() > 2) | 
 | 309 |           ErrorParsing |= | 
 | 310 |             Opt->error(" error - this positional option will never be matched, " | 
 | 311 |                        "because it does not Require a value, and a " | 
 | 312 |                        "cl::ConsumeAfter option is active!"); | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 313 |       } else if (UnboundedFound && !Opt->ArgStr[0]) { | 
 | 314 |         // This option does not "require" a value...  Make sure this option is | 
 | 315 |         // not specified after an option that eats all extra arguments, or this | 
 | 316 |         // one will never get any! | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 317 |         // | 
 | 318 |         ErrorParsing |= Opt->error(" error - option can never match, because " | 
 | 319 |                                    "another positional argument will match an " | 
 | 320 |                                    "unbounded number of values, and this option" | 
 | 321 |                                    " does not require a value!"); | 
 | 322 |       } | 
 | 323 |       UnboundedFound |= EatsUnboundedNumberOfValues(Opt); | 
 | 324 |     } | 
 | 325 |   } | 
 | 326 |  | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 327 |   // PositionalVals - A vector of "positional" arguments we accumulate into | 
 | 328 |   // the process at the end... | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 329 |   // | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 330 |   std::vector<std::pair<std::string,unsigned> > PositionalVals; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 331 |  | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 332 |   // If the program has named positional arguments, and the name has been run | 
 | 333 |   // across, keep track of which positional argument was named.  Otherwise put | 
 | 334 |   // the positional args into the PositionalVals list... | 
 | 335 |   Option *ActivePositionalArg = 0; | 
 | 336 |  | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 337 |   // Loop over all of the arguments... processing them. | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 338 |   bool DashDashFound = false;  // Have we read '--'? | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 339 |   for (int i = 1; i < argc; ++i) { | 
 | 340 |     Option *Handler = 0; | 
 | 341 |     const char *Value = ""; | 
 | 342 |     const char *ArgName = ""; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 343 |  | 
 | 344 |     // Check to see if this is a positional argument.  This argument is | 
 | 345 |     // considered to be positional if it doesn't start with '-', if it is "-" | 
| Misha Brukman | 1115e04 | 2003-07-10 21:38:28 +0000 | [diff] [blame] | 346 |     // itself, or if we have seen "--" already. | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 347 |     // | 
 | 348 |     if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) { | 
 | 349 |       // Positional argument! | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 350 |       if (ActivePositionalArg) { | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 351 |         ProvidePositionalOption(ActivePositionalArg, argv[i], i); | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 352 |         continue;  // We are done! | 
 | 353 |       } else if (!PositionalOpts.empty()) { | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 354 |         PositionalVals.push_back(std::make_pair(argv[i],i)); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 355 |  | 
 | 356 |         // All of the positional arguments have been fulfulled, give the rest to | 
 | 357 |         // the consume after option... if it's specified... | 
 | 358 |         // | 
| Chris Lattner | d16714b | 2002-07-31 16:29:43 +0000 | [diff] [blame] | 359 |         if (PositionalVals.size() >= NumPositionalRequired &&  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 360 |             ConsumeAfterOpt != 0) { | 
 | 361 |           for (++i; i < argc; ++i) | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 362 |             PositionalVals.push_back(std::make_pair(argv[i],i)); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 363 |           break;   // Handle outside of the argument processing loop... | 
 | 364 |         } | 
 | 365 |  | 
 | 366 |         // Delay processing positional arguments until the end... | 
 | 367 |         continue; | 
 | 368 |       } | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 369 |     } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 && | 
 | 370 |                !DashDashFound) { | 
 | 371 |       DashDashFound = true;  // This is the mythical "--"? | 
 | 372 |       continue;              // Don't try to process it as an argument itself. | 
 | 373 |     } else if (ActivePositionalArg && | 
 | 374 |                (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) { | 
 | 375 |       // If there is a positional argument eating options, check to see if this | 
 | 376 |       // option is another positional argument.  If so, treat it as an argument, | 
 | 377 |       // otherwise feed it to the eating positional. | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 378 |       ArgName = argv[i]+1; | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 379 |       Handler = LookupOption(ArgName, Value); | 
 | 380 |       if (!Handler || Handler->getFormattingFlag() != cl::Positional) { | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 381 |         ProvidePositionalOption(ActivePositionalArg, argv[i], i); | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 382 |         continue;  // We are done! | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 383 |       } | 
 | 384 |  | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 385 |     } else {     // We start with a '-', must be an argument... | 
 | 386 |       ArgName = argv[i]+1; | 
 | 387 |       Handler = LookupOption(ArgName, Value); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 388 |  | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 389 |       // Check to see if this "option" is really a prefixed or grouped argument. | 
 | 390 |       if (Handler == 0 && *Value == 0) { | 
 | 391 |         std::string RealName(ArgName); | 
 | 392 |         if (RealName.size() > 1) { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 393 |           unsigned Length = 0; | 
 | 394 |           Option *PGOpt = getOptionPred(RealName, Length, isPrefixedOrGrouping); | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 395 |    | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 396 |           // If the option is a prefixed option, then the value is simply the | 
 | 397 |           // rest of the name...  so fall through to later processing, by | 
 | 398 |           // setting up the argument name flags and value fields. | 
 | 399 |           // | 
 | 400 |           if (PGOpt && PGOpt->getFormattingFlag() == cl::Prefix) { | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 401 |             Value = ArgName+Length; | 
 | 402 |             assert(Opts.find(std::string(ArgName, Value)) != Opts.end() && | 
 | 403 |                    Opts.find(std::string(ArgName, Value))->second == PGOpt); | 
 | 404 |             Handler = PGOpt; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 405 |           } else if (PGOpt) { | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 406 |             // This must be a grouped option... handle them now. | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 407 |             assert(isGrouping(PGOpt) && "Broken getOptionPred!"); | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 408 |              | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 409 |             do { | 
 | 410 |               // Move current arg name out of RealName into RealArgName... | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 411 |               std::string RealArgName(RealName.begin(), | 
 | 412 |                                       RealName.begin() + Length); | 
 | 413 |               RealName.erase(RealName.begin(), RealName.begin() + Length); | 
 | 414 |                | 
| Misha Brukman | b5c520b | 2003-07-10 17:05:26 +0000 | [diff] [blame] | 415 |               // Because ValueRequired is an invalid flag for grouped arguments, | 
 | 416 |               // we don't need to pass argc/argv in... | 
 | 417 |               // | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 418 |               assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired && | 
 | 419 |                      "Option can not be cl::Grouping AND cl::ValueRequired!"); | 
 | 420 |               int Dummy; | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 421 |               ErrorParsing |= ProvideOption(PGOpt, RealArgName.c_str(), | 
 | 422 |                                             "", 0, 0, Dummy); | 
 | 423 |                | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 424 |               // Get the next grouping option... | 
| Chris Lattner | bf455c2 | 2004-05-06 22:04:31 +0000 | [diff] [blame] | 425 |               PGOpt = getOptionPred(RealName, Length, isGrouping); | 
 | 426 |             } while (PGOpt && Length != RealName.size()); | 
 | 427 |              | 
 | 428 |             Handler = PGOpt; // Ate all of the options. | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 429 |           } | 
| Misha Brukman | b5c520b | 2003-07-10 17:05:26 +0000 | [diff] [blame] | 430 |         } | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 431 |       } | 
 | 432 |     } | 
 | 433 |  | 
 | 434 |     if (Handler == 0) { | 
| Brian Gaeke | c86e84b | 2003-09-16 18:00:35 +0000 | [diff] [blame] | 435 |       std::cerr << "Unknown command line argument '" << argv[i] << "'.  Try: '" | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 436 |                 << argv[0] << " --help'\n"; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 437 |       ErrorParsing = true; | 
 | 438 |       continue; | 
 | 439 |     } | 
 | 440 |  | 
| Chris Lattner | 72fb8e5 | 2003-05-22 20:26:17 +0000 | [diff] [blame] | 441 |     // Check to see if this option accepts a comma separated list of values.  If | 
 | 442 |     // it does, we have to split up the value into multiple values... | 
 | 443 |     if (Handler->getMiscFlags() & CommaSeparated) { | 
 | 444 |       std::string Val(Value); | 
 | 445 |       std::string::size_type Pos = Val.find(','); | 
 | 446 |  | 
 | 447 |       while (Pos != std::string::npos) { | 
 | 448 |         // Process the portion before the comma... | 
 | 449 |         ErrorParsing |= ProvideOption(Handler, ArgName, | 
 | 450 |                                       std::string(Val.begin(), | 
 | 451 |                                                   Val.begin()+Pos).c_str(), | 
 | 452 |                                       argc, argv, i); | 
 | 453 |         // Erase the portion before the comma, AND the comma... | 
 | 454 |         Val.erase(Val.begin(), Val.begin()+Pos+1); | 
 | 455 |         Value += Pos+1;  // Increment the original value pointer as well... | 
 | 456 |  | 
 | 457 |         // Check for another comma... | 
 | 458 |         Pos = Val.find(','); | 
 | 459 |       } | 
 | 460 |     } | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 461 |  | 
 | 462 |     // If this is a named positional argument, just remember that it is the | 
 | 463 |     // active one... | 
 | 464 |     if (Handler->getFormattingFlag() == cl::Positional) | 
 | 465 |       ActivePositionalArg = Handler; | 
 | 466 |     else  | 
 | 467 |       ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 468 |   } | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 469 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 470 |   // Check and handle positional arguments now... | 
 | 471 |   if (NumPositionalRequired > PositionalVals.size()) { | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 472 |     std::cerr << "Not enough positional command line arguments specified!\n" | 
 | 473 |               << "Must specify at least " << NumPositionalRequired | 
 | 474 |               << " positional arguments: See: " << argv[0] << " --help\n"; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 475 |     ErrorParsing = true; | 
 | 476 |  | 
 | 477 |  | 
 | 478 |   } else if (ConsumeAfterOpt == 0) { | 
 | 479 |     // Positional args have already been handled if ConsumeAfter is specified... | 
 | 480 |     unsigned ValNo = 0, NumVals = PositionalVals.size(); | 
 | 481 |     for (unsigned i = 0, e = PositionalOpts.size(); i != e; ++i) { | 
 | 482 |       if (RequiresValue(PositionalOpts[i])) { | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 483 |         ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo].first,  | 
 | 484 |                                 PositionalVals[ValNo].second); | 
 | 485 |         ValNo++; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 486 |         --NumPositionalRequired;  // We fulfilled our duty... | 
 | 487 |       } | 
 | 488 |  | 
 | 489 |       // If we _can_ give this option more arguments, do so now, as long as we | 
 | 490 |       // do not give it values that others need.  'Done' controls whether the | 
 | 491 |       // option even _WANTS_ any more. | 
 | 492 |       // | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 493 |       bool Done = PositionalOpts[i]->getNumOccurrencesFlag() == cl::Required; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 494 |       while (NumVals-ValNo > NumPositionalRequired && !Done) { | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 495 |         switch (PositionalOpts[i]->getNumOccurrencesFlag()) { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 496 |         case cl::Optional: | 
 | 497 |           Done = true;          // Optional arguments want _at most_ one value | 
 | 498 |           // FALL THROUGH | 
 | 499 |         case cl::ZeroOrMore:    // Zero or more will take all they can get... | 
 | 500 |         case cl::OneOrMore:     // One or more will take all they can get... | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 501 |           ProvidePositionalOption(PositionalOpts[i], | 
 | 502 |                                   PositionalVals[ValNo].first, | 
 | 503 |                                   PositionalVals[ValNo].second); | 
 | 504 |           ValNo++; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 505 |           break; | 
 | 506 |         default: | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 507 |           assert(0 && "Internal error, unexpected NumOccurrences flag in " | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 508 |                  "positional argument processing!"); | 
 | 509 |         } | 
 | 510 |       } | 
| Chris Lattner | caccd76 | 2001-10-27 05:54:17 +0000 | [diff] [blame] | 511 |     } | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 512 |   } else { | 
 | 513 |     assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size()); | 
 | 514 |     unsigned ValNo = 0; | 
 | 515 |     for (unsigned j = 1, e = PositionalOpts.size(); j != e; ++j) | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 516 |       if (RequiresValue(PositionalOpts[j])) { | 
| Chris Lattner | faba809 | 2002-07-24 20:15:13 +0000 | [diff] [blame] | 517 |         ErrorParsing |= ProvidePositionalOption(PositionalOpts[j], | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 518 |                                                 PositionalVals[ValNo].first, | 
 | 519 |                                                 PositionalVals[ValNo].second); | 
 | 520 |         ValNo++; | 
 | 521 |       } | 
| Chris Lattner | faba809 | 2002-07-24 20:15:13 +0000 | [diff] [blame] | 522 |  | 
 | 523 |     // Handle the case where there is just one positional option, and it's | 
 | 524 |     // optional.  In this case, we want to give JUST THE FIRST option to the | 
 | 525 |     // positional option and keep the rest for the consume after.  The above | 
 | 526 |     // loop would have assigned no values to positional options in this case. | 
 | 527 |     // | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 528 |     if (PositionalOpts.size() == 2 && ValNo == 0 && !PositionalVals.empty()) { | 
| Chris Lattner | faba809 | 2002-07-24 20:15:13 +0000 | [diff] [blame] | 529 |       ErrorParsing |= ProvidePositionalOption(PositionalOpts[1], | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 530 |                                               PositionalVals[ValNo].first, | 
 | 531 |                                               PositionalVals[ValNo].second); | 
 | 532 |       ValNo++; | 
 | 533 |     } | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 534 |      | 
 | 535 |     // Handle over all of the rest of the arguments to the | 
 | 536 |     // cl::ConsumeAfter command line option... | 
 | 537 |     for (; ValNo != PositionalVals.size(); ++ValNo) | 
 | 538 |       ErrorParsing |= ProvidePositionalOption(ConsumeAfterOpt, | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 539 |                                               PositionalVals[ValNo].first, | 
 | 540 |                                               PositionalVals[ValNo].second); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 541 |   } | 
 | 542 |  | 
| Chris Lattner | dc4693d | 2001-07-23 23:02:45 +0000 | [diff] [blame] | 543 |   // Loop over args and make sure all required args are specified! | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 544 |   for (std::map<std::string, Option*>::iterator I = Opts.begin(),  | 
| Misha Brukman | b5c520b | 2003-07-10 17:05:26 +0000 | [diff] [blame] | 545 |          E = Opts.end(); I != E; ++I) { | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 546 |     switch (I->second->getNumOccurrencesFlag()) { | 
| Chris Lattner | dc4693d | 2001-07-23 23:02:45 +0000 | [diff] [blame] | 547 |     case Required: | 
 | 548 |     case OneOrMore: | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 549 |       if (I->second->getNumOccurrences() == 0) { | 
| Misha Brukman | b5c520b | 2003-07-10 17:05:26 +0000 | [diff] [blame] | 550 |         I->second->error(" must be specified at least once!"); | 
| Chris Lattner | f038acb | 2001-10-24 06:21:56 +0000 | [diff] [blame] | 551 |         ErrorParsing = true; | 
 | 552 |       } | 
| Chris Lattner | dc4693d | 2001-07-23 23:02:45 +0000 | [diff] [blame] | 553 |       // Fall through | 
 | 554 |     default: | 
 | 555 |       break; | 
 | 556 |     } | 
 | 557 |   } | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 558 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 559 |   // Free all of the memory allocated to the map.  Command line options may only | 
 | 560 |   // be processed once! | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 561 |   delete CommandLineOptions; | 
 | 562 |   CommandLineOptions = 0; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 563 |   PositionalOpts.clear(); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 564 |  | 
 | 565 |   // If we had an error processing our arguments, don't let the program execute | 
 | 566 |   if (ErrorParsing) exit(1); | 
 | 567 | } | 
 | 568 |  | 
 | 569 | //===----------------------------------------------------------------------===// | 
 | 570 | // Option Base class implementation | 
 | 571 | // | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 572 |  | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 573 | bool Option::error(std::string Message, const char *ArgName) { | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 574 |   if (ArgName == 0) ArgName = ArgStr; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 575 |   if (ArgName[0] == 0) | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 576 |     std::cerr << HelpStr;  // Be nice for positional arguments | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 577 |   else | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 578 |     std::cerr << "-" << ArgName; | 
 | 579 |   std::cerr << " option" << Message << "\n"; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 580 |   return true; | 
 | 581 | } | 
 | 582 |  | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 583 | bool Option::addOccurrence(unsigned pos, const char *ArgName, const std::string &Value) { | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 584 |   NumOccurrences++;   // Increment the number of times we have been seen | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 585 |  | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 586 |   switch (getNumOccurrencesFlag()) { | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 587 |   case Optional: | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 588 |     if (NumOccurrences > 1) | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 589 |       return error(": may only occur zero or one times!", ArgName); | 
 | 590 |     break; | 
 | 591 |   case Required: | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 592 |     if (NumOccurrences > 1) | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 593 |       return error(": must occur exactly one time!", ArgName); | 
 | 594 |     // Fall through | 
 | 595 |   case OneOrMore: | 
| Chris Lattner | caccd76 | 2001-10-27 05:54:17 +0000 | [diff] [blame] | 596 |   case ZeroOrMore: | 
 | 597 |   case ConsumeAfter: break; | 
| Misha Brukman | b5c520b | 2003-07-10 17:05:26 +0000 | [diff] [blame] | 598 |   default: return error(": bad num occurrences flag value!"); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 599 |   } | 
 | 600 |  | 
| Reid Spencer | 1e13fd2 | 2004-08-13 19:47:30 +0000 | [diff] [blame] | 601 |   return handleOccurrence(pos, ArgName, Value); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 602 | } | 
 | 603 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 604 | // addArgument - Tell the system that this Option subclass will handle all | 
| Misha Brukman | b5c520b | 2003-07-10 17:05:26 +0000 | [diff] [blame] | 605 | // occurrences of -ArgStr on the command line. | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 606 | // | 
 | 607 | void Option::addArgument(const char *ArgStr) { | 
 | 608 |   if (ArgStr[0]) | 
 | 609 |     AddArgument(ArgStr, this); | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 610 |  | 
 | 611 |   if (getFormattingFlag() == Positional) | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 612 |     getPositionalOpts().push_back(this); | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 613 |   else if (getNumOccurrencesFlag() == ConsumeAfter) { | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 614 |     if (!getPositionalOpts().empty() && | 
 | 615 |         getPositionalOpts().front()->getNumOccurrencesFlag() == ConsumeAfter) | 
 | 616 |       error("Cannot specify more than one option with cl::ConsumeAfter!"); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 617 |     getPositionalOpts().insert(getPositionalOpts().begin(), this); | 
 | 618 |   } | 
 | 619 | } | 
 | 620 |  | 
| Chris Lattner | aa852bb | 2002-07-23 17:15:12 +0000 | [diff] [blame] | 621 | void Option::removeArgument(const char *ArgStr) { | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 622 |   if (ArgStr[0]) | 
| Chris Lattner | e8e258b | 2002-07-29 20:58:42 +0000 | [diff] [blame] | 623 |     RemoveArgument(ArgStr, this); | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 624 |  | 
 | 625 |   if (getFormattingFlag() == Positional) { | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 626 |     std::vector<Option*>::iterator I = | 
| Chris Lattner | aa852bb | 2002-07-23 17:15:12 +0000 | [diff] [blame] | 627 |       std::find(getPositionalOpts().begin(), getPositionalOpts().end(), this); | 
 | 628 |     assert(I != getPositionalOpts().end() && "Arg not registered!"); | 
 | 629 |     getPositionalOpts().erase(I); | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 630 |   } else if (getNumOccurrencesFlag() == ConsumeAfter) { | 
| Chris Lattner | aa852bb | 2002-07-23 17:15:12 +0000 | [diff] [blame] | 631 |     assert(!getPositionalOpts().empty() && getPositionalOpts()[0] == this && | 
 | 632 |            "Arg not registered correctly!"); | 
 | 633 |     getPositionalOpts().erase(getPositionalOpts().begin()); | 
 | 634 |   } | 
 | 635 | } | 
 | 636 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 637 |  | 
 | 638 | // getValueStr - Get the value description string, using "DefaultMsg" if nothing | 
 | 639 | // has been specified yet. | 
 | 640 | // | 
 | 641 | static const char *getValueStr(const Option &O, const char *DefaultMsg) { | 
 | 642 |   if (O.ValueStr[0] == 0) return DefaultMsg; | 
 | 643 |   return O.ValueStr; | 
 | 644 | } | 
 | 645 |  | 
 | 646 | //===----------------------------------------------------------------------===// | 
 | 647 | // cl::alias class implementation | 
 | 648 | // | 
 | 649 |  | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 650 | // Return the width of the option tag for printing... | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 651 | unsigned alias::getOptionWidth() const { | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 652 |   return std::strlen(ArgStr)+6; | 
 | 653 | } | 
 | 654 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 655 | // Print out the option for the alias... | 
 | 656 | void alias::printOptionInfo(unsigned GlobalWidth) const { | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 657 |   unsigned L = std::strlen(ArgStr); | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 658 |   std::cerr << "  -" << ArgStr << std::string(GlobalWidth-L-6, ' ') << " - " | 
 | 659 |             << HelpStr << "\n"; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 660 | } | 
 | 661 |  | 
 | 662 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 663 |  | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 664 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 665 | // Parser Implementation code... | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 666 | // | 
 | 667 |  | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 668 | // basic_parser implementation | 
 | 669 | // | 
 | 670 |  | 
 | 671 | // Return the width of the option tag for printing... | 
 | 672 | unsigned basic_parser_impl::getOptionWidth(const Option &O) const { | 
 | 673 |   unsigned Len = std::strlen(O.ArgStr); | 
 | 674 |   if (const char *ValName = getValueName()) | 
 | 675 |     Len += std::strlen(getValueStr(O, ValName))+3; | 
 | 676 |  | 
 | 677 |   return Len + 6; | 
 | 678 | } | 
 | 679 |  | 
 | 680 | // printOptionInfo - Print out information about this option.  The  | 
 | 681 | // to-be-maintained width is specified. | 
 | 682 | // | 
 | 683 | void basic_parser_impl::printOptionInfo(const Option &O, | 
 | 684 |                                         unsigned GlobalWidth) const { | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 685 |   std::cerr << "  -" << O.ArgStr; | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 686 |  | 
 | 687 |   if (const char *ValName = getValueName()) | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 688 |     std::cerr << "=<" << getValueStr(O, ValName) << ">"; | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 689 |  | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 690 |   std::cerr << std::string(GlobalWidth-getOptionWidth(O), ' ') << " - " | 
 | 691 |             << O.HelpStr << "\n"; | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 692 | } | 
 | 693 |  | 
 | 694 |  | 
 | 695 |  | 
 | 696 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 697 | // parser<bool> implementation | 
 | 698 | // | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 699 | bool parser<bool>::parse(Option &O, const char *ArgName, | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 700 |                          const std::string &Arg, bool &Value) { | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 701 |   if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||  | 
 | 702 |       Arg == "1") { | 
 | 703 |     Value = true; | 
 | 704 |   } else if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { | 
 | 705 |     Value = false; | 
 | 706 |   } else { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 707 |     return O.error(": '" + Arg + | 
 | 708 |                    "' is invalid value for boolean argument! Try 0 or 1"); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 709 |   } | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 710 |   return false; | 
 | 711 | } | 
 | 712 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 713 | // parser<int> implementation | 
 | 714 | // | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 715 | bool parser<int>::parse(Option &O, const char *ArgName, | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 716 |                         const std::string &Arg, int &Value) { | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 717 |   char *End; | 
| Chris Lattner | d2a6fc3 | 2003-06-28 15:47:20 +0000 | [diff] [blame] | 718 |   Value = (int)strtol(Arg.c_str(), &End, 0); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 719 |   if (*End != 0)  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 720 |     return O.error(": '" + Arg + "' value invalid for integer argument!"); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 721 |   return false; | 
 | 722 | } | 
 | 723 |  | 
| Chris Lattner | d2a6fc3 | 2003-06-28 15:47:20 +0000 | [diff] [blame] | 724 | // parser<unsigned> implementation | 
 | 725 | // | 
 | 726 | bool parser<unsigned>::parse(Option &O, const char *ArgName, | 
 | 727 |                              const std::string &Arg, unsigned &Value) { | 
 | 728 |   char *End; | 
| Brian Gaeke | 2d6a236 | 2003-10-10 17:01:36 +0000 | [diff] [blame] | 729 |   errno = 0; | 
 | 730 |   unsigned long V = strtoul(Arg.c_str(), &End, 0); | 
| Chris Lattner | d2a6fc3 | 2003-06-28 15:47:20 +0000 | [diff] [blame] | 731 |   Value = (unsigned)V; | 
| Brian Gaeke | 2d6a236 | 2003-10-10 17:01:36 +0000 | [diff] [blame] | 732 |   if (((V == ULONG_MAX) && (errno == ERANGE)) | 
 | 733 |       || (*End != 0) | 
 | 734 |       || (Value != V)) | 
| Chris Lattner | d2a6fc3 | 2003-06-28 15:47:20 +0000 | [diff] [blame] | 735 |     return O.error(": '" + Arg + "' value invalid for uint argument!"); | 
 | 736 |   return false; | 
 | 737 | } | 
 | 738 |  | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 739 | // parser<double>/parser<float> implementation | 
| Chris Lattner | d215fd1 | 2001-10-13 06:53:19 +0000 | [diff] [blame] | 740 | // | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 741 | static bool parseDouble(Option &O, const std::string &Arg, double &Value) { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 742 |   const char *ArgStart = Arg.c_str(); | 
 | 743 |   char *End; | 
 | 744 |   Value = strtod(ArgStart, &End); | 
 | 745 |   if (*End != 0)  | 
 | 746 |     return O.error(": '" +Arg+ "' value invalid for floating point argument!"); | 
| Chris Lattner | d215fd1 | 2001-10-13 06:53:19 +0000 | [diff] [blame] | 747 |   return false; | 
 | 748 | } | 
 | 749 |  | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 750 | bool parser<double>::parse(Option &O, const char *AN, | 
 | 751 |                            const std::string &Arg, double &Val) { | 
 | 752 |   return parseDouble(O, Arg, Val); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 753 | } | 
 | 754 |  | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 755 | bool parser<float>::parse(Option &O, const char *AN, | 
 | 756 |                           const std::string &Arg, float &Val) { | 
 | 757 |   double dVal; | 
 | 758 |   if (parseDouble(O, Arg, dVal)) | 
 | 759 |     return true; | 
 | 760 |   Val = (float)dVal; | 
 | 761 |   return false; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 762 | } | 
 | 763 |  | 
 | 764 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 765 |  | 
 | 766 | // generic_parser_base implementation | 
 | 767 | // | 
 | 768 |  | 
| Chris Lattner | aa852bb | 2002-07-23 17:15:12 +0000 | [diff] [blame] | 769 | // findOption - Return the option number corresponding to the specified | 
 | 770 | // argument string.  If the option is not found, getNumOptions() is returned. | 
 | 771 | // | 
 | 772 | unsigned generic_parser_base::findOption(const char *Name) { | 
 | 773 |   unsigned i = 0, e = getNumOptions(); | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 774 |   std::string N(Name); | 
| Chris Lattner | aa852bb | 2002-07-23 17:15:12 +0000 | [diff] [blame] | 775 |  | 
 | 776 |   while (i != e) | 
 | 777 |     if (getOption(i) == N) | 
 | 778 |       return i; | 
 | 779 |     else | 
 | 780 |       ++i; | 
 | 781 |   return e; | 
 | 782 | } | 
 | 783 |  | 
 | 784 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 785 | // Return the width of the option tag for printing... | 
 | 786 | unsigned generic_parser_base::getOptionWidth(const Option &O) const { | 
 | 787 |   if (O.hasArgStr()) { | 
 | 788 |     unsigned Size = std::strlen(O.ArgStr)+6; | 
 | 789 |     for (unsigned i = 0, e = getNumOptions(); i != e; ++i) | 
 | 790 |       Size = std::max(Size, (unsigned)std::strlen(getOption(i))+8); | 
 | 791 |     return Size; | 
 | 792 |   } else { | 
 | 793 |     unsigned BaseSize = 0; | 
 | 794 |     for (unsigned i = 0, e = getNumOptions(); i != e; ++i) | 
 | 795 |       BaseSize = std::max(BaseSize, (unsigned)std::strlen(getOption(i))+8); | 
 | 796 |     return BaseSize; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 797 |   } | 
 | 798 | } | 
 | 799 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 800 | // printOptionInfo - Print out information about this option.  The  | 
 | 801 | // to-be-maintained width is specified. | 
 | 802 | // | 
 | 803 | void generic_parser_base::printOptionInfo(const Option &O, | 
 | 804 |                                           unsigned GlobalWidth) const { | 
 | 805 |   if (O.hasArgStr()) { | 
 | 806 |     unsigned L = std::strlen(O.ArgStr); | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 807 |     std::cerr << "  -" << O.ArgStr << std::string(GlobalWidth-L-6, ' ') | 
 | 808 |               << " - " << O.HelpStr << "\n"; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 809 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 810 |     for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { | 
 | 811 |       unsigned NumSpaces = GlobalWidth-strlen(getOption(i))-8; | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 812 |       std::cerr << "    =" << getOption(i) << std::string(NumSpaces, ' ') | 
 | 813 |                 << " - " << getDescription(i) << "\n"; | 
| Chris Lattner | 9c9be48 | 2002-01-31 00:42:56 +0000 | [diff] [blame] | 814 |     } | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 815 |   } else { | 
 | 816 |     if (O.HelpStr[0]) | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 817 |       std::cerr << "  " << O.HelpStr << "\n";  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 818 |     for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { | 
 | 819 |       unsigned L = std::strlen(getOption(i)); | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 820 |       std::cerr << "    -" << getOption(i) << std::string(GlobalWidth-L-8, ' ') | 
 | 821 |                 << " - " << getDescription(i) << "\n"; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 822 |     } | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 823 |   } | 
 | 824 | } | 
 | 825 |  | 
 | 826 |  | 
 | 827 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 828 | // --help and --help-hidden option implementation | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 829 | // | 
 | 830 | namespace { | 
 | 831 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 832 | class HelpPrinter { | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 833 |   unsigned MaxArgLen; | 
 | 834 |   const Option *EmptyArg; | 
 | 835 |   const bool ShowHidden; | 
 | 836 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 837 |   // isHidden/isReallyHidden - Predicates to be used to filter down arg lists. | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 838 |   inline static bool isHidden(std::pair<std::string, Option *> &OptPair) { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 839 |     return OptPair.second->getOptionHiddenFlag() >= Hidden; | 
 | 840 |   } | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 841 |   inline static bool isReallyHidden(std::pair<std::string, Option *> &OptPair) { | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 842 |     return OptPair.second->getOptionHiddenFlag() == ReallyHidden; | 
 | 843 |   } | 
 | 844 |  | 
 | 845 | public: | 
 | 846 |   HelpPrinter(bool showHidden) : ShowHidden(showHidden) { | 
 | 847 |     EmptyArg = 0; | 
 | 848 |   } | 
 | 849 |  | 
 | 850 |   void operator=(bool Value) { | 
 | 851 |     if (Value == false) return; | 
 | 852 |  | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 853 |     // Copy Options into a vector so we can sort them as we like... | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 854 |     std::vector<std::pair<std::string, Option*> > Options; | 
| Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 855 |     copy(getOpts().begin(), getOpts().end(), std::back_inserter(Options)); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 856 |  | 
 | 857 |     // Eliminate Hidden or ReallyHidden arguments, depending on ShowHidden | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 858 |     Options.erase(std::remove_if(Options.begin(), Options.end(),  | 
 | 859 |                          std::ptr_fun(ShowHidden ? isReallyHidden : isHidden)), | 
| Misha Brukman | b5c520b | 2003-07-10 17:05:26 +0000 | [diff] [blame] | 860 |                   Options.end()); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 861 |  | 
 | 862 |     // Eliminate duplicate entries in table (from enum flags options, f.e.) | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 863 |     {  // Give OptionSet a scope | 
 | 864 |       std::set<Option*> OptionSet; | 
 | 865 |       for (unsigned i = 0; i != Options.size(); ++i) | 
 | 866 |         if (OptionSet.count(Options[i].second) == 0) | 
 | 867 |           OptionSet.insert(Options[i].second);   // Add new entry to set | 
 | 868 |         else | 
 | 869 |           Options.erase(Options.begin()+i--);    // Erase duplicate | 
 | 870 |     } | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 871 |  | 
 | 872 |     if (ProgramOverview) | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 873 |       std::cerr << "OVERVIEW:" << ProgramOverview << "\n"; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 874 |  | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 875 |     std::cerr << "USAGE: " << ProgramName << " [options]"; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 876 |  | 
 | 877 |     // Print out the positional options... | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 878 |     std::vector<Option*> &PosOpts = getPositionalOpts(); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 879 |     Option *CAOpt = 0;   // The cl::ConsumeAfter option, if it exists... | 
| Misha Brukman | dd6cb6a | 2003-07-10 16:49:51 +0000 | [diff] [blame] | 880 |     if (!PosOpts.empty() && PosOpts[0]->getNumOccurrencesFlag() == ConsumeAfter) | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 881 |       CAOpt = PosOpts[0]; | 
 | 882 |  | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 883 |     for (unsigned i = CAOpt != 0, e = PosOpts.size(); i != e; ++i) { | 
 | 884 |       if (PosOpts[i]->ArgStr[0]) | 
 | 885 |         std::cerr << " --" << PosOpts[i]->ArgStr; | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 886 |       std::cerr << " " << PosOpts[i]->HelpStr; | 
| Chris Lattner | 9cf3d47 | 2003-07-30 17:34:02 +0000 | [diff] [blame] | 887 |     } | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 888 |  | 
 | 889 |     // Print the consume after option info if it exists... | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 890 |     if (CAOpt) std::cerr << " " << CAOpt->HelpStr; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 891 |  | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 892 |     std::cerr << "\n\n"; | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 893 |  | 
 | 894 |     // Compute the maximum argument length... | 
 | 895 |     MaxArgLen = 0; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 896 |     for (unsigned i = 0, e = Options.size(); i != e; ++i) | 
 | 897 |       MaxArgLen = std::max(MaxArgLen, Options[i].second->getOptionWidth()); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 898 |  | 
| Chris Lattner | ca6433f | 2003-05-22 20:06:43 +0000 | [diff] [blame] | 899 |     std::cerr << "OPTIONS:\n"; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 900 |     for (unsigned i = 0, e = Options.size(); i != e; ++i) | 
 | 901 |       Options[i].second->printOptionInfo(MaxArgLen); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 902 |  | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 903 |     // Halt the program if help information is printed | 
 | 904 |     exit(1); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 905 |   } | 
 | 906 | }; | 
 | 907 |  | 
| Reid Spencer | 69105f3 | 2004-08-04 00:36:06 +0000 | [diff] [blame] | 908 | class VersionPrinter { | 
 | 909 | public: | 
 | 910 |   void operator=(bool OptionWasSpecified) { | 
 | 911 |     if (OptionWasSpecified) { | 
 | 912 |       std::cerr << "Low Level Virtual Machine (" << PACKAGE_NAME << ") "  | 
 | 913 |         << PACKAGE_VERSION << " (see http://llvm.org/)\n"; | 
 | 914 |       exit(1); | 
 | 915 |     } | 
 | 916 |   } | 
 | 917 | }; | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 918 |  | 
 | 919 |  | 
 | 920 | // Define the two HelpPrinter instances that are used to print out help, or | 
 | 921 | // help-hidden... | 
 | 922 | // | 
 | 923 | HelpPrinter NormalPrinter(false); | 
 | 924 | HelpPrinter HiddenPrinter(true); | 
 | 925 |  | 
 | 926 | cl::opt<HelpPrinter, true, parser<bool> >  | 
 | 927 | HOp("help", cl::desc("display available options (--help-hidden for more)"), | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 928 |     cl::location(NormalPrinter), cl::ValueDisallowed); | 
| Chris Lattner | 331de23 | 2002-07-22 02:07:59 +0000 | [diff] [blame] | 929 |  | 
 | 930 | cl::opt<HelpPrinter, true, parser<bool> > | 
 | 931 | HHOp("help-hidden", cl::desc("display all available options"), | 
| Chris Lattner | 9b14eb5 | 2002-08-07 18:36:37 +0000 | [diff] [blame] | 932 |      cl::location(HiddenPrinter), cl::Hidden, cl::ValueDisallowed); | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 933 |  | 
| Reid Spencer | 69105f3 | 2004-08-04 00:36:06 +0000 | [diff] [blame] | 934 | // Define the --version option that prints out the LLVM version for the tool | 
 | 935 | VersionPrinter VersionPrinterInstance; | 
 | 936 | cl::opt<VersionPrinter, true, parser<bool> > | 
 | 937 | VersOp("version", cl::desc("display the version"),  | 
 | 938 |     cl::location(VersionPrinterInstance), cl::ValueDisallowed); | 
 | 939 |  | 
| Chris Lattner | dbab15a | 2001-07-23 17:17:47 +0000 | [diff] [blame] | 940 | } // End anonymous namespace |