1 //===-- llvm-rc.cpp - Compile .rc scripts into .res -------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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>
33 // Input options tables.
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) \
44 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
48 static const opt::OptTable::Info InfoTable
[] = {
49 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
50 HELPTEXT, METAVAR, VALUES) \
52 PREFIX, NAME, HELPTEXT, \
53 METAVAR, OPT_##ID, opt::Option::KIND##Class, \
54 PARAM, FLAGS, OPT_##GROUP, \
55 OPT_##ALIAS, ALIASARGS, VALUES},
60 class RcOptTable
: public opt::OptTable
{
62 RcOptTable() : OptTable(InfoTable
, /* IgnoreCase = */ true) {}
65 static ExitOnError ExitOnErr
;
67 LLVM_ATTRIBUTE_NORETURN
static void fatalError(Twine Message
) {
68 errs() << Message
<< "\n";
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
)));
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);
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
);
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
));
119 const Twine TokenNames
[] = {
120 #define TOKEN(Name) #Name,
121 #define SHORT_TOKEN(Name, Ch) #Name,
122 #include "ResourceScriptTokenList.h"
127 for (const RCToken
&Token
: Tokens
) {
128 outs() << TokenNames
[static_cast<int>(Token
.kind())] << ": "
130 if (Token
.kind() == RCToken::Kind::Int
)
131 outs() << "; int value = " << Token
.intValue();
137 rc::RCParser Parser
{std::move(Tokens
)};
138 while (!Parser
.isEof()) {
139 auto Resource
= ExitOnErr(Parser
.parseSingleResource());
141 Resource
->log(outs());