]> granicus.if.org Git - clang/commitdiff
Add OptTable::PrintHelp.
authorDaniel Dunbar <daniel@zuster.org>
Thu, 3 Dec 2009 07:01:38 +0000 (07:01 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 3 Dec 2009 07:01:38 +0000 (07:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90420 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Driver/OptTable.h
lib/Driver/Driver.cpp
lib/Driver/OptTable.cpp

index faaeba69e2e6d25055d811b90cf0e288a02d6bae..ff2e108609c09e3b905a75e0270f7dd29ee83623 100644 (file)
 #include "clang/Driver/OptSpecifier.h"
 #include <cassert>
 
+namespace llvm {
+  class raw_ostream;
+}
+
 namespace clang {
 namespace driver {
 namespace options {
@@ -156,6 +160,14 @@ namespace options {
                             const char **ArgEnd,
                             unsigned &MissingArgIndex,
                             unsigned &MissingArgCount) const;
+
+    /// PrintHelp - Render the help text for an option table.
+    ///
+    /// \param OS - The stream to write the help text to.
+    /// \param Name - The name to use in the usage line.
+    /// \param Title - The title to use in the usage line.
+    void PrintHelp(llvm::raw_ostream &OS, const char *Name,
+                   const char *Title) const;
   };
 }
 }
index 87357cf08a3bad2ab337cd3fa9e3dc31060b2387..7c21594e6fe6b626c33c0499a2bca98d7a838c75 100644 (file)
@@ -312,6 +312,8 @@ static std::string getOptionHelpName(const OptTable &Opts, options::ID Id) {
   return Name;
 }
 
+// FIXME: Move -ccc options to real options in the .td file (or eliminate), and
+// then move to using OptTable::PrintHelp.
 void Driver::PrintHelp(bool ShowHidden) const {
   llvm::raw_ostream &OS = llvm::outs();
 
index f68a1d8db77c1c2a4b908e400f808055459f879b..fc89cef14ac18d1fe7c2b5252d0d49396a580415 100644 (file)
@@ -11,6 +11,7 @@
 #include "clang/Driver/Arg.h"
 #include "clang/Driver/ArgList.h"
 #include "clang/Driver/Option.h"
+#include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cassert>
 
@@ -255,3 +256,77 @@ InputArgList *OptTable::ParseArgs(const char **ArgBegin, const char **ArgEnd,
 
   return Args;
 }
+
+static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
+  std::string Name = Opts.getOptionName(Id);
+
+  // Add metavar, if used.
+  switch (Opts.getOptionKind(Id)) {
+  case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
+    assert(0 && "Invalid option with help text.");
+
+  case Option::MultiArgClass: case Option::JoinedAndSeparateClass:
+    assert(0 && "Cannot print metavar for this kind of option.");
+
+  case Option::FlagClass:
+    break;
+
+  case Option::SeparateClass: case Option::JoinedOrSeparateClass:
+    Name += ' ';
+    // FALLTHROUGH
+  case Option::JoinedClass: case Option::CommaJoinedClass:
+    if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
+      Name += MetaVarName;
+    else
+      Name += "<value>";
+    break;
+  }
+
+  return Name;
+}
+
+void OptTable::PrintHelp(llvm::raw_ostream &OS, const char *Name,
+                         const char *Title) const {
+  OS << "OVERVIEW: " << Title << "\n";
+  OS << '\n';
+  OS << "USAGE: " << Name << " [options] <inputs>\n";
+  OS << '\n';
+  OS << "OPTIONS:\n";
+
+  // Render help text into (option, help) pairs.
+  std::vector< std::pair<std::string, const char*> > OptionHelp;
+  for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+    unsigned Id = i + 1;
+    if (const char *Text = getOptionHelpText(Id))
+      OptionHelp.push_back(std::make_pair(getOptionHelpName(*this, Id), Text));
+  }
+
+  // Find the maximum option length.
+  unsigned OptionFieldWidth = 0;
+  for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
+    // Skip titles.
+    if (!OptionHelp[i].second)
+      continue;
+
+    // Limit the amount of padding we are willing to give up for alignment.
+    unsigned Length = OptionHelp[i].first.size();
+    if (Length <= 23)
+      OptionFieldWidth = std::max(OptionFieldWidth, Length);
+  }
+
+  const unsigned InitialPad = 2;
+  for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
+    const std::string &Option = OptionHelp[i].first;
+    int Pad = OptionFieldWidth - int(Option.size());
+    OS.indent(InitialPad) << Option;
+
+    // Break on long option names.
+    if (Pad < 0) {
+      OS << "\n";
+      Pad = OptionFieldWidth + InitialPad;
+    }
+    OS.indent(Pad + 1) << OptionHelp[i].second << '\n';
+  }
+
+  OS.flush();
+}