Mercurial > hg > CbC > CbC_llvm
comparison tools/llvm-rc/llvm-rc.cpp @ 122:36195a0db682
merging ( incomplete )
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Nov 2017 20:32:31 +0900 |
parents | 803732b1fca8 |
children | 3a76565eade5 |
comparison
equal
deleted
inserted
replaced
119:d9df2cbd60cd | 122:36195a0db682 |
---|---|
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. | |
12 // | |
13 //===----------------------------------------------------------------------===// | |
14 | |
15 #include "ResourceFileWriter.h" | |
16 #include "ResourceScriptParser.h" | |
17 #include "ResourceScriptStmt.h" | |
18 #include "ResourceScriptToken.h" | |
19 | |
20 #include "llvm/Option/Arg.h" | |
21 #include "llvm/Option/ArgList.h" | |
22 #include "llvm/Support/Error.h" | |
23 #include "llvm/Support/FileSystem.h" | |
24 #include "llvm/Support/ManagedStatic.h" | |
25 #include "llvm/Support/PrettyStackTrace.h" | |
26 #include "llvm/Support/Process.h" | |
27 #include "llvm/Support/Signals.h" | |
28 #include "llvm/Support/raw_ostream.h" | |
29 | |
30 #include <system_error> | |
31 | |
32 using namespace llvm; | |
33 using namespace llvm::rc; | |
34 | |
35 namespace { | |
36 | |
37 // Input options tables. | |
38 | |
39 enum ID { | |
40 OPT_INVALID = 0, // This is not a correct option ID. | |
41 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ | |
42 HELPTEXT, METAVAR, VALUES) \ | |
43 OPT_##ID, | |
44 #include "Opts.inc" | |
45 #undef OPTION | |
46 }; | |
47 | |
48 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; | |
49 #include "Opts.inc" | |
50 #undef PREFIX | |
51 | |
52 static const opt::OptTable::Info InfoTable[] = { | |
53 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ | |
54 HELPTEXT, METAVAR, VALUES) \ | |
55 { \ | |
56 PREFIX, NAME, HELPTEXT, \ | |
57 METAVAR, OPT_##ID, opt::Option::KIND##Class, \ | |
58 PARAM, FLAGS, OPT_##GROUP, \ | |
59 OPT_##ALIAS, ALIASARGS, VALUES}, | |
60 #include "Opts.inc" | |
61 #undef OPTION | |
62 }; | |
63 | |
64 class RcOptTable : public opt::OptTable { | |
65 public: | |
66 RcOptTable() : OptTable(InfoTable, /* IgnoreCase = */ true) {} | |
67 }; | |
68 | |
69 static ExitOnError ExitOnErr; | |
70 | |
71 LLVM_ATTRIBUTE_NORETURN static void fatalError(const Twine &Message) { | |
72 errs() << Message << "\n"; | |
73 exit(1); | |
74 } | |
75 | |
76 } // anonymous namespace | |
77 | |
78 int main(int argc_, const char *argv_[]) { | |
79 sys::PrintStackTraceOnErrorSignal(argv_[0]); | |
80 PrettyStackTraceProgram X(argc_, argv_); | |
81 | |
82 ExitOnErr.setBanner("llvm-rc: "); | |
83 | |
84 SmallVector<const char *, 256> argv; | |
85 SpecificBumpPtrAllocator<char> ArgAllocator; | |
86 ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector( | |
87 argv, makeArrayRef(argv_, argc_), ArgAllocator))); | |
88 | |
89 llvm_shutdown_obj Y; | |
90 | |
91 RcOptTable T; | |
92 unsigned MAI, MAC; | |
93 ArrayRef<const char *> ArgsArr = makeArrayRef(argv_ + 1, argc_); | |
94 opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC); | |
95 | |
96 // The tool prints nothing when invoked with no command-line arguments. | |
97 if (InputArgs.hasArg(OPT_HELP)) { | |
98 T.PrintHelp(outs(), "rc", "Resource Converter", false); | |
99 return 0; | |
100 } | |
101 | |
102 const bool BeVerbose = InputArgs.hasArg(OPT_VERBOSE); | |
103 | |
104 std::vector<std::string> InArgsInfo = InputArgs.getAllArgValues(OPT_INPUT); | |
105 if (InArgsInfo.size() != 1) { | |
106 fatalError("Exactly one input file should be provided."); | |
107 } | |
108 | |
109 // Read and tokenize the input file. | |
110 ErrorOr<std::unique_ptr<MemoryBuffer>> File = | |
111 MemoryBuffer::getFile(InArgsInfo[0]); | |
112 if (!File) { | |
113 fatalError("Error opening file '" + Twine(InArgsInfo[0]) + | |
114 "': " + File.getError().message()); | |
115 } | |
116 | |
117 std::unique_ptr<MemoryBuffer> FileContents = std::move(*File); | |
118 StringRef Contents = FileContents->getBuffer(); | |
119 | |
120 std::vector<RCToken> Tokens = ExitOnErr(tokenizeRC(Contents)); | |
121 | |
122 if (BeVerbose) { | |
123 const Twine TokenNames[] = { | |
124 #define TOKEN(Name) #Name, | |
125 #define SHORT_TOKEN(Name, Ch) #Name, | |
126 #include "ResourceScriptTokenList.h" | |
127 #undef TOKEN | |
128 #undef SHORT_TOKEN | |
129 }; | |
130 | |
131 for (const RCToken &Token : Tokens) { | |
132 outs() << TokenNames[static_cast<int>(Token.kind())] << ": " | |
133 << Token.value(); | |
134 if (Token.kind() == RCToken::Kind::Int) | |
135 outs() << "; int value = " << Token.intValue(); | |
136 | |
137 outs() << "\n"; | |
138 } | |
139 } | |
140 | |
141 SearchParams Params; | |
142 SmallString<128> InputFile(InArgsInfo[0]); | |
143 llvm::sys::fs::make_absolute(InputFile); | |
144 Params.InputFilePath = InputFile; | |
145 Params.Include = InputArgs.getAllArgValues(OPT_INCLUDE); | |
146 Params.NoInclude = InputArgs.getAllArgValues(OPT_NOINCLUDE); | |
147 | |
148 std::unique_ptr<ResourceFileWriter> Visitor; | |
149 bool IsDryRun = InputArgs.hasArg(OPT_DRY_RUN); | |
150 | |
151 if (!IsDryRun) { | |
152 auto OutArgsInfo = InputArgs.getAllArgValues(OPT_FILEOUT); | |
153 if (OutArgsInfo.size() != 1) | |
154 fatalError( | |
155 "Exactly one output file should be provided (using /FO flag)."); | |
156 | |
157 std::error_code EC; | |
158 auto FOut = | |
159 llvm::make_unique<raw_fd_ostream>(OutArgsInfo[0], EC, sys::fs::F_RW); | |
160 if (EC) | |
161 fatalError("Error opening output file '" + OutArgsInfo[0] + | |
162 "': " + EC.message()); | |
163 Visitor = llvm::make_unique<ResourceFileWriter>(Params, std::move(FOut)); | |
164 Visitor->AppendNull = InputArgs.hasArg(OPT_ADD_NULL); | |
165 | |
166 ExitOnErr(NullResource().visit(Visitor.get())); | |
167 | |
168 // Set the default language; choose en-US arbitrarily. | |
169 ExitOnErr(LanguageResource(0x09, 0x01).visit(Visitor.get())); | |
170 } | |
171 | |
172 rc::RCParser Parser{std::move(Tokens)}; | |
173 while (!Parser.isEof()) { | |
174 auto Resource = ExitOnErr(Parser.parseSingleResource()); | |
175 if (BeVerbose) | |
176 Resource->log(outs()); | |
177 if (!IsDryRun) | |
178 ExitOnErr(Resource->visit(Visitor.get())); | |
179 } | |
180 | |
181 // STRINGTABLE resources come at the very end. | |
182 if (!IsDryRun) | |
183 ExitOnErr(Visitor->dumpAllStringTables()); | |
184 | |
185 return 0; | |
186 } |