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