xref: /openbsd-src/gnu/llvm/llvm/tools/llvm-rc/ResourceFileWriter.h (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- ResourceSerializator.h ----------------------------------*- C++-*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===---------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This defines a visitor serializing resources to a .res stream.
1009467b48Spatrick //
1109467b48Spatrick //===---------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #ifndef LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
1409467b48Spatrick #define LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
1509467b48Spatrick 
1609467b48Spatrick #include "ResourceScriptStmt.h"
1709467b48Spatrick #include "ResourceVisitor.h"
1809467b48Spatrick 
1909467b48Spatrick #include "llvm/Support/Endian.h"
2009467b48Spatrick 
2109467b48Spatrick namespace llvm {
2209467b48Spatrick 
2309467b48Spatrick class MemoryBuffer;
2409467b48Spatrick 
2509467b48Spatrick namespace rc {
2609467b48Spatrick 
2709467b48Spatrick enum CodePage {
2809467b48Spatrick   CpAcp = 0,        // The current used codepage. Since there's no such
2909467b48Spatrick                     // notion in LLVM what codepage it actually means,
3009467b48Spatrick                     // this only allows ASCII.
3109467b48Spatrick   CpWin1252 = 1252, // A codepage where most 8 bit values correspond to
3209467b48Spatrick                     // unicode code points with the same value.
3309467b48Spatrick   CpUtf8 = 65001,   // UTF-8.
3409467b48Spatrick };
3509467b48Spatrick 
3609467b48Spatrick struct WriterParams {
3709467b48Spatrick   std::vector<std::string> Include;   // Additional folders to search for files.
3873471bf0Spatrick   bool NoInclude;                     // Ignore the INCLUDE variable.
3909467b48Spatrick   StringRef InputFilePath;            // The full path of the input file.
4009467b48Spatrick   int CodePage = CpAcp;               // The codepage for interpreting characters.
4109467b48Spatrick };
4209467b48Spatrick 
4309467b48Spatrick class ResourceFileWriter : public Visitor {
4409467b48Spatrick public:
ResourceFileWriter(const WriterParams & Params,std::unique_ptr<raw_fd_ostream> Stream)4509467b48Spatrick   ResourceFileWriter(const WriterParams &Params,
4609467b48Spatrick                      std::unique_ptr<raw_fd_ostream> Stream)
4709467b48Spatrick       : Params(Params), FS(std::move(Stream)), IconCursorID(1) {
4809467b48Spatrick     assert(FS && "Output stream needs to be provided to the serializator");
4909467b48Spatrick   }
5009467b48Spatrick 
5109467b48Spatrick   Error visitNullResource(const RCResource *) override;
5209467b48Spatrick   Error visitAcceleratorsResource(const RCResource *) override;
5309467b48Spatrick   Error visitCursorResource(const RCResource *) override;
5409467b48Spatrick   Error visitDialogResource(const RCResource *) override;
5509467b48Spatrick   Error visitHTMLResource(const RCResource *) override;
5609467b48Spatrick   Error visitIconResource(const RCResource *) override;
5709467b48Spatrick   Error visitMenuResource(const RCResource *) override;
5809467b48Spatrick   Error visitVersionInfoResource(const RCResource *) override;
5909467b48Spatrick   Error visitStringTableResource(const RCResource *) override;
6009467b48Spatrick   Error visitUserDefinedResource(const RCResource *) override;
6109467b48Spatrick 
6209467b48Spatrick   Error visitCaptionStmt(const CaptionStmt *) override;
6309467b48Spatrick   Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
6409467b48Spatrick   Error visitClassStmt(const ClassStmt *) override;
6509467b48Spatrick   Error visitExStyleStmt(const ExStyleStmt *) override;
6609467b48Spatrick   Error visitFontStmt(const FontStmt *) override;
6709467b48Spatrick   Error visitLanguageStmt(const LanguageResource *) override;
6809467b48Spatrick   Error visitStyleStmt(const StyleStmt *) override;
6909467b48Spatrick   Error visitVersionStmt(const VersionStmt *) override;
7009467b48Spatrick 
7109467b48Spatrick   // Stringtables are output at the end of .res file. We need a separate
7209467b48Spatrick   // function to do it.
7309467b48Spatrick   Error dumpAllStringTables();
7409467b48Spatrick 
7509467b48Spatrick   bool AppendNull = false; // Append '\0' to each existing STRINGTABLE element?
7609467b48Spatrick 
7709467b48Spatrick   struct ObjectInfo {
7809467b48Spatrick     uint16_t LanguageInfo;
7909467b48Spatrick     uint32_t Characteristics;
8009467b48Spatrick     uint32_t VersionInfo;
8109467b48Spatrick 
82*d415bd75Srobert     std::optional<uint32_t> Style;
83*d415bd75Srobert     std::optional<uint32_t> ExStyle;
8409467b48Spatrick     StringRef Caption;
8509467b48Spatrick     struct FontInfo {
8609467b48Spatrick       uint32_t Size;
8709467b48Spatrick       StringRef Typeface;
8809467b48Spatrick       uint32_t Weight;
8909467b48Spatrick       bool IsItalic;
9009467b48Spatrick       uint32_t Charset;
9109467b48Spatrick     };
92*d415bd75Srobert     std::optional<FontInfo> Font;
9309467b48Spatrick     IntOrString Class;
9409467b48Spatrick 
ObjectInfoObjectInfo9509467b48Spatrick     ObjectInfo()
9609467b48Spatrick         : LanguageInfo(0), Characteristics(0), VersionInfo(0),
9709467b48Spatrick           Class(StringRef()) {}
9809467b48Spatrick   } ObjectData;
9909467b48Spatrick 
10009467b48Spatrick   struct StringTableInfo {
10109467b48Spatrick     // Each STRINGTABLE bundle depends on ID of the bundle and language
10209467b48Spatrick     // description.
10309467b48Spatrick     using BundleKey = std::pair<uint16_t, uint16_t>;
10409467b48Spatrick     // Each bundle is in fact an array of 16 strings.
10509467b48Spatrick     struct Bundle {
106*d415bd75Srobert       std::array<std::optional<std::vector<StringRef>>, 16> Data;
10709467b48Spatrick       ObjectInfo DeclTimeInfo;
10809467b48Spatrick       uint16_t MemoryFlags;
BundleStringTableInfo::Bundle10909467b48Spatrick       Bundle(const ObjectInfo &Info, uint16_t Flags)
11009467b48Spatrick           : DeclTimeInfo(Info), MemoryFlags(Flags) {}
11109467b48Spatrick     };
11209467b48Spatrick     std::map<BundleKey, Bundle> BundleData;
11309467b48Spatrick     // Bundles are listed in the order of their first occurrence.
11409467b48Spatrick     std::vector<BundleKey> BundleList;
11509467b48Spatrick   } StringTableData;
11609467b48Spatrick 
11709467b48Spatrick private:
11809467b48Spatrick   Error handleError(Error Err, const RCResource *Res);
11909467b48Spatrick 
12009467b48Spatrick   Error
12109467b48Spatrick   writeResource(const RCResource *Res,
12209467b48Spatrick                 Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
12309467b48Spatrick 
12409467b48Spatrick   // NullResource
12509467b48Spatrick   Error writeNullBody(const RCResource *);
12609467b48Spatrick 
12709467b48Spatrick   // AcceleratorsResource
12809467b48Spatrick   Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
12909467b48Spatrick                                bool IsLastItem);
13009467b48Spatrick   Error writeAcceleratorsBody(const RCResource *);
13109467b48Spatrick 
13209467b48Spatrick   // BitmapResource
13309467b48Spatrick   Error visitBitmapResource(const RCResource *) override;
13409467b48Spatrick   Error writeBitmapBody(const RCResource *);
13509467b48Spatrick 
13609467b48Spatrick   // CursorResource and IconResource
13709467b48Spatrick   Error visitIconOrCursorResource(const RCResource *);
13809467b48Spatrick   Error visitIconOrCursorGroup(const RCResource *);
13909467b48Spatrick   Error visitSingleIconOrCursor(const RCResource *);
14009467b48Spatrick   Error writeSingleIconOrCursorBody(const RCResource *);
14109467b48Spatrick   Error writeIconOrCursorGroupBody(const RCResource *);
14209467b48Spatrick 
14309467b48Spatrick   // DialogResource
14409467b48Spatrick   Error writeSingleDialogControl(const Control &, bool IsExtended);
14509467b48Spatrick   Error writeDialogBody(const RCResource *);
14609467b48Spatrick 
14709467b48Spatrick   // HTMLResource
14809467b48Spatrick   Error writeHTMLBody(const RCResource *);
14909467b48Spatrick 
15009467b48Spatrick   // MenuResource
15109467b48Spatrick   Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
15209467b48Spatrick                             uint16_t Flags);
15309467b48Spatrick   Error writeMenuDefinitionList(const MenuDefinitionList &List);
15409467b48Spatrick   Error writeMenuBody(const RCResource *);
15509467b48Spatrick 
15609467b48Spatrick   // StringTableResource
15709467b48Spatrick   Error visitStringTableBundle(const RCResource *);
15809467b48Spatrick   Error writeStringTableBundleBody(const RCResource *);
15909467b48Spatrick   Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
160097a140dSpatrick                                uint16_t StringID,
161097a140dSpatrick                                const std::vector<StringRef> &String);
16209467b48Spatrick 
16309467b48Spatrick   // User defined resource
16409467b48Spatrick   Error writeUserDefinedBody(const RCResource *);
16509467b48Spatrick 
16609467b48Spatrick   // VersionInfoResource
16709467b48Spatrick   Error writeVersionInfoBody(const RCResource *);
16809467b48Spatrick   Error writeVersionInfoBlock(const VersionInfoBlock &);
16909467b48Spatrick   Error writeVersionInfoValue(const VersionInfoValue &);
17009467b48Spatrick 
17109467b48Spatrick   const WriterParams &Params;
17209467b48Spatrick 
17309467b48Spatrick   // Output stream handling.
17409467b48Spatrick   std::unique_ptr<raw_fd_ostream> FS;
17509467b48Spatrick 
tell()17609467b48Spatrick   uint64_t tell() const { return FS->tell(); }
17709467b48Spatrick 
17809467b48Spatrick   uint64_t writeObject(const ArrayRef<uint8_t> Data);
17909467b48Spatrick 
writeInt(const T & Value)18009467b48Spatrick   template <typename T> uint64_t writeInt(const T &Value) {
18109467b48Spatrick     support::detail::packed_endian_specific_integral<T, support::little,
18209467b48Spatrick                                                      support::unaligned>
18309467b48Spatrick         Object(Value);
18409467b48Spatrick     return writeObject(Object);
18509467b48Spatrick   }
18609467b48Spatrick 
writeObject(const T & Value)18709467b48Spatrick   template <typename T> uint64_t writeObject(const T &Value) {
18809467b48Spatrick     return writeObject(ArrayRef<uint8_t>(
18909467b48Spatrick         reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
19009467b48Spatrick   }
19109467b48Spatrick 
writeObjectAt(const T & Value,uint64_t Position)19209467b48Spatrick   template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
19309467b48Spatrick     FS->pwrite((const char *)&Value, sizeof(T), Position);
19409467b48Spatrick   }
19509467b48Spatrick 
19609467b48Spatrick   Error writeCString(StringRef Str, bool WriteTerminator = true);
19709467b48Spatrick 
19809467b48Spatrick   Error writeIdentifier(const IntOrString &Ident);
19909467b48Spatrick   Error writeIntOrString(const IntOrString &Data);
20009467b48Spatrick 
20109467b48Spatrick   void writeRCInt(RCInt);
20209467b48Spatrick 
20309467b48Spatrick   Error appendFile(StringRef Filename);
20409467b48Spatrick 
20509467b48Spatrick   void padStream(uint64_t Length);
20609467b48Spatrick 
20709467b48Spatrick   Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;
20809467b48Spatrick 
20909467b48Spatrick   // Icon and cursor IDs are allocated starting from 1 and increasing for
21009467b48Spatrick   // each icon/cursor dumped. This maintains the current ID to be allocated.
21109467b48Spatrick   uint16_t IconCursorID;
21209467b48Spatrick };
21309467b48Spatrick 
21409467b48Spatrick } // namespace rc
21509467b48Spatrick } // namespace llvm
21609467b48Spatrick 
21709467b48Spatrick #endif
218