• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- 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 
22 namespace llvm {
23 
24 class MemoryBuffer;
25 
26 namespace rc {
27 
28 enum 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 
37 struct WriterParams {
38   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.
41   int CodePage = CpAcp;               // The codepage for interpreting characters.
42 };
43 
44 class ResourceFileWriter : public Visitor {
45 public:
ResourceFileWriter(const WriterParams & Params,std::unique_ptr<raw_fd_ostream> Stream)46   ResourceFileWriter(const WriterParams &Params,
47                      std::unique_ptr<raw_fd_ostream> Stream)
48       : Params(Params), FS(std::move(Stream)), IconCursorID(1) {
49     assert(FS && "Output stream needs to be provided to the serializator");
50   }
51 
52   Error visitNullResource(const RCResource *) override;
53   Error visitAcceleratorsResource(const RCResource *) override;
54   Error visitCursorResource(const RCResource *) override;
55   Error visitDialogResource(const RCResource *) override;
56   Error visitHTMLResource(const RCResource *) override;
57   Error visitIconResource(const RCResource *) override;
58   Error visitMenuResource(const RCResource *) override;
59   Error visitVersionInfoResource(const RCResource *) override;
60   Error visitStringTableResource(const RCResource *) override;
61   Error visitUserDefinedResource(const RCResource *) override;
62 
63   Error visitCaptionStmt(const CaptionStmt *) override;
64   Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
65   Error visitClassStmt(const ClassStmt *) override;
66   Error visitFontStmt(const FontStmt *) override;
67   Error visitLanguageStmt(const LanguageResource *) override;
68   Error visitStyleStmt(const StyleStmt *) override;
69   Error visitVersionStmt(const VersionStmt *) override;
70 
71   // Stringtables are output at the end of .res file. We need a separate
72   // function to do it.
73   Error dumpAllStringTables();
74 
75   bool AppendNull; // Append '\0' to each existing STRINGTABLE element?
76 
77   struct ObjectInfo {
78     uint16_t LanguageInfo;
79     uint32_t Characteristics;
80     uint32_t VersionInfo;
81 
82     Optional<uint32_t> Style;
83     StringRef Caption;
84     struct FontInfo {
85       uint32_t Size;
86       StringRef Typeface;
87       uint32_t Weight;
88       bool IsItalic;
89       uint32_t Charset;
90     };
91     Optional<FontInfo> Font;
92     IntOrString Class;
93 
ObjectInfoObjectInfo94     ObjectInfo()
95         : LanguageInfo(0), Characteristics(0), VersionInfo(0),
96           Class(StringRef()) {}
97   } ObjectData;
98 
99   struct StringTableInfo {
100     // Each STRINGTABLE bundle depends on ID of the bundle and language
101     // description.
102     using BundleKey = std::pair<uint16_t, uint16_t>;
103     // Each bundle is in fact an array of 16 strings.
104     struct Bundle {
105       std::array<Optional<StringRef>, 16> Data;
106       ObjectInfo DeclTimeInfo;
107       uint16_t MemoryFlags;
BundleStringTableInfo::Bundle108       Bundle(const ObjectInfo &Info, uint16_t Flags)
109           : DeclTimeInfo(Info), MemoryFlags(Flags) {}
110     };
111     std::map<BundleKey, Bundle> BundleData;
112     // Bundles are listed in the order of their first occurrence.
113     std::vector<BundleKey> BundleList;
114   } StringTableData;
115 
116 private:
117   Error handleError(Error Err, const RCResource *Res);
118 
119   Error
120   writeResource(const RCResource *Res,
121                 Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
122 
123   // NullResource
124   Error writeNullBody(const RCResource *);
125 
126   // AcceleratorsResource
127   Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
128                                bool IsLastItem);
129   Error writeAcceleratorsBody(const RCResource *);
130 
131   // BitmapResource
132   Error visitBitmapResource(const RCResource *) override;
133   Error writeBitmapBody(const RCResource *);
134 
135   // CursorResource and IconResource
136   Error visitIconOrCursorResource(const RCResource *);
137   Error visitIconOrCursorGroup(const RCResource *);
138   Error visitSingleIconOrCursor(const RCResource *);
139   Error writeSingleIconOrCursorBody(const RCResource *);
140   Error writeIconOrCursorGroupBody(const RCResource *);
141 
142   // DialogResource
143   Error writeSingleDialogControl(const Control &, bool IsExtended);
144   Error writeDialogBody(const RCResource *);
145 
146   // HTMLResource
147   Error writeHTMLBody(const RCResource *);
148 
149   // MenuResource
150   Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
151                             uint16_t Flags);
152   Error writeMenuDefinitionList(const MenuDefinitionList &List);
153   Error writeMenuBody(const RCResource *);
154 
155   // StringTableResource
156   Error visitStringTableBundle(const RCResource *);
157   Error writeStringTableBundleBody(const RCResource *);
158   Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
159                                uint16_t StringID, StringRef String);
160 
161   // User defined resource
162   Error writeUserDefinedBody(const RCResource *);
163 
164   // VersionInfoResource
165   Error writeVersionInfoBody(const RCResource *);
166   Error writeVersionInfoBlock(const VersionInfoBlock &);
167   Error writeVersionInfoValue(const VersionInfoValue &);
168 
169   const WriterParams &Params;
170 
171   // Output stream handling.
172   std::unique_ptr<raw_fd_ostream> FS;
173 
tell()174   uint64_t tell() const { return FS->tell(); }
175 
176   uint64_t writeObject(const ArrayRef<uint8_t> Data);
177 
writeInt(const T & Value)178   template <typename T> uint64_t writeInt(const T &Value) {
179     support::detail::packed_endian_specific_integral<T, support::little,
180                                                      support::unaligned>
181         Object(Value);
182     return writeObject(Object);
183   }
184 
writeObject(const T & Value)185   template <typename T> uint64_t writeObject(const T &Value) {
186     return writeObject(ArrayRef<uint8_t>(
187         reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
188   }
189 
writeObjectAt(const T & Value,uint64_t Position)190   template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
191     FS->pwrite((const char *)&Value, sizeof(T), Position);
192   }
193 
194   Error writeCString(StringRef Str, bool WriteTerminator = true);
195 
196   Error writeIdentifier(const IntOrString &Ident);
197   Error writeIntOrString(const IntOrString &Data);
198 
199   void writeRCInt(RCInt);
200 
201   Error appendFile(StringRef Filename);
202 
203   void padStream(uint64_t Length);
204 
205   Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;
206 
207   // Icon and cursor IDs are allocated starting from 1 and increasing for
208   // each icon/cursor dumped. This maintains the current ID to be allocated.
209   uint16_t IconCursorID;
210 };
211 
212 } // namespace rc
213 } // namespace llvm
214 
215 #endif
216