Remove the default clause from a fully-covering switch
[llvm-core.git] / tools / llvm-rc / llvm-rc.cpp
blob9446b11a507d410a9ec3592e8ce7dc00266d13b5
1 //===-- llvm-rc.cpp - Compile .rc scripts into .res -------------*- C++ -*-===//
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 //
10 // Compile .rc scripts into .res files. This is intended to be a
11 // platform-independent port of Microsoft's rc.exe tool.
13 //===----------------------------------------------------------------------===//
15 #include "ResourceScriptToken.h"
16 #include "ResourceScriptParser.h"
18 #include "llvm/Option/Arg.h"
19 #include "llvm/Option/ArgList.h"
20 #include "llvm/Support/Error.h"
21 #include "llvm/Support/ManagedStatic.h"
22 #include "llvm/Support/PrettyStackTrace.h"
23 #include "llvm/Support/Process.h"
24 #include "llvm/Support/Signals.h"
25 #include "llvm/Support/raw_ostream.h"
27 #include <system_error>
29 using namespace llvm;
31 namespace {
33 // Input options tables.
35 enum ID {
36 OPT_INVALID = 0, // This is not a correct option ID.
37 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
38 HELPTEXT, METAVAR, VALUES) \
39 OPT_##ID,
40 #include "Opts.inc"
41 #undef OPTION
44 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
45 #include "Opts.inc"
46 #undef PREFIX
48 static const opt::OptTable::Info InfoTable[] = {
49 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
50 HELPTEXT, METAVAR, VALUES) \
51 { \
52 PREFIX, NAME, HELPTEXT, \
53 METAVAR, OPT_##ID, opt::Option::KIND##Class, \
54 PARAM, FLAGS, OPT_##GROUP, \
55 OPT_##ALIAS, ALIASARGS, VALUES},
56 #include "Opts.inc"
57 #undef OPTION
60 class RcOptTable : public opt::OptTable {
61 public:
62 RcOptTable() : OptTable(InfoTable, /* IgnoreCase = */ true) {}
65 static ExitOnError ExitOnErr;
67 LLVM_ATTRIBUTE_NORETURN static void fatalError(Twine Message) {
68 errs() << Message << "\n";
69 exit(1);
72 } // anonymous namespace
74 int main(int argc_, const char *argv_[]) {
75 sys::PrintStackTraceOnErrorSignal(argv_[0]);
76 PrettyStackTraceProgram X(argc_, argv_);
78 ExitOnErr.setBanner("llvm-rc: ");
80 SmallVector<const char *, 256> argv;
81 SpecificBumpPtrAllocator<char> ArgAllocator;
82 ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector(
83 argv, makeArrayRef(argv_, argc_), ArgAllocator)));
85 llvm_shutdown_obj Y;
87 RcOptTable T;
88 unsigned MAI, MAC;
89 ArrayRef<const char *> ArgsArr = makeArrayRef(argv_ + 1, argc_);
90 opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC);
92 // The tool prints nothing when invoked with no command-line arguments.
93 if (InputArgs.hasArg(OPT_HELP)) {
94 T.PrintHelp(outs(), "rc", "Resource Converter", false);
95 return 0;
98 const bool BeVerbose = InputArgs.hasArg(OPT_VERBOSE);
100 std::vector<std::string> InArgsInfo = InputArgs.getAllArgValues(OPT_INPUT);
101 if (InArgsInfo.size() != 1) {
102 fatalError("Exactly one input file should be provided.");
105 // Read and tokenize the input file.
106 const Twine &Filename = InArgsInfo[0];
107 ErrorOr<std::unique_ptr<MemoryBuffer>> File = MemoryBuffer::getFile(Filename);
108 if (!File) {
109 fatalError("Error opening file '" + Filename +
110 "': " + File.getError().message());
113 std::unique_ptr<MemoryBuffer> FileContents = std::move(*File);
114 StringRef Contents = FileContents->getBuffer();
116 std::vector<RCToken> Tokens = ExitOnErr(tokenizeRC(Contents));
118 if (BeVerbose) {
119 const Twine TokenNames[] = {
120 #define TOKEN(Name) #Name,
121 #define SHORT_TOKEN(Name, Ch) #Name,
122 #include "ResourceScriptTokenList.h"
123 #undef TOKEN
124 #undef SHORT_TOKEN
127 for (const RCToken &Token : Tokens) {
128 outs() << TokenNames[static_cast<int>(Token.kind())] << ": "
129 << Token.value();
130 if (Token.kind() == RCToken::Kind::Int)
131 outs() << "; int value = " << Token.intValue();
133 outs() << "\n";
137 rc::RCParser Parser{std::move(Tokens)};
138 while (!Parser.isEof()) {
139 auto Resource = ExitOnErr(Parser.parseSingleResource());
140 if (BeVerbose)
141 Resource->log(outs());
144 return 0;