blob: 36d57da11eb6105acbf8b76d4047734bb3d1cf95 [file] [log] [blame]
Marek Sokolowskie37621b2017-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 Turnere847ec42017-11-17 01:00:35 +000023
24class MemoryBuffer;
25
Marek Sokolowskie37621b2017-09-29 17:14:09 +000026namespace rc {
27
Martin Storsjoe99f5b42018-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 Turnere315d732017-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 Storsjoe99f5b42018-05-02 19:43:44 +000041 int CodePage = CpAcp; // The codepage for interpreting characters.
Zachary Turnere315d732017-10-11 20:12:09 +000042};
43
Marek Sokolowskie37621b2017-09-29 17:14:09 +000044class ResourceFileWriter : public Visitor {
45public:
Martin Storsjoe99f5b42018-05-02 19:43:44 +000046 ResourceFileWriter(const WriterParams &Params,
Zachary Turnere315d732017-10-11 20:12:09 +000047 std::unique_ptr<raw_fd_ostream> Stream)
48 : Params(Params), FS(std::move(Stream)), IconCursorID(1) {
Marek Sokolowskie37621b2017-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 Sokolowskib121e772017-09-29 19:07:44 +000053 Error visitAcceleratorsResource(const RCResource *) override;
Zachary Turner4c72b952017-10-06 21:25:44 +000054 Error visitCursorResource(const RCResource *) override;
Marek Sokolowskibbf12f32017-09-30 00:38:52 +000055 Error visitDialogResource(const RCResource *) override;
Marek Sokolowskie37621b2017-09-29 17:14:09 +000056 Error visitHTMLResource(const RCResource *) override;
Zachary Turner4c72b952017-10-06 21:25:44 +000057 Error visitIconResource(const RCResource *) override;
Marek Sokolowskiea529932017-09-29 22:25:05 +000058 Error visitMenuResource(const RCResource *) override;
Zachary Turner93bb30d2017-10-06 21:26:06 +000059 Error visitVersionInfoResource(const RCResource *) override;
Zachary Turner84ad96b2017-10-06 21:30:55 +000060 Error visitStringTableResource(const RCResource *) override;
Zachary Turner080f10e2017-10-06 21:52:15 +000061 Error visitUserDefinedResource(const RCResource *) override;
Marek Sokolowskie37621b2017-09-29 17:14:09 +000062
Zachary Turner44bde8d2017-10-06 20:51:20 +000063 Error visitCaptionStmt(const CaptionStmt *) override;
Marek Sokolowskib121e772017-09-29 19:07:44 +000064 Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
Martin Storsjo65de7bd2018-05-15 19:21:28 +000065 Error visitClassStmt(const ClassStmt *) override;
Martin Storsjocec32ed2018-11-29 12:17:39 +000066 Error visitExStyleStmt(const ExStyleStmt *) override;
Zachary Turner44bde8d2017-10-06 20:51:20 +000067 Error visitFontStmt(const FontStmt *) override;
Marek Sokolowskie37621b2017-09-29 17:14:09 +000068 Error visitLanguageStmt(const LanguageResource *) override;
Zachary Turner44bde8d2017-10-06 20:51:20 +000069 Error visitStyleStmt(const StyleStmt *) override;
Marek Sokolowskib121e772017-09-29 19:07:44 +000070 Error visitVersionStmt(const VersionStmt *) override;
Marek Sokolowskie37621b2017-09-29 17:14:09 +000071
Zachary Turner84ad96b2017-10-06 21:30:55 +000072 // Stringtables are output at the end of .res file. We need a separate
73 // function to do it.
74 Error dumpAllStringTables();
75
76 bool AppendNull; // Append '\0' to each existing STRINGTABLE element?
77
Marek Sokolowskie37621b2017-09-29 17:14:09 +000078 struct ObjectInfo {
79 uint16_t LanguageInfo;
Marek Sokolowskib121e772017-09-29 19:07:44 +000080 uint32_t Characteristics;
81 uint32_t VersionInfo;
Marek Sokolowskie37621b2017-09-29 17:14:09 +000082
Zachary Turner44bde8d2017-10-06 20:51:20 +000083 Optional<uint32_t> Style;
Martin Storsjocec32ed2018-11-29 12:17:39 +000084 Optional<uint32_t> ExStyle;
Zachary Turner44bde8d2017-10-06 20:51:20 +000085 StringRef Caption;
86 struct FontInfo {
87 uint32_t Size;
88 StringRef Typeface;
89 uint32_t Weight;
90 bool IsItalic;
91 uint32_t Charset;
92 };
93 Optional<FontInfo> Font;
Martin Storsjo65de7bd2018-05-15 19:21:28 +000094 IntOrString Class;
Zachary Turner44bde8d2017-10-06 20:51:20 +000095
Martin Storsjo65de7bd2018-05-15 19:21:28 +000096 ObjectInfo()
97 : LanguageInfo(0), Characteristics(0), VersionInfo(0),
98 Class(StringRef()) {}
Marek Sokolowskie37621b2017-09-29 17:14:09 +000099 } ObjectData;
100
Zachary Turner84ad96b2017-10-06 21:30:55 +0000101 struct StringTableInfo {
102 // Each STRINGTABLE bundle depends on ID of the bundle and language
103 // description.
104 using BundleKey = std::pair<uint16_t, uint16_t>;
105 // Each bundle is in fact an array of 16 strings.
106 struct Bundle {
107 std::array<Optional<StringRef>, 16> Data;
108 ObjectInfo DeclTimeInfo;
Martin Storsjo370633f2018-05-15 06:35:29 +0000109 uint16_t MemoryFlags;
110 Bundle(const ObjectInfo &Info, uint16_t Flags)
111 : DeclTimeInfo(Info), MemoryFlags(Flags) {}
Zachary Turner84ad96b2017-10-06 21:30:55 +0000112 };
113 std::map<BundleKey, Bundle> BundleData;
Malcolm Parsons5fc96282018-01-24 10:33:39 +0000114 // Bundles are listed in the order of their first occurrence.
Zachary Turner84ad96b2017-10-06 21:30:55 +0000115 std::vector<BundleKey> BundleList;
116 } StringTableData;
117
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000118private:
Zachary Turner5d1b2d32017-10-09 18:50:29 +0000119 Error handleError(Error Err, const RCResource *Res);
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000120
121 Error
122 writeResource(const RCResource *Res,
123 Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
124
Marek Sokolowskib121e772017-09-29 19:07:44 +0000125 // NullResource
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000126 Error writeNullBody(const RCResource *);
Marek Sokolowskib121e772017-09-29 19:07:44 +0000127
128 // AcceleratorsResource
129 Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
130 bool IsLastItem);
131 Error writeAcceleratorsBody(const RCResource *);
132
Martin Storsjo31dc80f2018-05-07 20:27:37 +0000133 // BitmapResource
Roman Lebedev64415492018-05-07 21:06:53 +0000134 Error visitBitmapResource(const RCResource *) override;
Martin Storsjo31dc80f2018-05-07 20:27:37 +0000135 Error writeBitmapBody(const RCResource *);
136
Zachary Turner4c72b952017-10-06 21:25:44 +0000137 // CursorResource and IconResource
138 Error visitIconOrCursorResource(const RCResource *);
139 Error visitIconOrCursorGroup(const RCResource *);
140 Error visitSingleIconOrCursor(const RCResource *);
141 Error writeSingleIconOrCursorBody(const RCResource *);
142 Error writeIconOrCursorGroupBody(const RCResource *);
143
Marek Sokolowskibbf12f32017-09-30 00:38:52 +0000144 // DialogResource
145 Error writeSingleDialogControl(const Control &, bool IsExtended);
146 Error writeDialogBody(const RCResource *);
147
Marek Sokolowskib121e772017-09-29 19:07:44 +0000148 // HTMLResource
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000149 Error writeHTMLBody(const RCResource *);
150
Marek Sokolowskiea529932017-09-29 22:25:05 +0000151 // MenuResource
152 Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
153 uint16_t Flags);
154 Error writeMenuDefinitionList(const MenuDefinitionList &List);
155 Error writeMenuBody(const RCResource *);
156
Zachary Turner84ad96b2017-10-06 21:30:55 +0000157 // StringTableResource
158 Error visitStringTableBundle(const RCResource *);
159 Error writeStringTableBundleBody(const RCResource *);
160 Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
161 uint16_t StringID, StringRef String);
162
Zachary Turner080f10e2017-10-06 21:52:15 +0000163 // User defined resource
164 Error writeUserDefinedBody(const RCResource *);
165
Zachary Turner93bb30d2017-10-06 21:26:06 +0000166 // VersionInfoResource
167 Error writeVersionInfoBody(const RCResource *);
168 Error writeVersionInfoBlock(const VersionInfoBlock &);
169 Error writeVersionInfoValue(const VersionInfoValue &);
170
Martin Storsjoe99f5b42018-05-02 19:43:44 +0000171 const WriterParams &Params;
Zachary Turnere315d732017-10-11 20:12:09 +0000172
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000173 // Output stream handling.
174 std::unique_ptr<raw_fd_ostream> FS;
175
176 uint64_t tell() const { return FS->tell(); }
177
178 uint64_t writeObject(const ArrayRef<uint8_t> Data);
179
180 template <typename T> uint64_t writeInt(const T &Value) {
181 support::detail::packed_endian_specific_integral<T, support::little,
182 support::unaligned>
183 Object(Value);
184 return writeObject(Object);
185 }
186
187 template <typename T> uint64_t writeObject(const T &Value) {
188 return writeObject(ArrayRef<uint8_t>(
189 reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
190 }
191
192 template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
193 FS->pwrite((const char *)&Value, sizeof(T), Position);
194 }
195
196 Error writeCString(StringRef Str, bool WriteTerminator = true);
197
198 Error writeIdentifier(const IntOrString &Ident);
199 Error writeIntOrString(const IntOrString &Data);
200
Zachary Turner93bb30d2017-10-06 21:26:06 +0000201 void writeRCInt(RCInt);
202
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000203 Error appendFile(StringRef Filename);
204
205 void padStream(uint64_t Length);
Zachary Turner4c72b952017-10-06 21:25:44 +0000206
Zachary Turnere315d732017-10-11 20:12:09 +0000207 Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;
208
Zachary Turner4c72b952017-10-06 21:25:44 +0000209 // Icon and cursor IDs are allocated starting from 1 and increasing for
210 // each icon/cursor dumped. This maintains the current ID to be allocated.
211 uint16_t IconCursorID;
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000212};
213
214} // namespace rc
215} // namespace llvm
216
217#endif