llvm.org GIT mirror llvm / 9878d6a
rearchitect the registration mechanism used by the command line option stuff. This dramatically reduce the amount of memory allocated by the commandline stuff at static init time, changing it to build local data structures when ParseCommandLineOptions is called. In a dummy empty program that links some llvm libraries, this reduces the number of malloc'd bytes from 4864 to 3360 on entry to main. Most of that memory is now allocated by non-commandline related stuff. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35701 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 13 years ago
3 changed file(s) with 127 addition(s) and 91 deletion(s). Raw diff Collapse all Expand all
141141 virtual enum ValueExpected getValueExpectedFlagDefault() const {
142142 return ValueOptional;
143143 }
144
144145 // Out of line virtual function to provide home for the class.
145146 virtual void anchor();
146147
147 int NumOccurrences; // The number of times specified
148 int Flags; // Flags for the argument
149 unsigned Position; // Position of last occurrence of the option
150 public:
151 const char *ArgStr; // The argument string itself (ex: "help", "o")
152 const char *HelpStr; // The descriptive text message for --help
153 const char *ValueStr; // String describing what the value of this option is
148 int NumOccurrences; // The number of times specified
149 int Flags; // Flags for the argument
150 unsigned Position; // Position of last occurrence of the option
151 Option *NextRegistered; // Singly linked list of registered options.
152 public:
153 const char *ArgStr; // The argument string itself (ex: "help", "o")
154 const char *HelpStr; // The descriptive text message for --help
155 const char *ValueStr; // String describing what the value of this option is
154156
155157 inline enum NumOccurrences getNumOccurrencesFlag() const {
156158 return static_cast(Flags & OccurrencesMask);
197199 protected:
198200 Option(unsigned DefaultFlags)
199201 : NumOccurrences(0), Flags(DefaultFlags | NormalFormatting), Position(0),
200 ArgStr(""), HelpStr(""), ValueStr("") {
202 NextRegistered(0), ArgStr(""), HelpStr(""), ValueStr("") {
201203 assert(getNumOccurrencesFlag() != 0 &&
202204 getOptionHiddenFlag() != 0 && "Not all default flags specified!");
203205 }
204206
205207 public:
206 // addArgument - Tell the system that this Option subclass will handle all
207 // occurrences of -ArgStr on the command line.
208 // addArgument - Register this argument with the commandline system.
208209 //
209 void addArgument(const char *ArgStr);
210 void addArgument();
211
212 Option *getNextRegisteredOption() const { return NextRegistered; }
210213
211214 // Return the width of the option tag for printing...
212215 virtual unsigned getOptionWidth() const = 0;
216219 //
217220 virtual void printOptionInfo(unsigned GlobalWidth) const = 0;
218221
222 virtual void getExtraOptionNames(std::vector &OptionNames) {}
223
219224 // addOccurrence - Wrapper around handleOccurrence that enforces Flags
220225 //
221226 bool addOccurrence(unsigned pos, const char *ArgName,
378383 // argstr field should be stable, copy it down now.
379384 //
380385 hasArgStr = O.hasArgStr();
381
386 }
387
388 void getExtraOptionNames(std::vector &OptionNames) {
382389 // If there has been no argstr specified, that means that we need to add an
383390 // argument for every possible option. This ensures that our options are
384391 // vectored to us.
385 //
386392 if (!hasArgStr)
387393 for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
388 O.addArgument(getOption(i));
389 }
394 OptionNames.push_back(getOption(i));
395 }
396
390397
391398 enum ValueExpected getValueExpectedFlagDefault() const {
392399 // If there is an ArgStr specified, then we are of the form:
482489 return ValueRequired;
483490 }
484491
492 void getExtraOptionNames(std::vector &OptionNames) {}
493
485494 void initialize(Option &O) {}
486495
487496 // Return the width of the option tag for printing...
771780 virtual enum ValueExpected getValueExpectedFlagDefault() const {
772781 return Parser.getValueExpectedFlagDefault();
773782 }
783 virtual void getExtraOptionNames(std::vector &OptionNames) {
784 return Parser.getExtraOptionNames(OptionNames);
785 }
774786
775787 // Forward printing stuff to the parser...
776788 virtual unsigned getOptionWidth() const {return Parser.getOptionWidth(*this);}
779791 }
780792
781793 void done() {
782 addArgument(ArgStr);
794 addArgument();
783795 Parser.initialize(*this);
784796 }
785797 public:
922934 virtual enum ValueExpected getValueExpectedFlagDefault() const {
923935 return Parser.getValueExpectedFlagDefault();
924936 }
925
937 virtual void getExtraOptionNames(std::vector &OptionNames) {
938 return Parser.getExtraOptionNames(OptionNames);
939 }
940
926941 virtual bool handleOccurrence(unsigned pos, const char *ArgName,
927942 const std::string &Arg) {
928943 typename ParserClass::parser_data_type Val =
942957 }
943958
944959 void done() {
945 addArgument(ArgStr);
960 addArgument();
946961 Parser.initialize(*this);
947962 }
948963 public:
11051120 virtual enum ValueExpected getValueExpectedFlagDefault() const {
11061121 return Parser.getValueExpectedFlagDefault();
11071122 }
1108
1123 virtual void getExtraOptionNames(std::vector &OptionNames) {
1124 return Parser.getExtraOptionNames(OptionNames);
1125 }
1126
11091127 virtual bool handleOccurrence(unsigned pos, const char *ArgName,
11101128 const std::string &Arg) {
11111129 typename ParserClass::parser_data_type Val =
11251143 }
11261144
11271145 void done() {
1128 addArgument(ArgStr);
1146 addArgument();
11291147 Parser.initialize(*this);
11301148 }
11311149 public:
12201238 error(": cl::alias must have argument name specified!");
12211239 if (AliasFor == 0)
12221240 error(": cl::alias must have an cl::aliasopt(option) specified!");
1223 addArgument(ArgStr);
1241 addArgument();
12241242 }
12251243 public:
12261244 void setAliasFor(Option &O) {
6969 abort();
7070 }
7171 addLiteralOption(P->getPassArgument(), P, P->getPassName());
72 Opt->addArgument(P->getPassArgument());
7372 }
7473 virtual void passEnumerate(const PassInfo *P) { passRegistered(P); }
7574
7070 MoreHelp->push_back(Help);
7171 }
7272
73 /// RegisteredOptionList - This is the list of the command line options that
74 /// have statically constructed themselves.
75 static Option *RegisteredOptionList = 0;
76
77 void Option::addArgument() {
78 assert(NextRegistered == 0 && "argument multiply registered!");
79
80 NextRegistered = RegisteredOptionList;
81 RegisteredOptionList = this;
82 }
83
7384 //===----------------------------------------------------------------------===//
7485 // Basic, shared command line option processing machinery.
7586 //
7687
77 static ManagedStatic > OptionsMap;
78 static ManagedStatic > PositionalOptions;
79
80 static Option *getOption(const std::string &Str) {
81 std::map::iterator I = OptionsMap->find(Str);
82 return I != OptionsMap->end() ? I->second : 0;
83 }
84
85 static void AddArgument(const char *ArgName, Option *Opt) {
86 if (getOption(ArgName)) {
87 cerr << ProgramName << ": CommandLine Error: Argument '"
88 << ArgName << "' defined more than once!\n";
89 } else {
90 // Add argument to the argument map!
91 (*OptionsMap)[ArgName] = Opt;
92 }
93 }
88 /// GetOptionInfo - Scan the list of registered options, turning them into data
89 /// structures that are easier to handle.
90 static void GetOptionInfo(std::vector &PositionalOpts,
91 std::map &OptionsMap) {
92 std::vector OptionNames;
93 for (Option *O = RegisteredOptionList; O; O = O->getNextRegisteredOption()) {
94 // If this option wants to handle multiple option names, get the full set.
95 // This handles enum options like "-O1 -O2" etc.
96 O->getExtraOptionNames(OptionNames);
97 if (O->ArgStr[0])
98 OptionNames.push_back(O->ArgStr);
99
100 // Handle named options.
101 for (unsigned i = 0, e = OptionNames.size(); i != e; ++i) {
102 // Add argument to the argument map!
103 if (!OptionsMap.insert(std::pair(OptionNames[i],
104 O)).second) {
105 cerr << ProgramName << ": CommandLine Error: Argument '"
106 << OptionNames[0] << "' defined more than once!\n";
107 }
108 }
109
110 OptionNames.clear();
111
112 // Remember information about positional options.
113 if (O->getFormattingFlag() == cl::Positional)
114 PositionalOpts.push_back(O);
115 else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) {
116 if (!PositionalOpts.empty() &&
117 PositionalOpts.front()->getNumOccurrencesFlag() == cl::ConsumeAfter)
118 O->error("Cannot specify more than one option with cl::ConsumeAfter!");
119 PositionalOpts.insert(PositionalOpts.begin(), O);
120 }
121 }
122 }
123
94124
95125 /// LookupOption - Lookup the option specified by the specified option on the
96126 /// command line. If there is a value specified (after an equal sign) return
97127 /// that as well.
98 static Option *LookupOption(const char *&Arg, const char *&Value) {
128 static Option *LookupOption(const char *&Arg, const char *&Value,
129 std::map &OptionsMap) {
99130 while (*Arg == '-') ++Arg; // Eat leading dashes
100131
101132 const char *ArgEnd = Arg;
109140 if (*Arg == 0) return 0;
110141
111142 // Look up the option.
112 std::map &Opts = *OptionsMap;
113143 std::map::iterator I =
114 Opts.find(std::string(Arg, ArgEnd));
115 return (I != Opts.end()) ? I->second : 0;
144 OptionsMap.find(std::string(Arg, ArgEnd));
145 return I != OptionsMap.end() ? I->second : 0;
116146 }
117147
118148 static inline bool ProvideOption(Option *Handler, const char *ArgName,
170200 // otherwise return null.
171201 //
172202 static Option *getOptionPred(std::string Name, unsigned &Length,
173 bool (*Pred)(const Option*)) {
174
175 Option *Op = getOption(Name);
176 if (Op && Pred(Op)) {
203 bool (*Pred)(const Option*),
204 std::map &OptionsMap) {
205
206 std::map::iterator OMI = OptionsMap.find(Name);
207 if (OMI != OptionsMap.end() && Pred(OMI->second)) {
177208 Length = Name.length();
178 return Op;
209 return OMI->second;
179210 }
180211
181212 if (Name.size() == 1) return 0;
182213 do {
183214 Name.erase(Name.end()-1, Name.end()); // Chop off the last character...
184 Op = getOption(Name);
215 OMI = OptionsMap.find(Name);
185216
186217 // Loop while we haven't found an option and Name still has at least two
187218 // characters in it (so that the next iteration will not be the empty
188219 // string...
189 } while ((Op == 0 || !Pred(Op)) && Name.size() > 1);
190
191 if (Op && Pred(Op)) {
220 } while ((OMI == OptionsMap.end() || !Pred(OMI->second)) && Name.size() > 1);
221
222 if (OMI != OptionsMap.end() && Pred(OMI->second)) {
192223 Length = Name.length();
193 return Op; // Found one!
224 return OMI->second; // Found one!
194225 }
195226 return 0; // No option found!
196227 }
285316
286317 void cl::ParseCommandLineOptions(int &argc, char **argv,
287318 const char *Overview) {
288 assert((!OptionsMap->empty() || !PositionalOptions->empty()) &&
289 "No options specified, or ParseCommandLineOptions called more"
290 " than once!");
319 // Process all registered options.
320 std::vector PositionalOpts;
321 std::map Opts;
322 GetOptionInfo(PositionalOpts, Opts);
323
324 assert((!Opts.empty() || !PositionalOpts.empty()) &&
325 "No options specified!");
291326 sys::Path progname(argv[0]);
292327
293328 // Copy the program name into ProgName, making sure not to overflow it.
297332
298333 ProgramOverview = Overview;
299334 bool ErrorParsing = false;
300
301 std::map &Opts = *OptionsMap;
302 std::vector &PositionalOpts = *PositionalOptions;
303335
304336 // Check out the positional arguments to collect information about them.
305337 unsigned NumPositionalRequired = 0;
397429 // option is another positional argument. If so, treat it as an argument,
398430 // otherwise feed it to the eating positional.
399431 ArgName = argv[i]+1;
400 Handler = LookupOption(ArgName, Value);
432 Handler = LookupOption(ArgName, Value, Opts);
401433 if (!Handler || Handler->getFormattingFlag() != cl::Positional) {
402434 ProvidePositionalOption(ActivePositionalArg, argv[i], i);
403435 continue; // We are done!
405437
406438 } else { // We start with a '-', must be an argument...
407439 ArgName = argv[i]+1;
408 Handler = LookupOption(ArgName, Value);
440 Handler = LookupOption(ArgName, Value, Opts);
409441
410442 // Check to see if this "option" is really a prefixed or grouped argument.
411443 if (Handler == 0) {
412444 std::string RealName(ArgName);
413445 if (RealName.size() > 1) {
414446 unsigned Length = 0;
415 Option *PGOpt = getOptionPred(RealName, Length, isPrefixedOrGrouping);
447 Option *PGOpt = getOptionPred(RealName, Length, isPrefixedOrGrouping,
448 Opts);
416449
417450 // If the option is a prefixed option, then the value is simply the
418451 // rest of the name... so fall through to later processing, by
443476 0, 0, 0, Dummy);
444477
445478 // Get the next grouping option...
446 PGOpt = getOptionPred(RealName, Length, isGrouping);
479 PGOpt = getOptionPred(RealName, Length, isGrouping, Opts);
447480 } while (PGOpt && Length != RealName.size());
448481
449482 Handler = PGOpt; // Ate all of the options.
632665 return handleOccurrence(pos, ArgName, Value);
633666 }
634667
635 // addArgument - Tell the system that this Option subclass will handle all
636 // occurrences of -ArgStr on the command line.
637 //
638 void Option::addArgument(const char *ArgStr) {
639 if (ArgStr[0])
640 AddArgument(ArgStr, this);
641
642 if (getFormattingFlag() == Positional)
643 PositionalOptions->push_back(this);
644 else if (getNumOccurrencesFlag() == ConsumeAfter) {
645 if (!PositionalOptions->empty() &&
646 PositionalOptions->front()->getNumOccurrencesFlag() == ConsumeAfter)
647 error("Cannot specify more than one option with cl::ConsumeAfter!");
648 PositionalOptions->insert(PositionalOptions->begin(), this);
649 }
650 }
651
652668
653669 // getValueStr - Get the value description string, using "DefaultMsg" if nothing
654670 // has been specified yet.
866882 void operator=(bool Value) {
867883 if (Value == false) return;
868884
885 // Get all the options.
886 std::vector PositionalOpts;
887 std::map OptMap;
888 GetOptionInfo(PositionalOpts, OptMap);
889
869890 // Copy Options into a vector so we can sort them as we like...
870891 std::vector > Opts;
871 copy(OptionsMap->begin(), OptionsMap->end(), std::back_inserter(Opts));
892 copy(OptMap.begin(), OptMap.end(), std::back_inserter(Opts));
872893
873894 // Eliminate Hidden or ReallyHidden arguments, depending on ShowHidden
874895 Opts.erase(std::remove_if(Opts.begin(), Opts.end(),
891912 cout << "USAGE: " << ProgramName << " [options]";
892913
893914 // Print out the positional options.
894 std::vector &PosOpts = *PositionalOptions;
895915 Option *CAOpt = 0; // The cl::ConsumeAfter option, if it exists...
896 if (!PosOpts.empty() && PosOpts[0]->getNumOccurrencesFlag() == ConsumeAfter)
897 CAOpt = PosOpts[0];
898
899 for (unsigned i = CAOpt != 0, e = PosOpts.size(); i != e; ++i) {
900 if (PosOpts[i]->ArgStr[0])
901 cout << " --" << PosOpts[i]->ArgStr;
902 cout << " " << PosOpts[i]->HelpStr;
916 if (!PositionalOpts.empty() &&
917 PositionalOpts[0]->getNumOccurrencesFlag() == ConsumeAfter)
918 CAOpt = PositionalOpts[0];
919
920 for (unsigned i = CAOpt != 0, e = PositionalOpts.size(); i != e; ++i) {
921 if (PositionalOpts[i]->ArgStr[0])
922 cout << " --" << PositionalOpts[i]->ArgStr;
923 cout << " " << PositionalOpts[i]->HelpStr;
903924 }
904925
905926 // Print the consume after option info if it exists...
923944 MoreHelp->clear();
924945
925946 // Halt the program since help information was printed
926 OptionsMap->clear(); // Don't bother making option dtors remove from map.
927947 exit(1);
928948 }
929949 };
969989 if (OptionWasSpecified) {
970990 if (OverrideVersionPrinter == 0) {
971991 print();
972 OptionsMap->clear();// Don't bother making option dtors remove from map.
973992 exit(1);
974993 } else {
975994 (*OverrideVersionPrinter)();