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