blob: 695d455b6eba3edde96d8804ad6d48396aab4169 [file] [log] [blame]
Marek Sokolowski8f193432017-09-29 17:14:09 +00001//===-- ResourceSerializator.h ----------------------------------*- 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// This defines a visitor serializing resources to a .res stream.
11//
12//===---------------------------------------------------------------------===//
13
14#ifndef LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
15#define LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
16
17#include "ResourceScriptStmt.h"
18#include "ResourceVisitor.h"
19
20#include "llvm/Support/Endian.h"
21
22namespace llvm {
Zachary Turnerbd159d32017-11-17 01:00:35 +000023
24class MemoryBuffer;
25
Marek Sokolowski8f193432017-09-29 17:14:09 +000026namespace rc {
27
Martin Storsjod1d046a2018-05-02 19:43:44 +000028enum CodePage {
29 CpAcp = 0, // The current used codepage. Since there's no such
30 // notion in LLVM what codepage it actually means,
31 // this only allows ASCII.
32 CpWin1252 = 1252, // A codepage where most 8 bit values correspond to
33 // unicode code points with the same value.
34 CpUtf8 = 65001, // UTF-8.
35};
36
37struct WriterParams {
Zachary Turnerfa0ca6c2017-10-11 20:12:09 +000038 std::vector<std::string> Include; // Additional folders to search for files.
39 std::vector<std::string> NoInclude; // Folders to exclude from file search.
40 StringRef InputFilePath; // The full path of the input file.
Martin Storsjod1d046a2018-05-02 19:43:44 +000041 int CodePage = CpAcp; // The codepage for interpreting characters.
Zachary Turnerfa0ca6c2017-10-11 20:12:09 +000042};
43
Marek Sokolowski8f193432017-09-29 17:14:09 +000044class ResourceFileWriter : public Visitor {
45public:
Martin Storsjod1d046a2018-05-02 19:43:44 +000046 ResourceFileWriter(const WriterParams &Params,
Zachary Turnerfa0ca6c2017-10-11 20:12:09 +000047 std::unique_ptr<raw_fd_ostream> Stream)
48 : Params(Params), FS(std::move(Stream)), IconCursorID(1) {
Marek Sokolowski8f193432017-09-29 17:14:09 +000049 assert(FS && "Output stream needs to be provided to the serializator");
50 }
51
52 Error visitNullResource(const RCResource *) override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000053 Error visitAcceleratorsResource(const RCResource *) override;
Zachary Turnerc3ab0132017-10-06 21:25:44 +000054 Error visitCursorResource(const RCResource *) override;
Marek Sokolowski7f7745c2017-09-30 00:38:52 +000055 Error visitDialogResource(const RCResource *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000056 Error visitHTMLResource(const RCResource *) override;
Zachary Turnerc3ab0132017-10-06 21:25:44 +000057 Error visitIconResource(const RCResource *) override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +000058 Error visitMenuResource(const RCResource *) override;
Zachary Turner07bc04f2017-10-06 21:26:06 +000059 Error visitVersionInfoResource(const RCResource *) override;
Zachary Turnerda366692017-10-06 21:30:55 +000060 Error visitStringTableResource(const RCResource *) override;
Zachary Turner9d8b3582017-10-06 21:52:15 +000061 Error visitUserDefinedResource(const RCResource *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000062
Zachary Turner420090a2017-10-06 20:51:20 +000063 Error visitCaptionStmt(const CaptionStmt *) override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000064 Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
Zachary Turner420090a2017-10-06 20:51:20 +000065 Error visitFontStmt(const FontStmt *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000066 Error visitLanguageStmt(const LanguageResource *) override;
Zachary Turner420090a2017-10-06 20:51:20 +000067 Error visitStyleStmt(const StyleStmt *) override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000068 Error visitVersionStmt(const VersionStmt *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000069
Zachary Turnerda366692017-10-06 21:30:55 +000070 // Stringtables are output at the end of .res file. We need a separate
71 // function to do it.
72 Error dumpAllStringTables();
73
74 bool AppendNull; // Append '\0' to each existing STRINGTABLE element?
75
Marek Sokolowski8f193432017-09-29 17:14:09 +000076 struct ObjectInfo {
77 uint16_t LanguageInfo;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000078 uint32_t Characteristics;
79 uint32_t VersionInfo;
Marek Sokolowski8f193432017-09-29 17:14:09 +000080
Zachary Turner420090a2017-10-06 20:51:20 +000081 Optional<uint32_t> Style;
82 StringRef Caption;
83 struct FontInfo {
84 uint32_t Size;
85 StringRef Typeface;
86 uint32_t Weight;
87 bool IsItalic;
88 uint32_t Charset;
89 };
90 Optional<FontInfo> Font;
91
Marek Sokolowski22fccd62017-09-29 19:07:44 +000092 ObjectInfo() : LanguageInfo(0), Characteristics(0), VersionInfo(0) {}
Marek Sokolowski8f193432017-09-29 17:14:09 +000093 } ObjectData;
94
Zachary Turnerda366692017-10-06 21:30:55 +000095 struct StringTableInfo {
96 // Each STRINGTABLE bundle depends on ID of the bundle and language
97 // description.
98 using BundleKey = std::pair<uint16_t, uint16_t>;
99 // Each bundle is in fact an array of 16 strings.
100 struct Bundle {
101 std::array<Optional<StringRef>, 16> Data;
102 ObjectInfo DeclTimeInfo;
Martin Storsjo11adbac2018-05-15 06:35:29 +0000103 uint16_t MemoryFlags;
104 Bundle(const ObjectInfo &Info, uint16_t Flags)
105 : DeclTimeInfo(Info), MemoryFlags(Flags) {}
Zachary Turnerda366692017-10-06 21:30:55 +0000106 };
107 std::map<BundleKey, Bundle> BundleData;
Malcolm Parsons21e545d2018-01-24 10:33:39 +0000108 // Bundles are listed in the order of their first occurrence.
Zachary Turnerda366692017-10-06 21:30:55 +0000109 std::vector<BundleKey> BundleList;
110 } StringTableData;
111
Marek Sokolowski8f193432017-09-29 17:14:09 +0000112private:
Zachary Turner514b7102017-10-09 18:50:29 +0000113 Error handleError(Error Err, const RCResource *Res);
Marek Sokolowski8f193432017-09-29 17:14:09 +0000114
115 Error
116 writeResource(const RCResource *Res,
117 Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
118
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000119 // NullResource
Marek Sokolowski8f193432017-09-29 17:14:09 +0000120 Error writeNullBody(const RCResource *);
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000121
122 // AcceleratorsResource
123 Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
124 bool IsLastItem);
125 Error writeAcceleratorsBody(const RCResource *);
126
Martin Storsjo577b9812018-05-07 20:27:37 +0000127 // BitmapResource
Roman Lebedeve461a0f2018-05-07 21:06:53 +0000128 Error visitBitmapResource(const RCResource *) override;
Martin Storsjo577b9812018-05-07 20:27:37 +0000129 Error writeBitmapBody(const RCResource *);
130
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000131 // CursorResource and IconResource
132 Error visitIconOrCursorResource(const RCResource *);
133 Error visitIconOrCursorGroup(const RCResource *);
134 Error visitSingleIconOrCursor(const RCResource *);
135 Error writeSingleIconOrCursorBody(const RCResource *);
136 Error writeIconOrCursorGroupBody(const RCResource *);
137
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000138 // DialogResource
139 Error writeSingleDialogControl(const Control &, bool IsExtended);
140 Error writeDialogBody(const RCResource *);
141
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000142 // HTMLResource
Marek Sokolowski8f193432017-09-29 17:14:09 +0000143 Error writeHTMLBody(const RCResource *);
144
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000145 // MenuResource
146 Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
147 uint16_t Flags);
148 Error writeMenuDefinitionList(const MenuDefinitionList &List);
149 Error writeMenuBody(const RCResource *);
150
Zachary Turnerda366692017-10-06 21:30:55 +0000151 // StringTableResource
152 Error visitStringTableBundle(const RCResource *);
153 Error writeStringTableBundleBody(const RCResource *);
154 Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
155 uint16_t StringID, StringRef String);
156
Zachary Turner9d8b3582017-10-06 21:52:15 +0000157 // User defined resource
158 Error writeUserDefinedBody(const RCResource *);
159
Zachary Turner07bc04f2017-10-06 21:26:06 +0000160 // VersionInfoResource
161 Error writeVersionInfoBody(const RCResource *);
162 Error writeVersionInfoBlock(const VersionInfoBlock &);
163 Error writeVersionInfoValue(const VersionInfoValue &);
164
Martin Storsjod1d046a2018-05-02 19:43:44 +0000165 const WriterParams &Params;
Zachary Turnerfa0ca6c2017-10-11 20:12:09 +0000166
Marek Sokolowski8f193432017-09-29 17:14:09 +0000167 // Output stream handling.
168 std::unique_ptr<raw_fd_ostream> FS;
169
170 uint64_t tell() const { return FS->tell(); }
171
172 uint64_t writeObject(const ArrayRef<uint8_t> Data);
173
174 template <typename T> uint64_t writeInt(const T &Value) {
175 support::detail::packed_endian_specific_integral<T, support::little,
176 support::unaligned>
177 Object(Value);
178 return writeObject(Object);
179 }
180
181 template <typename T> uint64_t writeObject(const T &Value) {
182 return writeObject(ArrayRef<uint8_t>(
183 reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
184 }
185
186 template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
187 FS->pwrite((const char *)&Value, sizeof(T), Position);
188 }
189
190 Error writeCString(StringRef Str, bool WriteTerminator = true);
191
192 Error writeIdentifier(const IntOrString &Ident);
193 Error writeIntOrString(const IntOrString &Data);
194
Zachary Turner07bc04f2017-10-06 21:26:06 +0000195 void writeRCInt(RCInt);
196
Marek Sokolowski8f193432017-09-29 17:14:09 +0000197 Error appendFile(StringRef Filename);
198
199 void padStream(uint64_t Length);
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000200
Zachary Turnerfa0ca6c2017-10-11 20:12:09 +0000201 Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;
202
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000203 // Icon and cursor IDs are allocated starting from 1 and increasing for
204 // each icon/cursor dumped. This maintains the current ID to be allocated.
205 uint16_t IconCursorID;
Marek Sokolowski8f193432017-09-29 17:14:09 +0000206};
207
208} // namespace rc
209} // namespace llvm
210
211#endif