OptTable.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. //===--- OptTable.cpp - Option Table Implementation -----------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "clang/Driver/OptTable.h"
  10. #include "clang/Driver/Arg.h"
  11. #include "clang/Driver/ArgList.h"
  12. #include "clang/Driver/Option.h"
  13. #include "llvm/Support/raw_ostream.h"
  14. #include <algorithm>
  15. #include <cassert>
  16. #include <map>
  17. using namespace clang::driver;
  18. using namespace clang::driver::options;
  19. // Ordering on Info. The ordering is *almost* lexicographic, with two
  20. // exceptions. First, '\0' comes at the end of the alphabet instead of
  21. // the beginning (thus options preceed any other options which prefix
  22. // them). Second, for options with the same name, the less permissive
  23. // version should come first; a Flag option should preceed a Joined
  24. // option, for example.
  25. static int StrCmpOptionName(const char *A, const char *B) {
  26. char a = *A, b = *B;
  27. while (a == b) {
  28. if (a == '\0')
  29. return 0;
  30. a = *++A;
  31. b = *++B;
  32. }
  33. if (a == '\0') // A is a prefix of B.
  34. return 1;
  35. if (b == '\0') // B is a prefix of A.
  36. return -1;
  37. // Otherwise lexicographic.
  38. return (a < b) ? -1 : 1;
  39. }
  40. namespace clang {
  41. namespace driver {
  42. static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
  43. if (&A == &B)
  44. return false;
  45. if (int N = StrCmpOptionName(A.Name, B.Name))
  46. return N == -1;
  47. // Names are the same, check that classes are in order; exactly one
  48. // should be joined, and it should succeed the other.
  49. assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
  50. "Unexpected classes for options with same name.");
  51. return B.Kind == Option::JoinedClass;
  52. }
  53. // Support lower_bound between info and an option name.
  54. static inline bool operator<(const OptTable::Info &I, const char *Name) {
  55. return StrCmpOptionName(I.Name, Name) == -1;
  56. }
  57. static inline bool operator<(const char *Name, const OptTable::Info &I) {
  58. return StrCmpOptionName(Name, I.Name) == -1;
  59. }
  60. }
  61. }
  62. //
  63. OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
  64. //
  65. OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
  66. : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos),
  67. Options(new Option*[NumOptionInfos]),
  68. TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0)
  69. {
  70. // Explicitly zero initialize the error to work around a bug in array
  71. // value-initialization on MinGW with gcc 4.3.5.
  72. memset(Options, 0, sizeof(*Options) * NumOptionInfos);
  73. // Find start of normal options.
  74. for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
  75. unsigned Kind = getInfo(i + 1).Kind;
  76. if (Kind == Option::InputClass) {
  77. assert(!TheInputOption && "Cannot have multiple input options!");
  78. TheInputOption = getOption(i + 1);
  79. } else if (Kind == Option::UnknownClass) {
  80. assert(!TheUnknownOption && "Cannot have multiple input options!");
  81. TheUnknownOption = getOption(i + 1);
  82. } else if (Kind != Option::GroupClass) {
  83. FirstSearchableIndex = i;
  84. break;
  85. }
  86. }
  87. assert(FirstSearchableIndex != 0 && "No searchable options?");
  88. #ifndef NDEBUG
  89. // Check that everything after the first searchable option is a
  90. // regular option class.
  91. for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
  92. Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
  93. assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
  94. Kind != Option::GroupClass) &&
  95. "Special options should be defined first!");
  96. }
  97. // Check that options are in order.
  98. for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
  99. if (!(getInfo(i) < getInfo(i + 1))) {
  100. getOption(i)->dump();
  101. getOption(i + 1)->dump();
  102. assert(0 && "Options are not in order!");
  103. }
  104. }
  105. #endif
  106. }
  107. OptTable::~OptTable() {
  108. for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
  109. delete Options[i];
  110. delete[] Options;
  111. }
  112. Option *OptTable::CreateOption(unsigned id) const {
  113. const Info &info = getInfo(id);
  114. const OptionGroup *Group =
  115. cast_or_null<OptionGroup>(getOption(info.GroupID));
  116. const Option *Alias = getOption(info.AliasID);
  117. Option *Opt = 0;
  118. switch (info.Kind) {
  119. case Option::InputClass:
  120. Opt = new InputOption(id); break;
  121. case Option::UnknownClass:
  122. Opt = new UnknownOption(id); break;
  123. case Option::GroupClass:
  124. Opt = new OptionGroup(id, info.Name, Group); break;
  125. case Option::FlagClass:
  126. Opt = new FlagOption(id, info.Name, Group, Alias); break;
  127. case Option::JoinedClass:
  128. Opt = new JoinedOption(id, info.Name, Group, Alias); break;
  129. case Option::SeparateClass:
  130. Opt = new SeparateOption(id, info.Name, Group, Alias); break;
  131. case Option::CommaJoinedClass:
  132. Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break;
  133. case Option::MultiArgClass:
  134. Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break;
  135. case Option::JoinedOrSeparateClass:
  136. Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break;
  137. case Option::JoinedAndSeparateClass:
  138. Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
  139. }
  140. if (info.Flags & DriverOption)
  141. Opt->setDriverOption(true);
  142. if (info.Flags & LinkerInput)
  143. Opt->setLinkerInput(true);
  144. if (info.Flags & NoArgumentUnused)
  145. Opt->setNoArgumentUnused(true);
  146. if (info.Flags & NoForward)
  147. Opt->setNoForward(true);
  148. if (info.Flags & RenderAsInput)
  149. Opt->setNoOptAsInput(true);
  150. if (info.Flags & RenderJoined) {
  151. assert((info.Kind == Option::JoinedOrSeparateClass ||
  152. info.Kind == Option::SeparateClass) && "Invalid option.");
  153. Opt->setRenderStyle(Option::RenderJoinedStyle);
  154. }
  155. if (info.Flags & RenderSeparate) {
  156. assert((info.Kind == Option::JoinedOrSeparateClass ||
  157. info.Kind == Option::JoinedClass) && "Invalid option.");
  158. Opt->setRenderStyle(Option::RenderSeparateStyle);
  159. }
  160. if (info.Flags & Unsupported)
  161. Opt->setUnsupported(true);
  162. return Opt;
  163. }
  164. Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const {
  165. unsigned Prev = Index;
  166. const char *Str = Args.getArgString(Index);
  167. // Anything that doesn't start with '-' is an input, as is '-' itself.
  168. if (Str[0] != '-' || Str[1] == '\0')
  169. return new Arg(TheInputOption, Index++, Str);
  170. const Info *Start = OptionInfos + FirstSearchableIndex;
  171. const Info *End = OptionInfos + getNumOptions();
  172. // Search for the first next option which could be a prefix.
  173. Start = std::lower_bound(Start, End, Str);
  174. // Options are stored in sorted order, with '\0' at the end of the
  175. // alphabet. Since the only options which can accept a string must
  176. // prefix it, we iteratively search for the next option which could
  177. // be a prefix.
  178. //
  179. // FIXME: This is searching much more than necessary, but I am
  180. // blanking on the simplest way to make it fast. We can solve this
  181. // problem when we move to TableGen.
  182. for (; Start != End; ++Start) {
  183. // Scan for first option which is a proper prefix.
  184. for (; Start != End; ++Start)
  185. if (memcmp(Str, Start->Name, strlen(Start->Name)) == 0)
  186. break;
  187. if (Start == End)
  188. break;
  189. // See if this option matches.
  190. if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index))
  191. return A;
  192. // Otherwise, see if this argument was missing values.
  193. if (Prev != Index)
  194. return 0;
  195. }
  196. return new Arg(TheUnknownOption, Index++, Str);
  197. }
  198. InputArgList *OptTable::ParseArgs(const char* const *ArgBegin,
  199. const char* const *ArgEnd,
  200. unsigned &MissingArgIndex,
  201. unsigned &MissingArgCount) const {
  202. InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
  203. // FIXME: Handle '@' args (or at least error on them).
  204. MissingArgIndex = MissingArgCount = 0;
  205. unsigned Index = 0, End = ArgEnd - ArgBegin;
  206. while (Index < End) {
  207. // Ignore empty arguments (other things may still take them as arguments).
  208. if (Args->getArgString(Index)[0] == '\0') {
  209. ++Index;
  210. continue;
  211. }
  212. unsigned Prev = Index;
  213. Arg *A = ParseOneArg(*Args, Index);
  214. assert(Index > Prev && "Parser failed to consume argument.");
  215. // Check for missing argument error.
  216. if (!A) {
  217. assert(Index >= End && "Unexpected parser error.");
  218. assert(Index - Prev - 1 && "No missing arguments!");
  219. MissingArgIndex = Prev;
  220. MissingArgCount = Index - Prev - 1;
  221. break;
  222. }
  223. Args->append(A);
  224. }
  225. return Args;
  226. }
  227. static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
  228. std::string Name = Opts.getOptionName(Id);
  229. // Add metavar, if used.
  230. switch (Opts.getOptionKind(Id)) {
  231. case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
  232. assert(0 && "Invalid option with help text.");
  233. case Option::MultiArgClass:
  234. assert(0 && "Cannot print metavar for this kind of option.");
  235. case Option::FlagClass:
  236. break;
  237. case Option::SeparateClass: case Option::JoinedOrSeparateClass:
  238. Name += ' ';
  239. // FALLTHROUGH
  240. case Option::JoinedClass: case Option::CommaJoinedClass:
  241. case Option::JoinedAndSeparateClass:
  242. if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
  243. Name += MetaVarName;
  244. else
  245. Name += "<value>";
  246. break;
  247. }
  248. return Name;
  249. }
  250. static void PrintHelpOptionList(llvm::raw_ostream &OS, llvm::StringRef Title,
  251. std::vector<std::pair<std::string,
  252. const char*> > &OptionHelp) {
  253. OS << Title << ":\n";
  254. // Find the maximum option length.
  255. unsigned OptionFieldWidth = 0;
  256. for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
  257. // Skip titles.
  258. if (!OptionHelp[i].second)
  259. continue;
  260. // Limit the amount of padding we are willing to give up for alignment.
  261. unsigned Length = OptionHelp[i].first.size();
  262. if (Length <= 23)
  263. OptionFieldWidth = std::max(OptionFieldWidth, Length);
  264. }
  265. const unsigned InitialPad = 2;
  266. for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
  267. const std::string &Option = OptionHelp[i].first;
  268. int Pad = OptionFieldWidth - int(Option.size());
  269. OS.indent(InitialPad) << Option;
  270. // Break on long option names.
  271. if (Pad < 0) {
  272. OS << "\n";
  273. Pad = OptionFieldWidth + InitialPad;
  274. }
  275. OS.indent(Pad + 1) << OptionHelp[i].second << '\n';
  276. }
  277. }
  278. static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
  279. unsigned GroupID = Opts.getOptionGroupID(Id);
  280. // If not in a group, return the default help group.
  281. if (!GroupID)
  282. return "OPTIONS";
  283. // Abuse the help text of the option groups to store the "help group"
  284. // name.
  285. //
  286. // FIXME: Split out option groups.
  287. if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
  288. return GroupHelp;
  289. // Otherwise keep looking.
  290. return getOptionHelpGroup(Opts, GroupID);
  291. }
  292. void OptTable::PrintHelp(llvm::raw_ostream &OS, const char *Name,
  293. const char *Title, bool ShowHidden) const {
  294. OS << "OVERVIEW: " << Title << "\n";
  295. OS << '\n';
  296. OS << "USAGE: " << Name << " [options] <inputs>\n";
  297. OS << '\n';
  298. // Render help text into a map of group-name to a list of (option, help)
  299. // pairs.
  300. typedef std::map<std::string,
  301. std::vector<std::pair<std::string, const char*> > > helpmap_ty;
  302. helpmap_ty GroupedOptionHelp;
  303. for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
  304. unsigned Id = i + 1;
  305. // FIXME: Split out option groups.
  306. if (getOptionKind(Id) == Option::GroupClass)
  307. continue;
  308. if (!ShowHidden && isOptionHelpHidden(Id))
  309. continue;
  310. if (const char *Text = getOptionHelpText(Id)) {
  311. const char *HelpGroup = getOptionHelpGroup(*this, Id);
  312. const std::string &OptName = getOptionHelpName(*this, Id);
  313. GroupedOptionHelp[HelpGroup].push_back(std::make_pair(OptName, Text));
  314. }
  315. }
  316. for (helpmap_ty::iterator it = GroupedOptionHelp .begin(),
  317. ie = GroupedOptionHelp.end(); it != ie; ++it) {
  318. if (it != GroupedOptionHelp .begin())
  319. OS << "\n";
  320. PrintHelpOptionList(OS, it->first, it->second);
  321. }
  322. OS.flush();
  323. }