138 lines · cpp
1#include "llvm/ADT/ArrayRef.h"2#include "llvm/ADT/StringRef.h"3#include "llvm/Option/ArgList.h"4#include "llvm/Option/OptTable.h"5#include "llvm/Support/Error.h"6#include "llvm/Support/InitLLVM.h"7#include "llvm/Support/raw_ostream.h"8 9using namespace llvm;10using namespace llvm::opt;11 12namespace {13enum ID {14 OPT_INVALID = 0,15#define OPTION(PREFIXES, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \16 VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, \17 VALUES, SUBCOMMANDIDS_OFFSET) \18 OPT_##ID,19#include "Opts.inc"20#undef OPTION21};22#define OPTTABLE_STR_TABLE_CODE23#include "Opts.inc"24#undef OPTTABLE_STR_TABLE_CODE25 26#define OPTTABLE_PREFIXES_TABLE_CODE27#include "Opts.inc"28#undef OPTTABLE_PREFIXES_TABLE_CODE29 30#define OPTTABLE_SUBCOMMAND_IDS_TABLE_CODE31#include "Opts.inc"32#undef OPTTABLE_SUBCOMMAND_IDS_TABLE_CODE33 34#define OPTTABLE_SUBCOMMANDS_CODE35#include "Opts.inc"36#undef OPTTABLE_SUBCOMMANDS_CODE37 38static constexpr OptTable::Info InfoTable[] = {39#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),40#include "Opts.inc"41#undef OPTION42};43 44class HelloSubOptTable : public GenericOptTable {45public:46 HelloSubOptTable()47 : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable,48 /*IgnoreCase=*/false, OptionSubCommands,49 OptionSubCommandIDsTable) {};50};51} // namespace52 53int main(int argc, char **argv) {54 InitLLVM X(argc, argv);55 HelloSubOptTable T;56 unsigned MissingArgIndex, MissingArgCount;57 58 auto HandleMultipleSubcommands = [](ArrayRef<StringRef> SubCommands) {59 assert(SubCommands.size() > 1);60 llvm::errs() << "error: more than one subcommand passed [\n";61 for (auto SC : SubCommands)62 llvm::errs() << " `" << SC << "`\n";63 llvm::errs() << "]\n";64 llvm::errs() << "See --help.\n";65 exit(1);66 };67 68 auto HandleOtherPositionals = [](ArrayRef<StringRef> Positionals) {69 assert(!Positionals.empty());70 llvm::errs() << "error: unknown positional argument(s) [\n";71 for (auto SC : Positionals)72 llvm::errs() << " `" << SC << "`\n";73 llvm::errs() << "]\n";74 llvm::errs() << "See --help.\n";75 exit(1);76 };77 78 InputArgList Args = T.ParseArgs(ArrayRef(argv + 1, argc - 1), MissingArgIndex,79 MissingArgCount);80 81 StringRef SubCommand = Args.getSubCommand(82 T.getSubCommands(), HandleMultipleSubcommands, HandleOtherPositionals);83 // Handle help. When help options is found, ignore all other options and exit84 // after printing help.85 86 if (Args.hasArg(OPT_help)) {87 T.printHelp(llvm::outs(), "llvm-hello-sub [subcommand] [options]",88 "LLVM Hello SubCommand Example", false, false, Visibility(),89 SubCommand);90 return 0;91 }92 93 auto HandleSubCommandArg = [&](ID OptionType) {94 if (!Args.hasArg(OptionType))95 return false;96 auto O = T.getOption(OptionType);97 if (!O.isRegisteredSC(SubCommand)) {98 llvm::errs() << "Option [" << O.getName()99 << "] is not valid for SubCommand [" << SubCommand << "]\n";100 return false;101 }102 return true;103 };104 105 bool HasUnknownOptions = false;106 for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {107 HasUnknownOptions = true;108 llvm::errs() << "Unknown option `" << A->getAsString(Args) << "'\n";109 }110 if (HasUnknownOptions) {111 llvm::errs() << "See `OptSubcommand --help`.\n";112 return 1;113 }114 if (SubCommand.empty()) {115 if (Args.hasArg(OPT_version))116 llvm::outs() << "LLVM Hello SubCommand Example 1.0\n";117 } else if (SubCommand == "foo") {118 if (HandleSubCommandArg(OPT_uppercase))119 llvm::outs() << "FOO\n";120 else if (HandleSubCommandArg(OPT_lowercase))121 llvm::outs() << "foo\n";122 123 if (HandleSubCommandArg(OPT_version))124 llvm::outs() << "LLVM Hello SubCommand foo Example 1.0\n";125 126 } else if (SubCommand == "bar") {127 if (HandleSubCommandArg(OPT_lowercase))128 llvm::outs() << "bar\n";129 else if (HandleSubCommandArg(OPT_uppercase))130 llvm::outs() << "BAR\n";131 132 if (HandleSubCommandArg(OPT_version))133 llvm::outs() << "LLVM Hello SubCommand bar Example 1.0\n";134 }135 136 return 0;137}138