| #include "llvm/ADT/ArrayRef.h" | |
| #include "llvm/ADT/StringRef.h" | |
| #include "llvm/Option/ArgList.h" | |
| #include "llvm/Option/OptTable.h" | |
| #include "llvm/Support/Error.h" | |
| #include "llvm/Support/InitLLVM.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| using namespace llvm; | |
| using namespace llvm::opt; | |
| namespace { | |
| enum ID { | |
| OPT_INVALID = 0, | |
| #define OPTION(PREFIXES, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ | |
| VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, \ | |
| VALUES, SUBCOMMANDIDS_OFFSET) \ | |
| OPT_##ID, | |
| #include "Opts.inc" | |
| #undef OPTION | |
| }; | |
| #define OPTTABLE_CODE | |
| #include "Opts.inc" | |
| class HelloSubOptTable : public OptTable { | |
| public: | |
| HelloSubOptTable() : OptTable(optionTables()) {}; | |
| }; | |
| } // namespace | |
| int main(int argc, char **argv) { | |
| InitLLVM X(argc, argv); | |
| HelloSubOptTable T; | |
| unsigned MissingArgIndex, MissingArgCount; | |
| auto HandleMultipleSubcommands = [](ArrayRef<StringRef> SubCommands) { | |
| assert(SubCommands.size() > 1); | |
| llvm::errs() << "error: more than one subcommand passed [\n"; | |
| for (auto SC : SubCommands) | |
| llvm::errs() << " `" << SC << "`\n"; | |
| llvm::errs() << "]\n"; | |
| llvm::errs() << "See --help.\n"; | |
| exit(1); | |
| }; | |
| auto HandleOtherPositionals = [](ArrayRef<StringRef> Positionals) { | |
| assert(!Positionals.empty()); | |
| llvm::errs() << "error: unknown positional argument(s) [\n"; | |
| for (auto SC : Positionals) | |
| llvm::errs() << " `" << SC << "`\n"; | |
| llvm::errs() << "]\n"; | |
| llvm::errs() << "See --help.\n"; | |
| exit(1); | |
| }; | |
| InputArgList Args = T.ParseArgs(ArrayRef(argv + 1, argc - 1), MissingArgIndex, | |
| MissingArgCount); | |
| StringRef SubCommand = Args.getSubCommand( | |
| T.getSubCommands(), HandleMultipleSubcommands, HandleOtherPositionals); | |
| // Handle help. When help options is found, ignore all other options and exit | |
| // after printing help. | |
| if (Args.hasArg(OPT_help)) { | |
| T.printHelp(llvm::outs(), "llvm-hello-sub [subcommand] [options]", | |
| "LLVM Hello SubCommand Example", false, false, Visibility(), | |
| SubCommand); | |
| return 0; | |
| } | |
| auto HandleSubCommandArg = [&](ID OptionType) { | |
| if (!Args.hasArg(OptionType)) | |
| return false; | |
| auto O = T.getOption(OptionType); | |
| if (!O.isRegisteredSC(SubCommand)) { | |
| llvm::errs() << "Option [" << O.getName() | |
| << "] is not valid for SubCommand [" << SubCommand << "]\n"; | |
| return false; | |
| } | |
| return true; | |
| }; | |
| bool HasUnknownOptions = false; | |
| for (const Arg *A : Args.filtered(OPT_UNKNOWN)) { | |
| HasUnknownOptions = true; | |
| llvm::errs() << "Unknown option `" << A->getAsString(Args) << "'\n"; | |
| } | |
| if (HasUnknownOptions) { | |
| llvm::errs() << "See `OptSubcommand --help`.\n"; | |
| return 1; | |
| } | |
| if (SubCommand.empty()) { | |
| if (Args.hasArg(OPT_version)) | |
| llvm::outs() << "LLVM Hello SubCommand Example 1.0\n"; | |
| } else if (SubCommand == "foo") { | |
| if (HandleSubCommandArg(OPT_uppercase)) | |
| llvm::outs() << "FOO\n"; | |
| else if (HandleSubCommandArg(OPT_lowercase)) | |
| llvm::outs() << "foo\n"; | |
| if (HandleSubCommandArg(OPT_version)) | |
| llvm::outs() << "LLVM Hello SubCommand foo Example 1.0\n"; | |
| } else if (SubCommand == "bar") { | |
| if (HandleSubCommandArg(OPT_lowercase)) | |
| llvm::outs() << "bar\n"; | |
| else if (HandleSubCommandArg(OPT_uppercase)) | |
| llvm::outs() << "BAR\n"; | |
| if (HandleSubCommandArg(OPT_version)) | |
| llvm::outs() << "LLVM Hello SubCommand bar Example 1.0\n"; | |
| } | |
| return 0; | |
| } |